reorganized order of icons - removed project and replaced with wrapper where possible

This commit is contained in:
Timo 2020-11-30 12:02:53 +02:00
parent c88194062f
commit f89b316c61
11 changed files with 121 additions and 94 deletions

View File

@ -1,24 +1,5 @@
<div class="file-actions"> <div class="file-actions">
<redaction-circle-button <!-- delete-->
(action)="reanalyseFile($event, fileStatus)"
*ngIf="permissionsService.canReanalyseFile(fileStatus) && screen === 'file-preview'"
tooltip="file-preview.reanalyse-notification"
type="warn"
tooltipClass="warn small"
icon="red:refresh"
>
</redaction-circle-button>
<redaction-circle-button
(action)="reanalyseFile($event, fileStatus)"
*ngIf="permissionsService.canReanalyseFile(fileStatus) && screen === 'project-overview'"
[tooltipPosition]="tooltipPosition"
tooltip="project-overview.reanalyse.action"
icon="red:refresh"
type="dark-bg"
>
</redaction-circle-button>
<redaction-circle-button <redaction-circle-button
(action)="openDeleteFileDialog($event, fileStatus)" (action)="openDeleteFileDialog($event, fileStatus)"
*ngIf="permissionsService.canDeleteFile(fileStatus)" *ngIf="permissionsService.canDeleteFile(fileStatus)"
@ -29,18 +10,7 @@
> >
</redaction-circle-button> </redaction-circle-button>
<redaction-circle-button <!-- assign-->
(action)="downloadFileRedactionReport($event, fileStatus)"
*ngIf="permissionsService.canShowRedactionReportDownloadBtn(fileStatus)"
[tooltipPosition]="tooltipPosition"
[tooltipClass]="'small'"
[tooltip]="fileStatus.isApproved ? 'report.action' : 'report.unavailable-single'"
[disabled]="!fileStatus.isApproved"
icon="red:report"
[type]="buttonType"
>
</redaction-circle-button>
<redaction-circle-button <redaction-circle-button
(action)="assignReviewer($event, fileStatus)" (action)="assignReviewer($event, fileStatus)"
*ngIf="permissionsService.canAssignReviewer(fileStatus) && screen === 'project-overview'" *ngIf="permissionsService.canAssignReviewer(fileStatus) && screen === 'project-overview'"
@ -51,16 +21,7 @@
> >
</redaction-circle-button> </redaction-circle-button>
<redaction-circle-button <!-- file state actions -->
(action)="downloadFile($event, fileStatus)"
*ngIf="permissionsService.canDownloadRedactedFile(fileStatus)"
[tooltipPosition]="tooltipPosition"
tooltip="project-overview.download-redacted-file"
icon="red:download"
[type]="buttonType"
>
</redaction-circle-button>
<redaction-circle-button <redaction-circle-button
(action)="setFileApproved($event, fileStatus)" (action)="setFileApproved($event, fileStatus)"
*ngIf="permissionsService.canApprove(fileStatus)" *ngIf="permissionsService.canApprove(fileStatus)"
@ -100,4 +61,51 @@
[type]="buttonType" [type]="buttonType"
> >
</redaction-circle-button> </redaction-circle-button>
<!-- download report-->
<redaction-circle-button
(action)="downloadFileRedactionReport($event, fileStatus)"
*ngIf="permissionsService.canShowRedactionReportDownloadBtn(fileStatus)"
[tooltipPosition]="tooltipPosition"
[tooltipClass]="'small'"
[tooltip]="fileStatus.isApproved ? 'report.action' : 'report.unavailable-single'"
[disabled]="!fileStatus.isApproved"
icon="red:report"
[type]="buttonType"
>
</redaction-circle-button>
<!-- download redacted file-->
<redaction-circle-button
(action)="downloadFile($event, fileStatus)"
*ngIf="permissionsService.canDownloadRedactedFile(fileStatus)"
[tooltipPosition]="tooltipPosition"
tooltip="project-overview.download-redacted-file"
icon="red:download"
[type]="buttonType"
>
</redaction-circle-button>
<!-- reanalyse file preview -->
<redaction-circle-button
(action)="reanalyseFile($event, fileStatus)"
*ngIf="permissionsService.canReanalyseFile(fileStatus) && screen === 'file-preview'"
[tooltipPosition]="'before'"
tooltip="file-preview.reanalyse-notification"
type="warn"
tooltipClass="warn small"
icon="red:refresh"
>
</redaction-circle-button>
<!-- reanalyse file listing -->
<redaction-circle-button
(action)="reanalyseFile($event, fileStatus)"
*ngIf="permissionsService.canReanalyseFile(fileStatus) && screen === 'project-overview'"
[tooltipPosition]="tooltipPosition"
tooltip="project-overview.reanalyse.action"
icon="red:refresh"
type="dark-bg"
>
</redaction-circle-button>
</div> </div>

