File Attributes

- added 'filterable' and 'displayedInFileList' to file attributes
- added dynamic filters and columns for new added file attributes
This commit is contained in:
Valentin 2021-08-22 23:30:06 +03:00 committed by Timo Bejan
parent 8ce3b1b51e
commit 232f2df003
10 changed files with 99 additions and 7 deletions

View File

@ -51,6 +51,18 @@
{{ 'add-edit-file-attribute.form.primary' | translate }}
</mat-checkbox>
</div>
<div class="red-input-group mt-0">
<mat-checkbox color="primary" formControlName="filterable" name="filterable">
{{ 'add-edit-file-attribute.form.filterable' | translate }}
</mat-checkbox>
</div>
<div class="red-input-group mt-0">
<mat-checkbox color="primary" formControlName="displayedInFileList" name="displayedInFileList">
{{ 'add-edit-file-attribute.form.displayedInFileList' | translate }}
</mat-checkbox>
</div>
</div>
</div>
<div class="dialog-actions">

View File

@ -32,7 +32,9 @@ export class AddEditFileAttributeDialogComponent {
csvColumnHeader: [this.fileAttribute?.csvColumnHeader, Validators.required],
type: [this.fileAttribute?.type || FileAttributeConfig.TypeEnum.TEXT, Validators.required],
readonly: [this.fileAttribute ? !this.fileAttribute.editable : false],
primaryAttribute: [this.fileAttribute?.primaryAttribute]
primaryAttribute: [this.fileAttribute?.primaryAttribute],
filterable: [this.fileAttribute?.filterable],
displayedInFileList: [this.fileAttribute?.displayedInFileList]
});
}

View File

@ -62,6 +62,12 @@
<div class="small-label">
{{ attribute.csvColumnHeader }}
</div>
<div class="center">
<iqser-round-checkbox *ngIf="attribute.filterable" [active]="true" [size]="18"></iqser-round-checkbox>
</div>
<div class="center">
<iqser-round-checkbox *ngIf="attribute.displayedInFileList" [active]="true" [size]="18"></iqser-round-checkbox>
</div>
<div class="center">
<iqser-round-checkbox *ngIf="attribute.primaryAttribute" [active]="true" [size]="18"></iqser-round-checkbox>
</div>

View File

