UI fixes and report download in 3/4 cases
This commit is contained in:
parent
40455e24b6
commit
64ed8265be
@ -95,6 +95,8 @@ import { RulesScreenComponent } from './screens/admin/rules-screen/rules-screen.
|
|||||||
import { WatermarkScreenComponent } from './screens/admin/watermark-screen/watermark-screen.component';
|
import { WatermarkScreenComponent } from './screens/admin/watermark-screen/watermark-screen.component';
|
||||||
import { PdfViewerScreenComponent } from './screens/pdf-viewer-screen/pdf-viewer-screen.component';
|
import { PdfViewerScreenComponent } from './screens/pdf-viewer-screen/pdf-viewer-screen.component';
|
||||||
import { HtmlDebugScreenComponent } from './screens/html-debug-screen/html-debug-screen.component';
|
import { HtmlDebugScreenComponent } from './screens/html-debug-screen/html-debug-screen.component';
|
||||||
|
import { ReportDownloadBtnComponent } from './components/buttons/report-download-btn/report-download-btn.component';
|
||||||
|
import { ProjectListingActionsComponent } from './screens/project-listing-screen/project-listing-actions/project-listing-actions.component';
|
||||||
|
|
||||||
export function HttpLoaderFactory(httpClient: HttpClient) {
|
export function HttpLoaderFactory(httpClient: HttpClient) {
|
||||||
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
|
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
|
||||||
@ -287,7 +289,9 @@ const matImports = [
|
|||||||
RulesScreenComponent,
|
RulesScreenComponent,
|
||||||
WatermarkScreenComponent,
|
WatermarkScreenComponent,
|
||||||
PdfViewerScreenComponent,
|
PdfViewerScreenComponent,
|
||||||
HtmlDebugScreenComponent
|
HtmlDebugScreenComponent,
|
||||||
|
ReportDownloadBtnComponent,
|
||||||
|
ProjectListingActionsComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<div class="file-actions">
|
<div class="file-actions" [class.active]="actionMenuOpen">
|
||||||
<!-- delete-->
|
<!-- delete-->
|
||||||
<redaction-circle-button
|
<redaction-circle-button
|
||||||
(action)="openDeleteFileDialog($event, fileStatus)"
|
(action)="openDeleteFileDialog($event, fileStatus)"
|
||||||
@ -22,17 +22,15 @@
|
|||||||
</redaction-circle-button>
|
</redaction-circle-button>
|
||||||
|
|
||||||
<!-- download report-->
|
<!-- download report-->
|
||||||
<redaction-circle-button
|
<redaction-report-download-btn
|
||||||
(action)="downloadFileRedactionReport($event, fileStatus)"
|
(menuStateChanged)="actionMenuOpen = $event === 'OPEN'"
|
||||||
*ngIf="permissionsService.canShowRedactionReportDownloadBtn(fileStatus)"
|
|
||||||
[disabled]="!fileStatus.isApproved"
|
|
||||||
[tooltipClass]="'small'"
|
[tooltipClass]="'small'"
|
||||||
[tooltipPosition]="tooltipPosition"
|
[tooltipPosition]="tooltipPosition"
|
||||||
[tooltip]="fileStatus.isApproved ? 'report.action' : 'report.unavailable-single'"
|
[file]="fileStatus"
|
||||||
[type]="buttonType"
|
[type]="buttonType"
|
||||||
icon="red:report"
|
[project]="appStateService.activeProject"
|
||||||
>
|
>
|
||||||
</redaction-circle-button>
|
</redaction-report-download-btn>
|
||||||
|
|
||||||
<!-- download redacted file-->
|
<!-- download redacted file-->
|
||||||
<redaction-circle-button
|
<redaction-circle-button
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import { saveAs } from 'file-saver';
|
|||||||
export class FileActionsComponent implements OnInit {
|
export class FileActionsComponent implements OnInit {
|
||||||
@Input() fileStatus: FileStatusWrapper;
|
@Input() fileStatus: FileStatusWrapper;
|
||||||
@Output() actionPerformed = new EventEmitter<string>();
|
@Output() actionPerformed = new EventEmitter<string>();
|
||||||
|
actionMenuOpen: boolean;
|
||||||
|
|
||||||
screen: 'file-preview' | 'project-overview';
|
screen: 'file-preview' | 'project-overview';
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,10 @@
|
|||||||
@import '../../../../assets/styles/red-variables';
|
@import '../../../../assets/styles/red-variables';
|
||||||
|
|
||||||
|
:host {
|
||||||
|
height: 34px;
|
||||||
|
width: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
height: 34px;
|
height: 34px;
|
||||||
width: 34px;
|
width: 34px;
|
||||||
@ -24,6 +29,7 @@ button {
|
|||||||
|
|
||||||
&.warn {
|
&.warn {
|
||||||
background-color: $yellow-2;
|
background-color: $yellow-2;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $yellow-2;
|
background-color: $yellow-2;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
<redaction-circle-button
|
||||||
|
*ngIf="project && permissionsService.isManagerAndOwner(project)"
|
||||||
|
[matMenuTriggerFor]="menu"
|
||||||
|
(click)="openReportMenu($event)"
|
||||||
|
[tooltipClass]="tooltipClass"
|
||||||
|
[tooltipPosition]="tooltipPosition"
|
||||||
|
[type]="type"
|
||||||
|
[tooltip]="isApproved ? 'report.action.label' : 'report.unavailable'"
|
||||||
|
[disabled]="!isApproved"
|
||||||
|
icon="red:report"
|
||||||
|
></redaction-circle-button>
|
||||||
|
|
||||||
|
<mat-menu #menu="matMenu" xPosition="before" (closed)="onMenuClosed()">
|
||||||
|
<div (click)="downloadRedactionReport($event, 'EFSA Template')" mat-menu-item>
|
||||||
|
<div [translate]="'report.action.efsa'"></div>
|
||||||
|
</div>
|
||||||
|
<div (click)="downloadRedactionReport($event, 'Syngenta Template')" mat-menu-item>
|
||||||
|
<div [translate]="'report.action.syngenta'"></div>
|
||||||
|
</div>
|
||||||
|
</mat-menu>
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
|
import { PermissionsService } from '../../../common/service/permissions.service';
|
||||||
|
import { AppStateService } from '../../../state/app-state.service';
|
||||||
|
import { ProjectWrapper } from '../../../state/model/project.wrapper';
|
||||||
|
import { FileStatusWrapper } from '../../../screens/file/model/file-status.wrapper';
|
||||||
|
|
||||||
|
export type MenuState = 'OPEN' | 'CLOSED';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'redaction-report-download-btn',
|
||||||
|
templateUrl: './report-download-btn.component.html',
|
||||||
|
styleUrls: ['./report-download-btn.component.scss']
|
||||||
|
})
|
||||||
|
export class ReportDownloadBtnComponent implements OnInit {
|
||||||
|
@Input() project: ProjectWrapper;
|
||||||
|
@Input() file: FileStatusWrapper;
|
||||||
|
@Input() tooltipPosition: 'above' | 'below' | 'before' | 'after' = 'above';
|
||||||
|
@Input() type: 'default' | 'primary' | 'warn' | 'dark-bg' = 'default';
|
||||||
|
@Input() tooltipClass: string;
|
||||||
|
|
||||||
|
@Output() menuStateChanged = new EventEmitter<MenuState>();
|
||||||
|
|
||||||
|
constructor(public readonly permissionsService: PermissionsService, private readonly _appStateService: AppStateService) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {}
|
||||||
|
|
||||||
|
openReportMenu($event: MouseEvent) {
|
||||||
|
$event.stopPropagation();
|
||||||
|
this.menuStateChanged.emit('OPEN');
|
||||||
|
}
|
||||||
|
|
||||||
|
onMenuClosed() {
|
||||||
|
this.menuStateChanged.emit('CLOSED');
|
||||||
|
}
|
||||||
|
|
||||||
|
get isApproved() {
|
||||||
|
if (this.file) {
|
||||||
|
return this.file.isApproved;
|
||||||
|
} else {
|
||||||
|
return this.project.allFilesApproved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadRedactionReport($event: MouseEvent, template: string) {
|
||||||
|
$event.preventDefault();
|
||||||
|
if (this.file) {
|
||||||
|
this._appStateService.downloadFileRedactionReport(this.file, template);
|
||||||
|
} else {
|
||||||
|
this._appStateService.downloadRedactionReport(this.project, template);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -16,10 +16,10 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="red-input-group required" *ngIf="!project">
|
<div class="red-input-group required">
|
||||||
<mat-form-field floatLabel="always">
|
<mat-form-field floatLabel="always">
|
||||||
<mat-label>{{ 'project-listing.add-edit-dialog.form.template' | translate }}</mat-label>
|
<mat-label>{{ 'project-listing.add-edit-dialog.form.template' | translate }}</mat-label>
|
||||||
<mat-select value="EFSA 1 (Vertebrate Authors)" style="width: 100%;">
|
<mat-select value="EFSA 1 (Vertebrate Authors)" style="width: 100%;" [disabled]="project?.hasFiles">
|
||||||
<mat-option *ngFor="let type of ['EFSA 1 (Vertebrate Authors)']" [value]="type">
|
<mat-option *ngFor="let type of ['EFSA 1 (Vertebrate Authors)']" [value]="type">
|
||||||
{{ type }}
|
{{ type }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
<div class="red-input-group required" *ngIf="!isDictionaryRequest">
|
<div class="red-input-group required" *ngIf="!isDictionaryRequest">
|
||||||
<label translate="manual-annotation.dialog.content.reason"></label>
|
<label translate="manual-annotation.dialog.content.reason"></label>
|
||||||
<mat-select formControlName="reason" class="full-width">
|
<mat-select formControlName="reason" class="full-width" [placeholder]="'manual-annotation.dialog.content.reason-placeholder' | translate">
|
||||||
<mat-option *ngFor="let option of legalOptions" [value]="option">
|
<mat-option *ngFor="let option of legalOptions" [value]="option">
|
||||||
{{ option.label }}
|
{{ option.label }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
|||||||
@ -59,6 +59,7 @@ export class IconsModule {
|
|||||||
'sort-desc',
|
'sort-desc',
|
||||||
'status',
|
'status',
|
||||||
'trash',
|
'trash',
|
||||||
|
'template',
|
||||||
'user',
|
'user',
|
||||||
'check-alt',
|
'check-alt',
|
||||||
'page',
|
'page',
|
||||||
|
|||||||
@ -38,6 +38,10 @@ export class AnnotationWrapper {
|
|||||||
return this.superType === 'ignore';
|
return this.superType === 'ignore';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isFalsePositive() {
|
||||||
|
return this.dictionary === 'false_positive';
|
||||||
|
}
|
||||||
|
|
||||||
get isManual() {
|
get isManual() {
|
||||||
return this.superType === 'manual';
|
return this.superType === 'manual';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,6 +45,10 @@ export class FileDataModel {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (annotation.isFalsePositive && !areDevFeaturesEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (annotation.isReadyForAnalysis && annotation.isApproved) {
|
if (annotation.isReadyForAnalysis && annotation.isApproved) {
|
||||||
//
|
//
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -0,0 +1,48 @@
|
|||||||
|
<redaction-status-bar [config]="getProjectStatusConfig(project)"></redaction-status-bar>
|
||||||
|
<div class="action-buttons" [class.active]="actionMenuOpen">
|
||||||
|
<redaction-circle-button
|
||||||
|
(action)="openDeleteProjectDialog($event, project)"
|
||||||
|
*ngIf="permissionsService.canDeleteProject(project)"
|
||||||
|
tooltip="project-listing.delete.action"
|
||||||
|
type="dark-bg"
|
||||||
|
icon="red:trash"
|
||||||
|
>
|
||||||
|
</redaction-circle-button>
|
||||||
|
|
||||||
|
<redaction-circle-button
|
||||||
|
(action)="openEditProjectDialog($event, project)"
|
||||||
|
*ngIf="permissionsService.isManager()"
|
||||||
|
tooltip="project-listing.edit.action"
|
||||||
|
type="dark-bg"
|
||||||
|
icon="red:edit"
|
||||||
|
>
|
||||||
|
</redaction-circle-button>
|
||||||
|
|
||||||
|
<redaction-report-download-btn (menuStateChanged)="actionMenuOpen = $event === 'OPEN'" [project]="project"> </redaction-report-download-btn>
|
||||||
|
|
||||||
|
<redaction-circle-button
|
||||||
|
(action)="openAssignProjectOwnerDialog($event, project)"
|
||||||
|
*ngIf="permissionsService.isManager()"
|
||||||
|
tooltip="project-listing.assign.action"
|
||||||
|
type="dark-bg"
|
||||||
|
icon="red:assign"
|
||||||
|
>
|
||||||
|
</redaction-circle-button>
|
||||||
|
|
||||||
|
<redaction-circle-button
|
||||||
|
*ngIf="permissionsService.displayReanalyseBtn(project)"
|
||||||
|
(action)="reanalyseProject($event, project)"
|
||||||
|
tooltip="project-listing.reanalyse.action"
|
||||||
|
type="dark-bg"
|
||||||
|
icon="red:refresh"
|
||||||
|
>
|
||||||
|
</redaction-circle-button>
|
||||||
|
|
||||||
|
<redaction-circle-button
|
||||||
|
(action)="downloadRedactedFiles($event, project)"
|
||||||
|
*ngIf="canDownloadRedactedFiles(project)"
|
||||||
|
tooltip="project-listing.download-files.action"
|
||||||
|
type="dark-bg"
|
||||||
|
icon="red:download"
|
||||||
|
></redaction-circle-button>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
|
import { PermissionsService } from '../../../common/service/permissions.service';
|
||||||
|
import { ProjectWrapper } from '../../../state/model/project.wrapper';
|
||||||
|
import { StatusSorter } from '../../../common/sorters/status-sorter';
|
||||||
|
import { download } from '../../../utils/file-download-utils';
|
||||||
|
import { computerize } from '../../../utils/functions';
|
||||||
|
import { FileManagementControllerService } from '@redaction/red-ui-http';
|
||||||
|
import { AppStateService } from '../../../state/app-state.service';
|
||||||
|
import { DialogService } from '../../../dialogs/dialog.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'redaction-project-listing-actions',
|
||||||
|
templateUrl: './project-listing-actions.component.html',
|
||||||
|
styleUrls: ['./project-listing-actions.component.scss']
|
||||||
|
})
|
||||||
|
export class ProjectListingActionsComponent implements OnInit {
|
||||||
|
@Input() project: ProjectWrapper;
|
||||||
|
@Output() actionPerformed = new EventEmitter();
|
||||||
|
actionMenuOpen: boolean = false;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public readonly permissionsService: PermissionsService,
|
||||||
|
public readonly appStateService: AppStateService,
|
||||||
|
private readonly _dialogService: DialogService,
|
||||||
|
private readonly _fileManagementControllerService: FileManagementControllerService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {}
|
||||||
|
|
||||||
|
public openAssignProjectOwnerDialog($event: MouseEvent, project: ProjectWrapper) {
|
||||||
|
this._dialogService.openAssignProjectMembersAndOwnerDialog($event, project);
|
||||||
|
}
|
||||||
|
|
||||||
|
public openDeleteProjectDialog($event: MouseEvent, project: ProjectWrapper) {
|
||||||
|
this._dialogService.openDeleteProjectDialog($event, project, () => {
|
||||||
|
this.actionPerformed.emit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
openEditProjectDialog($event: MouseEvent, project: ProjectWrapper) {
|
||||||
|
this._dialogService.openEditProjectDialog($event, project, () => {
|
||||||
|
this.actionPerformed.emit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async reanalyseProject($event: MouseEvent, project: ProjectWrapper) {
|
||||||
|
$event.stopPropagation();
|
||||||
|
await this.appStateService.reanalyzeProject(project);
|
||||||
|
await this.appStateService.loadAllProjects();
|
||||||
|
this.actionPerformed.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download Files
|
||||||
|
public downloadRedactedFiles($event: MouseEvent, project: ProjectWrapper) {
|
||||||
|
$event.stopPropagation();
|
||||||
|
this._fileManagementControllerService
|
||||||
|
.downloadRedactedFiles({ fileIds: project.files.map((file) => file.fileId) }, project.projectId, false, 'response')
|
||||||
|
.subscribe((data) => {
|
||||||
|
download(data, 'redacted_files_' + computerize(project.name) + '.zip');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public canDownloadRedactedFiles(project: ProjectWrapper) {
|
||||||
|
return project.files.reduce((acc, file) => acc && this.permissionsService.canDownloadRedactedFile(file), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getProjectStatusConfig(pw: ProjectWrapper) {
|
||||||
|
const obj = pw.files.reduce((acc, file) => {
|
||||||
|
const status = file.status;
|
||||||
|
if (!acc[status]) {
|
||||||
|
acc[status] = 1;
|
||||||
|
} else {
|
||||||
|
acc[status]++;
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
return Object.keys(obj)
|
||||||
|
.sort((a, b) => StatusSorter[a] - StatusSorter[b])
|
||||||
|
.map((status) => ({ length: obj[status], color: status }));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -105,62 +105,7 @@
|
|||||||
<redaction-initials-avatar [userId]="pw.project.ownerId" [withName]="true"></redaction-initials-avatar>
|
<redaction-initials-avatar [userId]="pw.project.ownerId" [withName]="true"></redaction-initials-avatar>
|
||||||
</div>
|
</div>
|
||||||
<div class="status-container">
|
<div class="status-container">
|
||||||
<redaction-status-bar [config]="getProjectStatusConfig(pw)"></redaction-status-bar>
|
<redaction-project-listing-actions [project]="pw" (actionPerformed)="actionPerformed(pw)"></redaction-project-listing-actions>
|
||||||
<div class="action-buttons">
|
|
||||||
<redaction-circle-button
|
|
||||||
(action)="openDeleteProjectDialog($event, pw)"
|
|
||||||
*ngIf="permissionsService.canDeleteProject(pw)"
|
|
||||||
tooltip="project-listing.delete.action"
|
|
||||||
type="dark-bg"
|
|
||||||
icon="red:trash"
|
|
||||||
>
|
|
||||||
</redaction-circle-button>
|
|
||||||
|
|
||||||
<redaction-circle-button
|
|
||||||
(action)="openEditProjectDialog($event, pw)"
|
|
||||||
*ngIf="permissionsService.isManager()"
|
|
||||||
tooltip="project-listing.edit.action"
|
|
||||||
type="dark-bg"
|
|
||||||
icon="red:edit"
|
|
||||||
>
|
|
||||||
</redaction-circle-button>
|
|
||||||
|
|
||||||
<redaction-circle-button
|
|
||||||
*ngIf="permissionsService.isManagerAndOwner(pw) && pw.hasFiles"
|
|
||||||
(action)="downloadRedactionReport($event, pw.project)"
|
|
||||||
[tooltip]="pw.allFilesApproved ? 'report.action' : 'report.unavailable'"
|
|
||||||
[disabled]="!pw.allFilesApproved"
|
|
||||||
type="dark-bg"
|
|
||||||
icon="red:report"
|
|
||||||
>
|
|
||||||
</redaction-circle-button>
|
|
||||||
|
|
||||||
<redaction-circle-button
|
|
||||||
(action)="openAssignProjectOwnerDialog($event, pw)"
|
|
||||||
*ngIf="permissionsService.isManager()"
|
|
||||||
tooltip="project-listing.assign.action"
|
|
||||||
type="dark-bg"
|
|
||||||
icon="red:assign"
|
|
||||||
>
|
|
||||||
</redaction-circle-button>
|
|
||||||
|
|
||||||
<redaction-circle-button
|
|
||||||
*ngIf="permissionsService.displayReanalyseBtn(pw)"
|
|
||||||
(action)="reanalyseProject($event, pw)"
|
|
||||||
tooltip="project-listing.reanalyse.action"
|
|
||||||
type="dark-bg"
|
|
||||||
icon="red:refresh"
|
|
||||||
>
|
|
||||||
</redaction-circle-button>
|
|
||||||
|
|
||||||
<redaction-circle-button
|
|
||||||
(action)="downloadRedactedFiles($event, pw)"
|
|
||||||
*ngIf="canDownloadRedactedFiles(pw)"
|
|
||||||
tooltip="project-listing.download-files.action"
|
|
||||||
type="dark-bg"
|
|
||||||
icon="red:download"
|
|
||||||
></redaction-circle-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="scrollbar-placeholder"></div>
|
<div class="scrollbar-placeholder"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { FileManagementControllerService, Project } from '@redaction/red-ui-http
|
|||||||
import { AppStateService } from '../../state/app-state.service';
|
import { AppStateService } from '../../state/app-state.service';
|
||||||
import { UserService } from '../../user/user.service';
|
import { UserService } from '../../user/user.service';
|
||||||
import { DoughnutChartConfig } from '../../components/simple-doughnut-chart/simple-doughnut-chart.component';
|
import { DoughnutChartConfig } from '../../components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||||
import { computerize, groupBy, humanize } from '../../utils/functions';
|
import { groupBy, humanize } from '../../utils/functions';
|
||||||
import { DialogService } from '../../dialogs/dialog.service';
|
import { DialogService } from '../../dialogs/dialog.service';
|
||||||
import { FilterModel } from '../../common/filter/model/filter.model';
|
import { FilterModel } from '../../common/filter/model/filter.model';
|
||||||
import {
|
import {
|
||||||
@ -25,7 +25,6 @@ import { StatusSorter } from '../../common/sorters/status-sorter';
|
|||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
import { debounce } from '../../utils/debounce';
|
import { debounce } from '../../utils/debounce';
|
||||||
import { download } from '../../utils/file-download-utils';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-project-listing-screen',
|
selector: 'redaction-project-listing-screen',
|
||||||
@ -37,6 +36,7 @@ export class ProjectListingScreenComponent implements OnInit, OnDestroy {
|
|||||||
public documentsChartData: DoughnutChartConfig[] = [];
|
public documentsChartData: DoughnutChartConfig[] = [];
|
||||||
|
|
||||||
public searchForm: FormGroup;
|
public searchForm: FormGroup;
|
||||||
|
public actionMenuOpen: boolean;
|
||||||
|
|
||||||
public statusFilters: FilterModel[];
|
public statusFilters: FilterModel[];
|
||||||
public peopleFilters: FilterModel[];
|
public peopleFilters: FilterModel[];
|
||||||
@ -153,44 +153,10 @@ export class ProjectListingScreenComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public openDeleteProjectDialog($event: MouseEvent, project: ProjectWrapper) {
|
|
||||||
this._dialogService.openDeleteProjectDialog($event, project, () => {
|
|
||||||
this._calculateData();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public downloadRedactionReport($event: MouseEvent, project: ProjectWrapper) {
|
|
||||||
$event.stopPropagation();
|
|
||||||
this.appStateService.downloadRedactionReport(project);
|
|
||||||
}
|
|
||||||
|
|
||||||
public openAssignProjectOwnerDialog($event: MouseEvent, project: ProjectWrapper) {
|
public openAssignProjectOwnerDialog($event: MouseEvent, project: ProjectWrapper) {
|
||||||
this._dialogService.openAssignProjectMembersAndOwnerDialog($event, project);
|
this._dialogService.openAssignProjectMembersAndOwnerDialog($event, project);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getProjectStatusConfig(pw: ProjectWrapper) {
|
|
||||||
const obj = pw.files.reduce((acc, file) => {
|
|
||||||
const status = file.status;
|
|
||||||
if (!acc[status]) {
|
|
||||||
acc[status] = 1;
|
|
||||||
} else {
|
|
||||||
acc[status]++;
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
return Object.keys(obj)
|
|
||||||
.sort((a, b) => StatusSorter[a] - StatusSorter[b])
|
|
||||||
.map((status) => ({ length: obj[status], color: status }));
|
|
||||||
}
|
|
||||||
|
|
||||||
async reanalyseProject($event: MouseEvent, project: ProjectWrapper) {
|
|
||||||
$event.stopPropagation();
|
|
||||||
await this.appStateService.reanalyzeProject(project);
|
|
||||||
await this.appStateService.loadAllProjects();
|
|
||||||
this._calculateData();
|
|
||||||
}
|
|
||||||
|
|
||||||
private _computeAllFilters() {
|
private _computeAllFilters() {
|
||||||
const allDistinctFileStatus = new Set<string>();
|
const allDistinctFileStatus = new Set<string>();
|
||||||
const allDistinctPeople = new Set<string>();
|
const allDistinctPeople = new Set<string>();
|
||||||
@ -284,23 +250,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: ProjectWrapper) {
|
actionPerformed(pw: ProjectWrapper) {
|
||||||
this._dialogService.openEditProjectDialog($event, project, () => {
|
this._calculateData();
|
||||||
this._calculateData();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Download Files
|
|
||||||
public downloadRedactedFiles($event: MouseEvent, project: ProjectWrapper) {
|
|
||||||
$event.stopPropagation();
|
|
||||||
this._fileManagementControllerService
|
|
||||||
.downloadRedactedFiles({ fileIds: project.files.map((file) => file.fileId) }, project.projectId, false, 'response')
|
|
||||||
.subscribe((data) => {
|
|
||||||
download(data, 'redacted_files_' + computerize(project.name) + '.zip');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public canDownloadRedactedFiles(project: ProjectWrapper) {
|
|
||||||
return project.files.reduce((acc, file) => acc && this.permissionsService.canDownloadRedactedFile(file), true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,6 +80,10 @@
|
|||||||
'project-overview.project-details.stats.due-date' | translate: { date: appStateService.activeProject.project.dueDate | date: 'd MMM. yyyy' }
|
'project-overview.project-details.stats.due-date' | translate: { date: appStateService.activeProject.project.dueDate | date: 'd MMM. yyyy' }
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<mat-icon svgIcon="red:template"></mat-icon>
|
||||||
|
<span>{{ 'EFSA 1 (Vertebrate Authors)' }} </span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-32" *ngIf="!!appStateService.activeProject.project.description">
|
<div class="mt-32" *ngIf="!!appStateService.activeProject.project.description">
|
||||||
|
|||||||
@ -57,14 +57,9 @@
|
|||||||
tooltipPosition="below"
|
tooltipPosition="below"
|
||||||
icon="red:assign"
|
icon="red:assign"
|
||||||
></redaction-circle-button>
|
></redaction-circle-button>
|
||||||
<redaction-circle-button
|
|
||||||
*ngIf="permissionsService.isManagerAndOwner()"
|
<redaction-report-download-btn [project]="appStateService.activeProject"> </redaction-report-download-btn>
|
||||||
(action)="downloadRedactionReport($event)"
|
|
||||||
[tooltip]="appStateService.activeProject.allFilesApproved ? 'report.action' : 'report.unavailable'"
|
|
||||||
[disabled]="!appStateService.activeProject.allFilesApproved"
|
|
||||||
tooltipPosition="below"
|
|
||||||
icon="red:report"
|
|
||||||
></redaction-circle-button>
|
|
||||||
<redaction-circle-button
|
<redaction-circle-button
|
||||||
(action)="downloadRedactedFiles()"
|
(action)="downloadRedactedFiles()"
|
||||||
*ngIf="canDownloadRedactedFiles"
|
*ngIf="canDownloadRedactedFiles"
|
||||||
|
|||||||
@ -319,11 +319,6 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public downloadRedactionReport($event: MouseEvent): void {
|
|
||||||
$event.stopPropagation();
|
|
||||||
this.appStateService.downloadRedactionReport();
|
|
||||||
}
|
|
||||||
|
|
||||||
public openAssignProjectMembersDialog(): void {
|
public openAssignProjectMembersDialog(): void {
|
||||||
this._dialogService.openAssignProjectMembersAndOwnerDialog(null, this.appStateService.activeProject, () => {
|
this._dialogService.openAssignProjectMembersAndOwnerDialog(null, this.appStateService.activeProject, () => {
|
||||||
this.reloadProjects();
|
this.reloadProjects();
|
||||||
|
|||||||
@ -267,7 +267,7 @@ export class AppStateService {
|
|||||||
await this._reanalysisControllerService.reanalyzeProject(project.projectId).toPromise();
|
await this._reanalysisControllerService.reanalyzeProject(project.projectId).toPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadRedactionReport(project?: ProjectWrapper) {
|
downloadRedactionReport(project?: ProjectWrapper, template?: string) {
|
||||||
if (!project) {
|
if (!project) {
|
||||||
project = this.activeProject;
|
project = this.activeProject;
|
||||||
}
|
}
|
||||||
@ -339,7 +339,9 @@ export class AppStateService {
|
|||||||
return foundProject.project;
|
return foundProject.project;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this._notificationService.showToastNotification(
|
this._notificationService.showToastNotification(
|
||||||
this._translateService.instant('projects.add-edit-dialog.errors.save'),
|
this._translateService.instant(
|
||||||
|
error.status === 409 ? 'projects.add-edit-dialog.errors.project-already-exists' : 'projects.add-edit-dialog.errors.generic'
|
||||||
|
),
|
||||||
null,
|
null,
|
||||||
NotificationType.ERROR
|
NotificationType.ERROR
|
||||||
);
|
);
|
||||||
@ -384,7 +386,7 @@ export class AppStateService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadFileRedactionReport(file?: FileStatusWrapper) {
|
downloadFileRedactionReport(file?: FileStatusWrapper, template?: string) {
|
||||||
if (!file) {
|
if (!file) {
|
||||||
file = this.activeFile;
|
file = this.activeFile;
|
||||||
}
|
}
|
||||||
@ -407,6 +409,7 @@ export class AppStateService {
|
|||||||
tap((typesResponse) => {
|
tap((typesResponse) => {
|
||||||
for (const type of typesResponse.types) {
|
for (const type of typesResponse.types) {
|
||||||
this._dictionaryData[type.type] = type;
|
this._dictionaryData[type.type] = type;
|
||||||
|
this._dictionaryData[type.type].virtual = type.type === 'false_positive';
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@ -67,7 +67,11 @@
|
|||||||
"report": {
|
"report": {
|
||||||
"unavailable": "Redaction report is only available once all files have been approved.",
|
"unavailable": "Redaction report is only available once all files have been approved.",
|
||||||
"unavailable-single": "Redaction report is only available once this file has been approved.",
|
"unavailable-single": "Redaction report is only available once this file has been approved.",
|
||||||
"action": "Download Redaction Report"
|
"action": {
|
||||||
|
"label": "Download Redaction Report",
|
||||||
|
"efsa": "Download with EFSA Template",
|
||||||
|
"syngenta": "Download with Syngenta Template"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"project-listing": {
|
"project-listing": {
|
||||||
"search": "Project name...",
|
"search": "Project name...",
|
||||||
@ -114,6 +118,10 @@
|
|||||||
"due-date": "Due Date",
|
"due-date": "Due Date",
|
||||||
"template": "Project Template"
|
"template": "Project Template"
|
||||||
},
|
},
|
||||||
|
"errors": {
|
||||||
|
"project-already-exists": "Project with this name already exists!",
|
||||||
|
"generic": "Failed to save project"
|
||||||
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
"save-and-add-members": "Save and Edit Team"
|
"save-and-add-members": "Save and Edit Team"
|
||||||
@ -469,6 +477,7 @@
|
|||||||
"rectangle": "Custom Rectangle",
|
"rectangle": "Custom Rectangle",
|
||||||
"dictionary": "Dictionary",
|
"dictionary": "Dictionary",
|
||||||
"reason": "Reason",
|
"reason": "Reason",
|
||||||
|
"reason-placeholder": "Select a reason ...",
|
||||||
"legalBasis": "Legal Basis",
|
"legalBasis": "Legal Basis",
|
||||||
"comment": "Comment"
|
"comment": "Comment"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,32 @@
|
|||||||
|
<svg id="Capa_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
|
||||||
|
width="475.092px" height="475.092px" viewBox="0 0 475.092 475.092"
|
||||||
|
style="enable-background:new 0 0 475.092 475.092;"
|
||||||
|
xml:space="preserve">
|
||||||
|
<g fill="#283241">
|
||||||
|
<path d="M442.822,209.562c1.715-6.283,2.57-12.847,2.57-19.702c0-14.655-3.621-28.361-10.852-41.112
|
||||||
|
c0.567-3.995,0.855-8.088,0.855-12.275c0-19.223-5.716-36.162-17.132-50.819v-1.427c0.191-26.075-7.946-46.632-24.414-61.669
|
||||||
|
C377.387,7.521,355.831,0,329.186,0h-31.977c-19.985,0-39.02,2.093-57.102,6.28c-18.086,4.189-39.304,10.468-63.666,18.842
|
||||||
|
c-22.08,7.616-35.211,11.422-39.399,11.422H54.821c-10.088,0-18.702,3.567-25.84,10.704C21.845,54.387,18.276,63,18.276,73.085
|
||||||
|
v182.728c0,10.089,3.566,18.698,10.705,25.837c7.142,7.139,15.752,10.705,25.84,10.705h78.228
|
||||||
|
c6.849,4.572,19.889,19.324,39.113,44.255c11.231,14.661,21.416,26.741,30.551,36.265c3.612,3.997,6.564,10.089,8.848,18.271
|
||||||
|
c2.284,8.186,3.949,16.228,4.998,24.126c1.047,7.898,3.475,16.516,7.281,25.837c3.806,9.329,8.944,17.139,15.415,23.422
|
||||||
|
c7.423,7.043,15.985,10.561,25.697,10.561c15.988,0,30.361-3.087,43.112-9.274c12.754-6.184,22.463-15.845,29.126-28.981
|
||||||
|
c6.663-12.943,9.996-30.646,9.996-53.103c0-17.702-4.568-35.974-13.702-54.819h50.244c19.801,0,36.925-7.23,51.394-21.7
|
||||||
|
c14.469-14.462,21.693-31.497,21.693-51.103C456.809,239.165,452.15,223.652,442.822,209.562z M85.942,104.219
|
||||||
|
c-3.616,3.615-7.898,5.424-12.847,5.424c-4.95,0-9.233-1.805-12.85-5.424c-3.615-3.621-5.424-7.898-5.424-12.851
|
||||||
|
c0-4.948,1.809-9.231,5.424-12.847c3.621-3.617,7.9-5.424,12.85-5.424c4.949,0,9.231,1.807,12.847,5.424
|
||||||
|
c3.617,3.616,5.426,7.898,5.426,12.847C91.368,96.317,89.56,100.598,85.942,104.219z M409.135,281.377
|
||||||
|
c-7.42,7.33-15.886,10.992-25.413,10.992H283.227c0,11.04,4.564,26.217,13.698,45.535c9.138,19.321,13.71,34.598,13.71,45.829
|
||||||
|
c0,18.647-3.046,32.449-9.134,41.395c-6.092,8.949-18.274,13.422-36.546,13.422c-4.951-4.948-8.572-13.045-10.854-24.276
|
||||||
|
c-2.276-11.225-5.185-23.168-8.706-35.83c-3.519-12.655-9.18-23.079-16.984-31.266c-4.184-4.373-11.516-13.038-21.982-25.98
|
||||||
|
c-0.761-0.951-2.952-3.806-6.567-8.562c-3.614-4.757-6.613-8.658-8.992-11.703c-2.38-3.046-5.664-7.091-9.851-12.136
|
||||||
|
c-4.189-5.044-7.995-9.232-11.422-12.565c-3.427-3.327-7.089-6.708-10.992-10.137c-3.901-3.426-7.71-5.996-11.421-7.707
|
||||||
|
c-3.711-1.711-7.089-2.566-10.135-2.566h-9.136V73.092h9.136c2.474,0,5.47-0.282,8.993-0.854c3.518-0.571,6.658-1.192,9.419-1.858
|
||||||
|
c2.76-0.666,6.377-1.713,10.849-3.14c4.476-1.425,7.804-2.522,9.994-3.283c2.19-0.763,5.568-1.951,10.138-3.571
|
||||||
|
c4.57-1.615,7.33-2.613,8.28-2.996c40.159-13.894,72.708-20.839,97.648-20.839h36.542c16.563,0,29.506,3.899,38.828,11.704
|
||||||
|
c9.328,7.804,13.989,19.795,13.989,35.975c0,4.949-0.479,10.279-1.423,15.987c5.708,3.046,10.231,8.042,13.559,14.987
|
||||||
|
c3.333,6.945,4.996,13.944,4.996,20.985c0,7.039-1.711,13.61-5.141,19.701c10.089,9.517,15.126,20.839,15.126,33.974
|
||||||
|
c0,4.759-0.948,10.039-2.847,15.846c-1.899,5.808-4.285,10.327-7.139,13.562c6.091,0.192,11.184,4.665,15.276,13.422
|
||||||
|
c4.093,8.754,6.14,16.468,6.14,23.127C420.277,265.525,416.561,274.043,409.135,281.377z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.0 KiB |
7
apps/red-ui/src/assets/icons/general/template.svg
Normal file
7
apps/red-ui/src/assets/icons/general/template.svg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<svg id="Capa_1" enable-background="new 0 0 508 508" height="512" viewBox="0 0 508 508" width="512"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g fill="currentColor">
|
||||||
|
<path
|
||||||
|
d="m264 459c0 5.52-4.49 10-10 10s-10-4.48-10-10c0-5.51 4.49-10 10-10s10 4.49 10 10zm-184.374-246c-5.523 0-10 4.477-10 10s4.477 10 10 10h20.374v100c0 5.523 4.477 10 10 10s10-4.477 10-10v-100h20.374c5.523 0 10-4.477 10-10s-4.477-10-10-10zm346.374-78c23.159 0 42 18.841 42 42s-18.841 42-42 42-42-18.841-42-42 18.841-42 42-42zm-22 42c0 12.131 9.869 22 22 22s22-9.869 22-22-9.869-22-22-22-22 9.869-22 22zm-6 292h-99c-5.731 0-10.359-4.847-9.978-10.669.348-5.315 5.003-9.331 10.329-9.331h88.649v-20h-74c-16.569 0-30-13.431-30-30v-26c0-16.569 13.431-30 30-30h74v-42h-138c-5.523 0-10-4.477-10-10v-186c0-5.523 4.477-10 10-10h138v-26c0-5.523-4.477-10-10-10h-248c-5.523 0-10 4.477-10 10v99h90c5.523 0 10 4.477 10 10v200c0 5.523-4.477 10-10 10h-90v61h88.649c5.326 0 9.981 4.016 10.329 9.331.381 5.822-4.247 10.669-9.978 10.669h-99c-5.523 0-10-4.477-10-10v-71h-90c-5.523 0-10-4.477-10-10v-200c0-5.523 4.477-10 10-10h90v-99c0-16.569 13.431-30 30-30h248c16.569 0 30 13.431 30 30v26h90c5.523 0 10 4.477 10 10v186c0 5.523-4.477 10-10 10h-90v42h26c16.569 0 30 13.431 30 30v26c0 16.569-13.431 30-30 30h-26v30c0 5.523-4.477 10-10 10zm-198-281h-180v180h180zm234 175h-120c-5.514 0-10 4.486-10 10v26c0 5.514 4.486 10 10 10h120c5.514 0 10-4.486 10-10v-26c0-5.514-4.486-10-10-10zm-174-82h154.895l-92.318-86.297c-11.488-10.738-29.486-10.74-40.973 0l-21.604 20.196zm228-166h-228v72.521l7.946-7.428c19.147-17.898 49.144-17.897 68.289 0l107.948 100.907h43.817z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
@ -81,6 +81,12 @@
|
|||||||
mat-icon {
|
mat-icon {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
display: flex;
|
||||||
|
// compensate for scroll
|
||||||
|
padding-right: 23px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user