View File

@ -49,6 +49,13 @@ export class PermissionsService {
); );
} }
displayReanalyseBtn(project?: ProjectWrapper) {
if (!project) {
project = this._appStateService.activeProject;
}
return this.isManagerAndOwner(project) && project.files.filter((file) => this.fileRequiresReanalysis(file)).length > 0;
}
canReanalyseFile(fileStatus?: FileStatusWrapper) { canReanalyseFile(fileStatus?: FileStatusWrapper) {
if (!fileStatus) { if (!fileStatus) {
fileStatus = this._appStateService.activeFile; fileStatus = this._appStateService.activeFile;
@ -66,7 +73,7 @@ export class PermissionsService {
return fileStatus.currentReviewer === this._userService.userId; return fileStatus.currentReviewer === this._userService.userId;
} }
canDeleteFile(fileStatus?: FileStatusWrapper, project?: Project) { canDeleteFile(fileStatus?: FileStatusWrapper, project?: ProjectWrapper) {
return this.isManagerAndOwner(project) || fileStatus.isUnassigned; return this.isManagerAndOwner(project) || fileStatus.isUnassigned;
} }
@ -110,22 +117,22 @@ export class PermissionsService {
return fileStatus.status === 'UNDER_REVIEW' && this.isReviewerOrOwner(fileStatus); return fileStatus.status === 'UNDER_REVIEW' && this.isReviewerOrOwner(fileStatus);
} }
isManagerAndOwner(project?: Project, user?: UserWrapper) { isManagerAndOwner(project?: ProjectWrapper, user?: UserWrapper) {
if (!user) { if (!user) {
user = this._userService.user; user = this._userService.user;
} }
if (!project) { if (!project) {
project = this._appStateService.activeProject.project; project = this._appStateService.activeProject;
} }
return user.isManager && project.ownerId === user.id; return user.isManager && project.ownerId === user.id;
} }
isProjectMember(project?: Project, user?: UserWrapper) { isProjectMember(project?: ProjectWrapper, user?: UserWrapper) {
if (!user) { if (!user) {
user = this._userService.user; user = this._userService.user;
} }
if (!project) { if (!project) {
project = this._appStateService.activeProject.project; project = this._appStateService.activeProject;
} }
return project.memberIds?.includes(user.id); return project.memberIds?.includes(user.id);
} }
@ -194,6 +201,6 @@ export class PermissionsService {
if (!project) { if (!project) {
project = this._appStateService.activeProject; project = this._appStateService.activeProject;
} }
return project.files.reduce((acc, file) => acc && this.canDeleteFile(file, project.project), true); return project.files.reduce((acc, file) => acc && this.canDeleteFile(file, project), true);
} }
} }

View File

