diff --git a/src/app/components/upload-dialog/file-uploading-dialog.component.ts b/src/app/components/upload-dialog/file-uploading-dialog.component.ts
new file mode 100644
index 000000000..129ec1f50
--- /dev/null
+++ b/src/app/components/upload-dialog/file-uploading-dialog.component.ts
@@ -0,0 +1,24 @@
+/*!
+ * @license
+ * Copyright 2016 Alfresco Software, Ltd.
+ *
+ * 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.
+ */
+
+import { Component } from '@angular/core';
+import { FileUploadingDialogComponent } from '@alfresco/adf-content-services';
+@Component({
+ selector: 'app-file-uploading-dialog',
+ templateUrl: './file-uploading-dialog.component.html'
+})
+export class AppFileUploadingDialogComponent extends FileUploadingDialogComponent {}
diff --git a/src/app/components/upload-dialog/file-uploading-list-row.component.html b/src/app/components/upload-dialog/file-uploading-list-row.component.html
new file mode 100644
index 000000000..315f70bfd
--- /dev/null
+++ b/src/app/components/upload-dialog/file-uploading-list-row.component.html
@@ -0,0 +1,109 @@
+
diff --git a/src/app/components/upload-dialog/file-uploading-list-row.component.ts b/src/app/components/upload-dialog/file-uploading-list-row.component.ts
new file mode 100644
index 000000000..688fc82ed
--- /dev/null
+++ b/src/app/components/upload-dialog/file-uploading-list-row.component.ts
@@ -0,0 +1,48 @@
+/*!
+ * @license
+ * Copyright 2016 Alfresco Software, Ltd.
+ *
+ * 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.
+ */
+
+import { Component } from '@angular/core';
+import { FileUploadingListRowComponent } from '@alfresco/adf-content-services';
+@Component({
+ selector: 'app-file-uploading-list-row',
+ templateUrl: './file-uploading-list-row.component.html'
+})
+export class AppFileUploadingListRowComponent extends FileUploadingListRowComponent {
+ isUploadVersion() {
+ return (
+ !!this.file.data &&
+ this.file.options &&
+ this.file.options.newVersion &&
+ this.file.data.entry.properties &&
+ this.file.data.entry.properties['cm:versionLabel']
+ );
+ }
+
+ // todo: move to ADF 3.x.x
+ get versionNumber() {
+ return this.file.data.entry.properties['cm:versionLabel'];
+ }
+
+ // todo: move to ADF 3.x.x
+ get mimeType(): string {
+ if (this.file && this.file.file && this.file.file.type) {
+ return this.file.file.type;
+ }
+
+ return 'default';
+ }
+}
diff --git a/src/app/components/upload-dialog/file-uploading-list.component.html b/src/app/components/upload-dialog/file-uploading-list.component.html
new file mode 100644
index 000000000..475b084b1
--- /dev/null
+++ b/src/app/components/upload-dialog/file-uploading-list.component.html
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/app/components/upload-dialog/file-uploading-list.component.ts b/src/app/components/upload-dialog/file-uploading-list.component.ts
new file mode 100644
index 000000000..da8ea0add
--- /dev/null
+++ b/src/app/components/upload-dialog/file-uploading-list.component.ts
@@ -0,0 +1,224 @@
+/*!
+ * @license
+ * Copyright 2016 Alfresco Software, Ltd.
+ *
+ * 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.
+ */
+
+import {
+ FileModel,
+ FileUploadStatus,
+ NodesApiService,
+ AlfrescoApiService,
+ TranslationService,
+ UploadService
+} from '@alfresco/adf-core';
+import {
+ Component,
+ ContentChild,
+ Input,
+ Output,
+ TemplateRef,
+ EventEmitter
+} from '@angular/core';
+import { Observable, forkJoin, of, from } from 'rxjs';
+import { map, catchError } from 'rxjs/operators';
+
+@Component({
+ selector: 'app-file-uploading-list',
+ templateUrl: './file-uploading-list.component.html'
+})
+export class AppFileUploadingListComponent {
+ FileUploadStatus = FileUploadStatus;
+
+ @ContentChild(TemplateRef)
+ template: any;
+
+ @Input()
+ files: FileModel[] = [];
+
+ /** Emitted when a file in the list has an error. */
+ @Output()
+ error: EventEmitter = new EventEmitter();
+
+ constructor(
+ private alfrescoApiService: AlfrescoApiService,
+ private uploadService: UploadService,
+ private nodesApi: NodesApiService,
+ private translateService: TranslationService
+ ) {}
+
+ /**
+ * Cancel file upload
+ *
+ * @param file File model to cancel upload for.
+ *
+ * @memberOf FileUploadingListComponent
+ */
+ cancelFile(file: FileModel): void {
+ this.uploadService.cancelUpload(file);
+ }
+
+ // todo: move to ADF 3.x.x
+ removeFile(file: FileModel): void {
+ if (file.options && file.options.newVersion) {
+ this.deleteNodeVersion(file).subscribe(() => {
+ if (file.status === FileUploadStatus.Error) {
+ this.notifyError(file);
+ }
+ this.uploadService.cancelUpload(file);
+ });
+ } else {
+ this.deleteNode(file).subscribe(() => {
+ if (file.status === FileUploadStatus.Error) {
+ this.notifyError(file);
+ }
+
+ this.cancelNodeVersionInstances(file);
+ this.uploadService.cancelUpload(file);
+ });
+ }
+ }
+
+ /**
+ * Call the appropriate method for each file, depending on state
+ */
+ cancelAllFiles(): void {
+ this.getUploadingFiles().forEach(file =>
+ this.uploadService.cancelUpload(file)
+ );
+
+ const deletedFiles = this.files
+ .filter(file => file.status === FileUploadStatus.Complete)
+ .map(file => this.deleteNode(file));
+
+ forkJoin(...deletedFiles).subscribe((files: FileModel[]) => {
+ const errors = files.filter(
+ file => file.status === FileUploadStatus.Error
+ );
+
+ if (errors.length) {
+ this.notifyError(...errors);
+ }
+
+ this.uploadService.cancelUpload(...files);
+ });
+ }
+
+ /**
+ * Checks if all the files are uploaded false if there is at least one file in Progress | Starting | Pending
+ */
+ isUploadCompleted(): boolean {
+ return (
+ !this.isUploadCancelled() &&
+ Boolean(this.files.length) &&
+ !this.files.some(
+ ({ status }) =>
+ status === FileUploadStatus.Starting ||
+ status === FileUploadStatus.Progress ||
+ status === FileUploadStatus.Pending
+ )
+ );
+ }
+
+ /**
+ * Check if all the files are Cancelled | Aborted | Error. false if there is at least one file in uploading states
+ */
+ isUploadCancelled(): boolean {
+ return (
+ !!this.files.length &&
+ this.files.every(
+ ({ status }) =>
+ status === FileUploadStatus.Aborted ||
+ status === FileUploadStatus.Cancelled ||
+ status === FileUploadStatus.Deleted
+ )
+ );
+ }
+
+ // todo: move to ADF 3.x.x
+ private deleteNodeVersion(file: FileModel): Observable {
+ return from(
+ this.alfrescoApiService.versionsApi.deleteVersion(
+ file.data.entry.id,
+ file.data.entry.properties['cm:versionLabel']
+ )
+ ).pipe(
+ map(() => {
+ file.status = FileUploadStatus.Deleted;
+ return file;
+ }),
+ catchError(() => {
+ file.status = FileUploadStatus.Error;
+ return of(file);
+ })
+ );
+ }
+
+ // todo: move to ADF 3.x.x
+ private cancelNodeVersionInstances(file) {
+ this.files
+ .filter(
+ item =>
+ item.data.entry.id === file.data.entry.id && item.options.newVersion
+ )
+ .map(item => {
+ item.status = FileUploadStatus.Deleted;
+ });
+ }
+
+ private deleteNode(file: FileModel): Observable {
+ const { id } = file.data.entry;
+
+ return this.nodesApi.deleteNode(id, { permanent: true }).pipe(
+ map(() => {
+ file.status = FileUploadStatus.Deleted;
+ return file;
+ }),
+ catchError(() => {
+ file.status = FileUploadStatus.Error;
+ return of(file);
+ })
+ );
+ }
+
+ private notifyError(...files: FileModel[]) {
+ let messageError: string = null;
+
+ if (files.length === 1) {
+ messageError = this.translateService.instant(
+ 'FILE_UPLOAD.MESSAGES.REMOVE_FILE_ERROR',
+ { fileName: files[0].name }
+ );
+ } else {
+ messageError = this.translateService.instant(
+ 'FILE_UPLOAD.MESSAGES.REMOVE_FILES_ERROR',
+ { total: files.length }
+ );
+ }
+
+ this.error.emit(messageError);
+ }
+
+ private getUploadingFiles() {
+ return this.files.filter(item => {
+ if (
+ item.status === FileUploadStatus.Pending ||
+ item.status === FileUploadStatus.Progress ||
+ item.status === FileUploadStatus.Starting
+ ) {
+ return item;
+ }
+ });
+ }
+}
diff --git a/src/app/components/upload-dialog/upload.module.ts b/src/app/components/upload-dialog/upload.module.ts
new file mode 100644
index 000000000..12e3060d2
--- /dev/null
+++ b/src/app/components/upload-dialog/upload.module.ts
@@ -0,0 +1,47 @@
+/*!
+ * @license
+ * Alfresco Example Content Application
+ *
+ * Copyright (C) 2005 - 2018 Alfresco Software Limited
+ *
+ * This file is part of the Alfresco Example Content Application.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * The Alfresco Example Content Application is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The Alfresco Example Content Application is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { CoreModule } from '@alfresco/adf-core';
+import { AppFileUploadingDialogComponent } from './file-uploading-dialog.component';
+import { AppFileUploadingListRowComponent } from './file-uploading-list-row.component';
+import { AppFileUploadingListComponent } from './file-uploading-list.component';
+import { UploadModule } from '@alfresco/adf-content-services';
+
+@NgModule({
+ imports: [CommonModule, CoreModule.forChild(), UploadModule],
+ declarations: [
+ AppFileUploadingDialogComponent,
+ AppFileUploadingListRowComponent,
+ AppFileUploadingListComponent
+ ],
+ exports: [
+ AppFileUploadingDialogComponent,
+ AppFileUploadingListRowComponent,
+ AppFileUploadingListComponent
+ ]
+})
+export class AppUploadingDialogModule {}
diff --git a/src/app/ui/overrides/adf-upload-dialog.theme.scss b/src/app/ui/overrides/adf-upload-dialog.theme.scss
index 9dca64b86..364f2f44c 100644
--- a/src/app/ui/overrides/adf-upload-dialog.theme.scss
+++ b/src/app/ui/overrides/adf-upload-dialog.theme.scss
@@ -7,6 +7,28 @@
z-index: 999;
}
+ // todo: move to ADF 3.x.x
+ .adf-file-uploading-row {
+ &__group,
+ &__block {
+ min-width: 100px;
+ display: flex;
+ justify-content: flex-end;
+ }
+
+ &__version {
+ flex: 0;
+
+ .mat-chip {
+ padding: 2px 6px;
+ }
+
+ .mat-chip.mat-chip-disabled {
+ opacity: 1;
+ }
+ }
+ }
+
.adf-file-uploading-row {
&__status {
&--done {
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index 6f214673e..83e55abe5 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -467,6 +467,11 @@
"INFO": "View details"
}
},
+ "FILE_UPLOAD": {
+ "ERRORS": {
+ "409": "This name is already in use, try a different name [409]"
+ }
+ },
"ADF_VERSION_LIST": {
"ACTIONS": {
"UPLOAD": {