reworked analysis required

This commit is contained in:
Timo Bejan 2020-11-09 23:47:29 +02:00
parent 5f16c2988e
commit 1f2acf201e
12 changed files with 71 additions and 34 deletions

View File

@ -1,8 +1,10 @@
import { FilterModel } from '../model/filter.model';
import { FileStatusWrapper } from '../../../screens/file/model/file-status.wrapper';
import { ProjectWrapper } from '../../../state/model/project.wrapper';
import { PermissionsService } from '../../service/permissions.service';
export const RedactionFilterSorter = {
analysis: 0,
hint: 1,
redaction: 2,
suggestion: 3,
@ -22,9 +24,16 @@ export function handleCheckedValue(filter: FilterModel) {
}
}
export function checkFilter(entity: any, filters: FilterModel[], validate: Function, matchAll: boolean = false) {
export function checkFilter(entity: any, filters: FilterModel[], validate: Function, validateArgs: any = [], matchAll: boolean = false) {
const hasChecked = filters.find((f) => f.checked);
if (validateArgs) {
if (!Array.isArray(validateArgs)) {
validateArgs = [validateArgs];
}
} else {
validateArgs = [];
}
if (!hasChecked) {
return true;
}
@ -33,9 +42,9 @@ export function checkFilter(entity: any, filters: FilterModel[], validate: Funct
for (const filter of filters) {
if (filter.checked) {
if (matchAll) {
filterMatched = filterMatched && validate(entity, filter);
filterMatched = filterMatched && validate(entity, filter, ...validateArgs);
} else {
filterMatched = filterMatched || validate(entity, filter);
filterMatched = filterMatched || validate(entity, filter, ...validateArgs);
}
}
}
@ -45,19 +54,26 @@ export function checkFilter(entity: any, filters: FilterModel[], validate: Funct
export const keyChecker = (key: string) => (entity: any, filter: FilterModel) => entity[key] === filter.key;
export const annotationFilterChecker = (f: FileStatusWrapper, filter: FilterModel) => {
export const annotationFilterChecker = (input: FileStatusWrapper | ProjectWrapper, filter: FilterModel, permissionsService: PermissionsService) => {
switch (filter.key) {
case 'analysis': {
if (input instanceof ProjectWrapper) {
return permissionsService.projectReanalysisRequired(input);
} else {
return permissionsService.fileRequiresReanalysis(input);
}
}
case 'suggestion': {
return f.hasRequests;
return input.hasRequests;
}
case 'redaction': {
return f.hasRedactions;
return input.hasRedactions;
}
case 'hint': {
return f.hintsOnly;
return input.hintsOnly;
}
case 'none': {
return f.hasNone;
return input.hasNone;
}
}
};
@ -72,12 +88,12 @@ export const dueDateChecker = (pw: ProjectWrapper, filter: FilterModel) => pw.du
export const addedDateChecker = (pw: ProjectWrapper, filter: FilterModel) => pw.addedDateMatches(filter.key);
export function getFilteredEntities(entities: any[], filters: { values: FilterModel[]; checker: Function; matchAll?: boolean }[]) {
export function getFilteredEntities(entities: any[], filters: { values: FilterModel[]; checker: Function; matchAll?: boolean; checkerArgs?: any }[]) {
const filteredEntities = [];
for (const entity of entities) {
let add = true;
for (const filter of filters) {
add = add && checkFilter(entity, filter.values, filter.checker, filter.matchAll);
add = add && checkFilter(entity, filter.values, filter.checker, filter.checkerArgs, filter.matchAll);
}
if (add) {
filteredEntities.push(entity);

View File

@ -3,6 +3,7 @@ import { AppStateService } from '../../state/app-state.service';
import { UserService, UserWrapper } from '../../user/user.service';
import { FileStatusWrapper } from '../../screens/file/model/file-status.wrapper';
import { Project, User } from '@redaction/red-ui-http';
import { ProjectWrapper } from '../../state/model/project.wrapper';
@Injectable({
providedIn: 'root'
@ -22,6 +23,15 @@ export class PermissionsService {
return this.isFileReviewer(fileStatus) || this.isManagerAndOwner();
}
projectReanalysisRequired(project?: ProjectWrapper) {
for (let file of project.files) {
const fileReanalysisRequired = this.fileRequiresReanalysis(file);
if (fileReanalysisRequired) {
return true;
}
}
}
fileRequiresReanalysis(fileStatus?: FileStatusWrapper) {
if (!fileStatus) {
fileStatus = this._appStateService.activeFile;

View File

@ -1,4 +1,5 @@
<div class="needs-work">
<redaction-annotation-icon *ngIf="reanalysisRequired()" [typeValue]="appStateService.getDictionaryTypeValue('analysis')"></redaction-annotation-icon>
<redaction-annotation-icon
*ngIf="needsWorkInput.hasRedactions"
[typeValue]="appStateService.getDictionaryTypeValue('redaction')"

View File

@ -1,11 +1,8 @@
import { Component, Input, OnInit } from '@angular/core';
import { AppStateService } from '../../../state/app-state.service';
export interface NeedsWorkInput {
hintsOnly?: boolean;
hasRedactions?: boolean;
hasRequests?: boolean;
}
import { PermissionsService } from '../../../common/service/permissions.service';
import { FileStatusWrapper } from '../../file/model/file-status.wrapper';
import { ProjectWrapper } from '../../../state/model/project.wrapper';
@Component({
selector: 'redaction-needs-work-badge',
@ -13,9 +10,17 @@ export interface NeedsWorkInput {
styleUrls: ['./needs-work-badge.component.scss']
})
export class NeedsWorkBadgeComponent implements OnInit {
@Input() needsWorkInput: NeedsWorkInput;
@Input() needsWorkInput: FileStatusWrapper | ProjectWrapper;
constructor(public appStateService: AppStateService) {}
constructor(public appStateService: AppStateService, public permissionsService: PermissionsService) {}
ngOnInit(): void {}
reanalysisRequired() {
if (this.needsWorkInput instanceof ProjectWrapper) {
return this.permissionsService.projectReanalysisRequired(this.needsWorkInput);
} else {
return this.permissionsService.fileRequiresReanalysis(this.needsWorkInput);
}
}
}

View File

@ -12,7 +12,7 @@
</div>
<div class="flex-1 filename page-title">
<span *ngIf="permissionsService.fileRequiresReanalysis()" class="pill" translate="project-overview.new-rule.label"></span>
<!-- <span *ngIf="permissionsService.fileRequiresReanalysis()" class="pill" translate="project-overview.new-rule.label"></span>-->
<span *ngIf="!permissionsService.canPerformAnnotationActions()" class="pill" translate="readonly-pill"></span>&nbsp;<span>{{
appStateService.activeFile.filename
}}</span>

View File

@ -167,10 +167,11 @@ export class ProjectListingScreenComponent implements OnInit {
// Needs work
entry.files.forEach((file) => {
if (file.hintsOnly) allDistinctNeedsWork.add('hint');
if (file.hasRedactions) allDistinctNeedsWork.add('redaction');
if (file.hasRequests) allDistinctNeedsWork.add('suggestion');
if (file.hasNone) allDistinctNeedsWork.add('none');
if (this.permissionsService.fileRequiresReanalysis(file)) allDistinctNeedsWork.add('analysis');
if (entry.hintsOnly) allDistinctNeedsWork.add('hint');
if (entry.hasRedactions) allDistinctNeedsWork.add('redaction');
if (entry.hasRequests) allDistinctNeedsWork.add('suggestion');
if (entry.hasNone) allDistinctNeedsWork.add('none');
});
});
@ -226,7 +227,7 @@ export class ProjectListingScreenComponent implements OnInit {
{ values: this.statusFilters, checker: projectStatusChecker },
{ values: this.peopleFilters, checker: projectMemberChecker },
{ values: this.dueDateFilters, checker: dueDateChecker },
{ values: this.needsWorkFilters, checker: annotationFilterChecker, matchAll: true }
{ values: this.needsWorkFilters, checker: annotationFilterChecker, matchAll: true, checkerArgs: this.permissionsService }
];
this.detailsContainerFilters = {
statusFilters: this.statusFilters.map((f) => ({ ...f }))

View File

@ -53,7 +53,7 @@
<div class="mt-24 legend" *ngIf="hasFiles">
<div *ngFor="let filter of filters.needsWorkFilters" [class.active]="filter.checked" (click)="toggleFilter('needsWorkFilters', filter.key)">
<redaction-annotation-icon *ngIf="filter.key !== 'none'" [typeValue]="appStateService.getDictionaryTypeValue(filter.key)"></redaction-annotation-icon>
{{ 'project-overview.legend.' + filter.key | translate }}
{{ 'filter.' + filter.key | translate }}
</div>
</div>

View File

@ -122,7 +122,7 @@
<div [class.disabled]="fileStatus.isPending || fileStatus.isProcessing" [class.error]="fileStatus.isError" class="table-item-title">
{{ fileStatus.filename }}
</div>
<span *ngIf="permissionsService.fileRequiresReanalysis(fileStatus)" class="pill" translate="project-overview.new-rule.label"></span>
<!-- <span *ngIf="permissionsService.fileRequiresReanalysis(fileStatus)" class="pill" translate="project-overview.new-rule.label"></span>-->
</div>
</div>

View File

@ -191,6 +191,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
// Needs work
this.appStateService.activeProject.files.forEach((file) => {
if (this.permissionsService.fileRequiresReanalysis(file)) allDistinctNeedsWork.add('analysis');
if (file.hintsOnly) allDistinctNeedsWork.add('hint');
if (file.hasRedactions) allDistinctNeedsWork.add('redaction');
if (file.hasRequests) allDistinctNeedsWork.add('suggestion');
@ -250,7 +251,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
const filters = [
{ values: this.statusFilters, checker: keyChecker('status') },
{ values: this.peopleFilters, checker: keyChecker('currentReviewer') },
{ values: this.needsWorkFilters, checker: annotationFilterChecker, matchAll: true }
{ values: this.needsWorkFilters, checker: annotationFilterChecker, matchAll: true, checkerArgs: this.permissionsService }
];
this.displayedFiles = getFilteredEntities(this.appStateService.activeProject.files, filters);
this.detailsContainerFilters = {

View File

@ -390,6 +390,11 @@ export class AppStateService {
type: 'add',
virtual: true
};
this._dictionaryData['analysis'] = {
hexColor: '#dd4d50',
type: 'analysis',
virtual: true
};
})
);

View File

@ -8,6 +8,7 @@ export class ProjectWrapper {
hintsOnly?: boolean;
hasRedactions?: boolean;
hasRequests?: boolean;
hasNone?: boolean;
allFilesApproved?: boolean;
@ -63,6 +64,7 @@ export class ProjectWrapper {
this.hintsOnly = false;
this.hasRedactions = false;
this.hasRequests = false;
this.hasNone = false;
this.allFilesApproved = true;
this._files.forEach((f) => {
this.hintsOnly = this.hintsOnly || f.hintsOnly;
@ -70,5 +72,6 @@ export class ProjectWrapper {
this.hasRequests = this.hasRequests || f.hasRequests;
this.allFilesApproved = this.allFilesApproved && f.isApproved;
});
this.hasNone = !this.hasRequests && !this.hasRedactions && !this.hintsOnly;
}
}

View File

@ -239,13 +239,7 @@
},
"header": "Project Overview",
"upload-document": "Upload Document",
"no-project": "Requested project: {{projectId}} does not exist! <a href='/ui/projects'>Back to Project Listing. <a/>",
"legend": {
"hint": "Hints only",
"redaction": "Redacted",
"suggestion": "Suggested Redaction",
"none": "No Annotations"
}
"no-project": "Requested project: {{projectId}} does not exist! <a href='/ui/projects'>Back to Project Listing. <a/>"
},
"file-preview": {
"show-redacted-view": "Show Redacted Preview",
@ -317,6 +311,7 @@
"hint": "Hints only",
"redaction": "Redacted",
"suggestion": "Suggested Redaction",
"analysis": "Re-analysis required",
"none": "No Annotations"
},
"annotation-filter": {