@ -11,7 +11,7 @@ iqser-table-header::ng-deep .header-item {
.content-container cdk-virtual-scroll-viewport {
::ng-deep.cdk-virtual-scroll-content-wrapper {
grid-template-columns: auto 2fr 1fr 1fr 1fr 1fr 1fr 11px;
grid-template-columns: auto 2fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 11px;
.table-item {
> div:not(.scrollbar-placeholder) {
@ -36,7 +36,7 @@ iqser-table-header::ng-deep .header-item {
}
&.has-scrollbar:hover ::ng-deep.cdk-virtual-scroll-content-wrapper {
grid-template-columns: auto 2fr 1fr 1fr 1fr 1fr 1fr;
grid-template-columns: auto 2fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
}
}

View File

@ -37,6 +37,14 @@ export class FileAttributesListingScreenComponent extends ListingComponent<FileA
class: 'flex-center'
},
{ label: _('file-attributes-listing.table-col-names.csv-column') },
{
label: _('file-attributes-listing.table-col-names.filterable'),
class: 'flex-center'
},
{
label: _('file-attributes-listing.table-col-names.displayed-in-file-list'),
class: 'flex-center'
},
{
label: _('file-attributes-listing.table-col-names.primary'),
class: 'flex-center',

View File

@ -1,6 +1,7 @@
<section *ngIf="!!currentDossier">
<redaction-page-header
[actionConfigs]="actionConfigs"
[fileAttributeConfigs]="fileAttributeConfigs"
[searchPlaceholder]="'dossier-overview.search' | translate"
[showCloseButton]="true"
>
@ -104,6 +105,10 @@
</div>
</div>
<div *ngFor="let config of displayedInFileListAttributes">
{{ fileStatus.fileAttributes.attributeIdToValue[config.id] }}
</div>
<div>
<div [class.error]="fileStatus.isError" class="small-label">
{{ fileStatus.added | date: 'd MMM. yyyy, hh:mm a' }}

View File

@ -17,7 +17,7 @@ iqser-table-column-name::ng-deep {
cdk-virtual-scroll-viewport {
::ng-deep.cdk-virtual-scroll-content-wrapper {
grid-template-columns: auto 3fr 2fr 1fr 2fr 1fr auto 11px;
grid-template-columns: auto 3fr 1fr 2fr 1fr 2fr 1fr auto 11px;
.table-item {
> div {
@ -67,7 +67,7 @@ cdk-virtual-scroll-viewport {
&.has-scrollbar:hover {
::ng-deep.cdk-virtual-scroll-content-wrapper {
grid-template-columns: auto 3fr 2fr 1fr 2fr 1fr auto;
grid-template-columns: auto 3fr 1fr 2fr 1fr 2fr 1fr auto;
}
}
}

View File

@ -30,6 +30,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { annotationFilterChecker } from '@shared/components/filters/popup-filter/utils/filter-utils';
import { PermissionsService } from '@services/permissions.service';
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
import { FileAttributeConfig } from '@redaction/red-ui-http';
@Component({
templateUrl: './dossier-overview-screen.component.html',
@ -50,7 +51,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
hide: !this.currentUser.isManager
}
];
readonly tableColumnConfigs: readonly TableColumnConfig<FileStatusWrapper>[] = [
tableColumnConfigs: readonly TableColumnConfig<FileStatusWrapper>[] = [
{
label: _('dossier-overview.table-col-names.name'),
sortByKey: 'filename'
@ -79,6 +80,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
];
collapsedDetails = false;
dossierAttributes: DossierAttributeWithValue[] = [];
fileAttributeConfigs: FileAttributeConfig[];
protected readonly _primaryKey = 'filename';
@ViewChild(DossierDetailsComponent, { static: false })
@ -106,9 +108,13 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
private readonly _userPreferenceService: UserPreferenceService,
private readonly _fileDropOverlayService: FileDropOverlayService,
private readonly _dossierAttributesService: DossierAttributesService
) {
) // private readonly _renderer: Renderer2,
// private readonly _elementRef: ElementRef,
{
super(_injector);
this._loadEntitiesFromState();
this.fileAttributeConfigs = this._appStateService.activeFileAttributesConfig.fileAttributeConfigs;
}
get checkedRequiredFilters() {
@ -141,6 +147,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
this.dossierAttributes = await this._dossierAttributesService.getValues(this.currentDossier);
this.searchService.setSearchKey('filename');
this.addDynamicColumns();
} catch (e) {
} finally {
this._loadingService.stop();
@ -235,6 +242,25 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
this.collapsedDetails = !this.collapsedDetails;
}
addDynamicColumns() {
const dynamicColumns: TableColumnConfig<FileStatusWrapper>[] = [];
for (const config of this.displayedInFileListAttributes) {
if (config.displayedInFileList) {
dynamicColumns.push({ label: config.label });
}
}
this.tableColumnConfigs = [this.tableColumnConfigs[0], ...dynamicColumns, ...this.tableColumnConfigs.slice(1)];
// const element = this._elementRef.nativeElement.querySelector('.cdk-virtual-scroll-content-wrapper');
// this._renderer.setStyle(element, 'grid-template-columns', 'auto 3fr 1fr 2fr 1fr 2fr 1fr auto 11px');
// this._renderer.addClass(element, 'has-scrollbar:hover')
// console.log('element: ', element);
}
get displayedInFileListAttributes() {
return this.fileAttributeConfigs.filter(config => config.displayedInFileList);
}
recentlyModifiedChecker = (file: FileStatusWrapper) =>
moment(file.lastUpdated).add(this._appConfigService.getConfig(AppConfigKey.RECENT_PERIOD_IN_HOURS), 'hours').isAfter(moment());
@ -256,6 +282,8 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
const allDistinctAddedDates = new Set<string>();
const allDistinctNeedsWork = new Set<string>();
const dynamicFilters = new Map<string, Set<string>>();
this.entitiesService.all.forEach(file => {
allDistinctPeople.add(file.currentReviewer);
allDistinctFileStatusWrapper.add(file.status);
@ -269,6 +297,31 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
if (file.hasImages) allDistinctNeedsWork.add('image');
if (file.hasNone) allDistinctNeedsWork.add('none');
if (file.hasAnnotationComments) allDistinctNeedsWork.add('comment');
// extract values for dynamic filters
this.fileAttributeConfigs.forEach(config => {
if (config.filterable) {
const filterKey = `${config.id}:${config.label}`;
let filters = dynamicFilters.get(filterKey);
if (!filters) {
dynamicFilters.set(filterKey, new Set<string>());
filters = dynamicFilters.get(filterKey);
}
filters.add(file.fileAttributes?.attributeIdToValue[config.id]);
}
});
});
dynamicFilters.forEach((filterValue: Set<string>, filterKey: string) => {
const id = filterKey.split(':')[0];
const key = filterKey.split(':')[1];
this.filterService.addFilterGroup({
slug: key,
label: key,
icon: 'red:template',
filters: [...filterValue].map<NestedFilter>((value: string) => ({ key: value, label: value })),
checker: (input: FileStatusWrapper, filter: NestedFilter) => filter.label === input.fileAttributes.attributeIdToValue[id]
});
});
const statusFilters = [...allDistinctFileStatusWrapper].map<NestedFilter>(item => ({

View File

@ -5,6 +5,7 @@ import { FilterService, SearchService } from '@iqser/common-ui';
import { distinctUntilChanged, map } from 'rxjs/operators';
import { combineLatest, Observable, of } from 'rxjs';
import { SearchPosition, SearchPositions } from '@shared/components/page-header/models/search-positions.type';
import { FileAttributeConfig } from '@redaction/red-ui-http';
@Component({
selector: 'redaction-page-header',
@ -18,6 +19,7 @@ export class PageHeaderComponent<T> {
@Input() showCloseButton: boolean;
@Input() actionConfigs: readonly ActionConfig[];
@Input() buttonConfigs: readonly ButtonConfig[];
@Input() fileAttributeConfigs: readonly FileAttributeConfig[];
@Input() searchPlaceholder: string;
@Input() searchWidth: number | 'full';
@Input() searchPosition: SearchPosition = SearchPositions.afterFilters;

View File

@ -82,6 +82,8 @@
"form": {
"column-header": "CSV Column Header",
"column-header-placeholder": "Enter CSV Column Header",
"displayedInFileList": "Displayed In File List",
"filterable": "Filterable",
"name": "Attribute Name",
"name-placeholder": "Enter Name",
"primary": "Set as Primary",
@ -928,6 +930,8 @@
"search": "Search by attribute name...",
"table-col-names": {
"csv-column": "CSV Column",
"displayed-in-file-list": "Dis. In File List",
"filterable": "Filterable",
"name": "Name",
"primary": "Primary",
"primary-info-tooltip": "The value of the attribute set as primary shows up under the file name in the documents list.",