CSV import search by column name

This commit is contained in:
Adina Țeudan 2021-04-13 17:52:29 +03:00
parent f78671d304
commit 05bde93f49
16 changed files with 86 additions and 30 deletions

View File

@ -25,13 +25,13 @@ import { ConfirmDeleteFileAttributeDialogComponent } from './dialogs/confirm-del
import { EditColorDialogComponent } from './dialogs/edit-color-dialog/edit-color-dialog.component';
import { ComboChartComponent, ComboSeriesVerticalComponent } from './components/combo-chart';
import { NgxChartsModule } from '@swimlane/ngx-charts';
import { AdminDialogService } from './services/admin-dialog-service.service';
import { AdminDialogService } from './services/admin-dialog.service';
import { SmtpConfigScreenComponent } from './screens/smtp-config/smtp-config-screen.component';
import { SmtpAuthDialogComponent } from './dialogs/smtp-auth-dialog/smtp-auth-dialog.component';
import { AddEditUserDialogComponent } from './dialogs/add-edit-user-dialog/add-edit-user-dialog.component';
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 './screens/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';
import { FileAttributesCsvImportDialogComponent } from './dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';
const dialogs = [
AddEditRuleSetDialogComponent,

View File

@ -2,7 +2,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
import { PermissionsService } from '../../../../services/permissions.service';
import { AppStateService } from '../../../../state/app-state.service';
import { Router } from '@angular/router';
import { AdminDialogService } from '../../services/admin-dialog-service.service';
import { AdminDialogService } from '../../services/admin-dialog.service';
@Component({
selector: 'redaction-rule-set-actions',

View File

@ -53,19 +53,37 @@
}}</span>
<span class="all-caps-label">{{ 'file-attributes-csv-import.selected' | translate: { value: activeFields.length } }}</span>
</div>
<div class="quick-activation">
<span class="all-caps-label primary pointer" (click)="activateAll()" translate="file-attributes-csv-import.quick-activation.all"></span>
<span
class="all-caps-label primary pointer"
(click)="deactivateAll()"
translate="file-attributes-csv-import.quick-activation.none"
></span>
<div class="actions">
<redaction-circle-button
icon="red:search"
(click)="isSearchOpen = !isSearchOpen"
[attr.aria-expanded]="isSearchOpen"
></redaction-circle-button>
<div class="quick-activation">
<span
class="all-caps-label primary pointer"
(click)="activateAll()"
translate="file-attributes-csv-import.quick-activation.all"
></span>
<span
class="all-caps-label primary pointer"
(click)="deactivateAll()"
translate="file-attributes-csv-import.quick-activation.none"
></span>
</div>
</div>
</div>
<div class="csv-header-pill-content">
<div class="search-input-container" *ngIf="isSearchOpen">
<redaction-search-input
[form]="searchForm"
placeholder="file-attributes-csv-import.search.placeholder"
width="full"
></redaction-search-input>
</div>
<div class="csv-header-pill-content" [class.search-open]="isSearchOpen">
<div
class="csv-header-pill"
*ngFor="let field of relevantFields"
*ngFor="let field of filteredFields"
(mouseenter)="hoveredColumn = field.csvColumn"
(mouseleave)="hoveredColumn = undefined"
(click)="toggleFieldActive(field)"

View File

@ -47,7 +47,8 @@
.csv-part {
display: flex;
max-height: calc(90vh - 251px);
min-height: calc(90vh - 240px);
max-height: calc(90vh - 240px);
.csv-part-header {
height: 50px;
@ -60,16 +61,31 @@
justify-content: space-between;
padding: 0 16px;
> :not(.quick-activation) > *:not(:last-child)::after {
> div:first-child > *:not(:last-child)::after {
content: '-';
margin: 0 4px;
}
.quick-activation > :not(:last-child) {
margin-right: 10px;
.actions {
display: flex;
align-items: center;
.quick-activation {
margin-left: 12px;
> :not(:last-child) {
margin-right: 10px;
}
}
}
}
.search-input-container {
background-color: $white;
border-bottom: 1px solid $separator;
padding: 8px 16px;
}
.csv-part-content {
overflow: auto;
@include no-scroll-bar;
@ -110,6 +126,10 @@
height: calc(100% - 58px);
@include no-scroll-bar;
&.search-open {
height: calc(100% - 58px - 51px);
}
.csv-header-pill {
min-height: 32px;
margin: 6px auto;

View File

@ -5,6 +5,7 @@ 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';
enum FieldType {
Text = 'Text',
@ -35,6 +36,9 @@ export class FileAttributesCsvImportDialogComponent implements OnInit {
public activeFields: Field[] = [];
public selectedFields: string[] = [];
public baseConfigForm: FormGroup;
public isSearchOpen = false;
public searchForm: FormGroup;
public filteredFields: Field[];
@ViewChild(CdkVirtualScrollViewport, { static: false }) cdkVirtualScrollViewport: CdkVirtualScrollViewport;
@ -48,6 +52,10 @@ export class FileAttributesCsvImportDialogComponent implements OnInit {
this.csvFile = data.csv;
this.ruleSetId = data.ruleSetId;
this.searchForm = this._formBuilder.group({
query: ['']
});
this.baseConfigForm = this._formBuilder.group({
filenameMappingColumnHeaderName: [undefined, Validators.required],
delimiter: [undefined, Validators.required],
@ -55,10 +63,8 @@ export class FileAttributesCsvImportDialogComponent implements OnInit {
});
this._readFile();
}
get relevantFields() {
return this.parseResult?.fields.filter((f) => this.getEntries(f.csvColumn) > 0);
this.searchForm.valueChanges.subscribe((value) => this._executeSearch(value));
}
ngOnInit(): void {
@ -70,6 +76,11 @@ export class FileAttributesCsvImportDialogComponent implements OnInit {
}, 500);
}
@debounce(200)
private _executeSearch(value: { query: string }) {
this.filteredFields = this.parseResult.fields.filter((f) => f.csvColumn.toLowerCase().includes(value.query.toLowerCase()));
}
private _readFile() {
const reader = new FileReader();
reader.addEventListener('load', async (event) => {
@ -82,7 +93,7 @@ export class FileAttributesCsvImportDialogComponent implements OnInit {
this.baseConfigForm.patchValue({ delimiter: this.parseResult.meta.delimiter });
}
this.parseResult.fields = this.parseResult.meta.fields.map((field) => this._buildAttribute(field));
console.log(this.parseResult);
this.filteredFields = [...this.parseResult.fields];
});
reader.readAsText(this.csvFile, this.baseConfigForm.get('encoding').value);
}

View File

@ -4,7 +4,7 @@ import { Colors, DictionaryControllerService } from '@redaction/red-ui-http';
import { ActivatedRoute } from '@angular/router';
import { SortingOption, SortingService } from '../../../../services/sorting.service';
import { PermissionsService } from '../../../../services/permissions.service';
import { AdminDialogService } from '../../services/admin-dialog-service.service';
import { AdminDialogService } from '../../services/admin-dialog.service';
@Component({
selector: 'redaction-default-colors-screen',

View File

@ -9,7 +9,7 @@ import { PermissionsService } from '../../../../services/permissions.service';
import { FormBuilder, FormGroup } from '@angular/forms';
import { debounce } from '../../../../utils/debounce';
import { ActivatedRoute } from '@angular/router';
import { AdminDialogService } from '../../services/admin-dialog-service.service';
import { AdminDialogService } from '../../services/admin-dialog.service';
@Component({
selector: 'redaction-dictionary-listing-screen',

View File

@ -11,7 +11,7 @@ import { Observable } from 'rxjs';
import { saveAs } from 'file-saver';
import { ComponentHasChanges } from '../../../../guards/can-deactivate.guard';
import { FormBuilder, FormGroup } from '@angular/forms';
import { AdminDialogService } from '../../services/admin-dialog-service.service';
import { AdminDialogService } from '../../services/admin-dialog.service';
declare var ace;

View File

@ -6,7 +6,7 @@ import { AppStateService } from '../../../../state/app-state.service';
import { ActivatedRoute } from '@angular/router';
import { debounce } from '../../../../utils/debounce';
import { SortingOption, SortingService } from '../../../../services/sorting.service';
import { AdminDialogService } from '../../services/admin-dialog-service.service';
import { AdminDialogService } from '../../services/admin-dialog.service';
@Component({
selector: 'redaction-file-attributes-listing-screen',

View File

@ -6,7 +6,7 @@ import { FormBuilder, FormGroup } from '@angular/forms';
import { debounce } from '../../../../utils/debounce';
import { RuleSetModel } from '@redaction/red-ui-http';
import { UserPreferenceService } from '../../../../services/user-preference.service';
import { AdminDialogService } from '../../services/admin-dialog-service.service';
import { AdminDialogService } from '../../services/admin-dialog.service';
@Component({
selector: 'redaction-rule-sets-listing-screen',

View File

@ -1,7 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { PermissionsService } from '../../../../services/permissions.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { AdminDialogService } from '../../services/admin-dialog-service.service';
import { AdminDialogService } from '../../services/admin-dialog.service';
import { SmtpConfigurationControllerService, SMTPConfigurationModel } from '@redaction/red-ui-http';
import { NotificationService, NotificationType } from '../../../../services/notification.service';
import { TranslateService } from '@ngx-translate/core';

View File

@ -4,7 +4,7 @@ import { UserService } from '../../../../services/user.service';
import { RuleSetModel, User, UserControllerService } from '@redaction/red-ui-http';
import { FormBuilder, FormGroup } from '@angular/forms';
import { debounce } from '../../../../utils/debounce';
import { AdminDialogService } from '../../services/admin-dialog-service.service';
import { AdminDialogService } from '../../services/admin-dialog.service';
import { TranslateService } from '@ngx-translate/core';
import { DoughnutChartConfig } from '../../../shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
import { TranslateChartService } from '../../../../services/translate-chart.service';

View File

@ -24,7 +24,7 @@ import { TranslateService } from '@ngx-translate/core';
import { SmtpAuthDialogComponent } from '../dialogs/smtp-auth-dialog/smtp-auth-dialog.component';
import { AddEditUserDialogComponent } from '../dialogs/add-edit-user-dialog/add-edit-user-dialog.component';
import { ConfirmDeleteUsersDialogComponent } from '../dialogs/confirm-delete-users-dialog/confirm-delete-users-dialog.component';
import { FileAttributesCsvImportDialogComponent } from '../screens/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';
import { FileAttributesCsvImportDialogComponent } from '../dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';
const largeDialogConfig = {
width: '90vw',

View File

@ -1,5 +1,5 @@
<form [formGroup]="form">
<div class="red-input-group" [style.width]="width + 'px'" [style.max-width]="width + 'px'">
<div class="red-input-group" [style.width]="computedWidth" [style.max-width]="computedWidth">
<input [placeholder]="placeholder | translate" class="with-icon mt-0" formControlName="query" name="query" type="text" />
<mat-icon *ngIf="!hasContent" class="icon-right" svgIcon="red:search"></mat-icon>
<mat-icon *ngIf="hasContent" class="icon-right pointer" svgIcon="red:close" (click)="clearContent()"></mat-icon>

View File

@ -9,7 +9,7 @@ import { FormGroup } from '@angular/forms';
export class SearchInputComponent implements OnInit {
@Input() form: FormGroup;
@Input() placeholder: string;
@Input() width = 250;
@Input() width: number | 'full' = 250;
constructor() {}
@ -22,4 +22,8 @@ export class SearchInputComponent implements OnInit {
public clearContent() {
this.form.patchValue({ query: '' });
}
public get computedWidth() {
return this.width === 'full' ? '100%' : `${this.width}px`;
}
}

View File

@ -1160,6 +1160,9 @@
"selected": "{{value}} selected",
"csv-column": "CSV Column",
"no-hovered-column": "Preview CSV column by hovering the entry.",
"search": {
"placeholder": "Search by column name..."
},
"table-header": {
"title": "{{length}} file attributes",
"actions": {