Refactor file attributes CSV import
This commit is contained in:
parent
f3dca378e2
commit
dfb3787d42
@ -32,6 +32,7 @@ import { AddEditUserDialogComponent } from './dialogs/add-edit-user-dialog/add-e
|
||||
import { UsersStatsComponent } from './components/users-stats/users-stats.component';
|
||||
import { ConfirmDeleteUsersDialogComponent } from './dialogs/confirm-delete-users-dialog/confirm-delete-users-dialog.component';
|
||||
import { FileAttributesCsvImportDialogComponent } from './dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';
|
||||
import { ActiveFieldsListingComponent } from './dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component';
|
||||
|
||||
const dialogs = [
|
||||
AddEditRuleSetDialogComponent,
|
||||
@ -41,7 +42,8 @@ const dialogs = [
|
||||
EditColorDialogComponent,
|
||||
SmtpAuthDialogComponent,
|
||||
AddEditUserDialogComponent,
|
||||
ConfirmDeleteUsersDialogComponent
|
||||
ConfirmDeleteUsersDialogComponent,
|
||||
FileAttributesCsvImportDialogComponent
|
||||
];
|
||||
|
||||
const screens = [
|
||||
@ -66,12 +68,14 @@ const components = [
|
||||
ComboChartComponent,
|
||||
ComboSeriesVerticalComponent,
|
||||
UsersStatsComponent,
|
||||
ActiveFieldsListingComponent,
|
||||
|
||||
...dialogs,
|
||||
...screens
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [...components, FileAttributesCsvImportDialogComponent],
|
||||
declarations: [...components],
|
||||
providers: [AdminDialogService],
|
||||
imports: [CommonModule, SharedModule, AdminRoutingModule, AceEditorModule, NgxChartsModule, ColorPickerModule]
|
||||
})
|
||||
|
||||
@ -0,0 +1,175 @@
|
||||
<div class="header-item">
|
||||
<div class="select-all-container">
|
||||
<div
|
||||
(click)="toggleSelectAll()"
|
||||
[class.active]="areAllEntitiesSelected"
|
||||
class="select-oval always-visible"
|
||||
*ngIf="!areAllEntitiesSelected && !areSomeEntitiesSelected"
|
||||
></div>
|
||||
<mat-icon *ngIf="areAllEntitiesSelected" (click)="toggleSelectAll()" class="selection-icon active" svgIcon="red:radio-selected"></mat-icon>
|
||||
<mat-icon
|
||||
*ngIf="areSomeEntitiesSelected && !areAllEntitiesSelected"
|
||||
(click)="toggleSelectAll()"
|
||||
class="selection-icon"
|
||||
svgIcon="red:radio-indeterminate"
|
||||
></mat-icon>
|
||||
</div>
|
||||
<span class="all-caps-label">
|
||||
{{ 'file-attributes-csv-import.table-header.title' | translate: { length: allEntities.length } }}
|
||||
</span>
|
||||
|
||||
<ng-container *ngIf="areSomeEntitiesSelected">
|
||||
<redaction-circle-button
|
||||
[matMenuTriggerFor]="readOnlyMenu"
|
||||
tooltip="file-attributes-csv-import.table-header.actions.read-only"
|
||||
type="dark-bg"
|
||||
icon="red:read-only"
|
||||
>
|
||||
</redaction-circle-button>
|
||||
<redaction-circle-button
|
||||
[matMenuTriggerFor]="displayMenu"
|
||||
tooltip="file-attributes-csv-import.table-header.actions.display"
|
||||
type="dark-bg"
|
||||
icon="red:visibility"
|
||||
>
|
||||
</redaction-circle-button>
|
||||
<redaction-circle-button
|
||||
(action)="deactivateSelection()"
|
||||
tooltip="file-attributes-csv-import.table-header.actions.remove-selected"
|
||||
type="dark-bg"
|
||||
icon="red:trash"
|
||||
>
|
||||
</redaction-circle-button>
|
||||
|
||||
<div class="separator"></div>
|
||||
|
||||
<redaction-chevron-button text="file-attributes-csv-import.table-header.actions.type" [matMenuTriggerFor]="typeMenu"></redaction-chevron-button>
|
||||
|
||||
<mat-menu #readOnlyMenu="matMenu" class="no-padding-bottom">
|
||||
<button
|
||||
mat-menu-item
|
||||
(click)="setAttributeForSelection('readonly', true)"
|
||||
translate="file-attributes-csv-import.table-header.actions.enable-read-only"
|
||||
></button>
|
||||
<button
|
||||
mat-menu-item
|
||||
(click)="setAttributeForSelection('readonly', false)"
|
||||
translate="file-attributes-csv-import.table-header.actions.disable-read-only"
|
||||
></button>
|
||||
</mat-menu>
|
||||
|
||||
<mat-menu #displayMenu="matMenu" class="no-padding-bottom">
|
||||
<button
|
||||
mat-menu-item
|
||||
(click)="setAttributeForSelection('display', true)"
|
||||
translate="file-attributes-csv-import.table-header.actions.enable-display"
|
||||
></button>
|
||||
<button
|
||||
mat-menu-item
|
||||
(click)="setAttributeForSelection('display', false)"
|
||||
translate="file-attributes-csv-import.table-header.actions.disable-display"
|
||||
></button>
|
||||
</mat-menu>
|
||||
|
||||
<mat-menu #typeMenu="matMenu" class="no-padding-bottom">
|
||||
<button *ngFor="let type of ['Text', 'Number', 'Date']" mat-menu-item (click)="setAttributeForSelection('type', type)">
|
||||
{{ 'file-attributes-csv-import.types.' + type | translate }}
|
||||
</button>
|
||||
</mat-menu>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<div class="table-header" redactionSyncWidth="table-item">
|
||||
<div class="select-oval-placeholder"></div>
|
||||
|
||||
<redaction-table-col-name label="file-attributes-csv-import.table-col-names.name" class="name"></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name label="file-attributes-csv-import.table-col-names.type"></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name label="file-attributes-csv-import.table-col-names.read-only" class="flex-center" icon="red:read-only"></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name label="file-attributes-csv-import.table-col-names.display" class="flex-center" icon="red:visibility"></redaction-table-col-name>
|
||||
|
||||
<div></div>
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
</div>
|
||||
|
||||
<redaction-empty-state *ngIf="!allEntities.length" icon="red:attribute" screen="file-attributes-csv-import"> </redaction-empty-state>
|
||||
|
||||
<cdk-virtual-scroll-viewport [itemSize]="50" redactionHasScrollbar>
|
||||
<!-- Table lines -->
|
||||
<div
|
||||
class="table-item"
|
||||
*cdkVirtualFor="let field of displayedEntities"
|
||||
(mouseenter)="setHoveredColumn.emit(field.csvColumn)"
|
||||
(mouseleave)="setHoveredColumn.emit()"
|
||||
>
|
||||
<div class="pr-0" (click)="toggleEntitySelected($event, field)">
|
||||
<div *ngIf="!isEntitySelected(field)" class="select-oval"></div>
|
||||
<mat-icon class="selection-icon active" *ngIf="isEntitySelected(field)" svgIcon="red:radio-selected"></mat-icon>
|
||||
</div>
|
||||
<div class="name" [class.editing]="field.editingName">
|
||||
<div *ngIf="!field.editingName">
|
||||
{{ field.name }}
|
||||
</div>
|
||||
<form (submit)="field.editingName = false; field.name = field.temporaryName" *ngIf="field.editingName">
|
||||
<div class="red-input-group w-200">
|
||||
<input name="name" [(ngModel)]="field.temporaryName" />
|
||||
</div>
|
||||
</form>
|
||||
<redaction-circle-button
|
||||
class="edit-name-button"
|
||||
*ngIf="!field.editingName"
|
||||
(action)="field.editingName = true"
|
||||
tooltip="file-attributes-csv-import.action.edit-name"
|
||||
type="dark-bg"
|
||||
icon="red:edit"
|
||||
>
|
||||
</redaction-circle-button>
|
||||
<ng-container *ngIf="field.editingName">
|
||||
<redaction-circle-button
|
||||
(action)="field.editingName = false; field.name = field.temporaryName"
|
||||
tooltip="file-attributes-csv-import.action.save-name"
|
||||
type="dark-bg"
|
||||
icon="red:check-alt"
|
||||
>
|
||||
</redaction-circle-button>
|
||||
<redaction-circle-button
|
||||
(action)="field.editingName = false; field.temporaryName = field.name"
|
||||
tooltip="file-attributes-csv-import.action.cancel-edit-name"
|
||||
type="dark-bg"
|
||||
icon="red:close"
|
||||
>
|
||||
</redaction-circle-button>
|
||||
</ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div class="red-input-group">
|
||||
<mat-form-field class="no-label">
|
||||
<mat-select [(ngModel)]="field.type">
|
||||
<mat-option *ngFor="let type of ['Text', 'Number', 'Date']" [value]="type">
|
||||
{{ 'file-attributes-csv-import.types.' + type | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="center">
|
||||
<mat-slide-toggle [(ngModel)]="field.readonly" color="primary"></mat-slide-toggle>
|
||||
</div>
|
||||
<div class="center"><mat-slide-toggle [(ngModel)]="field.display" color="primary"></mat-slide-toggle></div>
|
||||
<div class="actions-container">
|
||||
<div class="action-buttons">
|
||||
<redaction-circle-button
|
||||
(action)="toggleFieldActive.emit(field)"
|
||||
[removeTooltip]="true"
|
||||
tooltip="file-attributes-csv-import.action.remove"
|
||||
type="dark-bg"
|
||||
icon="red:trash"
|
||||
>
|
||||
</redaction-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
</div>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
@ -0,0 +1,84 @@
|
||||
@import '../../../../../../assets/styles/red-variables';
|
||||
|
||||
redaction-table-col-name::ng-deep {
|
||||
> div {
|
||||
padding: 0 13px 0 10px !important;
|
||||
|
||||
&.name {
|
||||
padding-left: 22px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header-item {
|
||||
padding: 0 24px 0 10px;
|
||||
box-shadow: none;
|
||||
border-top: 1px solid $separator;
|
||||
|
||||
.all-caps-label {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
redaction-circle-button {
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.separator {
|
||||
margin-left: 14px;
|
||||
background-color: $separator;
|
||||
width: 1px;
|
||||
height: 30px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
cdk-virtual-scroll-viewport {
|
||||
height: calc(100% - 80px);
|
||||
|
||||
::ng-deep.cdk-virtual-scroll-content-wrapper {
|
||||
grid-template-columns: 30px minmax(0, 25vw) 150px auto auto auto 11px;
|
||||
|
||||
.table-item {
|
||||
> div {
|
||||
height: 50px;
|
||||
|
||||
&:not(.scrollbar-placeholder) {
|
||||
padding-left: 10px;
|
||||
|
||||
&.center {
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
&.name {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
|
||||
&:not(.editing) {
|
||||
padding-left: 22px;
|
||||
}
|
||||
|
||||
.edit-name-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
redaction-circle-button:first-of-type {
|
||||
margin-left: 7px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .name .edit-name-button {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.has-scrollbar:hover {
|
||||
::ng-deep.cdk-virtual-scroll-content-wrapper {
|
||||
grid-template-columns: 30px minmax(0, 25vw) 150px auto auto auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
import { Component, EventEmitter, Injector, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
|
||||
import { BaseListingComponent } from '../../../../shared/base/base-listing.component';
|
||||
import { Field } from '../file-attributes-csv-import-dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-active-fields-listing',
|
||||
templateUrl: './active-fields-listing.component.html',
|
||||
styleUrls: ['./active-fields-listing.component.scss']
|
||||
})
|
||||
export class ActiveFieldsListingComponent extends BaseListingComponent<Field> implements OnChanges {
|
||||
@Input() public allEntities: Field[];
|
||||
@Output() public allEntitiesChange = new EventEmitter<Field[]>();
|
||||
@Output() public setHoveredColumn = new EventEmitter<string>();
|
||||
@Output() public toggleFieldActive = new EventEmitter<Field>();
|
||||
|
||||
protected readonly _selectionKey = 'csvColumn';
|
||||
|
||||
constructor(protected readonly _injector: Injector) {
|
||||
super(_injector);
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes.allEntities) {
|
||||
this.displayedEntities = this.allEntities;
|
||||
this._updateSelection();
|
||||
}
|
||||
}
|
||||
|
||||
public deactivateSelection() {
|
||||
this.allEntities = [...this.allEntities.filter((field) => !this.isEntitySelected(field))];
|
||||
this.allEntitiesChange.emit(this.allEntities);
|
||||
this.selectedEntitiesIds = [];
|
||||
}
|
||||
|
||||
public setAttributeForSelection(attribute: string, value: any) {
|
||||
for (const csvColumn of this.selectedEntitiesIds) {
|
||||
this.allEntities.find((f) => f.csvColumn === csvColumn)[attribute] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -90,7 +90,7 @@
|
||||
<div class="csv-header-pill-content" [class.search-open]="isSearchOpen">
|
||||
<div
|
||||
class="csv-header-pill-wrapper"
|
||||
*ngFor="let field of filteredFields"
|
||||
*ngFor="let field of displayedEntities"
|
||||
(mouseenter)="setHoveredColumn(field.csvColumn)"
|
||||
(mouseleave)="setHoveredColumn()"
|
||||
(click)="toggleFieldActive(field)"
|
||||
@ -128,197 +128,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-container">
|
||||
<div class="header-item">
|
||||
<div class="select-all-container">
|
||||
<div
|
||||
(click)="toggleSelectAll()"
|
||||
[class.active]="areAllFieldsSelected"
|
||||
class="select-oval always-visible"
|
||||
*ngIf="!areAllFieldsSelected && !areSomeFieldsSelected"
|
||||
></div>
|
||||
<mat-icon
|
||||
*ngIf="areAllFieldsSelected"
|
||||
(click)="toggleSelectAll()"
|
||||
class="selection-icon active"
|
||||
svgIcon="red:radio-selected"
|
||||
></mat-icon>
|
||||
<mat-icon
|
||||
*ngIf="areSomeFieldsSelected && !areAllFieldsSelected"
|
||||
(click)="toggleSelectAll()"
|
||||
class="selection-icon"
|
||||
svgIcon="red:radio-indeterminate"
|
||||
></mat-icon>
|
||||
</div>
|
||||
<span class="all-caps-label">
|
||||
{{ 'file-attributes-csv-import.table-header.title' | translate: { length: activeFields.length } }}
|
||||
</span>
|
||||
|
||||
<ng-container *ngIf="areSomeFieldsSelected">
|
||||
<redaction-circle-button
|
||||
[matMenuTriggerFor]="readOnlyMenu"
|
||||
tooltip="file-attributes-csv-import.table-header.actions.read-only"
|
||||
type="dark-bg"
|
||||
icon="red:read-only"
|
||||
>
|
||||
</redaction-circle-button>
|
||||
<redaction-circle-button
|
||||
[matMenuTriggerFor]="displayMenu"
|
||||
tooltip="file-attributes-csv-import.table-header.actions.display"
|
||||
type="dark-bg"
|
||||
icon="red:visibility"
|
||||
>
|
||||
</redaction-circle-button>
|
||||
<redaction-circle-button
|
||||
(action)="deactivateSelection()"
|
||||
tooltip="file-attributes-csv-import.table-header.actions.remove-selected"
|
||||
type="dark-bg"
|
||||
icon="red:trash"
|
||||
>
|
||||
</redaction-circle-button>
|
||||
|
||||
<div class="separator"></div>
|
||||
|
||||
<redaction-chevron-button
|
||||
text="file-attributes-csv-import.table-header.actions.type"
|
||||
[matMenuTriggerFor]="typeMenu"
|
||||
></redaction-chevron-button>
|
||||
|
||||
<mat-menu #readOnlyMenu="matMenu" class="no-padding-bottom">
|
||||
<button
|
||||
mat-menu-item
|
||||
(click)="setAttributeForSelection('readonly', true)"
|
||||
translate="file-attributes-csv-import.table-header.actions.enable-read-only"
|
||||
></button>
|
||||
<button
|
||||
mat-menu-item
|
||||
(click)="setAttributeForSelection('readonly', false)"
|
||||
translate="file-attributes-csv-import.table-header.actions.disable-read-only"
|
||||
></button>
|
||||
</mat-menu>
|
||||
|
||||
<mat-menu #displayMenu="matMenu" class="no-padding-bottom">
|
||||
<button
|
||||
mat-menu-item
|
||||
(click)="setAttributeForSelection('display', true)"
|
||||
translate="file-attributes-csv-import.table-header.actions.enable-display"
|
||||
></button>
|
||||
<button
|
||||
mat-menu-item
|
||||
(click)="setAttributeForSelection('display', false)"
|
||||
translate="file-attributes-csv-import.table-header.actions.disable-display"
|
||||
></button>
|
||||
</mat-menu>
|
||||
|
||||
<mat-menu #typeMenu="matMenu" class="no-padding-bottom">
|
||||
<button *ngFor="let type of ['Text', 'Number', 'Date']" mat-menu-item (click)="setAttributeForSelection('type', type)">
|
||||
{{ 'file-attributes-csv-import.types.' + type | translate }}
|
||||
</button>
|
||||
</mat-menu>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<div class="table-header" redactionSyncWidth="table-item">
|
||||
<div class="select-oval-placeholder"></div>
|
||||
|
||||
<redaction-table-col-name label="file-attributes-csv-import.table-col-names.name" class="name"></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name label="file-attributes-csv-import.table-col-names.type"></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
label="file-attributes-csv-import.table-col-names.read-only"
|
||||
class="flex-center"
|
||||
icon="red:read-only"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
label="file-attributes-csv-import.table-col-names.display"
|
||||
class="flex-center"
|
||||
icon="red:visibility"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<div></div>
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
</div>
|
||||
|
||||
<redaction-empty-state *ngIf="!activeFields.length" icon="red:attribute" screen="file-attributes-csv-import"> </redaction-empty-state>
|
||||
|
||||
<cdk-virtual-scroll-viewport [itemSize]="50" redactionHasScrollbar>
|
||||
<!-- Table lines -->
|
||||
<div
|
||||
class="table-item"
|
||||
*cdkVirtualFor="let field of activeFields"
|
||||
(mouseenter)="setHoveredColumn(field.csvColumn)"
|
||||
(mouseleave)="setHoveredColumn()"
|
||||
>
|
||||
<div class="pr-0" (click)="toggleFieldSelected(field.csvColumn)">
|
||||
<div *ngIf="!isFieldSelected(field.csvColumn)" class="select-oval"></div>
|
||||
<mat-icon class="selection-icon active" *ngIf="isFieldSelected(field.csvColumn)" svgIcon="red:radio-selected"></mat-icon>
|
||||
</div>
|
||||
<div class="name" [class.editing]="field.editingName">
|
||||
<div *ngIf="!field.editingName">
|
||||
{{ field.name }}
|
||||
</div>
|
||||
<form (submit)="field.editingName = false; field.name = field.temporaryName" *ngIf="field.editingName">
|
||||
<div class="red-input-group w-200">
|
||||
<input name="name" [(ngModel)]="field.temporaryName" />
|
||||
</div>
|
||||
</form>
|
||||
<redaction-circle-button
|
||||
class="edit-name-button"
|
||||
*ngIf="!field.editingName"
|
||||
(action)="field.editingName = true"
|
||||
tooltip="file-attributes-csv-import.action.edit-name"
|
||||
type="dark-bg"
|
||||
icon="red:edit"
|
||||
>
|
||||
</redaction-circle-button>
|
||||
<ng-container *ngIf="field.editingName">
|
||||
<redaction-circle-button
|
||||
(action)="field.editingName = false; field.name = field.temporaryName"
|
||||
tooltip="file-attributes-csv-import.action.save-name"
|
||||
type="dark-bg"
|
||||
icon="red:check-alt"
|
||||
>
|
||||
</redaction-circle-button>
|
||||
<redaction-circle-button
|
||||
(action)="field.editingName = false; field.temporaryName = field.name"
|
||||
tooltip="file-attributes-csv-import.action.cancel-edit-name"
|
||||
type="dark-bg"
|
||||
icon="red:close"
|
||||
>
|
||||
</redaction-circle-button>
|
||||
</ng-container>
|
||||
</div>
|
||||
<div>
|
||||
<div class="red-input-group">
|
||||
<mat-form-field class="no-label">
|
||||
<mat-select [(ngModel)]="field.type">
|
||||
<mat-option *ngFor="let type of ['Text', 'Number', 'Date']" [value]="type">
|
||||
{{ 'file-attributes-csv-import.types.' + type | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="center">
|
||||
<mat-slide-toggle [(ngModel)]="field.readonly" color="primary"></mat-slide-toggle>
|
||||
</div>
|
||||
<div class="center"><mat-slide-toggle [(ngModel)]="field.display" color="primary"></mat-slide-toggle></div>
|
||||
<div class="actions-container">
|
||||
<div class="action-buttons">
|
||||
<redaction-circle-button
|
||||
(action)="toggleFieldActive(field)"
|
||||
[removeTooltip]="true"
|
||||
tooltip="file-attributes-csv-import.action.remove"
|
||||
type="dark-bg"
|
||||
icon="red:trash"
|
||||
>
|
||||
</redaction-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
</div>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
<redaction-active-fields-listing
|
||||
[(allEntities)]="activeFields"
|
||||
(setHoveredColumn)="setHoveredColumn($event)"
|
||||
(toggleFieldActive)="toggleFieldActive($event)"
|
||||
></redaction-active-fields-listing>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -114,6 +114,7 @@
|
||||
|
||||
> .left {
|
||||
width: 375px;
|
||||
min-width: 375px;
|
||||
background: $grey-2;
|
||||
|
||||
.csv-header-pill-content {
|
||||
@ -198,88 +199,5 @@
|
||||
|
||||
> .content-container {
|
||||
width: 100%;
|
||||
|
||||
redaction-table-col-name::ng-deep {
|
||||
> div {
|
||||
padding: 0 13px 0 10px !important;
|
||||
|
||||
&.name {
|
||||
padding-left: 22px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header-item {
|
||||
padding: 0 24px 0 10px;
|
||||
box-shadow: none;
|
||||
border-top: 1px solid $separator;
|
||||
|
||||
.all-caps-label {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
redaction-circle-button {
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.separator {
|
||||
margin-left: 14px;
|
||||
background-color: $separator;
|
||||
width: 1px;
|
||||
height: 30px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
cdk-virtual-scroll-viewport {
|
||||
height: calc(100% - 80px);
|
||||
|
||||
::ng-deep.cdk-virtual-scroll-content-wrapper {
|
||||
grid-template-columns: 30px minmax(0, 25vw) 150px auto auto auto 11px;
|
||||
|
||||
.table-item {
|
||||
> div {
|
||||
height: 50px;
|
||||
|
||||
&:not(.scrollbar-placeholder) {
|
||||
padding-left: 10px;
|
||||
|
||||
&.center {
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
&.name {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
|
||||
&:not(.editing) {
|
||||
padding-left: 22px;
|
||||
}
|
||||
|
||||
.edit-name-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
redaction-circle-button:first-of-type {
|
||||
margin-left: 7px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .name .edit-name-button {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.has-scrollbar:hover {
|
||||
::ng-deep.cdk-virtual-scroll-content-wrapper {
|
||||
grid-template-columns: 30px minmax(0, 25vw) 150px auto auto auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { Component, Inject, ViewChild } from '@angular/core';
|
||||
import { AbstractControl, FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms';
|
||||
import { Component, Inject, Injector, ViewChild } from '@angular/core';
|
||||
import { AbstractControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import * as Papa from 'papaparse';
|
||||
import { FileAttributesControllerService } from '@redaction/red-ui-http';
|
||||
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
|
||||
import { debounce } from '../../../../utils/debounce';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map, startWith } from 'rxjs/operators';
|
||||
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
|
||||
|
||||
enum FieldType {
|
||||
Text = 'Text',
|
||||
@ -15,7 +15,7 @@ enum FieldType {
|
||||
Date = 'Date'
|
||||
}
|
||||
|
||||
interface Field {
|
||||
export interface Field {
|
||||
csvColumn: string;
|
||||
name: string;
|
||||
type: FieldType;
|
||||
@ -30,17 +30,16 @@ interface Field {
|
||||
templateUrl: './file-attributes-csv-import-dialog.component.html',
|
||||
styleUrls: ['./file-attributes-csv-import-dialog.component.scss']
|
||||
})
|
||||
export class FileAttributesCsvImportDialogComponent {
|
||||
export class FileAttributesCsvImportDialogComponent extends BaseListingComponent<Field> {
|
||||
protected readonly _searchKey = 'csvColumn';
|
||||
|
||||
public csvFile: File;
|
||||
public ruleSetId: string;
|
||||
public parseResult: { data: any[]; errors: any[]; meta: any; fields: Field[] };
|
||||
public hoveredColumn: string;
|
||||
public activeFields: Field[] = [];
|
||||
public selectedFields: string[] = [];
|
||||
public baseConfigForm: FormGroup;
|
||||
public isSearchOpen = false;
|
||||
public searchForm: FormGroup;
|
||||
public filteredFields: Field[];
|
||||
public previewExpanded = true;
|
||||
public filteredKeyOptions: Observable<string[]>;
|
||||
public keepPreview = false;
|
||||
@ -50,18 +49,15 @@ export class FileAttributesCsvImportDialogComponent {
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _fileAttributesControllerService: FileAttributesControllerService,
|
||||
public dialogRef: MatDialogRef<FileAttributesCsvImportDialogComponent>,
|
||||
protected readonly _injector: Injector,
|
||||
@Inject(MAT_DIALOG_DATA) public data: { csv: File; ruleSetId: string }
|
||||
) {
|
||||
super(_injector);
|
||||
this.csvFile = data.csv;
|
||||
this.ruleSetId = data.ruleSetId;
|
||||
|
||||
this.searchForm = this._formBuilder.group({
|
||||
query: ['']
|
||||
});
|
||||
|
||||
this.baseConfigForm = this._formBuilder.group({
|
||||
filenameMappingColumnHeaderName: ['', [Validators.required, this._autocompleteStringValidator()]],
|
||||
delimiter: [undefined, Validators.required],
|
||||
@ -69,13 +65,6 @@ export class FileAttributesCsvImportDialogComponent {
|
||||
});
|
||||
|
||||
this._readFile();
|
||||
|
||||
this.searchForm.valueChanges.subscribe((value) => this._executeSearch(value));
|
||||
}
|
||||
|
||||
@debounce(200)
|
||||
private _executeSearch(value: { query: string }) {
|
||||
this.filteredFields = this.parseResult.fields.filter((f) => f.csvColumn.toLowerCase().includes(value.query.toLowerCase()));
|
||||
}
|
||||
|
||||
private _autocompleteStringValidator(): ValidatorFn {
|
||||
@ -98,12 +87,14 @@ export class FileAttributesCsvImportDialogComponent {
|
||||
if (!this.baseConfigForm.get('delimiter').value) {
|
||||
this.baseConfigForm.patchValue({ delimiter: this.parseResult.meta.delimiter });
|
||||
}
|
||||
this.parseResult.fields = this.parseResult.meta.fields.map((field) => this._buildAttribute(field));
|
||||
this.filteredFields = [...this.parseResult.fields];
|
||||
this.allEntities = this.parseResult.meta.fields.map((field) => this._buildAttribute(field));
|
||||
this.displayedEntities = [...this.allEntities];
|
||||
|
||||
this.filteredKeyOptions = this.baseConfigForm.get('filenameMappingColumnHeaderName').valueChanges.pipe(
|
||||
startWith(''),
|
||||
map((value: string) => this.parseResult.meta.fields.filter((field) => field.toLowerCase().indexOf(value.toLowerCase()) !== -1))
|
||||
map((value: string) =>
|
||||
this.allEntities.filter((field) => field.csvColumn.toLowerCase().indexOf(value.toLowerCase()) !== -1).map((field) => field.csvColumn)
|
||||
)
|
||||
);
|
||||
});
|
||||
reader.readAsText(this.csvFile, this.baseConfigForm.get('encoding').value);
|
||||
@ -137,9 +128,6 @@ export class FileAttributesCsvImportDialogComponent {
|
||||
} else {
|
||||
this.activeFields.splice(this.activeFields.indexOf(field), 1);
|
||||
this.activeFields = [...this.activeFields];
|
||||
if (this.isFieldSelected(field.csvColumn)) {
|
||||
this.toggleFieldSelected(field.csvColumn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,52 +145,11 @@ export class FileAttributesCsvImportDialogComponent {
|
||||
}
|
||||
|
||||
public activateAll() {
|
||||
this.activeFields = [...this.parseResult.fields];
|
||||
this.activeFields = [...this.allEntities];
|
||||
}
|
||||
|
||||
public deactivateAll() {
|
||||
this.activeFields = [];
|
||||
this.selectedFields = [];
|
||||
}
|
||||
|
||||
public toggleFieldSelected(field: string) {
|
||||
const idx = this.selectedFields.indexOf(field);
|
||||
if (idx === -1) {
|
||||
this.selectedFields.push(field);
|
||||
} else {
|
||||
this.selectedFields.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public toggleSelectAll() {
|
||||
if (this.areSomeFieldsSelected) {
|
||||
this.selectedFields = [];
|
||||
} else {
|
||||
this.selectedFields = this.activeFields.map((field) => field.csvColumn);
|
||||
}
|
||||
}
|
||||
|
||||
public get areAllFieldsSelected() {
|
||||
return this.activeFields.length !== 0 && this.selectedFields.length === this.activeFields.length;
|
||||
}
|
||||
|
||||
public get areSomeFieldsSelected() {
|
||||
return this.selectedFields.length > 0;
|
||||
}
|
||||
|
||||
public isFieldSelected(field: string) {
|
||||
return this.selectedFields.indexOf(field) !== -1;
|
||||
}
|
||||
|
||||
public deactivateSelection() {
|
||||
this.activeFields = [...this.activeFields.filter((field) => !this.isFieldSelected(field.csvColumn))];
|
||||
this.selectedFields = [];
|
||||
}
|
||||
|
||||
public setAttributeForSelection(attribute: string, value: any) {
|
||||
for (const csvColumn of this.selectedFields) {
|
||||
this.activeFields.find((f) => f.csvColumn === csvColumn)[attribute] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public async save() {
|
||||
|
||||
@ -2,7 +2,7 @@ import { Component, Injector, OnInit } from '@angular/core';
|
||||
import { DoughnutChartConfig } from '../../../shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { DictionaryControllerService, TypeValue } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { defaultIfEmpty, tap } from 'rxjs/operators';
|
||||
import { forkJoin } from 'rxjs';
|
||||
import { PermissionsService } from '../../../../services/permissions.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
@ -51,9 +51,11 @@ export class DictionaryListingScreenComponent extends BaseListingComponent<TypeV
|
||||
})
|
||||
)
|
||||
);
|
||||
forkJoin(dataObs).subscribe(() => {
|
||||
this._calculateData();
|
||||
});
|
||||
forkJoin(dataObs)
|
||||
.pipe(defaultIfEmpty(null))
|
||||
.subscribe(() => {
|
||||
this._calculateData();
|
||||
});
|
||||
}
|
||||
|
||||
private _calculateData() {
|
||||
|
||||
@ -108,8 +108,6 @@
|
||||
[selectedFileIds]="selectedEntitiesIds"
|
||||
(reload)="bulkActionPerformed()"
|
||||
></redaction-project-overview-bulk-actions>
|
||||
|
||||
{{ selectedEntitiesIds.length }} selected
|
||||
</div>
|
||||
|
||||
<div class="table-header" redactionSyncWidth="table-item" [class.no-data]="!allEntities.length">
|
||||
|
||||
@ -88,6 +88,10 @@ export class BaseListingComponent<T = any> {
|
||||
this.displayedEntities = (this.filters.length ? this.filteredEntities : this.allEntities).filter((entity) =>
|
||||
this._searchField(entity).toLowerCase().includes(this.searchForm.get('query').value.toLowerCase())
|
||||
);
|
||||
this._updateSelection();
|
||||
}
|
||||
|
||||
protected _updateSelection() {
|
||||
if (this._selectionKey) {
|
||||
this.selectedEntitiesIds = this.displayedEntities.map((entity) => entity[this.selectionKey]).filter((id) => this.selectedEntitiesIds.includes(id));
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user