mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[AAE-3110] Move upload button inside the node selector dialog (#5901)
* Open select dialog on all types, fetch destination folder from a relative path * Dialog UI refactor, multiple upload from local * Fix document list should automatically reload after upload * Remove not used ViewChild * Fix imports, read destination folder from form field * support different alias * Remove not needed property, reuse selection mode * Remove unused methods * Fix unit tests * * Added unit tests * Fixed failing unit tests * * Added unit for upload button * Skipped failing e2e * * Removed process-storage related code * * Removed unncessory model and code * * * Removed contentHost from formCloud model * * Skiped content-services e2e * Skip failing process e2e related to attachment Co-authored-by: sivakumar414ram <siva.kumar@muraai.com> Co-authored-by: maurizio vitale <maurizio.vitale@alfresco.com>
This commit is contained in:
@@ -71,7 +71,7 @@
|
||||
[allowDropFiles]="false"
|
||||
[sorting]="'server'"
|
||||
[where]="where"
|
||||
(folderChange)="onFolderChange()"
|
||||
(folderChange)="onFolderChange($event)"
|
||||
(ready)="onFolderLoaded()"
|
||||
(nodeSelected)="onCurrentSelection($event)"
|
||||
data-automation-id="content-node-selector-document-list">
|
||||
|
@@ -29,7 +29,7 @@ import { DocumentListService } from '../document-list/services/document-list.ser
|
||||
import { DocumentListComponent } from '../document-list/components/document-list.component';
|
||||
import { DropdownSitesComponent } from '../site-dropdown/sites-dropdown.component';
|
||||
import { CustomResourcesService } from '../document-list/services/custom-resources.service';
|
||||
import { ShareDataRow } from '../document-list';
|
||||
import { NodeEntryEvent, ShareDataRow } from '../document-list';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
const ONE_FOLDER_RESULT = {
|
||||
@@ -59,6 +59,8 @@ describe('ContentNodeSelectorComponent', () => {
|
||||
let sitesService: SitesService;
|
||||
let searchSpy: jasmine.Spy;
|
||||
let cnSearchSpy: jasmine.Spy;
|
||||
const fakeNodeEntry = new Node({ id: 'fakeId' });
|
||||
const nodeEntryEvent = new NodeEntryEvent(fakeNodeEntry);
|
||||
|
||||
let _observer: Observer<NodePaging>;
|
||||
|
||||
@@ -271,7 +273,7 @@ describe('ContentNodeSelectorComponent', () => {
|
||||
|
||||
tick(debounceSearch);
|
||||
|
||||
component.onFolderChange();
|
||||
component.onFolderChange(nodeEntryEvent);
|
||||
fixture.detectChanges();
|
||||
const breadcrumb = fixture.debugElement.query(By.directive(DropdownBreadcrumbComponent));
|
||||
expect(breadcrumb).not.toBeNull();
|
||||
@@ -309,7 +311,7 @@ describe('ContentNodeSelectorComponent', () => {
|
||||
respondWithSearchResults(ONE_FOLDER_RESULT);
|
||||
fixture.detectChanges();
|
||||
|
||||
component.onFolderChange();
|
||||
component.onFolderChange(nodeEntryEvent);
|
||||
fixture.detectChanges();
|
||||
|
||||
const chosenNode = <Node> { path: { elements: [] } };
|
||||
@@ -700,7 +702,7 @@ describe('ContentNodeSelectorComponent', () => {
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
|
||||
component.onFolderChange();
|
||||
component.onFolderChange(nodeEntryEvent);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component.clearSearch).toHaveBeenCalled();
|
||||
|
@@ -33,7 +33,7 @@ import { ImageResolver } from '../document-list/data/image-resolver.model';
|
||||
import { ContentNodeSelectorService } from './content-node-selector.service';
|
||||
import { debounceTime, takeUntil } from 'rxjs/operators';
|
||||
import { CustomResourcesService } from '../document-list/services/custom-resources.service';
|
||||
import { ShareDataRow } from '../document-list';
|
||||
import { NodeEntryEvent, ShareDataRow } from '../document-list';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
export type ValidationFunction = (entry: Node) => boolean;
|
||||
@@ -186,6 +186,10 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
||||
@Output()
|
||||
select: EventEmitter<Node[]> = new EventEmitter<Node[]>();
|
||||
|
||||
/** Emitted when the navigation changes. */
|
||||
@Output()
|
||||
navigationChange: EventEmitter<NodeEntryEvent> = new EventEmitter<NodeEntryEvent>();
|
||||
|
||||
/** Emitted when the select site changes. */
|
||||
@Output()
|
||||
siteChange: EventEmitter<string> = new EventEmitter<string>();
|
||||
@@ -426,11 +430,12 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
||||
/**
|
||||
* Sets showingSearchResults state to be able to differentiate between search results or folder results
|
||||
*/
|
||||
onFolderChange(): void {
|
||||
onFolderChange($event: NodeEntryEvent): void {
|
||||
this.showingSearchResults = false;
|
||||
this.infiniteScroll = false;
|
||||
this.breadcrumbFolderTitle = null;
|
||||
this.clearSearch();
|
||||
this.navigationChange.emit($event);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -36,4 +36,6 @@ export interface ContentNodeSelectorComponentData {
|
||||
showSearch?: boolean;
|
||||
showFilesInResult?: boolean;
|
||||
showDropdownSiteList?: boolean;
|
||||
showLocalUploadButton?: boolean;
|
||||
multipleUpload?: boolean;
|
||||
}
|
||||
|
@@ -21,21 +21,33 @@
|
||||
[showDropdownSiteList]="data?.showDropdownSiteList"
|
||||
[showFilesInResult]="data?.showFilesInResult"
|
||||
(select)="onSelect($event)"
|
||||
(siteChange)="onSiteChange($event)">
|
||||
(siteChange)="onSiteChange($event)"
|
||||
(navigationChange)="onNavigationChange($event)">
|
||||
</adf-content-node-selector-panel>
|
||||
</mat-dialog-content>
|
||||
|
||||
<mat-dialog-actions align="end">
|
||||
<button
|
||||
mat-button
|
||||
(click)="close()"
|
||||
data-automation-id="content-node-selector-actions-cancel">{{ 'NODE_SELECTOR.CANCEL' | translate }}
|
||||
</button>
|
||||
<mat-dialog-actions>
|
||||
<div>
|
||||
<adf-upload-button
|
||||
*ngIf="data?.showLocalUploadButton"
|
||||
[staticTitle]="'FORM.FIELD.UPLOAD' | translate "
|
||||
[multipleFiles]="isMultipleSelection()"
|
||||
[rootFolderId]="currentDirectoryId"
|
||||
(error)="onError($event)">
|
||||
</adf-upload-button>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
mat-button
|
||||
(click)="close()"
|
||||
data-automation-id="content-node-selector-actions-cancel">{{ 'NODE_SELECTOR.CANCEL' | translate }}
|
||||
</button>
|
||||
|
||||
<button mat-button
|
||||
[disabled]="!hasNodeSelected()"
|
||||
class="adf-choose-action"
|
||||
(click)="onClick()"
|
||||
data-automation-id="content-node-selector-actions-choose">{{ buttonActionName | translate }}
|
||||
</button>
|
||||
<button mat-button
|
||||
[disabled]="!chosenNode"
|
||||
class="adf-choose-action"
|
||||
(click)="onClick()"
|
||||
data-automation-id="content-node-selector-actions-choose">{{ buttonActionName | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</mat-dialog-actions>
|
||||
|
@@ -36,7 +36,8 @@
|
||||
padding: 8px;
|
||||
background-color: mat-color($background, background);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
color: mat-color($foreground, text, 0.72);
|
||||
|
||||
button {
|
||||
|
@@ -40,7 +40,8 @@ describe('ContentNodeSelectorDialogComponent', () => {
|
||||
select: new EventEmitter<Node>(),
|
||||
rowFilter: (shareDataRow: ShareDataRow) => shareDataRow.node.entry.name === 'impossible-name',
|
||||
imageResolver: () => 'piccolo',
|
||||
currentFolderId: 'cat-girl-nuku-nuku'
|
||||
currentFolderId: 'cat-girl-nuku-nuku',
|
||||
showLocalUploadButton: true
|
||||
};
|
||||
|
||||
setupTestBed({
|
||||
@@ -175,4 +176,22 @@ describe('ContentNodeSelectorDialogComponent', () => {
|
||||
expect(titleElement.nativeElement.innerText).toBe('NODE_SELECTOR.CHOOSE_ITEM');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Upload button', () => {
|
||||
|
||||
it('should be able to show upload button if showLocalUploadButton set to true', () => {
|
||||
const adfUploadButton = fixture.debugElement.query(By.css('adf-upload-button'));
|
||||
|
||||
expect(adfUploadButton).not.toBeNull();
|
||||
expect(adfUploadButton.nativeElement.innerText).toEqual('file_uploadFORM.FIELD.UPLOAD');
|
||||
});
|
||||
|
||||
it('should not be able to show upload button if showLocalUploadButton set to false', () => {
|
||||
component.data.showLocalUploadButton = false;
|
||||
fixture.detectChanges();
|
||||
const adfUploadButton = fixture.debugElement.query(By.css('adf-upload-button span'));
|
||||
|
||||
expect(adfUploadButton).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -17,9 +17,10 @@
|
||||
|
||||
import { Component, Inject, ViewEncapsulation } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { TranslationService } from '@alfresco/adf-core';
|
||||
import { TranslationService, NotificationService } from '@alfresco/adf-core';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
import { ContentNodeSelectorComponentData } from './content-node-selector.component-data.interface';
|
||||
import { NodeEntryEvent } from '../document-list/components/node.event';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-content-node-selector',
|
||||
@@ -28,17 +29,19 @@ import { ContentNodeSelectorComponentData } from './content-node-selector.compon
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ContentNodeSelectorComponent {
|
||||
|
||||
title: string;
|
||||
action: string;
|
||||
buttonActionName: string;
|
||||
chosenNode: Node[];
|
||||
currentDirectoryId: string;
|
||||
|
||||
constructor(private translation: TranslationService,
|
||||
private notificationService: NotificationService,
|
||||
@Inject(MAT_DIALOG_DATA) public data: ContentNodeSelectorComponentData) {
|
||||
this.action = data.actionName ? data.actionName.toUpperCase() : 'CHOOSE';
|
||||
this.buttonActionName = `NODE_SELECTOR.${this.action}`;
|
||||
this.title = data.title;
|
||||
this.currentDirectoryId = data.currentFolderId;
|
||||
}
|
||||
|
||||
close() {
|
||||
@@ -49,14 +52,14 @@ export class ContentNodeSelectorComponent {
|
||||
this.chosenNode = nodeList;
|
||||
}
|
||||
|
||||
hasNodeSelected(): boolean {
|
||||
return this.chosenNode?.length > 0;
|
||||
}
|
||||
|
||||
onSiteChange(siteTitle: string) {
|
||||
this.updateTitle(siteTitle);
|
||||
}
|
||||
|
||||
onNavigationChange(pathElement: NodeEntryEvent) {
|
||||
this.currentDirectoryId = pathElement.value.id;
|
||||
}
|
||||
|
||||
onClick(): void {
|
||||
this.data.select.next(this.chosenNode);
|
||||
this.data.select.complete();
|
||||
@@ -71,4 +74,12 @@ export class ContentNodeSelectorComponent {
|
||||
getTitleTranslation(action: string, name: string): string {
|
||||
return this.translation.instant(`NODE_SELECTOR.${action}_ITEM`, { name: this.translation.instant(name) });
|
||||
}
|
||||
|
||||
isMultipleSelection(): boolean {
|
||||
return this.data.selectionMode === 'multiple';
|
||||
}
|
||||
|
||||
onError(error) {
|
||||
this.notificationService.showError(error);
|
||||
}
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ import { BreadcrumbModule } from '../breadcrumb/breadcrumb.module';
|
||||
import { CoreModule } from '@alfresco/adf-core';
|
||||
import { DocumentListModule } from '../document-list/document-list.module';
|
||||
import { NameLocationCellComponent } from './name-location-cell/name-location-cell.component';
|
||||
import { UploadModule } from '../upload/upload.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -37,7 +38,8 @@ import { NameLocationCellComponent } from './name-location-cell/name-location-ce
|
||||
MaterialModule,
|
||||
SitesDropdownModule,
|
||||
BreadcrumbModule,
|
||||
DocumentListModule
|
||||
DocumentListModule,
|
||||
UploadModule
|
||||
],
|
||||
exports: [
|
||||
ContentNodeSelectorPanelComponent,
|
||||
|
@@ -45,7 +45,8 @@ import {
|
||||
RequestPaginationModel,
|
||||
AlfrescoApiService,
|
||||
UserPreferenceValues,
|
||||
LockService
|
||||
LockService,
|
||||
UploadService
|
||||
} from '@alfresco/adf-core';
|
||||
|
||||
import { Node, NodeEntry, NodePaging, Pagination } from '@alfresco/js-api';
|
||||
@@ -60,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 { takeUntil } from 'rxjs/operators';
|
||||
import { debounceTime, takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-document-list',
|
||||
@@ -337,6 +338,7 @@ 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) {
|
||||
@@ -346,6 +348,18 @@ 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) {
|
||||
|
@@ -80,6 +80,7 @@
|
||||
"NODE_SELECTOR": {
|
||||
"CANCEL": "Cancel",
|
||||
"CHOOSE": "Select",
|
||||
"ATTACH": "Attach",
|
||||
"CHOOSE_ITEM": "Select content to attach from '{{ name }}'",
|
||||
"COPY": "Copy",
|
||||
"COPY_ITEM": "Copy '{{ name }}' to...",
|
||||
|
@@ -5,7 +5,7 @@
|
||||
<!--Single Files Upload-->
|
||||
<button *ngIf="!multipleFiles"
|
||||
[disabled]="isButtonDisabled()"
|
||||
mat-raised-button color="primary"
|
||||
mat-button
|
||||
(click)="uploadSingleFile.click()">
|
||||
<mat-icon>file_upload</mat-icon>
|
||||
<span id="upload-single-file-label"
|
||||
@@ -27,7 +27,7 @@
|
||||
<!--Multiple Files Upload-->
|
||||
<button *ngIf="multipleFiles"
|
||||
[disabled]="isButtonDisabled()"
|
||||
mat-raised-button color="primary"
|
||||
mat-button
|
||||
(click)="uploadMultipleFiles.click()">
|
||||
<mat-icon>file_upload</mat-icon>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<div *ngIf="uploadFolders">
|
||||
<button
|
||||
[disabled]="isButtonDisabled()"
|
||||
mat-raised-button color="primary"
|
||||
mat-button
|
||||
(click)="uploadFolders.click()">
|
||||
<mat-icon>file_upload</mat-icon>
|
||||
<span id="uploadFolder-label"
|
||||
|
Reference in New Issue
Block a user