mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[MNT-24128] in ADW/ADF, when downloading a ZIP from a selection of files and folders, display a progress bar (#9957)
This commit is contained in:
@@ -1,6 +1,12 @@
|
|||||||
<h1 matDialogTitle>{{ 'CORE.DIALOG.DOWNLOAD_ZIP.TITLE' | translate }}</h1>
|
<h1 matDialogTitle>{{ 'CORE.DIALOG.DOWNLOAD_ZIP.TITLE' | translate }}</h1>
|
||||||
<div mat-dialog-content>
|
<div mat-dialog-content class="adf-dialog-content">
|
||||||
<mat-progress-bar color="primary" mode="indeterminate"></mat-progress-bar>
|
<mat-progress-bar value="{{ percentageDone }}" color="primary" mode="determinate"></mat-progress-bar>
|
||||||
|
<div class="adf-dialog-content-progress-text">
|
||||||
|
<span class="adf-dialog-content-progress-text-percentage">
|
||||||
|
{{ percentageDone }}%
|
||||||
|
</span>
|
||||||
|
{{ 'CORE.DIALOG.DOWNLOAD_ZIP.COMPLETE' | translate }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<mat-dialog-actions align="end">
|
<mat-dialog-actions align="end">
|
||||||
<button class="adf-download-zip-dialog-button" mat-button color="primary" id="cancel-button" (click)="cancelDownload()">
|
<button class="adf-download-zip-dialog-button" mat-button color="primary" id="cancel-button" (click)="cancelDownload()">
|
||||||
|
@@ -1,3 +1,15 @@
|
|||||||
.adf-download-zip-dialog-button {
|
.adf-download-zip-dialog-button {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.adf-dialog-content:has(.adf-dialog-content-progress-text) {
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.adf-dialog-content-progress-text {
|
||||||
|
margin-top: 4px;
|
||||||
|
|
||||||
|
&-percentage {
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -19,6 +19,7 @@ import { TestBed, ComponentFixture } from '@angular/core/testing';
|
|||||||
import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
||||||
import { DownloadZipDialogComponent } from './download-zip.dialog';
|
import { DownloadZipDialogComponent } from './download-zip.dialog';
|
||||||
import { DownloadZipService } from './services/download-zip.service';
|
import { DownloadZipService } from './services/download-zip.service';
|
||||||
|
import { DownloadEntry, FileDownloadStatus } from '@alfresco/js-api';
|
||||||
import { EMPTY, Observable, of } from 'rxjs';
|
import { EMPTY, Observable, of } from 'rxjs';
|
||||||
import { AlfrescoApiService, AlfrescoApiServiceMock, RedirectAuthService, TranslationMock, TranslationService } from '@alfresco/adf-core';
|
import { AlfrescoApiService, AlfrescoApiServiceMock, RedirectAuthService, TranslationMock, TranslationService } from '@alfresco/adf-core';
|
||||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||||
@@ -167,4 +168,28 @@ describe('DownloadZipDialogComponent', () => {
|
|||||||
expect(component.cancelDownload).toHaveBeenCalled();
|
expect(component.cancelDownload).toHaveBeenCalled();
|
||||||
expect(component.download).not.toHaveBeenCalled();
|
expect(component.download).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should waitForDownload and display correct download %', () => {
|
||||||
|
const downloadEntry$: Observable<DownloadEntry> = new Observable((observer) => {
|
||||||
|
observer.next({
|
||||||
|
entry: {
|
||||||
|
filesAdded: 10,
|
||||||
|
bytesAdded: 1000,
|
||||||
|
id: '1',
|
||||||
|
totalFiles: 10,
|
||||||
|
totalBytes: 1000,
|
||||||
|
status: FileDownloadStatus.DONE
|
||||||
|
}
|
||||||
|
});
|
||||||
|
observer.complete();
|
||||||
|
});
|
||||||
|
|
||||||
|
const downloadZipSpy = spyOn(downloadZipService, 'getDownload').and.callFake(() => downloadEntry$);
|
||||||
|
|
||||||
|
component.waitAndDownload('1', 'testUrl', 'filename');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(downloadZipSpy).toHaveBeenCalledWith('1');
|
||||||
|
expect(component.percentageDone).toBe(100);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -19,6 +19,7 @@ import { Component, Input, OnInit, OnChanges } from '@angular/core';
|
|||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { DownloadZipDialogComponent } from './download-zip.dialog';
|
import { DownloadZipDialogComponent } from './download-zip.dialog';
|
||||||
import { zipNode, downloadEntry } from './mock/download-zip-data.mock';
|
import { zipNode, downloadEntry } from './mock/download-zip-data.mock';
|
||||||
|
import { FileDownloadStatus } from '@alfresco/js-api';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-download-zip-dialog-storybook',
|
selector: 'adf-download-zip-dialog-storybook',
|
||||||
@@ -40,9 +41,9 @@ export class DownloadZipDialogStorybookComponent implements OnInit, OnChanges {
|
|||||||
|
|
||||||
setEntryStatus(isLoading: boolean) {
|
setEntryStatus(isLoading: boolean) {
|
||||||
if (!isLoading) {
|
if (!isLoading) {
|
||||||
downloadEntry.entry.status = 'DONE';
|
downloadEntry.entry.status = FileDownloadStatus.DONE;
|
||||||
} else {
|
} else {
|
||||||
downloadEntry.entry.status = 'PACKING';
|
downloadEntry.entry.status = FileDownloadStatus.IN_PROGRESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,6 +20,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
|||||||
import { NodesApiService } from '../../common/services/nodes-api.service';
|
import { NodesApiService } from '../../common/services/nodes-api.service';
|
||||||
import { DownloadZipService } from './services/download-zip.service';
|
import { DownloadZipService } from './services/download-zip.service';
|
||||||
import { ContentService } from '../../common/services/content.service';
|
import { ContentService } from '../../common/services/content.service';
|
||||||
|
import { FileDownloadStatus } from '@alfresco/js-api';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-download-zip-dialog',
|
selector: 'adf-download-zip-dialog',
|
||||||
@@ -32,6 +33,7 @@ export class DownloadZipDialogComponent implements OnInit {
|
|||||||
// flag for async threads
|
// flag for async threads
|
||||||
cancelled = false;
|
cancelled = false;
|
||||||
downloadId: string;
|
downloadId: string;
|
||||||
|
percentageDone = 0;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private dialogRef: MatDialogRef<DownloadZipDialogComponent>,
|
private dialogRef: MatDialogRef<DownloadZipDialogComponent>,
|
||||||
@@ -79,7 +81,12 @@ export class DownloadZipDialogComponent implements OnInit {
|
|||||||
|
|
||||||
this.downloadZipService.getDownload(downloadId).subscribe((downloadEntry) => {
|
this.downloadZipService.getDownload(downloadId).subscribe((downloadEntry) => {
|
||||||
if (downloadEntry.entry) {
|
if (downloadEntry.entry) {
|
||||||
if (downloadEntry.entry.status === 'DONE') {
|
if (downloadEntry.entry.status === FileDownloadStatus.IN_PROGRESS) {
|
||||||
|
this.percentageDone = Number(((downloadEntry.entry.bytesAdded * 100) / downloadEntry.entry.totalBytes).toFixed(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (downloadEntry.entry.status === FileDownloadStatus.DONE) {
|
||||||
|
this.percentageDone = 100;
|
||||||
this.download(url, fileName);
|
this.download(url, fileName);
|
||||||
} else {
|
} else {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@@ -107,7 +107,8 @@
|
|||||||
"ACTIONS": {
|
"ACTIONS": {
|
||||||
"CANCEL": "Cancel"
|
"CANCEL": "Cancel"
|
||||||
},
|
},
|
||||||
"TITLE": "Adding files to zip, this could take a few minutes"
|
"TITLE": "Adding files to zip, this could take a few minutes",
|
||||||
|
"COMPLETE": "complete"
|
||||||
},
|
},
|
||||||
"EDIT_JSON": {
|
"EDIT_JSON": {
|
||||||
"CLOSE": "Close",
|
"CLOSE": "Close",
|
||||||
|
26
lib/js-api/src/api/content-rest-api/model/download-status.ts
Normal file
26
lib/js-api/src/api/content-rest-api/model/download-status.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const FileDownloadStatus = {
|
||||||
|
PENDING: 'PENDING',
|
||||||
|
CANCELLED: 'CANCELLED',
|
||||||
|
IN_PROGRESS: 'IN_PROGRESS',
|
||||||
|
DONE: 'DONE',
|
||||||
|
MAX_CONTENT_SIZE_EXCEEDED: 'MAX_CONTENT_SIZE_EXCEEDED'
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type DownloadStatus = keyof typeof FileDownloadStatus;
|
@@ -15,6 +15,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { DownloadStatus } from './download-status';
|
||||||
|
|
||||||
export interface Download {
|
export interface Download {
|
||||||
/**
|
/**
|
||||||
* number of files added so far in the zip
|
* number of files added so far in the zip
|
||||||
@@ -39,5 +41,5 @@ export interface Download {
|
|||||||
/**
|
/**
|
||||||
* the current status of the download node creation
|
* the current status of the download node creation
|
||||||
*/
|
*/
|
||||||
status?: 'PENDING' | 'CANCELLED' | 'IN_PROGRESS' | 'DONE' | 'MAX_CONTENT_SIZE_EXCEEDED' | string;
|
status?: DownloadStatus;
|
||||||
}
|
}
|
||||||
|
@@ -68,6 +68,7 @@ export * from './deletedNodesPagingList';
|
|||||||
export * from './directAccessUrl';
|
export * from './directAccessUrl';
|
||||||
export * from './directAccessUrlEntry';
|
export * from './directAccessUrlEntry';
|
||||||
export * from './download';
|
export * from './download';
|
||||||
|
export * from './download-status';
|
||||||
export * from './downloadBodyCreate';
|
export * from './downloadBodyCreate';
|
||||||
export * from './downloadEntry';
|
export * from './downloadEntry';
|
||||||
export * from './errorError';
|
export * from './errorError';
|
||||||
|
Reference in New Issue
Block a user