Filters in project overview

This commit is contained in:
Adina Țeudan 2020-11-02 05:40:59 +02:00
parent b03607dd1f
commit b60b5154fc
2 changed files with 152 additions and 24 deletions

View File

@ -9,24 +9,36 @@
<div *ngIf="appStateService.activeProject" class="page-header">
<div class="filters flex-row">
<div translate="filters.filter-by.label"></div>
<button mat-button translate="filters.status.label">
<mat-icon svgIcon="red:status"></mat-icon>
</button>
<button mat-button translate="filters.people.label">
<mat-icon svgIcon="red:user"></mat-icon>
</button>
<button mat-button translate="filters.due-date.label">
<mat-icon svgIcon="red:lightning"></mat-icon>
</button>
<button mat-button translate="filters.created-on.label">
<mat-icon svgIcon="red:calendar"></mat-icon>
</button>
<button mat-button translate="filters.project.label">
<mat-icon svgIcon="red:folder"></mat-icon>
</button>
<button mat-button translate="filters.document.label">
<mat-icon svgIcon="red:document"></mat-icon>
</button>
<redaction-filter
[filters]="statusFilters"
[filterLabel]="'filters.status.label'"
[hasArrow]="false"
[icon]="'red:status'"
(filtersChanged)="filtersChanged()"
></redaction-filter>
<redaction-filter
[filters]="peopleFilters"
[filterLabel]="'filters.people.label'"
[hasArrow]="false"
[icon]="'red:user'"
(filtersChanged)="filtersChanged()"
></redaction-filter>
<!-- <button mat-button translate="filters.due-date.label">-->
<!-- <mat-icon svgIcon="red:lightning"></mat-icon>-->
<!-- </button>-->
<redaction-filter
[filters]="addedDateFilters"
[filterLabel]="'filters.created-on.label'"
[hasArrow]="false"
[icon]="'red:calendar'"
(filtersChanged)="filtersChanged()"
></redaction-filter>
<!-- <button mat-button translate="filters.project.label">-->
<!-- <mat-icon svgIcon="red:folder"></mat-icon>-->
<!-- </button>-->
<!-- <button mat-button translate="filters.document.label">-->
<!-- <mat-icon svgIcon="red:document"></mat-icon>-->
<!-- </button>-->
</div>
<button
(click)="fileInput.click()"
@ -127,11 +139,17 @@
></span>
</div>
<div
*ngIf="displayedFiles?.length === 0"
class="no-data"
translate="project-overview.no-files.label"
></div>
<div
class="table-item"
[class.pointer]="canOpenFile(fileStatus)"
*ngFor="
let fileStatus of appStateService.activeProject.files
let fileStatus of displayedFiles
| sortBy: sortingOption.order:sortingOption.column;
trackBy: fileId
"

View File

@ -15,10 +15,12 @@ import { UploadStatusOverlayService } from '../../upload/upload-status-dialog/se
import { UserService } from '../../user/user.service';
import { SortingOption } from '../../utils/types';
import { DoughnutChartConfig } from '../../components/simple-doughnut-chart/simple-doughnut-chart.component';
import { groupBy } from '../../utils/functions';
import { groupBy, humanize } from '../../utils/functions';
import { DialogService } from '../../dialogs/dialog.service';
import { TranslateService } from '@ngx-translate/core';
import { FileActionService } from '../file/service/file-action.service';
import { FilterModel } from '../../common/filter/model/filter.model';
import * as moment from 'moment';
@Component({
selector: 'redaction-project-overview-screen',
@ -51,6 +53,12 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
public documentsChartData: DoughnutChartConfig[] = [];
public bulkSelectActive = false;
public statusFilters: FilterModel[];
public peopleFilters: FilterModel[];
public addedDateFilters: FilterModel[];
public displayedFiles: FileStatus[] = [];
constructor(
public readonly appStateService: AppStateService,
public readonly userService: UserService,
@ -72,13 +80,13 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
});
this.appStateService.fileStatusChanged.subscribe(() => {
this._calculateChartConfig();
this._calculateData();
});
}
ngOnInit(): void {
this._fileDropOverlayService.initFileDropHandling();
this._calculateChartConfig();
this._calculateData();
this._displayNewRuleToast();
}
@ -162,10 +170,16 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
private _reloadProjects() {
this.appStateService.loadAllProjects().then(() => {
this._calculateChartConfig();
this._calculateData();
});
}
private _calculateData(): void {
this._computeAllFilters();
this._filterFiles();
this._calculateChartConfig();
}
private _calculateChartConfig() {
if (this.appStateService.activeProject) {
const groups = groupBy(this.appStateService.activeProject?.files, 'status');
@ -213,7 +227,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
fileStatus.projectId,
fileStatus.fileId,
() => {
this._calculateChartConfig();
this._calculateData();
}
);
}
@ -284,6 +298,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
this._fileUploadService.uploadFiles(uploadFiles);
this._uploadStatusOverlayService.openStatusOverlay();
}
public canOpenFile(fileStatus: FileStatus): boolean {
// TODO check correct condition for this
return !this.isError(fileStatus) && !this.isProcessing(fileStatus);
@ -293,4 +308,99 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
const sortedByRecent: boolean = this.sortingOption === this.sortingOptions[0];
this.sortingOption = sortedByRecent ? this.sortingOptions[1] : this.sortingOptions[0];
}
private _computeAllFilters() {
const allDistinctFileStatus = new Set<string>();
const allDistinctPeople = new Set<string>();
const allDistinctAddedDates = new Set<string>();
// All people
this.appStateService.activeProject.project.memberIds.forEach((memberId) =>
allDistinctPeople.add(memberId)
);
// File statuses
this.appStateService.activeProject.files.forEach((file) =>
allDistinctFileStatus.add(file.status)
);
// Added dates
this.appStateService.activeProject.files.forEach((file) =>
allDistinctAddedDates.add(moment(file.added).format('DD/MM/YYYY'))
);
this.statusFilters = [];
allDistinctFileStatus.forEach((status) => {
this.statusFilters.push({
key: status,
label: humanize(status)
});
});
this.peopleFilters = [];
allDistinctPeople.forEach((userId) => {
this.peopleFilters.push({
key: userId,
label: this.userService.getNameForId(userId)
});
});
this.addedDateFilters = [];
allDistinctAddedDates.forEach((date) => {
this.addedDateFilters.push({
key: date,
label: date
});
});
}
filtersChanged() {
this._filterFiles();
}
private _filterFiles() {
const filteredFiles = [];
for (const file of this.appStateService.activeProject.files) {
const statusFilterMatched = this._checkFilter(
file,
this.statusFilters,
(file: FileStatus, filter: FilterModel) => file.status === filter.key
);
const peopleFilterMatched = this._checkFilter(
file,
this.peopleFilters,
(file: FileStatus, filter: FilterModel) => file.currentReviewer === filter.key
);
const addedFilterMatched = this._checkFilter(
file,
this.peopleFilters,
(file: FileStatus, filter: FilterModel) =>
moment(file.added).format('DD/MM/YYYY') === filter.key
);
if (statusFilterMatched && peopleFilterMatched && addedFilterMatched) {
filteredFiles.push(file);
}
}
this.displayedFiles = filteredFiles;
}
private _checkFilter(file: FileStatus, filters: FilterModel[], validate: Function) {
const hasChecked = filters.find((f) => f.checked);
if (!hasChecked) {
return true;
}
let filterMatched = false;
for (const filter of filters) {
if (filter.checked && validate(file, filter)) {
filterMatched = true;
break;
}
}
return filterMatched;
}
}