diff --git a/demo-shell/src/app/components/files/files.component.html b/demo-shell/src/app/components/files/files.component.html
index ba891abda0..8db9dd3ecf 100644
--- a/demo-shell/src/app/components/files/files.component.html
+++ b/demo-shell/src/app/components/files/files.component.html
@@ -13,6 +13,7 @@
[currentFolderId]="'-recent-'"
locationFormat="/files"
[display]="'gallery'"
+ [preselectNodes]="selectedNodes"
[showHeader]="false"
[maxItems]="5"
(preview)="showFile($event)"
@@ -221,6 +222,7 @@
[contentActions]="true"
[allowDropFiles]="allowDropFiles"
[selectionMode]="selectionMode"
+ [preselectNodes]="selectedNodes"
[multiselect]="multiselect"
[display]="displayMode"
[node]="nodeResult"
@@ -550,7 +552,7 @@
-
+
{{'DOCUMENT_LIST.MULTIPLE_FILE_UPLOAD' | translate}}
@@ -643,6 +645,21 @@
+
+
+
+
Upload
diff --git a/demo-shell/src/app/components/files/files.component.scss b/demo-shell/src/app/components/files/files.component.scss
index 79bb0c0db7..db5b54b3fa 100644
--- a/demo-shell/src/app/components/files/files.component.scss
+++ b/demo-shell/src/app/components/files/files.component.scss
@@ -88,4 +88,8 @@
justify-content: center;
}
}
+
+ .adf-preselect-nodes-input {
+ width: 100%;
+ }
}
diff --git a/demo-shell/src/app/components/files/files.component.ts b/demo-shell/src/app/components/files/files.component.ts
index 6f654785b6..6b4c4afbe2 100644
--- a/demo-shell/src/app/components/files/files.component.ts
+++ b/demo-shell/src/app/components/files/files.component.ts
@@ -23,13 +23,14 @@ import { Location } from '@angular/common';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Params, Router } from '@angular/router';
-import { MinimalNodeEntity, NodePaging, Pagination, MinimalNodeEntryEntity, SiteEntry, SearchEntry } from '@alfresco/js-api';
+import { MinimalNodeEntity, NodePaging, Pagination, MinimalNodeEntryEntity, SiteEntry, SearchEntry, NodeEntry } from '@alfresco/js-api';
import {
AlfrescoApiService, AuthenticationService, AppConfigService, AppConfigValues, ContentService, TranslationService, FolderCreatedEvent, LogService, NotificationService,
UploadService, DataRow, UserPreferencesService,
PaginationComponent, FormValues, DisplayMode, ShowHeaderMode, InfinitePaginationComponent, HighlightDirective,
SharedLinksApiService,
- FormRenderingService
+ FormRenderingService,
+ FileUploadEvent
} from '@alfresco/adf-core';
import {
@@ -47,7 +48,7 @@ import { VersionManagerDialogAdapterComponent } from './version-manager-dialog-a
import { MetadataDialogAdapterComponent } from './metadata-dialog-adapter.component';
import { Subject } from 'rxjs';
import { PreviewService } from '../../services/preview.service';
-import { takeUntil } from 'rxjs/operators';
+import { takeUntil, debounceTime, scan } from 'rxjs/operators';
const DEFAULT_FOLDER_TO_SHOW = '-my-';
@@ -208,6 +209,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
permissionsStyle: PermissionStyleModel[] = [];
infiniteScrolling: boolean;
stickyHeader: boolean;
+ preselectNodes: boolean;
warnOnMultipleUploads = false;
thumbnails = false;
@@ -216,6 +218,8 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
displayEmptyMetadata = false;
hyperlinkNavigation = false;
+ selectedNodes = [];
+
constructor(private notificationService: NotificationService,
private uploadService: UploadService,
private contentService: ContentService,
@@ -277,6 +281,33 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
});
}
+ this.uploadService.fileUploadComplete
+ .pipe(
+ debounceTime(300),
+ scan((files, currentFile) => [...files, currentFile], []),
+ takeUntil(this.onDestroy$)
+ )
+ .subscribe((value: any[]) => {
+ let selectedNodes: NodeEntry[] = [];
+
+ if (this.preselectNodes) {
+ if (value && value.length > 0 ) {
+ if (this.selectionMode === 'single') {
+ selectedNodes = [...[value[value.length - 1]].map((uploadedFile) => uploadedFile.data)];
+ } else {
+ selectedNodes = [...value.map((uploadedFile) => uploadedFile.data)];
+ }
+ this.selectedNodes = [...selectedNodes];
+ }
+ }
+
+ this.onFileUploadEvent(value[0]);
+ });
+
+ this.uploadService.fileUploadDeleted
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(value => this.onFileUploadEvent(value));
+
this.contentService.folderCreated
.pipe(takeUntil(this.onDestroy$))
.subscribe(value => this.onFolderCreated(value));
@@ -302,6 +333,12 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
});
}
+ onFileUploadEvent(event: FileUploadEvent) {
+ if (event && event.file.options.parentId === this.documentList.currentFolderId) {
+ this.documentList.reload();
+ }
+ }
+
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
@@ -669,4 +706,30 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
this.router.navigate([], { relativeTo: this.route, queryParams: objectFromMap });
}
+ setPreselectNodes(nodes: string) {
+ this.selectedNodes = this.getArrayFromString(nodes);
+ this.documentList.reload();
+ }
+
+ isStringArray(str: string): boolean {
+ try {
+ const result = JSON.parse(str);
+ return Array.isArray(result);
+ } catch (e) {
+ return false;
+ }
+ }
+
+ private getArrayFromString(value: string): T[] {
+ if (this.isStringArray(value)) {
+ return JSON.parse(value);
+ } else {
+ return [];
+ }
+ }
+
+ onMultipleFilesUpload() {
+ this.selectedNodes = [];
+ }
+
}
diff --git a/docs/content-services/components/document-list.component.md b/docs/content-services/components/document-list.component.md
index d0b7af639d..16b81339e1 100644
--- a/docs/content-services/components/document-list.component.md
+++ b/docs/content-services/components/document-list.component.md
@@ -73,6 +73,7 @@ Displays the documents from a repository.
| navigationMode | `string` | | [User](../../../lib/core/pipes/user-initial.pipe.ts) interaction for folder navigation or file preview. Valid values are "click" and "dblclick". Default value: "dblclick" |
| node | [`NodePaging`](https://github.com/Alfresco/alfresco-js-api/blob/develop/src/api/content-rest-api/docs/NodePaging.md) | null | The Document list will show all the nodes contained in the [NodePaging](https://github.com/Alfresco/alfresco-js-api/blob/develop/src/api/content-rest-api/docs/NodePaging.md) entity |
| permissionsStyle | [`PermissionStyleModel`](../../../lib/content-services/src/lib/document-list/models/permissions-style.model.ts)`[]` | \[] | Define a set of CSS styles to apply depending on the permission of the user on that node. See the [Permission Style model](../../../lib/content-services/src/lib/document-list/models/permissions-style.model.ts) page for further details and examples. |
+| preselectNodes | [`NodeEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/alfresco-core-rest-api/docs/NodeEntry.md) `[]` | \[] | Array of nodes to preselect . |
| rowStyle | `string` | | The inline style to apply to every row. See the Angular NgStyle docs for more details and usage examples. |
| rowStyleClass | `string` | | The CSS class to apply to every row |
| selectionMode | `string` | "single" | Row selection mode. Can be null, `single` or `multiple`. For `multiple` mode, you can use Cmd (macOS) or Ctrl (Win) modifier key to toggle selection for multiple rows. |
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 ad626731a4..23592e57e1 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
@@ -61,6 +61,7 @@
adf-highlight-selector=".adf-name-location-cell-name"
[showHeader]="false"
[node]="nodePaging"
+ [preselectNodes]="preselectNodes"
[maxItems]="pageSize"
[rowFilter]="_rowFilter"
[imageResolver]="imageResolver"
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 d4fec5ac1b..4719de8554 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
@@ -23,7 +23,9 @@ import {
UserPreferenceValues,
InfinitePaginationComponent, PaginatedComponent,
NodesApiService,
- SitesService
+ SitesService,
+ UploadService,
+ FileUploadCompleteEvent
} from '@alfresco/adf-core';
import { FormControl } from '@angular/forms';
import { Node, NodePaging, Pagination, SiteEntry, SitePaging, NodeEntry } from '@alfresco/js-api';
@@ -31,7 +33,7 @@ import { DocumentListComponent } from '../document-list/components/document-list
import { RowFilter } from '../document-list/data/row-filter.model';
import { ImageResolver } from '../document-list/data/image-resolver.model';
import { ContentNodeSelectorService } from './content-node-selector.service';
-import { debounceTime, takeUntil } from 'rxjs/operators';
+import { debounceTime, takeUntil, scan } from 'rxjs/operators';
import { CustomResourcesService } from '../document-list/services/custom-resources.service';
import { NodeEntryEvent, ShareDataRow } from '../document-list';
import { Subject } from 'rxjs';
@@ -222,6 +224,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
searchInput: FormControl = new FormControl();
target: PaginatedComponent;
+ preselectNodes: NodeEntry[] = [];
private onDestroy$ = new Subject();
@@ -229,6 +232,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
private customResourcesService: CustomResourcesService,
private userPreferencesService: UserPreferencesService,
private nodesApiService: NodesApiService,
+ private uploadService: UploadService,
private sitesService: SitesService) {
}
@@ -267,6 +271,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
this.breadcrumbTransform = this.breadcrumbTransform ? this.breadcrumbTransform : null;
this.isSelectionValid = this.isSelectionValid ? this.isSelectionValid : defaultValidation;
+ this.onFileUploadEvent();
}
ngOnDestroy() {
@@ -274,6 +279,19 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
this.onDestroy$.complete();
}
+ private onFileUploadEvent() {
+ this.uploadService.fileUploadComplete
+ .pipe(
+ debounceTime(300),
+ scan((files, currentFile) => [...files, currentFile], []),
+ takeUntil(this.onDestroy$)
+ )
+ .subscribe((uploadedFiles: FileUploadCompleteEvent[]) => {
+ this.preselectNodes = this.getPreselectNodesBasedOnSelectionMode(uploadedFiles);
+ this.documentList.reload();
+ });
+ }
+
private getStartSite() {
this.nodesApiService.getNode(this.currentFolderId).subscribe((startNodeEntry) => {
this.startSiteGuid = this.sitesService.getSiteNameFromNodePath(startNodeEntry);
@@ -363,7 +381,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
this.searchTerm = '';
this.nodePaging = null;
this.pagination.maxItems = this.pageSize;
- this.chosenNode = null;
+ this.resetChosenNode();
this.showingSearchResults = false;
}
@@ -434,6 +452,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
this.showingSearchResults = false;
this.infiniteScroll = false;
this.breadcrumbFolderTitle = null;
+ this.preselectNodes = [];
this.clearSearch();
this.navigationChange.emit($event);
}
@@ -476,8 +495,6 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
private attemptNodeSelection(entry: Node): void {
if (entry && this.isSelectionValid(entry)) {
this.chosenNode = [entry];
- } else {
- this.resetChosenNode();
}
}
@@ -510,4 +527,26 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
this.breadcrumbFolderTitle = null;
}
}
+
+ hasPreselectNodes(): boolean {
+ return this.preselectNodes && this.preselectNodes.length > 0;
+ }
+
+ isSingleSelectionMode(): boolean {
+ return this.selectionMode === 'single';
+ }
+
+ private getPreselectNodesBasedOnSelectionMode(uploadedFiles: FileUploadCompleteEvent[]): NodeEntry[] {
+ let selectedNodes: NodeEntry[] = [];
+
+ if (uploadedFiles && uploadedFiles.length > 0 ) {
+ if (this.isSingleSelectionMode()) {
+ selectedNodes = [...[uploadedFiles[uploadedFiles.length - 1]].map((uploadedFile) => uploadedFile.data)];
+ } else {
+ selectedNodes = [...uploadedFiles.map((uploadedFile) => uploadedFile.data)];
+ }
+ }
+
+ return selectedNodes;
+ }
}
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 34d4e3d9e6..61f9a5d7d2 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
@@ -26,7 +26,8 @@ import {
DataTableComponent,
DataTableModule,
ObjectDataTableAdapter,
- ShowHeaderMode
+ ShowHeaderMode,
+ ThumbnailService
} from '@alfresco/adf-core';
import { Subject, of, throwError } from 'rxjs';
import {
@@ -34,7 +35,9 @@ import {
fakeNodeAnswerWithNOEntries,
fakeNodeWithNoPermission,
fakeGetSitesAnswer,
- fakeGetSiteMembership
+ fakeGetSiteMembership,
+ mockPreselectedNodes,
+ mockNodePagingWithPreselectedNodes
} from '../../mock';
import { ContentActionModel } from '../models/content-action.model';
import { NodeMinimal, NodeMinimalEntry, NodePaging } from '../models/document-library.model';
@@ -56,6 +59,7 @@ describe('DocumentList', () => {
let documentListService: DocumentListService;
let apiService: AlfrescoApiService;
let customResourcesService: CustomResourcesService;
+ let thumbnailService: ThumbnailService;
let fixture: ComponentFixture;
let element: HTMLElement;
let eventMock: any;
@@ -86,6 +90,7 @@ describe('DocumentList', () => {
documentListService = TestBed.inject(DocumentListService);
apiService = TestBed.inject(AlfrescoApiService);
customResourcesService = TestBed.inject(CustomResourcesService);
+ thumbnailService = TestBed.inject(ThumbnailService);
spyFolder = spyOn(documentListService, 'getFolder').and.callFake(() => {
return Promise.resolve({ list: {} });
@@ -1515,6 +1520,74 @@ describe('DocumentList', () => {
where: undefined
}), undefined);
});
+
+ describe('Preselect nodes', () => {
+
+ beforeEach(() => {
+ spyOn(thumbnailService, 'getMimeTypeIcon').and.returnValue(`assets/images/ft_ic_created.svg`);
+ });
+
+ it('should able to emit nodeSelected event with preselectNodes on the reload', async () => {
+ const nodeSelectedSpy = spyOn(documentList.nodeSelected, 'emit');
+
+ fixture.detectChanges();
+
+ documentList.node = mockNodePagingWithPreselectedNodes;
+ documentList.preselectNodes = mockPreselectedNodes;
+ documentList.reload();
+
+ fixture.detectChanges();
+ await fixture.whenStable();
+
+ expect(documentList.preselectNodes.length).toBe(2);
+ expect(nodeSelectedSpy).toHaveBeenCalled();
+ });
+
+ it('should able to select first node from the preselectNodes when selectionMode set to single', async () => {
+ documentList.selectionMode = 'single';
+ fixture.detectChanges();
+
+ documentList.node = mockNodePagingWithPreselectedNodes;
+ documentList.preselectNodes = mockPreselectedNodes;
+ documentList.reload();
+
+ fixture.detectChanges();
+ await fixture.whenStable();
+
+ expect(documentList.preselectNodes.length).toBe(2);
+ expect(documentList.getPreselectNodesBasedOnSelectionMode().length).toBe(1);
+ });
+
+ it('should able to select all preselectNodes when selectionMode set to multiple', async () => {
+ documentList.selectionMode = 'multiple';
+ fixture.detectChanges();
+
+ documentList.node = mockNodePagingWithPreselectedNodes;
+ documentList.preselectNodes = mockPreselectedNodes;
+ documentList.reload();
+
+ fixture.detectChanges();
+ await fixture.whenStable();
+
+ expect(documentList.preselectNodes.length).toBe(2);
+ expect(documentList.getPreselectNodesBasedOnSelectionMode().length).toBe(2);
+ });
+
+ it('should not emit nodeSelected event when preselectNodes undefined/empty', async () => {
+ const nodeSelectedSpy = spyOn(documentList.nodeSelected, 'emit');
+
+ fixture.detectChanges();
+
+ documentList.node = mockNodePagingWithPreselectedNodes;
+ documentList.preselectNodes = [];
+ documentList.reload();
+
+ fixture.detectChanges();
+ await fixture.whenStable();
+
+ expect(nodeSelectedSpy).not.toHaveBeenCalled();
+ });
+ });
});
@Component({
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 079c7faefe..d6b50c14c2 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
@@ -46,7 +46,7 @@ import {
AlfrescoApiService,
UserPreferenceValues,
LockService,
- UploadService
+ DataRow
} from '@alfresco/adf-core';
import { Node, NodeEntry, NodePaging, Pagination } from '@alfresco/js-api';
@@ -61,7 +61,7 @@ import { NavigableComponentInterface } from '../../breadcrumb/navigable-componen
import { RowFilter } from '../data/row-filter.model';
import { DocumentListService } from '../services/document-list.service';
import { DocumentLoaderNode } from '../models/document-folder.model';
-import { debounceTime, takeUntil } from 'rxjs/operators';
+import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-document-list',
@@ -259,6 +259,13 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
@Input()
currentFolderId: string = null;
+ /** Array of nodes to be pre-selected. All nodes in the
+ * array are pre-selected in multi selection mode, but only the first node
+ * is pre-selected in single selection mode.
+ */
+ @Input()
+ preselectNodes: NodeEntry[] = [];
+
/** The Document list will show all the nodes contained in the NodePaging entity */
@Input()
node: NodePaging = null;
@@ -327,7 +334,6 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
private appConfig: AppConfigService,
private userPreferencesService: UserPreferencesService,
private contentService: ContentService,
- private uploadService: UploadService,
private thumbnailService: ThumbnailService,
private alfrescoApiService: AlfrescoApiService,
private lockService: LockService) {
@@ -337,18 +343,6 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
.subscribe(pagSize => {
this.maxItems = this._pagination.maxItems = pagSize;
});
-
- this.uploadService.fileUploadComplete
- .pipe(
- debounceTime(300),
- takeUntil(this.onDestroy$))
- .subscribe(() => this.reload());
-
- this.uploadService.fileUploadDeleted
- .pipe(
- debounceTime(300),
- takeUntil(this.onDestroy$))
- .subscribe(() => this.reload());
}
getContextActions(node: NodeEntry) {
@@ -469,7 +463,8 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
if (changes['currentFolderId']?.currentValue !== changes['currentFolderId']?.previousValue) {
if (this.data) {
- this.data.loadPage(null, false);
+ this.data.loadPage(null, false, null, this.getPreselectNodesBasedOnSelectionMode());
+ this.onPreselectNodes();
this.resetNewFolderPagination();
}
@@ -483,7 +478,8 @@ 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);
+ this.data.loadPage(changes.node.currentValue, merge, null, this.getPreselectNodesBasedOnSelectionMode());
+ this.onPreselectNodes();
this.onDataReady(changes.node.currentValue);
} else if (changes.imageResolver) {
this.data.setImageResolver(changes.imageResolver.currentValue);
@@ -495,7 +491,8 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
this.ngZone.run(() => {
this.resetSelection();
if (this.node) {
- this.data.loadPage(this.node, this._pagination.merge);
+ this.data.loadPage(this.node, this._pagination.merge, null, this.getPreselectNodesBasedOnSelectionMode());
+ this.onPreselectNodes();
this.onDataReady(this.node);
} else {
this.loadFolder();
@@ -685,7 +682,8 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
onPageLoaded(nodePaging: NodePaging) {
if (nodePaging) {
- this.data.loadPage(nodePaging, this._pagination.merge, this.allowDropFiles);
+ this.data.loadPage(nodePaging, this._pagination.merge, this.allowDropFiles, this.getPreselectNodesBasedOnSelectionMode());
+ this.onPreselectNodes();
this.setLoadingState(false);
this.onDataReady(nodePaging);
}
@@ -787,7 +785,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
this.selection = event.selection.map((entry) => entry.node);
const domEvent = new CustomEvent('node-select', {
detail: {
- node: event.row.node,
+ node: event.row ? event.row.node : null,
selection: this.selection
},
bubbles: true
@@ -898,4 +896,40 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
this.setLoadingState(false);
this.error.emit(err);
}
+
+ getPreselectNodesBasedOnSelectionMode(): NodeEntry[] {
+ let selectedNodes: NodeEntry[] = [];
+
+ if (this.hasPreselectNodes()) {
+ if (this.isSingleSelectionMode()) {
+ selectedNodes = [this.preselectNodes[0]];
+ } else {
+ selectedNodes = this.preselectNodes;
+ }
+ }
+
+ return selectedNodes;
+ }
+
+ private onPreselectNodes() {
+ if (this.hasPreselectNodes()) {
+ let selectedNodes: DataRow[] = [];
+
+ if (this.isSingleSelectionMode()) {
+ selectedNodes = [this.data.getPreselectRows()[0]];
+ } else {
+ selectedNodes = this.data.getPreselectRows();
+ }
+
+ this.onNodeSelect({ row: undefined, selection: selectedNodes });
+ }
+ }
+
+ isSingleSelectionMode(): boolean {
+ return this.selectionMode === 'single';
+ }
+
+ hasPreselectNodes(): boolean {
+ return this.preselectNodes && 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 e68f7130ea..b5a2ca2b29 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 } from './../../mock';
+import { FileNode, FolderNode, SmartFolderNode, RuleFolderNode, LinkFolderNode, mockPreselectedNodes, mockNodePagingWithPreselectedNodes, mockNode2, fakeNodePaging } from './../../mock';
import { ShareDataRow } from './share-data-row.model';
import { ShareDataTableAdapter } from './share-datatable-adapter';
import { ContentTestingModule } from '../../testing/content.testing.module';
@@ -481,4 +481,31 @@ describe('ShareDataTableAdapter', () => {
expect(row.isDropTarget).toBeFalsy();
});
});
+
+ describe('Preselect rows', () => {
+
+ it('should set isSelected to be true for each preselectRow if the preselectNodes 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);
+ });
+
+ it('should set preselectRows empty if preselectedNodes are undefined/empty', () => {
+ const adapter = new ShareDataTableAdapter(thumbnailService, contentService, []);
+ adapter.loadPage(mockNodePagingWithPreselectedNodes, null, null, []);
+
+ expect(adapter.getPreselectRows().length).toBe(0);
+ });
+
+ it('should set preselectRows 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);
+ });
+ });
});
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 c95adb906a..d4a2e4e499 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,6 +45,7 @@ export class ShareDataTableAdapter implements DataTableAdapter {
permissionsStyle: PermissionStyleModel[];
selectedRow: DataRow;
allowDropFiles: boolean;
+ preselectRows: DataRow[] = [];
set sortingMode(value: string) {
let newValue = (value || 'client').toLowerCase();
@@ -81,6 +82,10 @@ export class ShareDataTableAdapter implements DataTableAdapter {
this.sort();
}
+ getPreselectRows(): Array {
+ return this.preselectRows;
+ }
+
getColumns(): Array {
return this.columns;
}
@@ -245,7 +250,7 @@ export class ShareDataTableAdapter implements DataTableAdapter {
}
}
- public loadPage(nodePaging: NodePaging, merge: boolean = false, allowDropFiles?: boolean) {
+ public loadPage(nodePaging: NodePaging, merge: boolean = false, allowDropFiles?: boolean, preselectNodes: NodeEntry[] = []) {
let shareDataRows: ShareDataRow[] = [];
if (allowDropFiles !== undefined) {
this.allowDropFiles = allowDropFiles;
@@ -292,6 +297,23 @@ export class ShareDataTableAdapter implements DataTableAdapter {
} else {
this.rows = shareDataRows;
}
+
+ this.selectRowsBasedOnGivenNodes(preselectNodes);
+ }
+
+ selectRowsBasedOnGivenNodes(preselectNodes: NodeEntry[]) {
+ if (preselectNodes && preselectNodes.length > 0) {
+ this.rows = this.rows.map((row) => {
+ preselectNodes.map((preselectedNode) => {
+ if (row.obj.entry.id === preselectedNode.entry.id) {
+ row.isSelected = true;
+ }
+ });
+ return row;
+ });
+ }
+
+ this.preselectRows = [...this.rows.filter((res) => res.isSelected)];
}
}
diff --git a/lib/content-services/src/lib/mock/document-list.component.mock.ts b/lib/content-services/src/lib/mock/document-list.component.mock.ts
index 365a9179c8..2f41038841 100644
--- a/lib/content-services/src/lib/mock/document-list.component.mock.ts
+++ b/lib/content-services/src/lib/mock/document-list.component.mock.ts
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-import { Node, NodePaging } from '@alfresco/js-api';
+import { Node, NodePaging, NodeEntry } from '@alfresco/js-api';
export const fakeNodeWithCreatePermission = new Node({
isFile: false,
@@ -215,3 +215,117 @@ export const fakeNodePaging: NodePaging = {
}]
}
};
+
+export const mockNode1 = new Node({
+ 'isFile': true,
+ 'createdByUser': { 'id': 'admin', 'displayName': 'Administrator' },
+ 'modifiedAt': '2017-05-24T15:08:55.640Z',
+ 'nodeType': 'cm:content',
+ 'content': {
+ 'mimeType': 'application/rtf',
+ 'mimeTypeName': 'Rich Text Format',
+ 'sizeInBytes': 14530,
+ 'encoding': 'UTF-8'
+ },
+ 'parentId': 'd124de26-6ba0-4f40-8d98-4907da2d337a',
+ 'createdAt': '2017-05-24T15:08:55.640Z',
+ 'path': {
+ 'name': '/Company Home/Guest Home',
+ 'isComplete': true,
+ 'elements': [{
+ 'id': '94acfc73-7014-4475-9bd9-93a2162f0f8c',
+ 'name': 'Company Home'
+ }, { 'id': 'd124de26-6ba0-4f40-8d98-4907da2d337a', 'name': 'Guest Home' }]
+ },
+ 'isFolder': false,
+ 'modifiedByUser': { 'id': 'admin', 'displayName': 'Administrator' },
+ 'name': 'b_txt_file.rtf',
+ 'id': '70e1cc6a-6918-468a-b84a-1048093b06fd',
+ 'properties': { 'cm:versionLabel': '1.0', 'cm:versionType': 'MAJOR' },
+ 'allowableOperations': ['delete', 'update']
+});
+
+export const mockNode2 = new Node({
+ 'isFile': true,
+ 'createdByUser': { 'id': 'admin', 'displayName': 'Administrator' },
+ 'modifiedAt': '2017-05-24T15:08:55.640Z',
+ 'nodeType': 'cm:content',
+ 'content': {
+ 'mimeType': 'application/rtf',
+ 'mimeTypeName': 'Rich Text Format',
+ 'sizeInBytes': 14530,
+ 'encoding': 'UTF-8'
+ },
+ 'parentId': 'd124de26-6ba0-4f40-8d98-4907da2d337a',
+ 'createdAt': '2017-05-24T15:08:55.640Z',
+ 'path': {
+ 'name': '/Company Home/Guest Home',
+ 'isComplete': true,
+ 'elements': [{
+ 'id': '94acfc73-7014-4475-9bd9-93a2162f0f8c',
+ 'name': 'Company Home'
+ }, { 'id': 'd124de26-6ba0-4f40-8d98-4907da2d337a', 'name': 'Guest Home' }]
+ },
+ 'isFolder': false,
+ 'modifiedByUser': { 'id': 'admin', 'displayName': 'Administrator' },
+ 'name': 'b_txt_file.rtf',
+ 'id': '67b80f77-dbca-4f58-be6c-71b9dd61e554',
+ 'properties': { 'cm:versionLabel': '1.0', 'cm:versionType': 'MAJOR' },
+ 'allowableOperations': ['delete', 'update']
+});
+
+export const mockNode3 = new Node({
+ 'isFile': true,
+ 'createdByUser': { 'id': 'admin', 'displayName': 'Administrator' },
+ 'modifiedAt': '2017-05-24T15:08:55.640Z',
+ 'nodeType': 'cm:content',
+ 'content': {
+ 'mimeType': 'application/rtf',
+ 'mimeTypeName': 'Rich Text Format',
+ 'sizeInBytes': 14530,
+ 'encoding': 'UTF-8'
+ },
+ 'parentId': 'd124de26-6ba0-4f40-8d98-4907da2d337a',
+ 'createdAt': '2017-05-24T15:08:55.640Z',
+ 'path': {
+ 'name': '/Company Home/Guest Home',
+ 'isComplete': true,
+ 'elements': [{
+ 'id': '94acfc73-7014-4475-9bd9-93a2162f0f8c',
+ 'name': 'Company Home'
+ }, { 'id': 'd124de26-6ba0-4f40-8d98-4907da2d337a', 'name': 'Guest Home' }]
+ },
+ 'isFolder': false,
+ 'modifiedByUser': { 'id': 'admin', 'displayName': 'Administrator' },
+ 'name': 'c_txt_file.rtf',
+ 'id': '67b80f77-dbca-4f58-be6c-71b9dd61e555',
+ 'properties': { 'cm:versionLabel': '1.0', 'cm:versionType': 'MAJOR' },
+ 'allowableOperations': ['delete', 'update']
+});
+
+export const mockPreselectedNodes: NodeEntry[] = [
+ {
+ entry: mockNode1
+ },
+ {
+ entry: mockNode1
+ }
+];
+
+export const mockNodePagingWithPreselectedNodes: NodePaging = {
+ list: {
+ pagination: {
+ count: 5,
+ hasMoreItems: false,
+ totalItems: 5,
+ skipCount: 0,
+ maxItems: 100
+ }, entries: [{
+ entry: mockNode1
+ }, {
+ entry: mockNode2
+ }, {
+ entry: mockNode3
+ }]
+ }
+};