added needs work for project overview, extracted component

This commit is contained in:
Timo Bejan 2020-11-06 12:26:26 +02:00
parent a3bc58c269
commit 6241ef254a
13 changed files with 125 additions and 85 deletions

View File

@ -70,6 +70,7 @@ import { SortingComponent } from './components/sorting/sorting.component';
import { TableColNameComponent } from './components/table-col-name/table-col-name.component';
import { ProjectDetailsComponent } from './screens/project-overview-screen/project-details/project-details.component';
import { PageIndicatorComponent } from './screens/file/page-indicator/page-indicator.component';
import { NeedsWorkBadgeComponent } from './screens/common/needs-work-badge/needs-work-badge.component';
export function HttpLoaderFactory(httpClient: HttpClient) {
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
@ -105,7 +106,8 @@ export function HttpLoaderFactory(httpClient: HttpClient) {
SortingComponent,
TableColNameComponent,
ProjectDetailsComponent,
PageIndicatorComponent
PageIndicatorComponent,
NeedsWorkBadgeComponent
],
imports: [
BrowserModule,

View File

@ -0,0 +1,14 @@
<div *ngIf="displayed" class="needs-work">
<redaction-annotation-icon
*ngIf="needsWorkInput.hasRedactions"
[typeValue]="appStateService.getDictionaryTypeValue('redaction')"
></redaction-annotation-icon>
<redaction-annotation-icon
*ngIf="needsWorkInput.hasHints"
[typeValue]="appStateService.getDictionaryTypeValue('hint')"
></redaction-annotation-icon>
<redaction-annotation-icon
*ngIf="needsWorkInput.hasRequests"
[typeValue]="appStateService.getDictionaryTypeValue('request')"
></redaction-annotation-icon>
</div>

View File

@ -0,0 +1,7 @@
.needs-work {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
gap: 4px;
}

View File

@ -0,0 +1,22 @@
import { Component, Input, OnInit } from '@angular/core';
import { AppStateService } from '../../../state/app-state.service';
export interface NeedsWorkInput {
hasHints?: boolean;
hasRedactions?: boolean;
hasRequests?: boolean;
}
@Component({
selector: 'redaction-needs-work-badge',
templateUrl: './needs-work-badge.component.html',
styleUrls: ['./needs-work-badge.component.scss']
})
export class NeedsWorkBadgeComponent implements OnInit {
@Input() displayed: boolean;
@Input() needsWorkInput: NeedsWorkInput;
constructor(public appStateService: AppStateService) {}
ngOnInit(): void {}
}

View File

@ -22,20 +22,13 @@
[icon]="'red:lightning'"
(filtersChanged)="filtersChanged()"
></redaction-filter>
<!-- <redaction-filter-->
<!-- [filters]="addedDateFilters"-->
<!-- [filterLabel]="'filters.created-on'"-->
<!-- [hasArrow]="false"-->
<!-- [icon]="'red:calendar'"-->
<!-- (filtersChanged)="filtersChanged()"-->
<!-- ></redaction-filter>-->
<!-- <button mat-button translate="filters.project">-->
<!-- <mat-icon svgIcon="red:folder"></mat-icon>-->
<!-- </button>-->
<!-- <button mat-button translate="filters.document">-->
<!-- <mat-icon svgIcon="red:document"></mat-icon>-->
<!-- </button>-->
<redaction-filter
(filtersChanged)="filtersChanged()"
[filterLabel]="'filters.needs-work'"
[filters]="needsWorkFilters"
[hasArrow]="false"
[icon]="'red:needs-work'"
></redaction-filter>
</div>
<button
(click)="openAddProjectDialog()"
@ -94,6 +87,10 @@
(toggleSort)="sortingComponent.toggleSort($event)"
></redaction-table-col-name>
<redaction-table-col-name
label="project-listing.table-col-names.needs-work"
></redaction-table-col-name>
<redaction-table-col-name
label="project-listing.table-col-names.owner"
></redaction-table-col-name>
@ -152,6 +149,12 @@
</div>
</div>
</div>
<div>
<redaction-needs-work-badge
[needsWorkInput]="pw"
[displayed]="true"
></redaction-needs-work-badge>
</div>
<div>
<redaction-initials-avatar
[userId]="pw.project.ownerId"

View File

@ -11,10 +11,10 @@
width: calc(100vw - #{$right-container-width} - 90px);
.grid-container {
grid-template-columns: 2fr 1fr auto;
grid-template-columns: 2fr 1fr 1fr auto;
&.bulk-select {
grid-template-columns: auto 2fr 1fr auto;
grid-template-columns: auto 2fr 1fr 1fr auto;
}
}

View File

@ -10,11 +10,13 @@ import * as moment from 'moment';
import { SortingComponent, SortingOption } from '../../components/sorting/sorting.component';
import {
addedDateChecker,
annotationFilterChecker,
dueDateChecker,
getFilteredEntities,
projectMemberChecker,
projectStatusChecker
} from '../../common/filter/utils/filter-utils';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'redaction-project-listing-screen',
@ -32,8 +34,7 @@ export class ProjectListingScreenComponent implements OnInit {
public statusFilters: FilterModel[];
public dueDateFilters: FilterModel[];
public peopleFilters: FilterModel[];
public addedDateFilters: FilterModel[];
public needsWorkFilters: FilterModel[];
public displayedProjects: ProjectWrapper[] = [];
@ViewChild('sortingComponent', { static: true }) public sortingComponent: SortingComponent;
@ -43,7 +44,8 @@ export class ProjectListingScreenComponent implements OnInit {
public readonly appStateService: AppStateService,
public readonly userService: UserService,
private readonly _changeDetectorRef: ChangeDetectorRef,
private readonly _dialogService: DialogService
private readonly _dialogService: DialogService,
private readonly _translateService: TranslateService
) {}
public ngOnInit(): void {
@ -158,7 +160,7 @@ export class ProjectListingScreenComponent implements OnInit {
const allDistinctFileStatus = new Set<string>();
const allDistinctPeople = new Set<string>();
const allDistinctDueDates = new Set<string>();
const allDistinctAddedDates = new Set<string>();
const allDistinctNeedsWork = new Set<string>();
this.appStateService.allProjects.forEach((entry) => {
// all people
entry.project.memberIds.forEach((memberId) => allDistinctPeople.add(memberId));
@ -166,12 +168,17 @@ export class ProjectListingScreenComponent implements OnInit {
if (entry.dueDate) {
allDistinctDueDates.add(moment(entry.dueDate).format('DD/MM/YYYY'));
}
// added date
allDistinctAddedDates.add(moment(entry.projectDate).format('DD/MM/YYYY'));
// file statuses
entry.files.forEach((file) => {
allDistinctFileStatus.add(file.status);
});
// Needs work
entry.files.forEach((file) => {
if (file.hasHints) allDistinctNeedsWork.add('hints');
if (file.hasRedactions) allDistinctNeedsWork.add('redactions');
if (file.hasRequests) allDistinctNeedsWork.add('requests');
});
});
this.statusFilters = [];
@ -198,11 +205,11 @@ export class ProjectListingScreenComponent implements OnInit {
});
});
this.addedDateFilters = [];
allDistinctAddedDates.forEach((date) => {
this.addedDateFilters.push({
key: date,
label: date
this.needsWorkFilters = [];
allDistinctNeedsWork.forEach((type) => {
this.needsWorkFilters.push({
key: type,
label: this._translateService.instant('filter.' + type)
});
});
}
@ -216,7 +223,7 @@ export class ProjectListingScreenComponent implements OnInit {
{ values: this.statusFilters, checker: projectStatusChecker },
{ values: this.peopleFilters, checker: projectMemberChecker },
{ values: this.dueDateFilters, checker: dueDateChecker },
{ values: this.addedDateFilters, checker: addedDateChecker }
{ values: this.needsWorkFilters, checker: annotationFilterChecker, matchAll: true }
];
this.displayedProjects = getFilteredEntities(this.appStateService.allProjects, filters);

View File

@ -27,16 +27,6 @@
[hasArrow]="false"
[icon]="'red:user'"
></redaction-filter>
<!-- <button mat-button translate="filters.due-date">-->
<!-- <mat-icon svgIcon="red:lightning"></mat-icon>-->
<!-- </button>-->
<redaction-filter
(filtersChanged)="filtersChanged()"
[filterLabel]="'filters.created-on'"
[filters]="addedDateFilters"
[hasArrow]="false"
[icon]="'red:calendar'"
></redaction-filter>
<redaction-filter
(filtersChanged)="filtersChanged()"
[filterLabel]="'filters.needs-work'"
@ -44,12 +34,6 @@
[hasArrow]="false"
[icon]="'red:needs-work'"
></redaction-filter>
<!-- <button mat-button translate="filters.project">-->
<!-- <mat-icon svgIcon="red:folder"></mat-icon>-->
<!-- </button>-->
<!-- <button mat-button translate="filters.document">-->
<!-- <mat-icon svgIcon="red:document"></mat-icon>-->
<!-- </button>-->
</div>
<div>
@ -210,21 +194,12 @@
</div>
</div>
<div *ngIf="!isError(fileStatus)" class="needs-work">
<redaction-annotation-icon
*ngIf="fileStatus.hasRedactions"
[typeValue]="appStateService.getDictionaryTypeValue('redaction')"
></redaction-annotation-icon>
<redaction-annotation-icon
*ngIf="fileStatus.hasHints"
[typeValue]="appStateService.getDictionaryTypeValue('hint')"
></redaction-annotation-icon>
<redaction-annotation-icon
*ngIf="fileStatus.hasRequests"
[typeValue]="appStateService.getDictionaryTypeValue('request')"
></redaction-annotation-icon>
<div>
<redaction-needs-work-badge
[needsWorkInput]="fileStatus"
[displayed]="!isError(fileStatus)"
></redaction-needs-work-badge>
</div>
<div *ngIf="!isError(fileStatus)" class="assigned-to">
<redaction-initials-avatar
[userId]="fileStatus.currentReviewer"

View File

@ -37,14 +37,6 @@
max-width: 25vw;
}
.needs-work {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
gap: 4px;
}
.pages {
display: flex;
flex-direction: row;

View File

@ -40,7 +40,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
public statusFilters: FilterModel[];
public peopleFilters: FilterModel[];
public addedDateFilters: FilterModel[];
// public addedDateFilters: FilterModel[];
public needsWorkFilters: FilterModel[];
public displayedFiles: FileStatusWrapper[] = [];
@ -305,14 +305,6 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
});
});
this.addedDateFilters = [];
allDistinctAddedDates.forEach((date) => {
this.addedDateFilters.push({
key: date,
label: date
});
});
this.needsWorkFilters = [];
allDistinctNeedsWork.forEach((type) => {
this.needsWorkFilters.push({
@ -330,7 +322,6 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
const filters = [
{ values: this.statusFilters, checker: keyChecker('status') },
{ values: this.peopleFilters, checker: keyChecker('currentReviewer') },
{ values: this.addedDateFilters, checker: fileAddedFilterChecker },
{ values: this.needsWorkFilters, checker: annotationFilterChecker, matchAll: true }
];
this.displayedFiles = getFilteredEntities(

View File

@ -1,7 +1,6 @@
import { EventEmitter, Injectable } from '@angular/core';
import {
DictionaryControllerService,
FileStatus,
FileUploadControllerService,
Project,
ProjectControllerService,
@ -9,7 +8,6 @@ import {
StatusControllerService,
TypeValue,
VersionsControllerService,
ViewedPages,
ViewedPagesControllerService
} from '@redaction/red-ui-http';
import { NotificationService, NotificationType } from '../notification/notification.service';
@ -38,11 +36,24 @@ export interface AppState {
export class ProjectWrapper {
totalNumberOfPages?: number;
hasStatus(status: string) {
return this.files.find((f) => f.status === status);
hasHints?: boolean;
hasRedactions?: boolean;
hasRequests?: boolean;
private _files: FileStatusWrapper[];
constructor(public project: Project, files: FileStatusWrapper[]) {
this._files = files ? files : [];
this._recomputeFileStatus();
}
constructor(public project: Project, public files: FileStatusWrapper[]) {}
set files(files: FileStatusWrapper[]) {
this._files = files ? files : [];
this._recomputeFileStatus();
}
get files() {
return this._files;
}
get projectDate() {
return this.project.date;
@ -52,6 +63,14 @@ export class ProjectWrapper {
return this.project.dueDate;
}
get hasFiles() {
return this._files.length > 0;
}
hasStatus(status: string) {
return this._files.find((f) => f.status === status);
}
hasMember(key: string) {
return this.project.memberIds.indexOf(key) >= 0;
}
@ -64,8 +83,15 @@ export class ProjectWrapper {
return moment(this.projectDate).format('DD/MM/YYYY') === key;
}
get hasFiles() {
return this.files?.length > 0;
private _recomputeFileStatus() {
this.hasHints = false;
this.hasRedactions = false;
this.hasRequests = false;
this._files.forEach((f) => {
this.hasHints = this.hasHints || f.hasHints;
this.hasRedactions = this.hasRedactions || f.hasRedactions;
this.hasRequests = this.hasRequests || f.hasRequests;
});
}
}

View File

@ -90,7 +90,7 @@
"created-on": "Created On",
"project": "Project",
"document": "Document",
"needs-work": "Needs Work"
"needs-work": "Analysed"
},
"project-listing": {
"report": {
@ -109,6 +109,7 @@
},
"table-col-names": {
"name": "Document",
"needs-work": "Analysed",
"owner": "Owner",
"status": "Status"
},