Pull request #67: RED-858: Show download-all button if all files are in APPROVED state

Merge in RED/ui from RED-858 to master

* commit '1e145809c59e76b04452d73a5d36c2d059de78f6':
  RED-858: Show download-all button if all files are in APPROVED state
This commit is contained in:
Timo Bejan 2020-12-13 16:48:05 +01:00
commit 58ad467180
6 changed files with 75 additions and 14 deletions

View File

@ -194,7 +194,8 @@ export class PermissionsService {
if (!fileStatus) { if (!fileStatus) {
fileStatus = this._appStateService.activeFile; fileStatus = this._appStateService.activeFile;
} }
return fileStatus.status === 'APPROVED' && this.isManagerAndOwner(); const project = this._appStateService.getProjectById(fileStatus.projectId);
return fileStatus.status === 'APPROVED' && this.isManagerAndOwner(project);
} }
canDeleteProject(project?: ProjectWrapper) { canDeleteProject(project?: ProjectWrapper) {

View File

@ -152,12 +152,18 @@
icon="red:refresh" icon="red:refresh"
> >
</redaction-circle-button> </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>
<div class="scrollbar-placeholder"></div> <div class="scrollbar-placeholder"></div>
</div> </div>
<!-- <redaction-virtual-scroll></redaction-virtual-scroll>-->
</div> </div>
</div> </div>

View File

@ -1,9 +1,9 @@
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { Project } from '@redaction/red-ui-http'; 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 { groupBy, humanize } from '../../utils/functions'; import { computerize, 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,6 +25,7 @@ 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',
@ -60,7 +61,8 @@ export class ProjectListingScreenComponent implements OnInit, OnDestroy {
private readonly _router: Router, private readonly _router: Router,
public readonly sortingService: SortingService, public readonly sortingService: SortingService,
public readonly translateChartService: TranslateChartService, public readonly translateChartService: TranslateChartService,
private readonly _formBuilder: FormBuilder private readonly _formBuilder: FormBuilder,
private readonly _fileManagementControllerService: FileManagementControllerService
) { ) {
this.searchForm = this._formBuilder.group({ this.searchForm = this._formBuilder.group({
query: [''] query: ['']
@ -257,7 +259,12 @@ export class ProjectListingScreenComponent implements OnInit, OnDestroy {
const filters = [ const filters = [
{ values: this.statusFilters, checker: projectStatusChecker }, { values: this.statusFilters, checker: projectStatusChecker },
{ values: this.peopleFilters, checker: projectMemberChecker }, { values: this.peopleFilters, checker: projectMemberChecker },
{ values: this.needsWorkFilters, checker: annotationFilterChecker, matchAll: true, checkerArgs: this.permissionsService } {
values: this.needsWorkFilters,
checker: annotationFilterChecker,
matchAll: true,
checkerArgs: this.permissionsService
}
]; ];
return getFilteredEntities(this.appStateService.allProjects, filters); return getFilteredEntities(this.appStateService.allProjects, filters);
} }
@ -282,4 +289,18 @@ export class ProjectListingScreenComponent implements OnInit, OnDestroy {
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);
}
} }

View File

@ -69,6 +69,15 @@
tooltipPosition="below" tooltipPosition="below"
icon="red:refresh" icon="red:refresh"
></redaction-circle-button> ></redaction-circle-button>
<redaction-circle-button
(action)="downloadRedactedFiles()"
*ngIf="canDownloadRedactedFiles"
tooltip="project-overview.header-actions.download-redacted-files"
tooltipPosition="below"
icon="red:download"
></redaction-circle-button>
<redaction-circle-button <redaction-circle-button
class="ml-14" class="ml-14"
(action)="fileInput.click()" (action)="fileInput.click()"

View File

@ -1,12 +1,12 @@
import { ChangeDetectorRef, Component, HostListener, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { NotificationService, NotificationType } from '../../notification/notification.service'; import { NotificationService } from '../../notification/notification.service';
import { AppStateService } from '../../state/app-state.service'; import { AppStateService } from '../../state/app-state.service';
import { FileDropOverlayService } from '../../upload/file-drop/service/file-drop-overlay.service'; import { FileDropOverlayService } from '../../upload/file-drop/service/file-drop-overlay.service';
import { FileUploadModel } from '../../upload/model/file-upload.model'; import { FileUploadModel } from '../../upload/model/file-upload.model';
import { FileUploadService } from '../../upload/file-upload.service'; import { FileUploadService } from '../../upload/file-upload.service';
import { UploadStatusOverlayService } from '../../upload/upload-status-dialog/service/upload-status-overlay.service'; import { UploadStatusOverlayService } from '../../upload/upload-status-dialog/service/upload-status-overlay.service';
import { humanize } from '../../utils/functions'; import { computerize, humanize } from '../../utils/functions';
import { DialogService } from '../../dialogs/dialog.service'; import { DialogService } from '../../dialogs/dialog.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { FileActionService } from '../file/service/file-action.service'; import { FileActionService } from '../file/service/file-action.service';
@ -18,13 +18,14 @@ import { annotationFilterChecker, getFilteredEntities, keyChecker, processFilter
import { SortingOption, SortingService } from '../../utils/sorting.service'; import { SortingOption, SortingService } from '../../utils/sorting.service';
import { PermissionsService } from '../../common/service/permissions.service'; import { PermissionsService } from '../../common/service/permissions.service';
import { UserService } from '../../user/user.service'; import { UserService } from '../../user/user.service';
import { FileStatus } from '@redaction/red-ui-http'; import { FileManagementControllerService, FileStatus } from '@redaction/red-ui-http';
import { Subscription, timer } from 'rxjs'; import { Subscription, timer } from 'rxjs';
import { tap } from 'rxjs/operators'; import { tap } from 'rxjs/operators';
import { RedactionFilterSorter } from '../../common/sorters/redaction-filter-sorter'; import { RedactionFilterSorter } from '../../common/sorters/redaction-filter-sorter';
import { StatusSorter } from '../../common/sorters/status-sorter'; import { StatusSorter } from '../../common/sorters/status-sorter';
import { FormBuilder, FormGroup, Validators } 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-overview-screen', selector: 'redaction-project-overview-screen',
@ -65,7 +66,8 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
private readonly _changeDetectorRef: ChangeDetectorRef, private readonly _changeDetectorRef: ChangeDetectorRef,
private readonly _translateService: TranslateService, private readonly _translateService: TranslateService,
private readonly _fileDropOverlayService: FileDropOverlayService, private readonly _fileDropOverlayService: FileDropOverlayService,
private readonly _formBuilder: FormBuilder private readonly _formBuilder: FormBuilder,
private readonly _fileManagementControllerService: FileManagementControllerService
) { ) {
this.searchForm = this._formBuilder.group({ this.searchForm = this._formBuilder.group({
query: [''] query: ['']
@ -331,4 +333,22 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
public toggleCollapsedDetails() { public toggleCollapsedDetails() {
this.collapsedDetails = !this.collapsedDetails; this.collapsedDetails = !this.collapsedDetails;
} }
// Download Files
public downloadRedactedFiles() {
this._fileManagementControllerService
.downloadRedactedFiles(
{ fileIds: this.appStateService.activeProject.files.map((file) => file.fileId) },
this.appStateService.activeProjectId,
false,
'response'
)
.subscribe((data) => {
download(data, 'redacted_files_' + computerize(this.appStateService.activeProject.name) + '.zip');
});
}
public get canDownloadRedactedFiles() {
return this.appStateService.activeProject.files.reduce((acc, file) => acc && this.permissionsService.canDownloadRedactedFile(file), true);
}
} }

View File

@ -77,6 +77,9 @@
"assign": { "assign": {
"action": "Assign Owner & Members" "action": "Assign Owner & Members"
}, },
"download-files": {
"action": "Download Redacted Files"
},
"table-header": { "table-header": {
"title": "{{length}} active projects", "title": "{{length}} active projects",
"bulk-select": "Toggle Selection", "bulk-select": "Toggle Selection",
@ -155,7 +158,8 @@
"edit": "Edit", "edit": "Edit",
"delete": "Delete", "delete": "Delete",
"assign": "Assign Owner & Members", "assign": "Assign Owner & Members",
"upload-document": "Upload Document" "upload-document": "Upload Document",
"download-redacted-files": "Download Redacted Files"
}, },
"download-redacted-file": "Download Redacted File", "download-redacted-file": "Download Redacted File",
"download-redacted-files": "Download Redacted Files", "download-redacted-files": "Download Redacted Files",