fixed lint
This commit is contained in:
parent
b8a35461c2
commit
9d407514b8
@ -71,6 +71,8 @@ import { TableColNameComponent } from './components/table-col-name/table-col-nam
|
||||
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';
|
||||
import { ProjectOverviewEmptyComponent } from './screens/empty-states/project-overview-empty/project-overview-empty.component';
|
||||
import { ProjectListingEmptyComponent } from './screens/empty-states/project-listing-empty/project-listing-empty.component';
|
||||
|
||||
export function HttpLoaderFactory(httpClient: HttpClient) {
|
||||
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
|
||||
@ -107,7 +109,9 @@ export function HttpLoaderFactory(httpClient: HttpClient) {
|
||||
TableColNameComponent,
|
||||
ProjectDetailsComponent,
|
||||
PageIndicatorComponent,
|
||||
NeedsWorkBadgeComponent
|
||||
NeedsWorkBadgeComponent,
|
||||
ProjectOverviewEmptyComponent,
|
||||
ProjectListingEmptyComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
<div class="empty-state-container">
|
||||
<div class="heading-xl" translate="project-listing.no-projects"></div>
|
||||
<button
|
||||
(click)="addProjectRequest.emit()"
|
||||
*ngIf="userService.isManager()"
|
||||
class="add-project-btn"
|
||||
color="primary"
|
||||
mat-flat-button
|
||||
>
|
||||
<mat-icon svgIcon="red:plus"></mat-icon>
|
||||
<span translate="project-listing.add-new"></span>
|
||||
</button>
|
||||
</div>
|
||||
@ -0,0 +1,13 @@
|
||||
import { Component, EventEmitter, Output } from '@angular/core';
|
||||
import { UserService } from '../../../user/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-project-listing-empty',
|
||||
templateUrl: './project-listing-empty.component.html',
|
||||
styleUrls: ['./project-listing-empty.component.scss']
|
||||
})
|
||||
export class ProjectListingEmptyComponent {
|
||||
@Output() addProjectRequest = new EventEmitter();
|
||||
|
||||
constructor(public userService: UserService) {}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
<div class="empty-state-container">
|
||||
<div
|
||||
*ngIf="!appStateService.activeProject"
|
||||
[innerHTML]="
|
||||
'project-overview.no-project'
|
||||
| translate: { projectId: appStateService.activeProjectId }
|
||||
"
|
||||
class="heading-xl"
|
||||
></div>
|
||||
|
||||
<div
|
||||
*ngIf="appStateService.activeProject"
|
||||
class="heading-xl"
|
||||
translate="project-overview.no-files"
|
||||
></div>
|
||||
<div *ngIf="appStateService.activeProject">
|
||||
<button (click)="fileInput.click()" color="primary" mat-flat-button>
|
||||
<mat-icon svgIcon="red:upload"></mat-icon>
|
||||
<span translate="project-overview.upload-files-btn"></span>
|
||||
</button>
|
||||
|
||||
<input
|
||||
#fileInput
|
||||
(change)="uploadFiles.emit($event.target.files)"
|
||||
class="file-upload-input"
|
||||
multiple="true"
|
||||
type="file"
|
||||
/>
|
||||
|
||||
<button [routerLink]="['/ui/projects/']" mat-icon-button class="close-btn">
|
||||
<mat-icon svgIcon="red:close"></mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,9 @@
|
||||
.file-upload-input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 14px;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
import { Component, EventEmitter, Output } from '@angular/core';
|
||||
import { AppStateService } from '../../../state/app-state.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-project-overview-empty',
|
||||
templateUrl: './project-overview-empty.component.html',
|
||||
styleUrls: ['./project-overview-empty.component.scss']
|
||||
})
|
||||
export class ProjectOverviewEmptyComponent {
|
||||
@Output() uploadFiles = new EventEmitter();
|
||||
|
||||
constructor(public appStateService: AppStateService) {}
|
||||
}
|
||||
@ -1,266 +1,279 @@
|
||||
<div class="page-header">
|
||||
<div class="filters flex-row">
|
||||
<div translate="filters.filter-by"></div>
|
||||
<redaction-filter
|
||||
[filters]="statusFilters"
|
||||
[filterLabel]="'filters.status'"
|
||||
[hasArrow]="false"
|
||||
[icon]="'red:status'"
|
||||
(filtersChanged)="filtersChanged()"
|
||||
></redaction-filter>
|
||||
<redaction-filter
|
||||
[filters]="peopleFilters"
|
||||
[filterLabel]="'filters.people'"
|
||||
[hasArrow]="false"
|
||||
[icon]="'red:user'"
|
||||
(filtersChanged)="filtersChanged()"
|
||||
></redaction-filter>
|
||||
<redaction-filter
|
||||
[filters]="dueDateFilters"
|
||||
[filterLabel]="'filters.due-date'"
|
||||
[hasArrow]="false"
|
||||
[icon]="'red:lightning'"
|
||||
(filtersChanged)="filtersChanged()"
|
||||
></redaction-filter>
|
||||
<redaction-filter
|
||||
(filtersChanged)="filtersChanged()"
|
||||
[filterLabel]="'filters.needs-work'"
|
||||
[filters]="needsWorkFilters"
|
||||
[hasArrow]="false"
|
||||
[icon]="'red:needs-work'"
|
||||
></redaction-filter>
|
||||
</div>
|
||||
<button
|
||||
(click)="openAddProjectDialog()"
|
||||
*ngIf="userService.isManager(user)"
|
||||
class="add-project-btn"
|
||||
color="primary"
|
||||
mat-flat-button
|
||||
>
|
||||
<mat-icon svgIcon="red:plus"></mat-icon>
|
||||
<span translate="project-listing.add-new"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex red-content-inner">
|
||||
<div class="left-container">
|
||||
<div class="table-header">
|
||||
<div class="select-all-container">
|
||||
<div
|
||||
*ngIf="bulkSelectActive"
|
||||
class="select-oval"
|
||||
[class.active]="areAllProjectsSelected()"
|
||||
(click)="toggleSelectAll()"
|
||||
></div>
|
||||
<span class="all-caps-label">
|
||||
{{
|
||||
'project-listing.table-header.title'
|
||||
| translate: { length: displayedProjects.length || 0 }
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<div
|
||||
translate="project-listing.table-header.bulk-select"
|
||||
class="pointer"
|
||||
[class.active]="bulkSelectActive"
|
||||
(click)="toggleBulkSelect()"
|
||||
></div>
|
||||
|
||||
<redaction-sorting
|
||||
#sortingComponent
|
||||
(optionChanged)="sortingOptionChanged($event)"
|
||||
type="project-listing"
|
||||
></redaction-sorting>
|
||||
</div>
|
||||
<section *ngIf="appStateService.hasProjects">
|
||||
<div class="page-header">
|
||||
<div class="filters flex-row">
|
||||
<div translate="filters.filter-by"></div>
|
||||
<redaction-filter
|
||||
[filters]="statusFilters"
|
||||
[filterLabel]="'filters.status'"
|
||||
[hasArrow]="false"
|
||||
[icon]="'red:status'"
|
||||
(filtersChanged)="filtersChanged()"
|
||||
></redaction-filter>
|
||||
<redaction-filter
|
||||
[filters]="peopleFilters"
|
||||
[filterLabel]="'filters.people'"
|
||||
[hasArrow]="false"
|
||||
[icon]="'red:user'"
|
||||
(filtersChanged)="filtersChanged()"
|
||||
></redaction-filter>
|
||||
<redaction-filter
|
||||
[filters]="dueDateFilters"
|
||||
[filterLabel]="'filters.due-date'"
|
||||
[hasArrow]="false"
|
||||
[icon]="'red:lightning'"
|
||||
(filtersChanged)="filtersChanged()"
|
||||
></redaction-filter>
|
||||
<redaction-filter
|
||||
(filtersChanged)="filtersChanged()"
|
||||
[filterLabel]="'filters.needs-work'"
|
||||
[filters]="needsWorkFilters"
|
||||
[hasArrow]="false"
|
||||
[icon]="'red:needs-work'"
|
||||
></redaction-filter>
|
||||
</div>
|
||||
<button
|
||||
(click)="openAddProjectDialog()"
|
||||
*ngIf="userService.isManager(user)"
|
||||
class="add-project-btn"
|
||||
color="primary"
|
||||
mat-flat-button
|
||||
>
|
||||
<mat-icon svgIcon="red:plus"></mat-icon>
|
||||
<span translate="project-listing.add-new"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="grid-container" [class.bulk-select]="bulkSelectActive">
|
||||
<div class="select-oval-placeholder" *ngIf="bulkSelectActive"></div>
|
||||
|
||||
<redaction-table-col-name
|
||||
label="project-listing.table-col-names.name"
|
||||
column="project.projectName"
|
||||
[activeSortingOption]="sortingOption"
|
||||
[withSort]="true"
|
||||
(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>
|
||||
|
||||
<redaction-table-col-name
|
||||
label="project-listing.table-col-names.status"
|
||||
class="flex-end"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<div
|
||||
*ngIf="displayedProjects?.length === 0"
|
||||
class="no-data heading-l"
|
||||
translate="project-listing.no-projects-match"
|
||||
></div>
|
||||
|
||||
<div
|
||||
*ngFor="
|
||||
let pw of displayedProjects | sortBy: sortingOption.order:sortingOption.column
|
||||
"
|
||||
[routerLink]="[canOpenProject(pw) ? '/ui/projects/' + pw.project.projectId : []]"
|
||||
class="table-item"
|
||||
[class.pointer]="canOpenProject(pw)"
|
||||
>
|
||||
<div class="pr-0" *ngIf="bulkSelectActive">
|
||||
<div class="flex red-content-inner">
|
||||
<div class="left-container">
|
||||
<div class="table-header">
|
||||
<div class="select-all-container">
|
||||
<div
|
||||
*ngIf="bulkSelectActive"
|
||||
class="select-oval"
|
||||
[class.active]="isProjectSelected(pw)"
|
||||
(click)="toggleProjectSelected($event, pw)"
|
||||
[class.active]="areAllProjectsSelected()"
|
||||
(click)="toggleSelectAll()"
|
||||
></div>
|
||||
<span class="all-caps-label">
|
||||
{{
|
||||
'project-listing.table-header.title'
|
||||
| translate: { length: displayedProjects.length || 0 }
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="table-item-title">
|
||||
{{ pw.project.projectName }}
|
||||
<div class="actions">
|
||||
<div
|
||||
translate="project-listing.table-header.bulk-select"
|
||||
class="pointer"
|
||||
[class.active]="bulkSelectActive"
|
||||
(click)="toggleBulkSelect()"
|
||||
></div>
|
||||
|
||||
<redaction-sorting
|
||||
#sortingComponent
|
||||
[initialOption]="sortingOption"
|
||||
(optionChanged)="sortingOptionChanged($event)"
|
||||
type="project-listing"
|
||||
></redaction-sorting>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid-container" [class.bulk-select]="bulkSelectActive">
|
||||
<div class="select-oval-placeholder" *ngIf="bulkSelectActive"></div>
|
||||
|
||||
<redaction-table-col-name
|
||||
label="project-listing.table-col-names.name"
|
||||
column="project.projectName"
|
||||
[activeSortingOption]="sortingOption"
|
||||
[withSort]="true"
|
||||
(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>
|
||||
|
||||
<redaction-table-col-name
|
||||
label="project-listing.table-col-names.status"
|
||||
class="flex-end"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<div
|
||||
*ngIf="displayedProjects?.length === 0"
|
||||
class="no-data heading-l"
|
||||
translate="project-listing.no-projects-match"
|
||||
></div>
|
||||
|
||||
<div
|
||||
*ngFor="
|
||||
let pw of displayedProjects
|
||||
| sortBy: sortingOption.order:sortingOption.column
|
||||
"
|
||||
[routerLink]="[
|
||||
canOpenProject(pw) ? '/ui/projects/' + pw.project.projectId : []
|
||||
]"
|
||||
class="table-item"
|
||||
[class.pointer]="canOpenProject(pw)"
|
||||
>
|
||||
<div class="pr-0" *ngIf="bulkSelectActive">
|
||||
<div
|
||||
class="select-oval"
|
||||
[class.active]="isProjectSelected(pw)"
|
||||
(click)="toggleProjectSelected($event, pw)"
|
||||
></div>
|
||||
</div>
|
||||
<div class="small-label stats-subtitle">
|
||||
<div>
|
||||
<mat-icon svgIcon="red:document"></mat-icon>
|
||||
{{ documentCount(pw) }}
|
||||
|
||||
<div>
|
||||
<div class="table-item-title">
|
||||
{{ pw.project.projectName }}
|
||||
</div>
|
||||
<div>
|
||||
<mat-icon svgIcon="red:pages"></mat-icon>
|
||||
{{ pw.totalNumberOfPages }}
|
||||
</div>
|
||||
<div>
|
||||
<mat-icon svgIcon="red:user"></mat-icon>
|
||||
{{ userCount(pw) }}
|
||||
</div>
|
||||
<div>
|
||||
<mat-icon svgIcon="red:calendar"></mat-icon>
|
||||
{{ pw.project.date | date: 'mediumDate' }}
|
||||
</div>
|
||||
<div *ngIf="pw.project.dueDate">
|
||||
<mat-icon svgIcon="red:lightning"></mat-icon>
|
||||
{{ pw.project.dueDate | date: 'mediumDate' }}
|
||||
<div class="small-label stats-subtitle">
|
||||
<div>
|
||||
<mat-icon svgIcon="red:document"></mat-icon>
|
||||
{{ documentCount(pw) }}
|
||||
</div>
|
||||
<div>
|
||||
<mat-icon svgIcon="red:pages"></mat-icon>
|
||||
{{ pw.totalNumberOfPages }}
|
||||
</div>
|
||||
<div>
|
||||
<mat-icon svgIcon="red:user"></mat-icon>
|
||||
{{ userCount(pw) }}
|
||||
</div>
|
||||
<div>
|
||||
<mat-icon svgIcon="red:calendar"></mat-icon>
|
||||
{{ pw.project.date | date: 'mediumDate' }}
|
||||
</div>
|
||||
<div *ngIf="pw.project.dueDate">
|
||||
<mat-icon svgIcon="red:lightning"></mat-icon>
|
||||
{{ pw.project.dueDate | date: 'mediumDate' }}
|
||||
</div>
|
||||
</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"
|
||||
withName="true"
|
||||
></redaction-initials-avatar>
|
||||
</div>
|
||||
<div class="status-container">
|
||||
<redaction-status-bar
|
||||
[config]="getProjectStatusConfig(pw)"
|
||||
></redaction-status-bar>
|
||||
<div>
|
||||
<redaction-needs-work-badge
|
||||
[needsWorkInput]="pw"
|
||||
[displayed]="true"
|
||||
></redaction-needs-work-badge>
|
||||
</div>
|
||||
<div>
|
||||
<redaction-initials-avatar
|
||||
[userId]="pw.project.ownerId"
|
||||
withName="true"
|
||||
></redaction-initials-avatar>
|
||||
</div>
|
||||
<div class="status-container">
|
||||
<redaction-status-bar
|
||||
[config]="getProjectStatusConfig(pw)"
|
||||
></redaction-status-bar>
|
||||
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
(click)="openDeleteProjectDialog($event, pw.project)"
|
||||
[matTooltip]="'project-listing.delete.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
*ngIf="userService.isManager(user)"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:trash"></mat-icon>
|
||||
</button>
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
(click)="openDeleteProjectDialog($event, pw.project)"
|
||||
[matTooltip]="'project-listing.delete.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
*ngIf="userService.isManager(user)"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:trash"></mat-icon>
|
||||
</button>
|
||||
|
||||
<button
|
||||
(click)="openEditProjectDialog($event, pw.project)"
|
||||
[matTooltip]="'project-listing.edit.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
*ngIf="userService.isManager(user)"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:edit"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
(click)="openEditProjectDialog($event, pw.project)"
|
||||
[matTooltip]="'project-listing.edit.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
*ngIf="userService.isManager(user)"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:edit"></mat-icon>
|
||||
</button>
|
||||
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="downloadRedactionReport($event, pw.project)"
|
||||
*ngIf="
|
||||
appStateService.isManagerAndOwner(user, pw.project) && pw.hasFiles
|
||||
"
|
||||
[matTooltip]="'project-listing.report.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
color="accent"
|
||||
>
|
||||
<mat-icon svgIcon="red:report"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
(click)="openAssignProjectOwnerDialog($event, pw.project)"
|
||||
[matTooltip]="'project-listing.assign.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
*ngIf="userService.isManager(user)"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:assign"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
color="accent"
|
||||
*ngIf="
|
||||
appStateService.isManagerAndOwner(user, pw.project) && pw.hasFiles
|
||||
"
|
||||
(click)="reanalyseProject($event, pw.project)"
|
||||
mat-icon-button
|
||||
[matTooltip]="'project-listing.reanalyse.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
>
|
||||
<mat-icon svgIcon="red:refresh"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="downloadRedactionReport($event, pw.project)"
|
||||
*ngIf="
|
||||
appStateService.isManagerAndOwner(user, pw.project) &&
|
||||
pw.hasFiles
|
||||
"
|
||||
[matTooltip]="'project-listing.report.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
color="accent"
|
||||
>
|
||||
<mat-icon svgIcon="red:report"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
(click)="openAssignProjectOwnerDialog($event, pw.project)"
|
||||
[matTooltip]="'project-listing.assign.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
*ngIf="userService.isManager(user)"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:assign"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
color="accent"
|
||||
*ngIf="
|
||||
appStateService.isManagerAndOwner(user, pw.project) &&
|
||||
pw.hasFiles
|
||||
"
|
||||
(click)="reanalyseProject($event, pw.project)"
|
||||
mat-icon-button
|
||||
[matTooltip]="'project-listing.reanalyse.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
>
|
||||
<mat-icon svgIcon="red:refresh"></mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-fixed-container">
|
||||
<div>
|
||||
<redaction-simple-doughnut-chart
|
||||
[config]="projectsChartData"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'project-listing.stats.charts.projects'"
|
||||
></redaction-simple-doughnut-chart>
|
||||
<div class="right-fixed-container">
|
||||
<div>
|
||||
<redaction-simple-doughnut-chart
|
||||
[config]="projectsChartData"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'project-listing.stats.charts.projects'"
|
||||
></redaction-simple-doughnut-chart>
|
||||
|
||||
<div class="project-stats-container">
|
||||
<div class="project-stats-item">
|
||||
<mat-icon svgIcon="red:document"></mat-icon>
|
||||
<div>
|
||||
<div class="heading">{{ totalPages }}</div>
|
||||
<div translate="project-listing.stats.analyzed-pages"></div>
|
||||
<div class="project-stats-container">
|
||||
<div class="project-stats-item">
|
||||
<mat-icon svgIcon="red:document"></mat-icon>
|
||||
<div>
|
||||
<div class="heading">{{ totalPages }}</div>
|
||||
<div translate="project-listing.stats.analyzed-pages"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="project-stats-item">
|
||||
<mat-icon svgIcon="red:user"></mat-icon>
|
||||
<div>
|
||||
<div class="heading">{{ totalPeople }}</div>
|
||||
<div translate="project-listing.stats.total-people"></div>
|
||||
<div class="project-stats-item">
|
||||
<mat-icon svgIcon="red:user"></mat-icon>
|
||||
<div>
|
||||
<div class="heading">{{ totalPeople }}</div>
|
||||
<div translate="project-listing.stats.total-people"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<redaction-simple-doughnut-chart
|
||||
[config]="documentsChartData"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'project-listing.stats.charts.total-documents'"
|
||||
></redaction-simple-doughnut-chart>
|
||||
<div>
|
||||
<redaction-simple-doughnut-chart
|
||||
[config]="documentsChartData"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'project-listing.stats.charts.total-documents'"
|
||||
></redaction-simple-doughnut-chart>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<redaction-project-listing-empty
|
||||
*ngIf="!appStateService.hasProjects"
|
||||
(addProjectRequest)="openAddProjectDialog()"
|
||||
></redaction-project-listing-empty>
|
||||
|
||||
@ -37,7 +37,6 @@ export class ProjectListingScreenComponent implements OnInit {
|
||||
public needsWorkFilters: FilterModel[];
|
||||
public displayedProjects: ProjectWrapper[] = [];
|
||||
|
||||
@ViewChild('sortingComponent', { static: true }) public sortingComponent: SortingComponent;
|
||||
public sortingOption: SortingOption = { column: 'projectDate', order: 'desc' };
|
||||
|
||||
constructor(
|
||||
@ -49,7 +48,6 @@ export class ProjectListingScreenComponent implements OnInit {
|
||||
) {}
|
||||
|
||||
public ngOnInit(): void {
|
||||
this.sortingComponent.setOption(this.sortingOption);
|
||||
this.appStateService.reset();
|
||||
this._calculateData();
|
||||
this.appStateService.fileStatusChanged.subscribe(() => {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Component, OnInit, Output, EventEmitter } from '@angular/core';
|
||||
import { Component, OnInit, Output, EventEmitter, ChangeDetectorRef } from '@angular/core';
|
||||
import { AppStateService } from '../../../state/app-state.service';
|
||||
import { UserService } from '../../../user/user.service';
|
||||
import { groupBy } from '../../../utils/functions';
|
||||
@ -18,11 +18,17 @@ export class ProjectDetailsComponent implements OnInit {
|
||||
constructor(
|
||||
public readonly appStateService: AppStateService,
|
||||
public readonly userService: UserService,
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
private readonly _dialogService: DialogService,
|
||||
private readonly _router: Router
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {}
|
||||
ngOnInit(): void {
|
||||
this.calculateChartConfig();
|
||||
this.appStateService.fileStatusChanged.subscribe((event) => {
|
||||
this.calculateChartConfig();
|
||||
});
|
||||
}
|
||||
|
||||
public get user() {
|
||||
return this.userService.user;
|
||||
@ -77,6 +83,7 @@ export class ProjectDetailsComponent implements OnInit {
|
||||
for (const key of Object.keys(groups)) {
|
||||
this.documentsChartData.push({ value: groups[key].length, color: key, label: key });
|
||||
}
|
||||
this._changeDetectorRef.detectChanges();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,339 +1,338 @@
|
||||
<div
|
||||
*ngIf="!appStateService.activeProject"
|
||||
[innerHTML]="
|
||||
'project-overview.no-project'
|
||||
| translate: { projectId: appStateService.activeProject.project.projectId }
|
||||
"
|
||||
class="heading-l"
|
||||
></div>
|
||||
|
||||
<div *ngIf="appStateService.activeProject" class="page-header">
|
||||
<div *ngIf="!appStateService.activeProject.hasFiles">
|
||||
<div class="no-data heading-l" translate="project-overview.no-files"></div>
|
||||
</div>
|
||||
<div class="filters flex-row" *ngIf="appStateService.activeProject.hasFiles">
|
||||
<div translate="filters.filter-by"></div>
|
||||
<redaction-filter
|
||||
(filtersChanged)="filtersChanged()"
|
||||
[filterLabel]="'filters.status'"
|
||||
[filters]="statusFilters"
|
||||
[hasArrow]="false"
|
||||
[icon]="'red:status'"
|
||||
></redaction-filter>
|
||||
<redaction-filter
|
||||
(filtersChanged)="filtersChanged()"
|
||||
[filterLabel]="'filters.people'"
|
||||
[filters]="peopleFilters"
|
||||
[hasArrow]="false"
|
||||
[icon]="'red:user'"
|
||||
></redaction-filter>
|
||||
<redaction-filter
|
||||
(filtersChanged)="filtersChanged()"
|
||||
[filterLabel]="'filters.needs-work'"
|
||||
[filters]="needsWorkFilters"
|
||||
[hasArrow]="false"
|
||||
[icon]="'red:needs-work'"
|
||||
></redaction-filter>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button (click)="fileInput.click()" color="primary" class="custom-mini-fab" mat-mini-fab>
|
||||
<mat-icon svgIcon="red:upload"></mat-icon>
|
||||
</button>
|
||||
<button [routerLink]="['/ui/projects/']" mat-icon-button>
|
||||
<mat-icon svgIcon="red:close"></mat-icon>
|
||||
</button>
|
||||
|
||||
<input
|
||||
#fileInput
|
||||
(change)="uploadFiles($event.target.files)"
|
||||
class="file-upload-input"
|
||||
multiple="true"
|
||||
type="file"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex red-content-inner">
|
||||
<div class="left-container" *ngIf="appStateService.activeProject.hasFiles">
|
||||
<div class="table-header">
|
||||
<div class="select-all-container">
|
||||
<div
|
||||
(click)="toggleSelectAll()"
|
||||
*ngIf="bulkSelectActive"
|
||||
[class.active]="areAllFilesSelected()"
|
||||
class="select-oval"
|
||||
></div>
|
||||
<span class="all-caps-label">
|
||||
{{
|
||||
'project-overview.table-header.title'
|
||||
| translate: { length: displayedFiles.length || 0 }
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div
|
||||
(click)="toggleBulkSelect()"
|
||||
[class.active]="bulkSelectActive"
|
||||
class="pointer"
|
||||
translate="project-overview.table-header.bulk-select"
|
||||
></div>
|
||||
<redaction-sorting
|
||||
#sortingComponent
|
||||
[initialOption]="sortingOption"
|
||||
(optionChanged)="sortingOptionChanged($event)"
|
||||
type="project-overview"
|
||||
></redaction-sorting>
|
||||
</div>
|
||||
<redaction-project-overview-empty
|
||||
(uploadFiles)="uploadFiles($event)"
|
||||
*ngIf="!appStateService.activeProject?.hasFiles"
|
||||
></redaction-project-overview-empty>
|
||||
<section *ngIf="appStateService.activeProject?.hasFiles">
|
||||
<div *ngIf="appStateService.activeProject" class="page-header">
|
||||
<div class="filters flex-row">
|
||||
<div translate="filters.filter-by"></div>
|
||||
<redaction-filter
|
||||
(filtersChanged)="filtersChanged()"
|
||||
[filterLabel]="'filters.status'"
|
||||
[filters]="statusFilters"
|
||||
[hasArrow]="false"
|
||||
[icon]="'red:status'"
|
||||
></redaction-filter>
|
||||
<redaction-filter
|
||||
(filtersChanged)="filtersChanged()"
|
||||
[filterLabel]="'filters.people'"
|
||||
[filters]="peopleFilters"
|
||||
[hasArrow]="false"
|
||||
[icon]="'red:user'"
|
||||
></redaction-filter>
|
||||
<redaction-filter
|
||||
(filtersChanged)="filtersChanged()"
|
||||
[filterLabel]="'filters.needs-work'"
|
||||
[filters]="needsWorkFilters"
|
||||
[hasArrow]="false"
|
||||
[icon]="'red:needs-work'"
|
||||
></redaction-filter>
|
||||
</div>
|
||||
|
||||
<div [class.bulk-select]="bulkSelectActive" class="grid-container">
|
||||
<!-- Table column names-->
|
||||
<div *ngIf="bulkSelectActive" class="select-oval-placeholder"></div>
|
||||
|
||||
<redaction-table-col-name
|
||||
(toggleSort)="sortingComponent.toggleSort($event)"
|
||||
[activeSortingOption]="sortingOption"
|
||||
[withSort]="true"
|
||||
column="filename"
|
||||
label="project-overview.table-col-names.name"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
(toggleSort)="sortingComponent.toggleSort($event)"
|
||||
[activeSortingOption]="sortingOption"
|
||||
[withSort]="true"
|
||||
column="added"
|
||||
label="project-overview.table-col-names.added-on"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
label="project-overview.table-col-names.needs-work"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
(toggleSort)="sortingComponent.toggleSort($event)"
|
||||
[activeSortingOption]="sortingOption"
|
||||
[withSort]="true"
|
||||
column="reviewerName"
|
||||
label="project-overview.table-col-names.assigned-to"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
(toggleSort)="sortingComponent.toggleSort($event)"
|
||||
[activeSortingOption]="sortingOption"
|
||||
[withSort]="true"
|
||||
column="pages"
|
||||
label="project-overview.table-col-names.pages"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
(toggleSort)="sortingComponent.toggleSort($event)"
|
||||
[activeSortingOption]="sortingOption"
|
||||
[withSort]="true"
|
||||
class="flex-end"
|
||||
column="status"
|
||||
label="project-overview.table-col-names.status"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<div
|
||||
*ngIf="displayedFiles?.length === 0"
|
||||
class="no-data heading-l"
|
||||
translate="project-overview.no-files-match"
|
||||
></div>
|
||||
|
||||
<div
|
||||
*ngFor="
|
||||
let fileStatus of displayedFiles
|
||||
| sortBy: sortingOption.order:sortingOption.column
|
||||
"
|
||||
[class.pointer]="canOpenFile(fileStatus)"
|
||||
[routerLink]="
|
||||
canOpenFile(fileStatus)
|
||||
? [
|
||||
'/ui/projects/' +
|
||||
appStateService.activeProject.project.projectId +
|
||||
'/file/' +
|
||||
fileStatus.fileId
|
||||
]
|
||||
: []
|
||||
"
|
||||
class="table-item"
|
||||
<div>
|
||||
<button
|
||||
(click)="fileInput.click()"
|
||||
color="primary"
|
||||
class="custom-mini-fab"
|
||||
mat-mini-fab
|
||||
>
|
||||
<div *ngIf="bulkSelectActive" class="pr-0">
|
||||
<mat-icon svgIcon="red:upload"></mat-icon>
|
||||
</button>
|
||||
<button [routerLink]="['/ui/projects/']" mat-icon-button>
|
||||
<mat-icon svgIcon="red:close"></mat-icon>
|
||||
</button>
|
||||
|
||||
<input
|
||||
#fileInput
|
||||
(change)="uploadFiles($event.target.files)"
|
||||
class="file-upload-input"
|
||||
multiple="true"
|
||||
type="file"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex red-content-inner">
|
||||
<div class="left-container">
|
||||
<div class="table-header">
|
||||
<div class="select-all-container">
|
||||
<div
|
||||
(click)="toggleFileSelected($event, fileStatus)"
|
||||
[class.active]="isFileSelected(fileStatus)"
|
||||
(click)="toggleSelectAll()"
|
||||
*ngIf="bulkSelectActive"
|
||||
[class.active]="areAllFilesSelected()"
|
||||
class="select-oval"
|
||||
></div>
|
||||
<span class="all-caps-label">
|
||||
{{
|
||||
'project-overview.table-header.title'
|
||||
| translate: { length: displayedFiles.length || 0 }
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div
|
||||
(click)="toggleBulkSelect()"
|
||||
[class.active]="bulkSelectActive"
|
||||
class="pointer"
|
||||
translate="project-overview.table-header.bulk-select"
|
||||
></div>
|
||||
<redaction-sorting
|
||||
#sortingComponent
|
||||
[initialOption]="sortingOption"
|
||||
(optionChanged)="sortingOptionChanged($event)"
|
||||
type="project-overview"
|
||||
></redaction-sorting>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div [class.bulk-select]="bulkSelectActive" class="grid-container">
|
||||
<!-- Table column names-->
|
||||
<div *ngIf="bulkSelectActive" class="select-oval-placeholder"></div>
|
||||
|
||||
<redaction-table-col-name
|
||||
(toggleSort)="sortingComponent.toggleSort($event)"
|
||||
[activeSortingOption]="sortingOption"
|
||||
[withSort]="true"
|
||||
column="filename"
|
||||
label="project-overview.table-col-names.name"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
(toggleSort)="sortingComponent.toggleSort($event)"
|
||||
[activeSortingOption]="sortingOption"
|
||||
[withSort]="true"
|
||||
column="added"
|
||||
label="project-overview.table-col-names.added-on"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
label="project-overview.table-col-names.needs-work"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
(toggleSort)="sortingComponent.toggleSort($event)"
|
||||
[activeSortingOption]="sortingOption"
|
||||
[withSort]="true"
|
||||
column="reviewerName"
|
||||
label="project-overview.table-col-names.assigned-to"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
(toggleSort)="sortingComponent.toggleSort($event)"
|
||||
[activeSortingOption]="sortingOption"
|
||||
[withSort]="true"
|
||||
column="pages"
|
||||
label="project-overview.table-col-names.pages"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name
|
||||
(toggleSort)="sortingComponent.toggleSort($event)"
|
||||
[activeSortingOption]="sortingOption"
|
||||
[withSort]="true"
|
||||
class="flex-end"
|
||||
column="status"
|
||||
label="project-overview.table-col-names.status"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<div
|
||||
[matTooltipPosition]="'above'"
|
||||
[matTooltip]="'[' + fileStatus.status + '] ' + fileStatus.filename"
|
||||
*ngIf="displayedFiles?.length === 0"
|
||||
class="no-data heading-l"
|
||||
translate="project-overview.no-files-match"
|
||||
></div>
|
||||
|
||||
<div
|
||||
*ngFor="
|
||||
let fileStatus of displayedFiles
|
||||
| sortBy: sortingOption.order:sortingOption.column
|
||||
"
|
||||
[class.pointer]="canOpenFile(fileStatus)"
|
||||
[routerLink]="
|
||||
canOpenFile(fileStatus)
|
||||
? [
|
||||
'/ui/projects/' +
|
||||
appStateService.activeProject.project.projectId +
|
||||
'/file/' +
|
||||
fileStatus.fileId
|
||||
]
|
||||
: []
|
||||
"
|
||||
class="table-item"
|
||||
>
|
||||
<div class="filename-wrapper">
|
||||
<div *ngIf="bulkSelectActive" class="pr-0">
|
||||
<div
|
||||
[class.disabled]="isPending(fileStatus) || isProcessing(fileStatus)"
|
||||
[class.error]="isError(fileStatus)"
|
||||
class="table-item-title"
|
||||
>
|
||||
{{ fileStatus.filename }}
|
||||
(click)="toggleFileSelected($event, fileStatus)"
|
||||
[class.active]="isFileSelected(fileStatus)"
|
||||
class="select-oval"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
[matTooltipPosition]="'above'"
|
||||
[matTooltip]="'[' + fileStatus.status + '] ' + fileStatus.filename"
|
||||
>
|
||||
<div class="filename-wrapper">
|
||||
<div
|
||||
[class.disabled]="isPending(fileStatus) || isProcessing(fileStatus)"
|
||||
[class.error]="isError(fileStatus)"
|
||||
class="table-item-title"
|
||||
>
|
||||
{{ fileStatus.filename }}
|
||||
</div>
|
||||
<span
|
||||
*ngIf="appStateService.fileNotUpToDateWithDictionary(fileStatus)"
|
||||
class="pill"
|
||||
translate="project-overview.new-rule.label"
|
||||
></span>
|
||||
</div>
|
||||
<span
|
||||
*ngIf="appStateService.fileNotUpToDateWithDictionary(fileStatus)"
|
||||
class="pill"
|
||||
translate="project-overview.new-rule.label"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div [class.error]="isError(fileStatus)" class="small-label">
|
||||
{{ fileStatus.added | date: 'd MMM. yyyy, hh:mm a' }}
|
||||
<div>
|
||||
<div [class.error]="isError(fileStatus)" class="small-label">
|
||||
{{ fileStatus.added | date: 'd MMM. yyyy, hh:mm a' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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"
|
||||
withName="true"
|
||||
></redaction-initials-avatar>
|
||||
</div>
|
||||
<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"
|
||||
withName="true"
|
||||
></redaction-initials-avatar>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!isError(fileStatus)" class="pages">
|
||||
<mat-icon svgIcon="red:pages"></mat-icon>
|
||||
{{ fileStatus.numberOfPages }}
|
||||
</div>
|
||||
<div *ngIf="!isError(fileStatus)" class="pages">
|
||||
<mat-icon svgIcon="red:pages"></mat-icon>
|
||||
{{ fileStatus.numberOfPages }}
|
||||
</div>
|
||||
|
||||
<div [class.extend-cols]="isError(fileStatus)" class="status-container">
|
||||
<div
|
||||
*ngIf="isError(fileStatus)"
|
||||
class="small-label error"
|
||||
translate="project-overview.file-listing.file-entry.file-error"
|
||||
></div>
|
||||
<div
|
||||
*ngIf="isPending(fileStatus)"
|
||||
class="small-label"
|
||||
translate="project-overview.file-listing.file-entry.file-pending"
|
||||
></div>
|
||||
<div
|
||||
*ngIf="isProcessing(fileStatus)"
|
||||
class="small-label"
|
||||
translate="processing"
|
||||
></div>
|
||||
<redaction-status-bar
|
||||
*ngIf="
|
||||
!isPending(fileStatus) &&
|
||||
!isProcessing(fileStatus) &&
|
||||
!isError(fileStatus)
|
||||
"
|
||||
[config]="[
|
||||
{
|
||||
color: fileStatus.status,
|
||||
length: 1
|
||||
}
|
||||
]"
|
||||
></redaction-status-bar>
|
||||
<div [class.extend-cols]="isError(fileStatus)" class="status-container">
|
||||
<div
|
||||
*ngIf="isError(fileStatus)"
|
||||
class="small-label error"
|
||||
translate="project-overview.file-listing.file-entry.file-error"
|
||||
></div>
|
||||
<div
|
||||
*ngIf="isPending(fileStatus)"
|
||||
class="small-label"
|
||||
translate="project-overview.file-listing.file-entry.file-pending"
|
||||
></div>
|
||||
<div
|
||||
*ngIf="isProcessing(fileStatus)"
|
||||
class="small-label"
|
||||
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)"
|
||||
*ngIf="
|
||||
userService.isManager(user) ||
|
||||
appStateService.isActiveProjectOwnerAndManager
|
||||
"
|
||||
[matTooltip]="'project-overview.delete.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:trash"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
(click)="downloadFileRedactionReport($event, fileStatus)"
|
||||
[matTooltip]="'project-overview.report.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:report"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
(click)="assignReviewer($event, fileStatus)"
|
||||
*ngIf="
|
||||
appStateService.isActiveProjectMember &&
|
||||
!isApprovedOrUnderApproval(fileStatus)
|
||||
"
|
||||
[matTooltip]="'project-overview.assign.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:assign"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
(click)="reanalyseFile($event, fileStatus)"
|
||||
*ngIf="!isApprovedOrUnderApproval(fileStatus)"
|
||||
[matTooltip]="'project-overview.reanalyse.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:refresh"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
(click)="requestApprovalOrApproveFile($event, fileStatus)"
|
||||
*ngIf="
|
||||
canApprove(fileStatus) &&
|
||||
appStateService.isActiveProjectOwnerAndManager
|
||||
"
|
||||
[matTooltip]="
|
||||
(fileStatus.status === 'UNDER_APPROVAL'
|
||||
? 'project-overview.approve'
|
||||
: 'project-overview.under-approval'
|
||||
) | translate
|
||||
"
|
||||
[matTooltipPosition]="'above'"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:check-alt"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
(click)="undoApproveOrUnderApproval($event, fileStatus)"
|
||||
*ngIf="
|
||||
isApprovedOrUnderApproval(fileStatus) &&
|
||||
appStateService.isActiveProjectOwnerAndManager
|
||||
"
|
||||
[matTooltip]="
|
||||
(fileStatus.status === 'APPROVED'
|
||||
? 'project-overview.under-approval'
|
||||
: 'project-overview.under-review'
|
||||
) | translate
|
||||
"
|
||||
[matTooltipPosition]="'above'"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:undo"></mat-icon>
|
||||
</button>
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
(click)="openDeleteFileDialog($event, fileStatus)"
|
||||
*ngIf="
|
||||
userService.isManager(user) ||
|
||||
appStateService.isActiveProjectOwnerAndManager
|
||||
"
|
||||
[matTooltip]="'project-overview.delete.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:trash"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
(click)="downloadFileRedactionReport($event, fileStatus)"
|
||||
[matTooltip]="'project-overview.report.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:report"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
(click)="assignReviewer($event, fileStatus)"
|
||||
*ngIf="
|
||||
appStateService.isActiveProjectMember &&
|
||||
!isApprovedOrUnderApproval(fileStatus)
|
||||
"
|
||||
[matTooltip]="'project-overview.assign.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:assign"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
(click)="reanalyseFile($event, fileStatus)"
|
||||
*ngIf="!isApprovedOrUnderApproval(fileStatus)"
|
||||
[matTooltip]="'project-overview.reanalyse.action' | translate"
|
||||
[matTooltipPosition]="'above'"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:refresh"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
(click)="requestApprovalOrApproveFile($event, fileStatus)"
|
||||
*ngIf="
|
||||
canApprove(fileStatus) &&
|
||||
appStateService.isActiveProjectOwnerAndManager
|
||||
"
|
||||
[matTooltip]="
|
||||
(fileStatus.status === 'UNDER_APPROVAL'
|
||||
? 'project-overview.approve'
|
||||
: 'project-overview.under-approval'
|
||||
) | translate
|
||||
"
|
||||
[matTooltipPosition]="'above'"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:check-alt"></mat-icon>
|
||||
</button>
|
||||
<button
|
||||
(click)="undoApproveOrUnderApproval($event, fileStatus)"
|
||||
*ngIf="
|
||||
isApprovedOrUnderApproval(fileStatus) &&
|
||||
appStateService.isActiveProjectOwnerAndManager
|
||||
"
|
||||
[matTooltip]="
|
||||
(fileStatus.status === 'APPROVED'
|
||||
? 'project-overview.under-approval'
|
||||
: 'project-overview.under-review'
|
||||
) | translate
|
||||
"
|
||||
[matTooltipPosition]="'above'"
|
||||
color="accent"
|
||||
mat-icon-button
|
||||
>
|
||||
<mat-icon svgIcon="red:undo"></mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-fixed-container">
|
||||
<redaction-project-details
|
||||
#projectDetailsComponent
|
||||
(reloadProjects)="reloadProjects()"
|
||||
></redaction-project-details>
|
||||
<div class="right-fixed-container">
|
||||
<redaction-project-details
|
||||
#projectDetailsComponent
|
||||
(reloadProjects)="reloadProjects()"
|
||||
></redaction-project-details>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -1,10 +1,6 @@
|
||||
@import '../../../assets/styles/red-variables';
|
||||
@import '../../../assets/styles/red-mixins';
|
||||
|
||||
.file-upload-input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.actions {
|
||||
.active {
|
||||
font-weight: 600;
|
||||
|
||||
@ -19,12 +19,11 @@ import { TranslateService } from '@ngx-translate/core';
|
||||
import { FileActionService } from '../file/service/file-action.service';
|
||||
import { FilterModel } from '../../common/filter/model/filter.model';
|
||||
import * as moment from 'moment';
|
||||
import { SortingComponent, SortingOption } from '../../components/sorting/sorting.component';
|
||||
import { SortingOption } from '../../components/sorting/sorting.component';
|
||||
import { ProjectDetailsComponent } from './project-details/project-details.component';
|
||||
import { FileStatusWrapper } from '../file/model/file-status.wrapper';
|
||||
import {
|
||||
annotationFilterChecker,
|
||||
fileAddedFilterChecker,
|
||||
getFilteredEntities,
|
||||
keyChecker
|
||||
} from '../../common/filter/utils/filter-utils';
|
||||
@ -40,12 +39,11 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
|
||||
|
||||
public statusFilters: FilterModel[];
|
||||
public peopleFilters: FilterModel[];
|
||||
// public addedDateFilters: FilterModel[];
|
||||
public needsWorkFilters: FilterModel[];
|
||||
|
||||
public displayedFiles: FileStatusWrapper[] = [];
|
||||
|
||||
@ViewChild('projectDetailsComponent', { static: true })
|
||||
@ViewChild('projectDetailsComponent', { static: false })
|
||||
private _projectDetailsComponent: ProjectDetailsComponent;
|
||||
|
||||
public sortingOption: SortingOption = { column: 'added', order: 'desc' };
|
||||
@ -161,7 +159,8 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
|
||||
private _calculateData(): void {
|
||||
this._computeAllFilters();
|
||||
this._filterFiles();
|
||||
this._projectDetailsComponent.calculateChartConfig();
|
||||
console.log('calculate parent');
|
||||
this._projectDetailsComponent?.calculateChartConfig();
|
||||
this._changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
|
||||
@ -215,6 +215,10 @@ export class AppStateService {
|
||||
return this._appState.projects;
|
||||
}
|
||||
|
||||
get hasProjects() {
|
||||
return this.allProjects?.length > 0;
|
||||
}
|
||||
|
||||
get activeFile(): FileStatusWrapper {
|
||||
return this._appState.activeFile;
|
||||
}
|
||||
@ -281,6 +285,9 @@ export class AppStateService {
|
||||
.toPromise();
|
||||
const oldFiles = [...project.files];
|
||||
|
||||
const fileStatusChangedEvent = [];
|
||||
const fileReanalysedEvent = [];
|
||||
|
||||
for (const file of files) {
|
||||
let found = false;
|
||||
for (const oldFile of oldFiles) {
|
||||
@ -291,10 +298,10 @@ export class AppStateService {
|
||||
file,
|
||||
this._userService.getNameForId(file.currentReviewer)
|
||||
);
|
||||
this.fileStatusChanged.emit(fileStatusWrapper);
|
||||
fileStatusChangedEvent.push(fileStatusWrapper);
|
||||
|
||||
if (oldFile.lastProcessed !== file.lastProcessed) {
|
||||
this.fileReanalysed.emit(fileStatusWrapper);
|
||||
fileReanalysedEvent.push(fileStatusWrapper);
|
||||
}
|
||||
}
|
||||
found = true;
|
||||
@ -303,12 +310,11 @@ export class AppStateService {
|
||||
}
|
||||
// emit for new file
|
||||
if (!found) {
|
||||
this.fileStatusChanged.emit(
|
||||
new FileStatusWrapper(
|
||||
file,
|
||||
this._userService.getNameForId(file.currentReviewer)
|
||||
)
|
||||
const fsw = new FileStatusWrapper(
|
||||
file,
|
||||
this._userService.getNameForId(file.currentReviewer)
|
||||
);
|
||||
fileStatusChangedEvent.push(fsw);
|
||||
}
|
||||
}
|
||||
|
||||
@ -317,6 +323,10 @@ export class AppStateService {
|
||||
);
|
||||
|
||||
this._computeStats();
|
||||
|
||||
fileReanalysedEvent.forEach((file) => this.fileReanalysed.emit(file));
|
||||
fileStatusChangedEvent.forEach((file) => this.fileStatusChanged.emit(file));
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
|
||||
@ -105,11 +105,17 @@ export class UserService {
|
||||
: undefined;
|
||||
}
|
||||
|
||||
isManager(user: User): boolean {
|
||||
isManager(user?: User): boolean {
|
||||
if (!user) {
|
||||
user = this.user;
|
||||
}
|
||||
return user.roles.indexOf('RED_MANAGER') >= 0;
|
||||
}
|
||||
|
||||
isUser(user: User): boolean {
|
||||
isUser(user?: User): boolean {
|
||||
if (!user) {
|
||||
user = this.user;
|
||||
}
|
||||
return user.roles.indexOf('RED_USER') >= 0;
|
||||
}
|
||||
|
||||
|
||||
@ -142,7 +142,7 @@
|
||||
"delete-failed": "Failed to delete project: {{projectName}}"
|
||||
},
|
||||
"add-new": "New Project",
|
||||
"no-projects": "You currently have no projects. You can start your work by creating a new one!",
|
||||
"no-projects": "You currently have no projects.",
|
||||
"no-projects-match": "No Projects match your current filters"
|
||||
},
|
||||
"file-details": {
|
||||
@ -172,6 +172,7 @@
|
||||
"no-files": "Project is empty!",
|
||||
"no-files-match": "No File match your current filters",
|
||||
"upload-files": "Drop files anywhere for upload!",
|
||||
"upload-files-btn": "Upload Files",
|
||||
"new-rule": {
|
||||
"label": "Outdated",
|
||||
"toast": {
|
||||
|
||||
@ -195,3 +195,13 @@ body {
|
||||
.pr-0 {
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
.empty-state-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
height: calc(100vh - 61px);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user