Sync width directive

This commit is contained in:
Adina Țeudan 2020-12-01 22:14:48 +02:00
parent 024f251a39
commit d040961e25
14 changed files with 140 additions and 95 deletions

View File

@ -87,6 +87,7 @@ import { CustomTooltipModule } from './common/red-tooltip/custom-tooltip.module'
import { ScrollingModule } from '@angular/cdk/scrolling';
import { VirtualScrollComponent } from './utils/virtual-scroll/virtual-scroll.component';
import { DragDropModule } from '@angular/cdk/drag-drop';
import { SyncWidthDirective } from './utils/sync-width.directive';
export function HttpLoaderFactory(httpClient: HttpClient) {
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
@ -139,7 +140,8 @@ export function HttpLoaderFactory(httpClient: HttpClient) {
CircleButtonComponent,
ChevronButtonComponent,
DictionaryListingScreenComponent,
VirtualScrollComponent
VirtualScrollComponent,
SyncWidthDirective
],
imports: [
BrowserModule,

View File

@ -2,7 +2,6 @@
:host {
display: flex;
border-bottom: 1px solid $separator;
height: 30px;
> div {

View File

@ -5,30 +5,29 @@
<div class="red-content-inner">
<div class="left-container">
<div class="grid-container">
<div class="header-item span-4">
<div class="select-all-container">
<div
(click)="toggleSelectAll()"
[class.active]="areAllDictsSelected"
class="select-oval always-visible"
*ngIf="!areAllDictsSelected && !areSomeDictsSelected"
></div>
<mat-icon *ngIf="areAllDictsSelected" (click)="toggleSelectAll()" class="selection-icon active" svgIcon="red:radio-selected"></mat-icon>
<mat-icon
*ngIf="areSomeDictsSelected && !areAllDictsSelected"
(click)="toggleSelectAll()"
class="selection-icon"
svgIcon="red:radio-indeterminate"
></mat-icon>
</div>
<span class="all-caps-label">
{{ 'dictionary-listing.table-header.title' | translate: { length: dictionaries.length } }}
</span>
<div class="header-item span-4">
<div class="select-all-container">
<div
(click)="toggleSelectAll()"
[class.active]="areAllDictsSelected"
class="select-oval always-visible"
*ngIf="!areAllDictsSelected && !areSomeDictsSelected"
></div>
<mat-icon *ngIf="areAllDictsSelected" (click)="toggleSelectAll()" class="selection-icon active" svgIcon="red:radio-selected"></mat-icon>
<mat-icon
*ngIf="areSomeDictsSelected && !areAllDictsSelected"
(click)="toggleSelectAll()"
class="selection-icon"
svgIcon="red:radio-indeterminate"
></mat-icon>
</div>
<!-- Table column names-->
<span class="all-caps-label">
{{ 'dictionary-listing.table-header.title' | translate: { length: dictionaries.length } }}
</span>
</div>
<div class="table-header" redactionSyncWidth="table-item">
<div class="select-oval-placeholder placeholder-bottom-border"></div>
<redaction-table-col-name
@ -40,8 +39,9 @@
></redaction-table-col-name>
<redaction-table-col-name label="dictionary-listing.table-col-names.hint-redaction" class="flex-center"></redaction-table-col-name>
<div class="placeholder-bottom-border"></div>
</div>
<!-- Table lines -->
<div class="grid-container">
<div class="table-item" *ngFor="let dict of dictionaries | sortBy: sortingOption.order:sortingOption.column">
<div class="pr-0" (click)="toggleDictSelected($event, dict)">
<div *ngIf="!isDictSelected(dict)" class="select-oval"></div>

View File

@ -1,20 +1,20 @@
@import '../../../../assets/styles/red-variables';
@import '../../../../assets/styles/red-mixins';
.header-item {
padding: 0 24px 0 10px;
}
redaction-table-col-name::ng-deep {
> div {
padding-left: 10px !important;
}
}
.left-container {
.grid-container {
grid-template-columns: auto 1fr 1fr 2fr;
.header-item {
padding: 0 24px 0 10px;
}
redaction-table-col-name::ng-deep {
> div {
padding-left: 10px;
}
}
.table-item {
> div {
display: flex;
@ -39,6 +39,7 @@
margin-top: 4px;
}
}
width: calc(100vw - 353px);
}
.right-container {

View File

@ -27,6 +27,7 @@
width: 100%;
height: 50px;
}
width: calc(100vw - 350px);
}
.right-container {

View File

@ -258,7 +258,6 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy {
@HostListener('window:keyup', ['$event'])
handleKeyEvent($event: KeyboardEvent) {
console.log('handle', $event.key);
if (!KEY_ARRAY.includes($event.key) || this._dialogRef?.getState() === MatDialogState.OPEN) {
return;
}

View File

@ -39,13 +39,13 @@
<div class="red-content-inner">
<div class="left-container">
<div class="grid-container">
<div class="header-item span-4">
<span class="all-caps-label">
{{ 'project-listing.table-header.title' | translate: { length: displayedProjects.length || 0 } }}
</span>
</div>
<div class="header-item">
<span class="all-caps-label">
{{ 'project-listing.table-header.title' | translate: { length: displayedProjects.length || 0 } }}
</span>
</div>
<div class="table-header" redactionSyncWidth="table-item">
<redaction-table-col-name
label="project-listing.table-col-names.name"
column="project.projectName"
@ -59,16 +59,18 @@
<redaction-table-col-name label="project-listing.table-col-names.owner"></redaction-table-col-name>
<redaction-table-col-name label="project-listing.table-col-names.status" class="flex-end"></redaction-table-col-name>
</div>
<div *ngIf="displayedProjects?.length === 0" class="no-data heading-l" translate="project-listing.no-projects-match"></div>
<div *ngIf="displayedProjects?.length === 0" class="no-data heading-l" translate="project-listing.no-projects-match"></div>
<div class="grid-container">
<div
*ngFor="let pw of displayedProjects | sortBy: sortingOption.order:sortingOption.column"
[routerLink]="[canOpenProject(pw) ? '/ui/projects/' + pw.project.projectId : []]"
class="table-item"
[class.pointer]="canOpenProject(pw)"
>
<div>
<div class="filename">
<div class="table-item-title heading">
{{ pw.project.projectName }}
</div>

View File

@ -13,6 +13,8 @@
.status-container {
width: 160px;
}
width: calc(100vw - 466px);
}
.right-container {

View File

@ -90,31 +90,31 @@
</div>
<div class="red-content-inner">
<div class="left-container" [class.extended]="collapsedDetails">
<div class="grid-container">
<div class="header-item span-7">
<div class="select-all-container">
<div
(click)="toggleSelectAll()"
[class.active]="areAllFilesSelected"
class="select-oval always-visible"
*ngIf="!areAllFilesSelected && !areSomeFilesSelected"
></div>
<mat-icon *ngIf="areAllFilesSelected" (click)="toggleSelectAll()" class="selection-icon active" svgIcon="red:radio-selected"></mat-icon>
<mat-icon
*ngIf="areSomeFilesSelected && !areAllFilesSelected"
(click)="toggleSelectAll()"
class="selection-icon"
svgIcon="red:radio-indeterminate"
></mat-icon>
</div>
<span class="all-caps-label">
{{ 'project-overview.table-header.title' | translate: { length: displayedFiles.length || 0 } }}
</span>
<redaction-bulk-actions [selectedFileIds]="selectedFileIds" (reload)="bulkActionPerformed()"></redaction-bulk-actions>
<div class="header-item">
<div class="select-all-container">
<div
(click)="toggleSelectAll()"
[class.active]="areAllFilesSelected"
class="select-oval always-visible"
*ngIf="!areAllFilesSelected && !areSomeFilesSelected"
></div>
<mat-icon *ngIf="areAllFilesSelected" (click)="toggleSelectAll()" class="selection-icon active" svgIcon="red:radio-selected"></mat-icon>
<mat-icon
*ngIf="areSomeFilesSelected && !areAllFilesSelected"
(click)="toggleSelectAll()"
class="selection-icon"
svgIcon="red:radio-indeterminate"
></mat-icon>
</div>
<span class="all-caps-label">
{{ 'project-overview.table-header.title' | translate: { length: displayedFiles.length || 0 } }}
</span>
<redaction-bulk-actions [selectedFileIds]="selectedFileIds" (reload)="bulkActionPerformed()"></redaction-bulk-actions>
</div>
<div class="table-header" redactionSyncWidth="table-item">
<!-- Table column names-->
<div class="select-oval-placeholder placeholder-bottom-border"></div>
@ -160,9 +160,11 @@
column="statusSort"
label="project-overview.table-col-names.status"
></redaction-table-col-name>
</div>
<div *ngIf="displayedFiles?.length === 0" class="no-data heading-l" translate="project-overview.no-files-match"></div>
<div *ngIf="displayedFiles?.length === 0" class="no-data heading-l" translate="project-overview.no-files-match"></div>
<div class="grid-container">
<div
*ngFor="let fileStatus of displayedFiles | sortBy: sortingOption.order:sortingOption.column"
[class.pointer]="permissionsService.canOpenFile(fileStatus)"

View File

@ -5,19 +5,19 @@
display: none;
}
.header-item {
padding: 0 24px 0 10px;
}
redaction-table-col-name::ng-deep {
> div {
padding-left: 10px !important;
}
}
.grid-container {
grid-template-columns: auto 3fr 2fr 1fr 1fr 2fr auto;
.header-item {
padding: 0 24px 0 10px;
}
redaction-table-col-name::ng-deep {
> div {
padding-left: 10px;
}
}
.table-item {
> div {
padding-left: 10px;
@ -63,7 +63,12 @@
}
}
.left-container {
width: calc(100vw - 350px);
}
.right-container {
display: flex;
width: 350px;
min-width: 350px;
padding: 16px 16px 16px 24px;

View File

@ -0,0 +1,38 @@
import { AfterViewChecked, Directive, ElementRef, HostListener, Input } from '@angular/core';
import { debounce } from './debounce';
@Directive({
selector: '[redactionSyncWidth]',
exportAs: 'redactionSyncWidth'
})
export class SyncWidthDirective implements AfterViewChecked {
@Input()
redactionSyncWidth: string;
constructor(private el: ElementRef) {}
ngAfterViewChecked() {
this.matchWidth();
}
@debounce(0)
matchWidth() {
const headerItems = this.el.nativeElement.children;
const tableRows = document.getElementsByClassName(this.redactionSyncWidth);
if (!tableRows || !tableRows.length) return;
const tableRow = tableRows[0];
if (tableRow.children.length !== headerItems.length) return;
for (let idx = 0; idx < headerItems.length; ++idx) {
headerItems[idx].style.width = `${tableRow.children[idx].getBoundingClientRect().width}px`;
headerItems[idx].style.minWidth = `${tableRow.children[idx].getBoundingClientRect().width}px`;
}
}
@HostListener('window:resize')
onResize() {
this.matchWidth();
}
}

View File

@ -1,4 +1,5 @@
@import 'red-variables';
@import 'red-mixins';
.header-item {
background-color: $grey-6;
@ -7,8 +8,6 @@
display: flex;
align-items: center;
z-index: 1;
position: sticky;
top: 0;
gap: 10px;
border-bottom: 1px solid $separator;
box-sizing: border-box;

View File

@ -66,7 +66,8 @@ body {
}
.left-container {
width: 100%;
overflow: hidden;
transition: width ease-in-out 0.2s, min-width ease-in-out 0.2s;
&.extended {
width: calc(100vw - 60px) !important;
@ -75,6 +76,7 @@ body {
.right-container {
border-left: 1px solid $grey-4;
box-sizing: border-box;
background: $white;
z-index: 1;
overflow-y: scroll;

View File

@ -1,29 +1,22 @@
@import 'red-variables';
@import 'red-mixins';
redaction-table-col-name,
.select-oval-placeholder {
background-color: $white;
position: sticky;
top: 50px;
z-index: 1;
.no-data {
padding: 24px;
}
.no-data {
grid-column: 1/-1;
padding: 12px;
.table-header {
display: flex;
justify-content: space-between;
border-bottom: 1px solid $separator;
}
.grid-container {
display: grid;
max-height: 100%;
max-height: calc(100vh - 50px - 30px - 111px);
overflow-y: scroll;
@include no-scroll-bar();
.placeholder-bottom-border {
border-bottom: 1px solid $separator;
}
.table-item {
display: contents;