diff --git a/docs/content-services/components/file-uploading-dialog.component.md b/docs/content-services/components/file-uploading-dialog.component.md index f2ee3095f4..8bd600a8ef 100644 --- a/docs/content-services/components/file-uploading-dialog.component.md +++ b/docs/content-services/components/file-uploading-dialog.component.md @@ -22,6 +22,7 @@ Shows a dialog listing all the files uploaded with the Upload Button or Drag Are | Name | Type | Default value | Description | | --- | --- | --- | --- | | position | `string` | "right" | Dialog position. Can be 'left' or 'right'. | +| alwaysVisible | `boolean` | false | Dialog visibility. When true it makes the dialog visible even when there are no uploads. | ### Events diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.html b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.html index 3db0bcd541..974a5992c9 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.html +++ b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.html @@ -70,7 +70,7 @@ adf-highlight-selector=".adf-name-location-cell-name" [showHeader]="false" [node]="nodePaging" - [preselectNodes]="preselectNodes" + [preselectNodes]="preselectedNodes" [maxItems]="pageSize" [rowFilter]="_rowFilter" [imageResolver]="imageResolver" diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.spec.ts b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.spec.ts index 1cd6997d2f..8abb43ba14 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.spec.ts +++ b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.spec.ts @@ -16,10 +16,10 @@ */ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; -import { tick, ComponentFixture, TestBed, fakeAsync } from '@angular/core/testing'; +import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { NodeEntry, Node, SiteEntry, SitePaging, NodePaging, ResultSetPaging, RequestScope } from '@alfresco/js-api'; -import { SitesService, setupTestBed, NodesApiService } from '@alfresco/adf-core'; +import { Node, NodeEntry, NodePaging, RequestScope, ResultSetPaging, SiteEntry, SitePaging } from '@alfresco/js-api'; +import { FileModel, FileUploadStatus, NodesApiService, setupTestBed, SitesService, UploadService } from '@alfresco/adf-core'; import { of, throwError } from 'rxjs'; import { DropdownBreadcrumbComponent } from '../breadcrumb'; import { ContentNodeSelectorPanelComponent } from './content-node-selector-panel.component'; @@ -65,6 +65,7 @@ describe('ContentNodeSelectorPanelComponent', () => { const nodeEntryEvent = new NodeEntryEvent(fakeNodeEntry); let searchQueryBuilderService: SearchQueryBuilderService; let contentNodeSelectorPanelService: ContentNodeSelectorPanelService; + let uploadService: UploadService; function typeToSearchBox(searchTerm = 'string-to-search') { const searchInput = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-input"]')); @@ -95,6 +96,7 @@ describe('ContentNodeSelectorPanelComponent', () => { nodeService = TestBed.inject(NodesApiService); sitesService = TestBed.inject(SitesService); contentNodeSelectorPanelService = TestBed.inject(ContentNodeSelectorPanelService); + uploadService = TestBed.inject(UploadService); searchQueryBuilderService = component.queryBuilderService; component.queryBuilderService.resetToDefaults(); @@ -1171,6 +1173,31 @@ describe('ContentNodeSelectorPanelComponent', () => { }); }); + describe('interaction with upload functionality', () => { + let documentListService: DocumentListService; + + beforeEach(() => { + documentListService = TestBed.inject(DocumentListService); + + spyOn(documentListService, 'getFolderNode'); + spyOn(documentListService, 'getFolder'); + }); + + it('should remove the node from the chosenNodes when an upload gets deleted', () => { + fixture.detectChanges(); + const selectSpy = spyOn(component.select, 'next'); + const fakeFileModel = new FileModel( { name: 'fake-name', size: 10000000 }); + const fakeNodes = [ { id: 'fakeNodeId' }, { id: 'fakeNodeId2' }]; + fakeFileModel.data = { entry: fakeNodes[0] }; + fakeFileModel.status = FileUploadStatus.Deleted; + component._chosenNode = [...fakeNodes]; + uploadService.cancelUpload(fakeFileModel); + + expect(selectSpy).toHaveBeenCalledWith([fakeNodes[1]]); + expect(component._chosenNode).toEqual([fakeNodes[1]]); + }); + }); + }); describe('Search panel', () => { diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.ts b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.ts index d3161306d5..28f83ae3a0 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.ts +++ b/lib/content-services/src/lib/content-node-selector/content-node-selector-panel.component.ts @@ -34,7 +34,9 @@ import { NodesApiService, SitesService, UploadService, - FileUploadCompleteEvent + FileUploadCompleteEvent, + FileUploadDeleteEvent, + FileModel } from '@alfresco/adf-core'; import { FormControl } from '@angular/forms'; import { Node, NodePaging, Pagination, SiteEntry, SitePaging, NodeEntry, QueryBody, RequestScope } from '@alfresco/js-api'; @@ -247,7 +249,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy { searchInput: FormControl = new FormControl(); target: PaginatedComponent; - preselectNodes: NodeEntry[] = []; + preselectedNodes: NodeEntry[] = []; searchPanelExpanded: boolean = false; @@ -320,6 +322,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy { this.breadcrumbTransform = this.breadcrumbTransform ? this.breadcrumbTransform : null; this.isSelectionValid = this.isSelectionValid ? this.isSelectionValid : defaultValidation; this.onFileUploadEvent(); + this.onFileUploadDeletedEvent(); this.resetPagination(); this.setSearchScopeToNodes(); @@ -351,11 +354,30 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy { takeUntil(this.onDestroy$) ) .subscribe((uploadedFiles: FileUploadCompleteEvent[]) => { - this.preselectNodes = this.getPreselectNodesBasedOnSelectionMode(uploadedFiles); + this.preselectedNodes = this.getPreselectNodesBasedOnSelectionMode(uploadedFiles); this.documentList.reload(); }); } + private onFileUploadDeletedEvent() { + this.uploadService.fileUploadDeleted + .pipe(takeUntil(this.onDestroy$)) + .subscribe((deletedFileEvent: FileUploadDeleteEvent) => { + this.removeFromChosenNodes(deletedFileEvent.file); + this.documentList.reload(); + }); + } + + private removeFromChosenNodes(file: FileModel) { + if (this.chosenNode) { + const fileIndex = this.chosenNode.findIndex((chosenNode: Node) => chosenNode.id === file.data.entry.id); + if (fileIndex !== -1) { + this._chosenNode.splice(fileIndex, 1); + this.select.next(this._chosenNode); + } + } + } + private getStartSite() { this.nodesApiService.getNode(this.currentFolderId).subscribe((startNodeEntry) => { this.startSiteGuid = this.sitesService.getSiteNameFromNodePath(startNodeEntry); @@ -511,7 +533,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy { this.showingSearchResults = false; this.infiniteScroll = false; this.breadcrumbFolderTitle = null; - this.preselectNodes = []; + this.preselectedNodes = []; this.clearSearch(); this.navigationChange.emit($event); } @@ -573,7 +595,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy { */ onCurrentSelection(nodesEntries: NodeEntry[]): void { const validNodesEntity = nodesEntries.filter((node) => this.isSelectionValid(node.entry)); - this.chosenNode = validNodesEntity.map((node) => node.entry ); + this.chosenNode = validNodesEntity.map((node) => node.entry); } setTitleIfCustomSite(site: SiteEntry) { @@ -589,7 +611,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy { } hasPreselectNodes(): boolean { - return this.preselectNodes && this.preselectNodes.length > 0; + return this.preselectedNodes?.length > 0; } isSingleSelectionMode(): boolean { diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.html b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.html index 6be6d2a23c..8e80064152 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.html +++ b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.html @@ -8,7 +8,7 @@ mat-align-tabs="start" (selectedIndexChange)="onTabSelectionChange($event)" [class.adf-content-node-selector-headless-tabs]="!canPerformLocalUpload()"> - + + +
+ +
+
diff --git a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.scss b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.scss index 73d996a3b4..251cee15f2 100644 --- a/lib/content-services/src/lib/content-node-selector/content-node-selector.component.scss +++ b/lib/content-services/src/lib/content-node-selector/content-node-selector.component.scss @@ -9,6 +9,22 @@ display: none; } } + + .adf-upload-dialog { + + &__content { + max-height: 64%; + } + + height: 100%; + width: 100%; + position: unset; + bottom: unset; + } + + .adf-upload-dialog-container { + height: 456px; + } } .adf-content-node-selector-dialog { diff --git a/lib/content-services/src/lib/document-list/components/document-list.component.spec.ts b/lib/content-services/src/lib/document-list/components/document-list.component.spec.ts index 8712261828..7874b9c29e 100644 --- a/lib/content-services/src/lib/document-list/components/document-list.component.spec.ts +++ b/lib/content-services/src/lib/document-list/components/document-list.component.spec.ts @@ -1532,7 +1532,7 @@ describe('DocumentList', () => { spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_created.svg`); }); - it('should able to emit nodeSelected event with preselectNodes on the reload', async () => { + it('should able to emit nodeSelected event with preselectedNodes on the reload', async () => { const nodeSelectedSpy = spyOn(documentList.nodeSelected, 'emit'); fixture.detectChanges(); @@ -1548,7 +1548,7 @@ describe('DocumentList', () => { expect(nodeSelectedSpy).toHaveBeenCalled(); }); - it('should be able to select first node from the preselectNodes when selectionMode set to single', async () => { + it('should be able to select first node from the preselectedNodes when selectionMode set to single', async () => { documentList.selectionMode = 'single'; fixture.detectChanges(); @@ -1560,10 +1560,10 @@ describe('DocumentList', () => { await fixture.whenStable(); expect(documentList.preselectNodes.length).toBe(2); - expect(documentList.getPreselectNodesBasedOnSelectionMode().length).toBe(1); + expect(documentList.getPreselectedNodesBasedOnSelectionMode().length).toBe(1); }); - it('should be able to select all preselectNodes when selectionMode set to multiple', async () => { + it('should be able to select all preselectedNodes when selectionMode set to multiple', async () => { documentList.selectionMode = 'multiple'; fixture.detectChanges(); @@ -1575,13 +1575,14 @@ describe('DocumentList', () => { await fixture.whenStable(); expect(documentList.preselectNodes.length).toBe(2); - expect(documentList.getPreselectNodesBasedOnSelectionMode().length).toBe(2); + expect(documentList.getPreselectedNodesBasedOnSelectionMode().length).toBe(2); }); it('should call the datatable select row method for each preselected node', async () => { const datatableSelectRowSpy = spyOn(documentList.dataTable, 'selectRow'); const fakeDatatableRows = [new ShareDataRow(mockPreselectedNodes[0], contentService, null), new ShareDataRow(mockPreselectedNodes[1], contentService, null)]; - spyOn(documentList.data, 'getPreselectRows').and.returnValue(fakeDatatableRows); + spyOn(documentList.data, 'hasPreselectedRows').and.returnValue(true); + spyOn(documentList.data, 'getPreselectedRows').and.returnValue(fakeDatatableRows); documentList.selectionMode = 'multiple'; documentList.preselectNodes = mockPreselectedNodes; @@ -1593,7 +1594,7 @@ describe('DocumentList', () => { expect(datatableSelectRowSpy.calls.count()).toEqual(fakeDatatableRows.length); }); - it('should not emit nodeSelected event when preselectNodes is undefined/empty', async () => { + it('should not emit nodeSelected event when preselectedNodes is undefined/empty', async () => { const nodeSelectedSpy = spyOn(documentList.nodeSelected, 'emit'); fixture.detectChanges(); diff --git a/lib/content-services/src/lib/document-list/components/document-list.component.ts b/lib/content-services/src/lib/document-list/components/document-list.component.ts index fdb31ec8ad..c3081cb7c8 100644 --- a/lib/content-services/src/lib/document-list/components/document-list.component.ts +++ b/lib/content-services/src/lib/document-list/components/document-list.component.ts @@ -487,7 +487,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte if (this.data) { if (changes.node && changes.node.currentValue) { const merge = this._pagination ? this._pagination.merge : false; - this.data.loadPage(changes.node.currentValue, merge, null, this.getPreselectNodesBasedOnSelectionMode()); + this.data.loadPage(changes.node.currentValue, merge, null, this.getPreselectedNodesBasedOnSelectionMode()); this.onPreselectNodes(); this.onDataReady(changes.node.currentValue); } else if (changes.imageResolver) { @@ -501,7 +501,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte this.resetSelection(); if (this.node) { if (this.data) { - this.data.loadPage(this.node, this._pagination.merge, null, this.getPreselectNodesBasedOnSelectionMode()); + this.data.loadPage(this.node, this._pagination.merge, null, this.getPreselectedNodesBasedOnSelectionMode()); } this.onPreselectNodes(); this.syncPagination(); @@ -694,7 +694,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte onPageLoaded(nodePaging: NodePaging) { if (nodePaging) { if (this.data) { - this.data.loadPage(nodePaging, this._pagination.merge, this.allowDropFiles, this.getPreselectNodesBasedOnSelectionMode()); + this.data.loadPage(nodePaging, this._pagination.merge, this.allowDropFiles, this.getPreselectedNodesBasedOnSelectionMode()); } this.onPreselectNodes(); this.setLoadingState(false); @@ -800,7 +800,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte } onNodeSelect(event: { row: ShareDataRow, selection: Array }) { - this.selection = event.selection.map((entry) => entry.node); + this.selection = event.selection.filter(entry => entry.node).map((entry) => entry.node); const domEvent = new CustomEvent('node-select', { detail: { node: event.row ? event.row.node : null, @@ -919,13 +919,13 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte this.error.emit(err); } - getPreselectNodesBasedOnSelectionMode(): NodeEntry[] { - return this.hasPreselectNodes() ? (this.isSingleSelectionMode() ? [this.preselectNodes[0]] : this.preselectNodes) : []; + getPreselectedNodesBasedOnSelectionMode(): NodeEntry[] { + return this.hasPreselectedNodes() ? (this.isSingleSelectionMode() ? [this.preselectNodes[0]] : this.preselectNodes) : []; } onPreselectNodes() { - if (this.hasPreselectNodes()) { - const preselectedNodes = [...this.isSingleSelectionMode() ? [this.data.getPreselectRows()[0]] : this.data.getPreselectRows()]; + if (this.data.hasPreselectedRows()) { + const preselectedNodes = [...this.isSingleSelectionMode() ? [this.data.getPreselectedRows()[0]] : this.data.getPreselectedRows()]; const selectedNodes = [...this.selection, ...preselectedNodes]; for (const node of preselectedNodes) { @@ -939,7 +939,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte return this.selectionMode === 'single'; } - hasPreselectNodes(): boolean { - return this.preselectNodes && this.preselectNodes.length > 0; + hasPreselectedNodes(): boolean { + return this.preselectNodes?.length > 0; } } diff --git a/lib/content-services/src/lib/document-list/data/share-datatable-adapter.spec.ts b/lib/content-services/src/lib/document-list/data/share-datatable-adapter.spec.ts index b5a2ca2b29..b4027eb037 100644 --- a/lib/content-services/src/lib/document-list/data/share-datatable-adapter.spec.ts +++ b/lib/content-services/src/lib/document-list/data/share-datatable-adapter.spec.ts @@ -16,7 +16,7 @@ */ import { DataColumn, DataRow, DataSorting, ContentService, ThumbnailService, setupTestBed } from '@alfresco/adf-core'; -import { FileNode, FolderNode, SmartFolderNode, RuleFolderNode, LinkFolderNode, mockPreselectedNodes, mockNodePagingWithPreselectedNodes, mockNode2, fakeNodePaging } from './../../mock'; +import { FileNode, FolderNode, SmartFolderNode, RuleFolderNode, LinkFolderNode, mockPreselectedNodes, mockNodePagingWithPreselectedNodes, mockNode2, fakeNodePaging, mockNode1 } from './../../mock'; import { ShareDataRow } from './share-data-row.model'; import { ShareDataTableAdapter } from './share-datatable-adapter'; import { ContentTestingModule } from '../../testing/content.testing.module'; @@ -484,28 +484,38 @@ describe('ShareDataTableAdapter', () => { describe('Preselect rows', () => { - it('should set isSelected to be true for each preselectRow if the preselectNodes are defined', () => { + it('should set isSelected to be true for each preselectRow if the preselectedNodes are defined', () => { const adapter = new ShareDataTableAdapter(thumbnailService, contentService, []); adapter.loadPage(mockNodePagingWithPreselectedNodes, null, null, mockPreselectedNodes); - expect(adapter.getPreselectRows().length).toBe(1); - expect(adapter.getPreselectRows()[0].isSelected).toBe(true); + expect(adapter.getPreselectedRows().length).toBe(1); + expect(adapter.getPreselectedRows()[0].isSelected).toBe(true); }); - it('should set preselectRows empty if preselectedNodes are undefined/empty', () => { + it('should set preselectedRows empty if preselectedNodes are undefined/empty', () => { const adapter = new ShareDataTableAdapter(thumbnailService, contentService, []); adapter.loadPage(mockNodePagingWithPreselectedNodes, null, null, []); - expect(adapter.getPreselectRows().length).toBe(0); + expect(adapter.getPreselectedRows().length).toBe(0); }); - it('should set preselectRows empty if preselectedNodes are not found in the list', () => { + it('should set preselectedRows empty if preselectedNodes are not found in the list', () => { const adapter = new ShareDataTableAdapter(thumbnailService, contentService, []); mockNode2.id = 'mock-file-id'; const preselectedNode = [ { entry: mockNode2 }]; adapter.loadPage(fakeNodePaging, null, null, preselectedNode); - expect(adapter.getPreselectRows().length).toBe(0); + expect(adapter.getPreselectedRows().length).toBe(0); + }); + + it('should preselected rows contain only the valid rows that exist in the datatable', () => { + const adapter = new ShareDataTableAdapter(thumbnailService, contentService, []); + const nonExistingEntry = {...mockNode1}; + nonExistingEntry.id = 'non-existing-entry-id'; + const preselectedNodes = [{ entry: nonExistingEntry }, { entry: mockNode1 }, { entry: mockNode2 }]; + adapter.loadPage(mockNodePagingWithPreselectedNodes, null, null, preselectedNodes); + + expect(adapter.getPreselectedRows().length).toBe(2); }); }); }); diff --git a/lib/content-services/src/lib/document-list/data/share-datatable-adapter.ts b/lib/content-services/src/lib/document-list/data/share-datatable-adapter.ts index d4a2e4e499..953b3cfb47 100644 --- a/lib/content-services/src/lib/document-list/data/share-datatable-adapter.ts +++ b/lib/content-services/src/lib/document-list/data/share-datatable-adapter.ts @@ -45,7 +45,7 @@ export class ShareDataTableAdapter implements DataTableAdapter { permissionsStyle: PermissionStyleModel[]; selectedRow: DataRow; allowDropFiles: boolean; - preselectRows: DataRow[] = []; + preselectedRows: DataRow[] = []; set sortingMode(value: string) { let newValue = (value || 'client').toLowerCase(); @@ -82,8 +82,8 @@ export class ShareDataTableAdapter implements DataTableAdapter { this.sort(); } - getPreselectRows(): Array { - return this.preselectRows; + getPreselectedRows(): Array { + return this.preselectedRows; } getColumns(): Array { @@ -208,7 +208,7 @@ export class ShareDataTableAdapter implements DataTableAdapter { } private getNodeAspectNames(node: any): any[] { - return node.entry && node.entry.aspectNames ? node.entry.aspectNames : node.aspectNames ? node.aspectNames : []; + return node.entry?.aspectNames ? node.entry.aspectNames : (node.aspectNames ? node.aspectNames : []); } private sortRows(rows: DataRow[], sorting: DataSorting) { @@ -218,7 +218,7 @@ export class ShareDataTableAdapter implements DataTableAdapter { const options: Intl.CollatorOptions = {}; - if (sorting && sorting.key && rows && rows.length > 0) { + if (sorting?.key && rows?.length) { if (sorting.key.includes('sizeInBytes') || sorting.key === 'name') { options.numeric = true; @@ -255,9 +255,9 @@ export class ShareDataTableAdapter implements DataTableAdapter { if (allowDropFiles !== undefined) { this.allowDropFiles = allowDropFiles; } - if (nodePaging && nodePaging.list) { + if (nodePaging?.list) { const nodeEntries: NodeEntry[] = nodePaging.list.entries; - if (nodeEntries && nodeEntries.length > 0) { + if (nodeEntries?.length) { shareDataRows = nodeEntries.map((item) => new ShareDataRow(item, this.contentService, this.permissionsStyle, this.thumbnailService, this.allowDropFiles)); @@ -267,7 +267,7 @@ export class ShareDataTableAdapter implements DataTableAdapter { if (this.sortingMode !== 'server') { // Sort by first sortable or just first column - if (this.columns && this.columns.length > 0) { + if (this.columns?.length) { const sorting = this.getSorting(); if (sorting) { this.sortRows(shareDataRows, sorting); @@ -302,7 +302,7 @@ export class ShareDataTableAdapter implements DataTableAdapter { } selectRowsBasedOnGivenNodes(preselectNodes: NodeEntry[]) { - if (preselectNodes && preselectNodes.length > 0) { + if (preselectNodes?.length) { this.rows = this.rows.map((row) => { preselectNodes.map((preselectedNode) => { if (row.obj.entry.id === preselectedNode.entry.id) { @@ -313,7 +313,11 @@ export class ShareDataTableAdapter implements DataTableAdapter { }); } - this.preselectRows = [...this.rows.filter((res) => res.isSelected)]; + this.preselectedRows = [...this.rows.filter((res) => res.isSelected)]; + } + + hasPreselectedRows(): boolean { + return this.preselectedRows?.length > 0; } } diff --git a/lib/content-services/src/lib/i18n/en.json b/lib/content-services/src/lib/i18n/en.json index 6d0756609f..9c74f4175f 100644 --- a/lib/content-services/src/lib/i18n/en.json +++ b/lib/content-services/src/lib/i18n/en.json @@ -89,7 +89,7 @@ "SELECT_LOCATION": "Select Location", "UPLOAD_BUTTON_SEARCH_WARNING_MESSAGE": "You can't upload a file whilst a search is still running", "UPLOAD_BUTTON_PERMISSION_WARNING_MESSAGE": "User doesn't have permission to upload content to the folder", - "FILE_SERVER": "File server", + "REPOSITORY": "Repository", "UPLOAD_FROM_DEVICE": "Upload from your device" }, "OPERATION": { diff --git a/lib/content-services/src/lib/upload/components/file-uploading-dialog.component.html b/lib/content-services/src/lib/upload/components/file-uploading-dialog.component.html index eec0bece7c..10250969ba 100644 --- a/lib/content-services/src/lib/upload/components/file-uploading-dialog.component.html +++ b/lib/content-services/src/lib/upload/components/file-uploading-dialog.component.html @@ -1,4 +1,4 @@ -
{{ 'ADF_FILE_UPLOAD.BUTTON.CANCEL_ALL' | translate }}