red-ui/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html
2020-10-30 12:22:05 +02:00

383 lines
15 KiB
HTML

<div
*ngIf="!appStateService.activeProject"
[innerHTML]="
'project-overview.no-project.label' | translate: { projectId: activeProject.projectId }
"
class="heading-l"
></div>
<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>
</div>
<button
(click)="fileInput.click()"
color="primary"
mat-flat-button
translate="project-overview.upload-document.label"
></button>
<input
#fileInput
(change)="uploadFiles($event.target.files)"
class="file-upload-input"
multiple="true"
type="file"
/>
</div>
<div class="flex red-content-inner">
<div class="left-container">
<div class="table-header">
<div class="select-all-container">
<div
class="select-oval"
[class.active]="areAllFilesSelected()"
(click)="toggleSelectAll()"
></div>
<span class="all-caps-label">
{{
'project-overview.table-header.title.label'
| translate
: { length: appStateService.activeProject?.files.length || 0 }
}}
</span>
</div>
<div class="actions">
<div translate="project-overview.table-header.bulk-select.label"></div>
<mat-form-field appearance="none" class="red-select">
<mat-select [(ngModel)]="sortingOption" panelClass="red-select-panel">
<mat-option *ngFor="let option of sortingOptions" [value]="option">
{{ option.label | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
<div class="grid-container">
<!-- Table column names-->
<div class="table-col-name"></div>
<div class="table-col-name">
<span
class="small-label"
translate="project-overview.table-col-names.name.label"
></span>
</div>
<div class="table-col-name pointer" (click)="toggleSortByAddedOn()">
<span
class="small-label"
translate="project-overview.table-col-names.added-on.label"
></span>
<div class="sort-arrows-container">
<mat-icon
svgIcon="red:arrow-up"
[color]="sortingOption === sortingOptions[0] ? 'primary' : 'currentColor'"
></mat-icon>
<mat-icon
svgIcon="red:arrow-down"
[color]="sortingOption === sortingOptions[1] ? 'primary' : 'currentColor'"
></mat-icon>
</div>
</div>
<div class="table-col-name">
<span
class="small-label"
translate="project-overview.table-col-names.needs-work.label"
></span>
</div>
<div class="table-col-name">
<span
class="small-label"
translate="project-overview.table-col-names.assigned-to.label"
></span>
</div>
<div class="table-col-name flex-end">
<span
class="small-label"
translate="project-overview.table-col-names.status.label"
></span>
</div>
<div
class="table-item"
[class.pointer]="canOpenFile(fileStatus)"
*ngFor="
let fileStatus of appStateService.activeProject.files
| sortBy: sortingOption.order:sortingOption.column;
trackBy: fileId
"
[routerLink]="
canOpenFile(fileStatus)
? ['/ui/projects/' + activeProject.projectId + '/file/' + fileStatus.fileId]
: []
"
>
<div class="pr-0">
<div
class="select-oval"
[class.active]="isFileSelected(fileStatus)"
(click)="toggleFileSelected($event, fileStatus)"
></div>
</div>
<div [matTooltip]="'[' + fileStatus.status + '] ' + fileStatus.filename">
<div class="filename-wrapper">
<div
class="table-item-title"
[class.disabled]="isPending(fileStatus) || isProcessing(fileStatus)"
[class.error]="isError(fileStatus)"
>
{{ fileStatus.filename }}
</div>
<span
*ngIf="fileStatus.newRule"
class="pill"
translate="project-overview.new-rule.label"
></span>
</div>
<div class="small-label stats-subtitle">
<div>
<mat-icon svgIcon="red:pages"></mat-icon>
{{ fileStatus.numberOfPages }}
</div>
</div>
</div>
<div>
<div class="small-label" [class.error]="isError(fileStatus)">
{{ fileStatus.added | date: 'd MMM. yyyy, hh:mm a' }}
</div>
</div>
<div class="needs-work" *ngIf="!isError(fileStatus)">
<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>
<div class="assigned-to" *ngIf="!isError(fileStatus)">
<redaction-initials-avatar
withName="true"
[userId]="fileStatus.currentReviewer"
></redaction-initials-avatar>
</div>
<div class="status-container" [class.extend-cols]="isError(fileStatus)">
<div
*ngIf="isError(fileStatus)"
class="small-label error"
translate="project-overview.file-listing.file-entry.file-error.label"
></div>
<div
class="small-label"
*ngIf="isPending(fileStatus)"
translate="project-overview.file-listing.file-entry.file-pending.label"
></div>
<div
class="small-label"
*ngIf="isProcessing(fileStatus)"
translate="processing"
></div>
<redaction-status-bar
*ngIf="
!isPending(fileStatus) &&
!isProcessing(fileStatus) &&
!isError(fileStatus)
"
[config]="[
{
color: fileStatus.status,
length: 1
}
]"
></redaction-status-bar>
<div class="action-buttons">
<button
(click)="openDeleteFileDialog($event, fileStatus)"
color="accent"
*ngIf="
userService.isManager(user) || appStateService.isActiveProjectOwner
"
mat-icon-button
[matTooltip]="'project-overview.delete.action.label' | translate"
>
<mat-icon svgIcon="red:trash"></mat-icon>
</button>
<button
(click)="downloadFileRedactionReport($event, fileStatus)"
color="accent"
mat-icon-button
[matTooltip]="'project-overview.report.action.label' | translate"
>
<mat-icon svgIcon="red:report"></mat-icon>
</button>
<button
(click)="openAssignFileReviewerDialog($event, fileStatus)"
color="accent"
*ngIf="appStateService.isActiveProjectMember"
mat-icon-button
[matTooltip]="'project-overview.assign.action.label' | translate"
>
<mat-icon svgIcon="red:assign"></mat-icon>
</button>
<button
(click)="reanalyseFile($event, fileStatus)"
color="accent"
mat-icon-button
[matTooltip]="'project-overview.reanalyse.action.label' | translate"
>
<mat-icon svgIcon="red:refresh"></mat-icon>
</button>
</div>
</div>
</div>
</div>
</div>
<div class="project-details-container right-fixed-container">
<div class="actions-row">
<button
mat-icon-button
*ngIf="userService.isManager(user)"
(click)="openDeleteProjectDialog($event)"
>
<mat-icon svgIcon="red:trash"></mat-icon>
</button>
<button
mat-icon-button
*ngIf="userService.isManager(user)"
(click)="openEditProjectDialog($event)"
>
<mat-icon svgIcon="red:edit"></mat-icon>
</button>
<button mat-icon-button (click)="downloadRedactionReport($event)">
<mat-icon svgIcon="red:report"></mat-icon>
</button>
</div>
<div class="small-label stats-subtitle mt-20">
<div>
<mat-icon svgIcon="red:pages"></mat-icon>
{{ appStateService.activeProject.files.length }}
</div>
<div>
<mat-icon svgIcon="red:user"></mat-icon>
{{ appStateService.activeProject.project.memberIds.length }}
</div>
<div>
<mat-icon svgIcon="red:calendar"></mat-icon>
{{ appStateService.activeProject.project.date | date: 'd MMM. yyyy' }}
</div>
<div *ngIf="appStateService.activeProject.project.dueDate">
<mat-icon svgIcon="red:lightning"></mat-icon>
{{ appStateService.activeProject.project.dueDate | date: 'mediumDate' }}
</div>
</div>
<div class="heading-xl mt-20">
{{ appStateService.activeProject.project.projectName }}
</div>
<div class="owner flex-row mt-20">
<redaction-initials-avatar
[userId]="activeProject.ownerId"
size="large"
withName="true"
></redaction-initials-avatar>
</div>
<div class="mt-20">
{{ appStateService.activeProject.project.description }}
</div>
<div class="project-team mt-20">
<div
class="all-caps-label"
translate="project-overview.project-details.project-team.label"
></div>
<div class="flex mt-20 members-container">
<div *ngFor="let userId of displayMembers" class="member">
<redaction-initials-avatar
[userId]="userId"
size="large"
></redaction-initials-avatar>
</div>
<div class="member" *ngIf="overflowCount">
<div class="oval large white-dark">+{{ overflowCount }}</div>
</div>
<div
class="member pointer"
(click)="openAssignProjectMembersDialog()"
*ngIf="userService.isManager(user)"
>
<div class="oval red-white large">+</div>
</div>
</div>
</div>
<div class="mt-32">
<redaction-simple-doughnut-chart
[config]="documentsChartData"
[strokeWidth]="15"
[radius]="70"
[subtitle]="'project-overview.project-details.charts.total-documents.label'"
direction="row"
></redaction-simple-doughnut-chart>
</div>
<div class="mt-32 legend">
<div>
<redaction-annotation-icon
[typeValue]="appStateService.getDictionaryTypeValue('hint')"
></redaction-annotation-icon>
{{ 'project-overview.legend.contains-hints.label' | translate }}
</div>
<div>
<redaction-annotation-icon
[typeValue]="appStateService.getDictionaryTypeValue('redaction')"
></redaction-annotation-icon>
{{ 'project-overview.legend.contains-redactions.label' | translate }}
</div>
<div>
<redaction-annotation-icon
[typeValue]="appStateService.getDictionaryTypeValue('request')"
></redaction-annotation-icon>
{{ 'project-overview.legend.contains-suggestions.label' | translate }}
</div>
</div>
</div>
</div>