From c5feae5de3b358ba66351a6d5d37743d7f9ba7aa Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Fri, 4 Aug 2017 14:55:15 +0100 Subject: [PATCH] [ADF-1300] Download as Zip feature and dialog (#2174) * Download API demo - download single selected file - download multiple selected files as ZIP - download one or multiple selected folders as ZIP - download all mixed content as ZIP (file + folder) * download dialog (first cut) * code cleanup --- demo-shell-ng2/app/app.module.ts | 8 +- .../app/components/files/files.component.html | 16 +- .../app/components/files/files.component.ts | 82 +++++++++- .../app/dialogs/download-zip.dialog.ts | 145 ++++++++++++++++++ demo-shell-ng2/app/material.module.ts | 11 +- 5 files changed, 249 insertions(+), 13 deletions(-) create mode 100644 demo-shell-ng2/app/dialogs/download-zip.dialog.ts diff --git a/demo-shell-ng2/app/app.module.ts b/demo-shell-ng2/app/app.module.ts index cb8adc16ab..a5e4fa05bd 100644 --- a/demo-shell-ng2/app/app.module.ts +++ b/demo-shell-ng2/app/app.module.ts @@ -40,10 +40,12 @@ import { ChartsModule } from 'ng2-charts'; import { AppComponent } from './app.component'; import { routing } from './app.routes'; import { CustomEditorsModule } from './components/activiti/custom-editor/custom-editor.component'; -import { CreateFolderDialogComponent } from './dialogs/create-folder.dialog'; import { MaterialModule } from './material.module'; import { DebugAppConfigService } from './services/debug-app-config.service'; +import { CreateFolderDialogComponent } from './dialogs/create-folder.dialog'; +import { DownloadZipDialogComponent } from './dialogs/download-zip.dialog'; + import { FormListDemoComponent } from './components/form/form-list-demo.component'; import { @@ -120,6 +122,7 @@ if (process.env.ENV === 'production') { FilesComponent, FormNodeViewerComponent, CreateFolderDialogComponent, + DownloadZipDialogComponent, SettingsComponent, FormDemoComponent, FormListDemoComponent @@ -129,7 +132,8 @@ if (process.env.ENV === 'production') { ], bootstrap: [ AppComponent ], entryComponents: [ - CreateFolderDialogComponent + CreateFolderDialogComponent, + DownloadZipDialogComponent ] }) export class AppModule { } diff --git a/demo-shell-ng2/app/components/files/files.component.html b/demo-shell-ng2/app/components/files/files.component.html index 5b918760ac..9487ad1528 100644 --- a/demo-shell-ng2/app/components/files/files.component.html +++ b/demo-shell-ng2/app/components/files/files.component.html @@ -27,9 +27,17 @@ [folderNode]="documentList.folderNode"> - + + + `, + styles: [` + .spacer { flex: 1 1 auto; } + + .adf-download-zip-dialog .mat-dialog-actions .mat-button-wrapper { + text-transform: uppercase; + } + `], + host: { 'class': 'adf-download-zip-dialog' }, + encapsulation: ViewEncapsulation.None +}) +export class DownloadZipDialogComponent implements OnInit { + + // flag for async threads + private cancelled = false; + + constructor(private apiService: AlfrescoApiService, + private dialogRef: MdDialogRef, + @Inject(MD_DIALOG_DATA) private data: { nodeIds?: string[] }) { + } + + private get downloadsApi() { + return this.apiService.getInstance().core.downloadsApi; + } + + private get nodesApi() { + return this.apiService.getInstance().core.nodesApi; + } + + private get contentApi() { + return this.apiService.getInstance().content; + } + + ngOnInit() { + if (this.data && this.data.nodeIds && this.data.nodeIds.length > 0) { + // change timeout to have a delay for demo purposes + setTimeout(() => { + if (!this.cancelled) { + this.downloadZip(this.data.nodeIds); + } else { + console.log('Cancelled'); + } + }, 0); + } + } + + cancelDownload() { + this.cancelled = true; + this.dialogRef.close(false); + } + + // Download as ZIP prototype + // js-api@alpha 1.8.0-c422a3b69b1b96f72abc61ab370eff53590f8ee4 + downloadZip(nodeIds: string[]) { + if (nodeIds && nodeIds.length > 0) { + + const promise: any = this.downloadsApi.createDownload({ nodeIds }); + + promise.on('progress', progress => console.log('Progress', progress)); + promise.on('error', error => console.log('Error', error)); + promise.on('abort', data => console.log('Abort', data)); + + promise.on('success', (data: DownloadEntry) => { + console.log('Success', data); + if (data && data.entry && data.entry.id) { + const url = this.contentApi.getContentUrl(data.entry.id, true); + // the call is needed only to get the name of the package + this.nodesApi.getNode(data.entry.id).then((downloadNode: MinimalNodeEntity) => { + console.log(downloadNode); + const fileName = downloadNode.entry.name; + // this.download(url, fileName); + this.waitAndDownload(data.entry.id, url, fileName); + }); + } + }); + } + } + + waitAndDownload(downloadId: string, url: string, fileName: string) { + if (this.cancelled) { + return; + } + + this.downloadsApi.getDownload(downloadId).then((d: DownloadEntry) => { + if (d.entry) { + if (d.entry.status === 'DONE') { + this.download(url, fileName); + } else { + setTimeout(() => { + this.waitAndDownload(downloadId, url, fileName); + }, 1000); + } + } + }); + } + + download(url: string, fileName: string) { + if (url && fileName) { + const link = document.createElement('a'); + + link.style.display = 'none'; + link.download = fileName; + link.href = url; + + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } + this.dialogRef.close(true); + } +} diff --git a/demo-shell-ng2/app/material.module.ts b/demo-shell-ng2/app/material.module.ts index 1e4b3a185b..98ef17108b 100644 --- a/demo-shell-ng2/app/material.module.ts +++ b/demo-shell-ng2/app/material.module.ts @@ -16,13 +16,20 @@ */ import { NgModule } from '@angular/core'; -import { MdDialogModule, MdInputModule, MdSelectModule, MdSlideToggleModule } from '@angular/material'; +import { + MdDialogModule, + MdInputModule, + MdProgressBarModule, + MdSelectModule, + MdSlideToggleModule +} from '@angular/material'; const MATERIAL_MODULES = [ MdSlideToggleModule, MdInputModule, MdSelectModule, - MdDialogModule + MdDialogModule, + MdProgressBarModule ]; @NgModule({