@ -3,6 +3,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Project } from '@redaction/red-ui-http'; import { Project } from '@redaction/red-ui-http';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { AppStateService } from '../../state/app-state.service'; import { AppStateService } from '../../state/app-state.service';
import { ProjectWrapper } from '../../state/model/project.wrapper';
@Component({ @Component({
selector: 'redaction-add-edit-project-dialog', selector: 'redaction-add-edit-project-dialog',
@ -16,7 +17,7 @@ export class AddEditProjectDialogComponent implements OnInit {
private readonly _appStateService: AppStateService, private readonly _appStateService: AppStateService,
private readonly _formBuilder: FormBuilder, private readonly _formBuilder: FormBuilder,
public dialogRef: MatDialogRef<AddEditProjectDialogComponent>, public dialogRef: MatDialogRef<AddEditProjectDialogComponent>,
@Inject(MAT_DIALOG_DATA) public project: Project @Inject(MAT_DIALOG_DATA) public project: ProjectWrapper
) {} ) {}
ngOnInit(): void { ngOnInit(): void {

View File

@ -12,6 +12,7 @@ import { ManualRedactionEntryWrapper } from '../screens/file/model/manual-redact
import { AnnotationWrapper } from '../screens/file/model/annotation.wrapper'; import { AnnotationWrapper } from '../screens/file/model/annotation.wrapper';
import { ManualAnnotationDialogComponent } from './manual-redaction-dialog/manual-annotation-dialog.component'; import { ManualAnnotationDialogComponent } from './manual-redaction-dialog/manual-annotation-dialog.component';
import { ManualAnnotationService } from '../screens/file/service/manual-annotation.service'; import { ManualAnnotationService } from '../screens/file/service/manual-annotation.service';
import { ProjectWrapper } from '../state/model/project.wrapper';
const dialogConfig = { const dialogConfig = {
width: '600px', width: '600px',
@ -124,7 +125,7 @@ export class DialogService {
return ref; return ref;
} }
public openEditProjectDialog($event: MouseEvent, project: Project, cb?: Function): MatDialogRef<AddEditProjectDialogComponent> { public openEditProjectDialog($event: MouseEvent, project: ProjectWrapper, cb?: Function): MatDialogRef<AddEditProjectDialogComponent> {
$event.stopPropagation(); $event.stopPropagation();
const ref = this._dialog.open(AddEditProjectDialogComponent, { const ref = this._dialog.open(AddEditProjectDialogComponent, {
...dialogConfig, ...dialogConfig,
@ -139,7 +140,7 @@ export class DialogService {
return ref; return ref;
} }
public openDeleteProjectDialog($event: MouseEvent, project: Project, cb?: Function): MatDialogRef<ConfirmationDialogComponent> { public openDeleteProjectDialog($event: MouseEvent, project: ProjectWrapper, cb?: Function): MatDialogRef<ConfirmationDialogComponent> {
$event.stopPropagation(); $event.stopPropagation();
const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig); const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig);
ref.afterClosed().subscribe(async (result) => { ref.afterClosed().subscribe(async (result) => {
@ -151,7 +152,7 @@ export class DialogService {
return ref; return ref;
} }
public openAssignProjectMembersAndOwnerDialog($event: MouseEvent, project: Project, cb?: Function): MatDialogRef<AssignOwnerDialogComponent> { public openAssignProjectMembersAndOwnerDialog($event: MouseEvent, project: ProjectWrapper, cb?: Function): MatDialogRef<AssignOwnerDialogComponent> {
$event?.stopPropagation(); $event?.stopPropagation();
const ref = this._dialog.open(AssignOwnerDialogComponent, { const ref = this._dialog.open(AssignOwnerDialogComponent, {
...dialogConfig, ...dialogConfig,

View File

@ -105,7 +105,7 @@
<redaction-status-bar [config]="getProjectStatusConfig(pw)"></redaction-status-bar> <redaction-status-bar [config]="getProjectStatusConfig(pw)"></redaction-status-bar>
<div class="action-buttons"> <div class="action-buttons">
<redaction-circle-button <redaction-circle-button
(action)="openDeleteProjectDialog($event, pw.project)" (action)="openDeleteProjectDialog($event, pw)"
*ngIf="permissionsService.canDeleteProject(pw)" *ngIf="permissionsService.canDeleteProject(pw)"
tooltip="project-listing.delete.action" tooltip="project-listing.delete.action"
type="dark-bg" type="dark-bg"
@ -114,7 +114,7 @@
</redaction-circle-button> </redaction-circle-button>
<redaction-circle-button <redaction-circle-button
(action)="openEditProjectDialog($event, pw.project)" (action)="openEditProjectDialog($event, pw)"
*ngIf="permissionsService.isManager()" *ngIf="permissionsService.isManager()"
tooltip="project-listing.edit.action" tooltip="project-listing.edit.action"
type="dark-bg" type="dark-bg"
@ -123,7 +123,7 @@
</redaction-circle-button> </redaction-circle-button>
<redaction-circle-button <redaction-circle-button
*ngIf="permissionsService.isManagerAndOwner(pw.project) && pw.hasFiles" *ngIf="permissionsService.isManagerAndOwner(pw) && pw.hasFiles"
(action)="downloadRedactionReport($event, pw.project)" (action)="downloadRedactionReport($event, pw.project)"
[tooltip]="pw.allFilesApproved ? 'report.action' : 'report.unavailable'" [tooltip]="pw.allFilesApproved ? 'report.action' : 'report.unavailable'"
[disabled]="!pw.allFilesApproved" [disabled]="!pw.allFilesApproved"
@ -133,7 +133,7 @@
</redaction-circle-button> </redaction-circle-button>
<redaction-circle-button <redaction-circle-button
(action)="openAssignProjectOwnerDialog($event, pw.project)" (action)="openAssignProjectOwnerDialog($event, pw)"
*ngIf="permissionsService.isManager()" *ngIf="permissionsService.isManager()"
tooltip="project-listing.assign.action" tooltip="project-listing.assign.action"
type="dark-bg" type="dark-bg"
@ -142,8 +142,8 @@
</redaction-circle-button> </redaction-circle-button>
<redaction-circle-button <redaction-circle-button
*ngIf="permissionsService.isManagerAndOwner(pw.project) && pw.hasFiles" *ngIf="permissionsService.displayReanalyseBtn(pw)"
(action)="reanalyseProject($event, pw.project)" (action)="reanalyseProject($event, pw)"
tooltip="project-listing.reanalyse.action" tooltip="project-listing.reanalyse.action"
type="dark-bg" type="dark-bg"
icon="red:refresh" icon="red:refresh"

View File

@ -146,18 +146,18 @@ export class ProjectListingScreenComponent implements OnInit, OnDestroy {
}); });
} }
public openDeleteProjectDialog($event: MouseEvent, project: Project) { public openDeleteProjectDialog($event: MouseEvent, project: ProjectWrapper) {
this._dialogService.openDeleteProjectDialog($event, project, () => { this._dialogService.openDeleteProjectDialog($event, project, () => {
this._calculateData(); this._calculateData();
}); });
} }
public downloadRedactionReport($event: MouseEvent, project: Project) { public downloadRedactionReport($event: MouseEvent, project: ProjectWrapper) {
$event.stopPropagation(); $event.stopPropagation();
this.appStateService.downloadRedactionReport(project); this.appStateService.downloadRedactionReport(project);
} }
public openAssignProjectOwnerDialog($event: MouseEvent, project: Project) { public openAssignProjectOwnerDialog($event: MouseEvent, project: ProjectWrapper) {
this._dialogService.openAssignProjectMembersAndOwnerDialog($event, project); this._dialogService.openAssignProjectMembersAndOwnerDialog($event, project);
} }
@ -177,7 +177,7 @@ export class ProjectListingScreenComponent implements OnInit, OnDestroy {
.map((status) => ({ length: obj[status], color: status })); .map((status) => ({ length: obj[status], color: status }));
} }
async reanalyseProject($event: MouseEvent, project: Project) { async reanalyseProject($event: MouseEvent, project: ProjectWrapper) {
$event.stopPropagation(); $event.stopPropagation();
await this.appStateService.reanalyzeProject(project); await this.appStateService.reanalyzeProject(project);
await this.appStateService.loadAllProjects(); await this.appStateService.loadAllProjects();
@ -272,7 +272,7 @@ export class ProjectListingScreenComponent implements OnInit, OnDestroy {
this.displayedProjects = this._filteredProjects.filter((project) => project.name.toLowerCase().includes(value.query.toLowerCase())); this.displayedProjects = this._filteredProjects.filter((project) => project.name.toLowerCase().includes(value.query.toLowerCase()));
} }
openEditProjectDialog($event: MouseEvent, project: Project) { openEditProjectDialog($event: MouseEvent, project: ProjectWrapper) {
this._dialogService.openEditProjectDialog($event, project, () => { this._dialogService.openEditProjectDialog($event, project, () => {
this._calculateData(); this._calculateData();
}); });

View File

@ -45,6 +45,13 @@
tooltipPosition="below" tooltipPosition="below"
icon="red:trash" icon="red:trash"
></redaction-circle-button> ></redaction-circle-button>
<redaction-circle-button
*ngIf="permissionsService.isManagerAndOwner()"
(action)="openAssignProjectMembersDialog()"
tooltip="project-overview.header-actions.assign"
tooltipPosition="below"
icon="red:assign"
></redaction-circle-button>
<redaction-circle-button <redaction-circle-button
*ngIf="permissionsService.isManagerAndOwner()" *ngIf="permissionsService.isManagerAndOwner()"
(action)="downloadRedactionReport($event)" (action)="downloadRedactionReport($event)"
@ -54,11 +61,13 @@
icon="red:report" icon="red:report"
></redaction-circle-button> ></redaction-circle-button>
<redaction-circle-button <redaction-circle-button
*ngIf="permissionsService.isManagerAndOwner()" *ngIf="permissionsService.displayReanalyseBtn()"
(action)="openAssignProjectMembersDialog()" (action)="reanalyseProject()"
tooltip="project-overview.header-actions.assign" [tooltip]="'project-overview.new-rule.toast.actions.reanalyse-all'"
type="warn"
tooltipClass="warn small"
tooltipPosition="below" tooltipPosition="below"
icon="red:assign" icon="red:refresh"
></redaction-circle-button> ></redaction-circle-button>
<redaction-circle-button <redaction-circle-button
class="ml-14" class="ml-14"
@ -82,7 +91,7 @@
<div class="flex red-content-inner"> <div class="flex red-content-inner">
<div class="left-container" [class.extended]="collapsedDetails"> <div class="left-container" [class.extended]="collapsedDetails">
<div class="grid-container"> <div class="grid-container">
<div class="header-item span-4"> <div class="header-item span-7">
<div class="select-all-container"> <div class="select-all-container">
<div <div
(click)="toggleSelectAll()" (click)="toggleSelectAll()"
@ -105,14 +114,6 @@
<redaction-bulk-actions [selectedFileIds]="selectedFileIds" (reload)="bulkActionPerformed()"></redaction-bulk-actions> <redaction-bulk-actions [selectedFileIds]="selectedFileIds" (reload)="bulkActionPerformed()"></redaction-bulk-actions>
</div> </div>
<div class="header-item span-3 justify-end">
<ng-container *ngIf="displayReanalyseBtn">
<strong>
{{ 'project-overview.new-rule.toast.message-project' | translate }}
</strong>
<a (click)="reanalyseProject()" class="reanalyse-link"> {{ 'project-overview.new-rule.toast.actions.reanalyse-all' | translate }}</a>
</ng-container>
</div>
<!-- Table column names--> <!-- Table column names-->
<div class="select-oval-placeholder placeholder-bottom-border"></div> <div class="select-oval-placeholder placeholder-bottom-border"></div>

View File

@ -105,13 +105,6 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
this.selectedFileIds = this.displayedFiles.map((d) => d.fileId).filter((x) => this.selectedFileIds.includes(x)); this.selectedFileIds = this.displayedFiles.map((d) => d.fileId).filter((x) => this.selectedFileIds.includes(x));
} }
get displayReanalyseBtn() {
return !!(
this.permissionsService.isManagerAndOwner() &&
this.appStateService.activeProject.files.filter((file) => this.permissionsService.fileRequiresReanalysis(file)).length
);
}
public reanalyseProject() { public reanalyseProject() {
return this.appStateService.reanalyzeProject().then(() => this.reloadProjects()); return this.appStateService.reanalyzeProject().then(() => this.reloadProjects());
} }
@ -309,11 +302,11 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
} }
public openEditProjectDialog($event: MouseEvent) { public openEditProjectDialog($event: MouseEvent) {
this._dialogService.openEditProjectDialog($event, this.appStateService.activeProject.project); this._dialogService.openEditProjectDialog($event, this.appStateService.activeProject);
} }
public openDeleteProjectDialog($event: MouseEvent) { public openDeleteProjectDialog($event: MouseEvent) {
this._dialogService.openDeleteProjectDialog($event, this.appStateService.activeProject.project, () => { this._dialogService.openDeleteProjectDialog($event, this.appStateService.activeProject, () => {
this._router.navigate(['/ui/projects']); this._router.navigate(['/ui/projects']);
}); });
} }
@ -324,7 +317,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
} }
public openAssignProjectMembersDialog(): void { public openAssignProjectMembersDialog(): void {
this._dialogService.openAssignProjectMembersAndOwnerDialog(null, this.appStateService.activeProject.project, () => { this._dialogService.openAssignProjectMembersAndOwnerDialog(null, this.appStateService.activeProject, () => {
this.reloadProjects(); this.reloadProjects();
}); });
} }

View File

@ -150,7 +150,7 @@ export class AppStateService {
const projects = await this._projectControllerService.getProjects().toPromise(); const projects = await this._projectControllerService.getProjects().toPromise();
if (projects) { if (projects) {
const mappedProjects = projects.map((p) => { const mappedProjects = projects.map((p) => {
return new ProjectWrapper(p, this._getExistingFiles(p)); return new ProjectWrapper(p, this._getExistingFiles(p.projectId));
}); });
for (const project of mappedProjects) { for (const project of mappedProjects) {
@ -162,8 +162,8 @@ export class AppStateService {
} }
} }
private _getExistingFiles(project: Project) { private _getExistingFiles(projectId: string) {
const found = this._appState.projects.find((p) => p.project.projectId === project.projectId); const found = this._appState.projects.find((p) => p.project.projectId === projectId);
return found ? found.files : []; return found ? found.files : [];
} }
@ -226,16 +226,16 @@ export class AppStateService {
return files; return files;
} }
async reanalyzeProject(project?: Project) { async reanalyzeProject(project?: ProjectWrapper) {
if (!project) { if (!project) {
project = this.activeProject.project; project = this.activeProject;
} }
await this._reanalysisControllerService.reanalyzeProject(project.projectId).toPromise(); await this._reanalysisControllerService.reanalyzeProject(project.projectId).toPromise();
} }
downloadRedactionReport(project?: Project) { downloadRedactionReport(project?: ProjectWrapper) {
if (!project) { if (!project) {
project = this.activeProject.project; project = this.activeProject;
} }
this._fileManagementControllerService.downloadRedactionReportForProject(project.projectId, true, 'body').subscribe((data) => { this._fileManagementControllerService.downloadRedactionReportForProject(project.projectId, true, 'body').subscribe((data) => {
saveAs(data, 'redaction-report-' + project.projectName + '.docx'); saveAs(data, 'redaction-report-' + project.projectName + '.docx');
@ -271,7 +271,7 @@ export class AppStateService {
this._appState.activeProjectId = null; this._appState.activeProjectId = null;
} }
deleteProject(project: Project) { deleteProject(project: ProjectWrapper) {
return this._projectControllerService return this._projectControllerService
.deleteProject(project.projectId) .deleteProject(project.projectId)
.toPromise() .toPromise()

View File

@ -20,6 +20,18 @@ export class ProjectWrapper {
this._recomputeFileStatus(); this._recomputeFileStatus();
} }
get projectName() {
return this.project.projectName;
}
get description() {
return this.project.description;
}
get ownerId() {
return this.project.ownerId;
}
get projectId() { get projectId() {
return this.project.projectId; return this.project.projectId;
} }

View File

@ -27,6 +27,10 @@
grid-column-end: span 4; grid-column-end: span 4;
} }
&.span-7 {
grid-column-end: span 7;
}
&.justify-end { &.justify-end {
justify-content: flex-end; justify-content: flex-end;
} }