diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.html b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.html
index e8951ad45..6aae70c94 100644
--- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.html
+++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.html
@@ -14,11 +14,18 @@
{{ 'file-attributes-csv-import.key-column' | translate }}
-
-
+
+
+
{{ field }}
-
+
diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.scss b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.scss
index 8b3df0e3a..447df33f7 100644
--- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.scss
+++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.scss
@@ -235,7 +235,7 @@
height: calc(100% - 80px);
::ng-deep.cdk-virtual-scroll-content-wrapper {
- grid-template-columns: 30px minmax(0, 20vw) 150px auto auto auto 11px;
+ grid-template-columns: 30px minmax(0, 25vw) 150px auto auto auto 11px;
.table-item {
> div {
@@ -277,7 +277,7 @@
&.has-scrollbar:hover {
::ng-deep.cdk-virtual-scroll-content-wrapper {
- grid-template-columns: 30px minmax(0, 20vw) 150px auto auto auto;
+ grid-template-columns: 30px minmax(0, 25vw) 150px auto auto auto;
}
}
}
diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts
index ae71e6f5e..60f282035 100644
--- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts
+++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts
@@ -1,11 +1,13 @@
-import { Component, Inject, OnInit, ViewChild } from '@angular/core';
-import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { Component, Inject, ViewChild } from '@angular/core';
+import { AbstractControl, FormBuilder, 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';
enum FieldType {
Text = 'Text',
@@ -28,7 +30,7 @@ interface Field {
templateUrl: './file-attributes-csv-import-dialog.component.html',
styleUrls: ['./file-attributes-csv-import-dialog.component.scss']
})
-export class FileAttributesCsvImportDialogComponent implements OnInit {
+export class FileAttributesCsvImportDialogComponent {
public csvFile: File;
public ruleSetId: string;
public parseResult: { data: any[]; errors: any[]; meta: any; fields: Field[] };
@@ -40,6 +42,7 @@ export class FileAttributesCsvImportDialogComponent implements OnInit {
public searchForm: FormGroup;
public filteredFields: Field[];
public previewExpanded = true;
+ public filteredKeyOptions: Observable;
@ViewChild(CdkVirtualScrollViewport, { static: false }) cdkVirtualScrollViewport: CdkVirtualScrollViewport;
@@ -58,7 +61,7 @@ export class FileAttributesCsvImportDialogComponent implements OnInit {
});
this.baseConfigForm = this._formBuilder.group({
- filenameMappingColumnHeaderName: [undefined, Validators.required],
+ filenameMappingColumnHeaderName: ['', [Validators.required, this._autocompleteStringValidator()]],
delimiter: [undefined, Validators.required],
encoding: ['UTF-8', Validators.required]
});
@@ -68,20 +71,20 @@ export class FileAttributesCsvImportDialogComponent implements OnInit {
this.searchForm.valueChanges.subscribe((value) => this._executeSearch(value));
}
- ngOnInit(): void {
- setTimeout(() => {
- // Calculate viewport size after dialog is completely expanded
- if (this.cdkVirtualScrollViewport) {
- this.cdkVirtualScrollViewport.checkViewportSize();
- }
- }, 500);
- }
-
@debounce(200)
private _executeSearch(value: { query: string }) {
this.filteredFields = this.parseResult.fields.filter((f) => f.csvColumn.toLowerCase().includes(value.query.toLowerCase()));
}
+ private _autocompleteStringValidator(): ValidatorFn {
+ return (control: AbstractControl): { [key: string]: any } | null => {
+ if ((this.parseResult?.meta?.fields || []).indexOf(control.value) !== -1) {
+ return null; /* valid option selected */
+ }
+ return { invalidAutocompleteString: { value: control.value } };
+ };
+ }
+
private _readFile() {
const reader = new FileReader();
reader.addEventListener('load', async (event) => {
@@ -95,6 +98,11 @@ export class FileAttributesCsvImportDialogComponent implements OnInit {
}
this.parseResult.fields = this.parseResult.meta.fields.map((field) => this._buildAttribute(field));
this.filteredFields = [...this.parseResult.fields];
+
+ this.filteredKeyOptions = this.baseConfigForm.get('filenameMappingColumnHeaderName').valueChanges.pipe(
+ startWith(''),
+ map((value: string) => this.parseResult.meta.fields.filter((field) => field.toLowerCase().indexOf(value.toLowerCase()) !== -1))
+ );
});
reader.readAsText(this.csvFile, this.baseConfigForm.get('encoding').value);
}
diff --git a/apps/red-ui/src/app/modules/mat-config/mat-config.module.ts b/apps/red-ui/src/app/modules/mat-config/mat-config.module.ts
index 79e2e3042..1ef613d30 100644
--- a/apps/red-ui/src/app/modules/mat-config/mat-config.module.ts
+++ b/apps/red-ui/src/app/modules/mat-config/mat-config.module.ts
@@ -15,6 +15,7 @@ import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { MatProgressBarModule } from '@angular/material/progress-bar';
+import { MatAutocompleteModule } from '@angular/material/autocomplete';
const matImports = [
MatDialogModule,
@@ -32,7 +33,8 @@ const matImports = [
MatDatepickerModule,
MatInputModule,
MatSelectModule,
- MatProgressBarModule
+ MatProgressBarModule,
+ MatAutocompleteModule
];
@NgModule({
diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json
index b38d12861..36e4b62af 100644
--- a/apps/red-ui/src/assets/i18n/en.json
+++ b/apps/red-ui/src/assets/i18n/en.json
@@ -1154,7 +1154,7 @@
"encoding": "Encoding",
"encoding-placeholder": "UTF-8",
"key-column": "Key Column",
- "key-column-placeholder": "Select Column ...",
+ "key-column-placeholder": "Select column...",
"total-rows": "{{rows}} rows in total",
"available": "{{value}} available",
"selected": "{{value}} selected",
diff --git a/apps/red-ui/src/assets/styles/red-autocomplete.scss b/apps/red-ui/src/assets/styles/red-autocomplete.scss
new file mode 100644
index 000000000..cd517e71b
--- /dev/null
+++ b/apps/red-ui/src/assets/styles/red-autocomplete.scss
@@ -0,0 +1,10 @@
+@import 'red-variables';
+@import 'red-mixins';
+
+.mat-autocomplete-panel {
+ @include scroll-bar;
+
+ .mat-option {
+ font-size: inherit;
+ }
+}
diff --git a/apps/red-ui/src/assets/styles/red-theme.scss b/apps/red-ui/src/assets/styles/red-theme.scss
index 46008285d..8802af2d4 100644
--- a/apps/red-ui/src/assets/styles/red-theme.scss
+++ b/apps/red-ui/src/assets/styles/red-theme.scss
@@ -8,6 +8,7 @@
@import 'red-input';
@import 'red-button';
@import 'red-select';
+@import 'red-autocomplete';
@import 'red-list';
@import 'red-checkbox';
@import 'red-toggle';