mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-08-07 17:48:54 +00:00
[AAE-10777] Move services from Core in Content the right place (#8242)
Clean core services and directive
This commit is contained in:
@@ -16,7 +16,8 @@
|
||||
*/
|
||||
|
||||
import { ChangeDetectorRef, Component, ElementRef, SimpleChange } from '@angular/core';
|
||||
import { ContentService, CoreTestingModule, setupTestBed } from '@alfresco/adf-core';
|
||||
import { CoreTestingModule, setupTestBed } from '@alfresco/adf-core';
|
||||
import { ContentService } from '../common/services/content.service';
|
||||
import { CheckAllowableOperationDirective } from './check-allowable-operation.directive';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
@@ -19,7 +19,8 @@
|
||||
|
||||
import { ChangeDetectorRef, Directive, ElementRef, Host, Inject, Input, OnChanges, Optional, Renderer2, SimpleChanges } from '@angular/core';
|
||||
import { NodeEntry } from '@alfresco/js-api';
|
||||
import { ContentService, EXTENDIBLE_COMPONENT } from '@alfresco/adf-core';
|
||||
import { EXTENDIBLE_COMPONENT } from '@alfresco/adf-core';
|
||||
import { ContentService } from '../common/services/content.service';
|
||||
import { NodeAllowableOperationSubject } from '../interfaces/node-allowable-operation-subject.interface';
|
||||
|
||||
@Directive({
|
||||
|
@@ -29,6 +29,7 @@ import { LibraryMembershipDirective } from './library-membership.directive';
|
||||
import { NodeDeleteDirective } from './node-delete.directive';
|
||||
import { NodeFavoriteDirective } from './node-favorite.directive';
|
||||
import { NodeRestoreDirective } from './node-restore.directive';
|
||||
import { NodeDownloadDirective } from './node-download.directive';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -46,7 +47,8 @@ import { NodeRestoreDirective } from './node-restore.directive';
|
||||
LibraryMembershipDirective,
|
||||
NodeDeleteDirective,
|
||||
NodeFavoriteDirective,
|
||||
NodeRestoreDirective
|
||||
NodeRestoreDirective,
|
||||
NodeDownloadDirective
|
||||
],
|
||||
exports: [
|
||||
NodeLockDirective,
|
||||
@@ -57,7 +59,8 @@ import { NodeRestoreDirective } from './node-restore.directive';
|
||||
LibraryMembershipDirective,
|
||||
NodeDeleteDirective,
|
||||
NodeFavoriteDirective,
|
||||
NodeRestoreDirective
|
||||
NodeRestoreDirective,
|
||||
NodeDownloadDirective
|
||||
]
|
||||
})
|
||||
export class ContentDirectiveModule {
|
||||
|
190
lib/content-services/src/lib/directives/node-download.directive.spec.ts
Executable file
190
lib/content-services/src/lib/directives/node-download.directive.spec.ts
Executable file
@@ -0,0 +1,190 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Component, DebugElement, ViewChild } from '@angular/core';
|
||||
import { setupTestBed, AlfrescoApiService, CoreTestingModule } from '@alfresco/adf-core';
|
||||
import { NodeDownloadDirective } from './node-download.directive';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { ContentDirectiveModule } from '@alfresco/adf-content-services';
|
||||
|
||||
@Component({
|
||||
template: '<div [adfNodeDownload]="selection" [version]="version"></div>'
|
||||
})
|
||||
class TestComponent {
|
||||
@ViewChild(NodeDownloadDirective, { static: true })
|
||||
downloadDirective: NodeDownloadDirective;
|
||||
|
||||
selection;
|
||||
version;
|
||||
}
|
||||
|
||||
describe('NodeDownloadDirective', () => {
|
||||
let component: TestComponent;
|
||||
let fixture: ComponentFixture<TestComponent>;
|
||||
let element: DebugElement;
|
||||
let dialog: MatDialog;
|
||||
let apiService: AlfrescoApiService;
|
||||
let contentService;
|
||||
let dialogSpy;
|
||||
const mockOauth2Auth: any = {
|
||||
oauth2Auth: {
|
||||
callCustomApi: () => Promise.resolve()
|
||||
},
|
||||
isEcmLoggedIn: jasmine.createSpy('isEcmLoggedIn'),
|
||||
reply: jasmine.createSpy('reply')
|
||||
};
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
ContentDirectiveModule,
|
||||
TranslateModule.forRoot(),
|
||||
CoreTestingModule
|
||||
],
|
||||
declarations: [
|
||||
TestComponent
|
||||
]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(TestComponent);
|
||||
component = fixture.componentInstance;
|
||||
element = fixture.debugElement.query(By.directive(NodeDownloadDirective));
|
||||
dialog = TestBed.inject(MatDialog);
|
||||
apiService = TestBed.inject(AlfrescoApiService);
|
||||
contentService = component.downloadDirective['contentApi'];
|
||||
dialogSpy = spyOn(dialog, 'open');
|
||||
});
|
||||
|
||||
it('should not download node when selection is empty', () => {
|
||||
spyOn(apiService, 'getInstance').and.returnValue(mockOauth2Auth);
|
||||
component.selection = [];
|
||||
|
||||
fixture.detectChanges();
|
||||
element.triggerEventHandler('click', null);
|
||||
|
||||
expect(apiService.getInstance).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not download zip when selection has no nodes', () => {
|
||||
component.selection = [];
|
||||
|
||||
fixture.detectChanges();
|
||||
element.triggerEventHandler('click', null);
|
||||
|
||||
expect(dialogSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should download selected node as file', () => {
|
||||
spyOn(contentService, 'getContentUrl');
|
||||
const node = { entry: { id: 'node-id', isFile: true } };
|
||||
component.selection = [node];
|
||||
|
||||
fixture.detectChanges();
|
||||
element.triggerEventHandler('click', null);
|
||||
|
||||
expect(contentService.getContentUrl).toHaveBeenCalledWith(node.entry.id, true);
|
||||
});
|
||||
|
||||
it('should download selected node version as file', () => {
|
||||
component.version = {
|
||||
entry: {
|
||||
id: '1.0'
|
||||
}
|
||||
};
|
||||
spyOn(contentService, 'getVersionContentUrl');
|
||||
const node = {entry: {id: 'node-id', isFile: true}};
|
||||
component.selection = [node];
|
||||
|
||||
fixture.detectChanges();
|
||||
element.triggerEventHandler('click', null);
|
||||
|
||||
expect(contentService.getVersionContentUrl).toHaveBeenCalledWith(node.entry.id, '1.0', true);
|
||||
});
|
||||
|
||||
it('should download selected shared node as file', () => {
|
||||
spyOn(contentService, 'getContentUrl');
|
||||
const node = { entry: { nodeId: 'shared-node-id', isFile: true } };
|
||||
component.selection = [node];
|
||||
|
||||
fixture.detectChanges();
|
||||
element.triggerEventHandler('click', null);
|
||||
|
||||
expect(contentService.getContentUrl).toHaveBeenCalledWith(node.entry.nodeId, true);
|
||||
});
|
||||
|
||||
it('should download selected files nodes as zip', () => {
|
||||
const node1 = { entry: { id: 'node-1' } };
|
||||
const node2 = { entry: { id: 'node-2' } };
|
||||
component.selection = [node1, node2];
|
||||
|
||||
fixture.detectChanges();
|
||||
element.triggerEventHandler('click', null);
|
||||
|
||||
expect(dialogSpy.calls.argsFor(0)[1].data).toEqual({ nodeIds: [ 'node-1', 'node-2' ] });
|
||||
});
|
||||
|
||||
it('should download selected shared files nodes as zip', () => {
|
||||
const node1 = { entry: { nodeId: 'shared-node-1' } };
|
||||
const node2 = { entry: { nodeId: 'shared-node-2' } };
|
||||
component.selection = [node1, node2];
|
||||
|
||||
fixture.detectChanges();
|
||||
element.triggerEventHandler('click', null);
|
||||
|
||||
expect(dialogSpy.calls.argsFor(0)[1].data).toEqual({ nodeIds: [ 'shared-node-1', 'shared-node-2' ] });
|
||||
});
|
||||
|
||||
it('should download selected folder node as zip', () => {
|
||||
const node = { entry: { isFolder: true, id: 'node-id' } };
|
||||
component.selection = [node];
|
||||
|
||||
fixture.detectChanges();
|
||||
element.triggerEventHandler('click', null);
|
||||
|
||||
expect(dialogSpy.calls.argsFor(0)[1].data).toEqual({ nodeIds: [ 'node-id' ] });
|
||||
});
|
||||
|
||||
it('should create link element to download file node', () => {
|
||||
const dummyLinkElement: any = {
|
||||
download: null,
|
||||
href: null,
|
||||
click: () => null,
|
||||
style: {
|
||||
display: null
|
||||
}
|
||||
};
|
||||
|
||||
const node = { entry: { name: 'dummy', isFile: true, id: 'node-id' } };
|
||||
|
||||
spyOn(contentService, 'getContentUrl').and.returnValue('somewhere-over-the-rainbow');
|
||||
spyOn(document, 'createElement').and.returnValue(dummyLinkElement);
|
||||
spyOn(document.body, 'appendChild').and.stub();
|
||||
spyOn(document.body, 'removeChild').and.stub();
|
||||
|
||||
component.selection = [node];
|
||||
|
||||
fixture.detectChanges();
|
||||
element.triggerEventHandler('click', null);
|
||||
|
||||
expect(document.createElement).toHaveBeenCalled();
|
||||
expect(dummyLinkElement.download).toBe('dummy');
|
||||
expect(dummyLinkElement.href).toContain('somewhere-over-the-rainbow');
|
||||
});
|
||||
});
|
142
lib/content-services/src/lib/directives/node-download.directive.ts
Executable file
142
lib/content-services/src/lib/directives/node-download.directive.ts
Executable file
@@ -0,0 +1,142 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 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 { Directive, Input, HostListener } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { AlfrescoApiService, DownloadService } from '@alfresco/adf-core';
|
||||
import { DownloadZipDialogComponent } from '../dialogs/download-zip/download-zip.dialog';
|
||||
import { ContentApi, NodeEntry, VersionEntry } from '@alfresco/js-api';
|
||||
|
||||
/**
|
||||
* Directive selectors without adf- prefix will be deprecated on 3.0.0
|
||||
*/
|
||||
@Directive({
|
||||
// eslint-disable-next-line @angular-eslint/directive-selector
|
||||
selector: '[adfNodeDownload]'
|
||||
})
|
||||
export class NodeDownloadDirective {
|
||||
|
||||
_contentApi: ContentApi;
|
||||
get contentApi(): ContentApi {
|
||||
this._contentApi = this._contentApi ?? new ContentApi(this.apiService.getInstance());
|
||||
return this._contentApi;
|
||||
}
|
||||
|
||||
/** Nodes to download. */
|
||||
@Input('adfNodeDownload')
|
||||
nodes: NodeEntry | NodeEntry[];
|
||||
|
||||
/** Node's version to download. */
|
||||
@Input()
|
||||
version: VersionEntry;
|
||||
|
||||
@HostListener('click')
|
||||
onClick() {
|
||||
this.downloadNodes(this.nodes);
|
||||
}
|
||||
|
||||
constructor(
|
||||
private apiService: AlfrescoApiService,
|
||||
private downloadService: DownloadService,
|
||||
private dialog: MatDialog) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads multiple selected nodes.
|
||||
* Packs result into a .ZIP archive if there is more than one node selected.
|
||||
*
|
||||
* @param selection Multiple selected nodes to download
|
||||
*/
|
||||
downloadNodes(selection: NodeEntry | Array<NodeEntry>) {
|
||||
|
||||
if (!this.isSelectionValid(selection)) {
|
||||
return;
|
||||
}
|
||||
if (selection instanceof Array) {
|
||||
if (selection.length === 1) {
|
||||
this.downloadNode(selection[0]);
|
||||
} else {
|
||||
this.downloadZip(selection);
|
||||
}
|
||||
} else {
|
||||
this.downloadNode(selection);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads a single node.
|
||||
* Packs result into a .ZIP archive is the node is a Folder.
|
||||
*
|
||||
* @param node Node to download
|
||||
*/
|
||||
downloadNode(node: NodeEntry) {
|
||||
if (node && node.entry) {
|
||||
const entry = node.entry;
|
||||
|
||||
if (entry.isFile) {
|
||||
this.downloadFile(node);
|
||||
}
|
||||
|
||||
if (entry.isFolder) {
|
||||
this.downloadZip([node]);
|
||||
}
|
||||
|
||||
// Check if there's nodeId for Shared Files
|
||||
if (!entry.isFile && !entry.isFolder && (entry as any).nodeId) {
|
||||
this.downloadFile(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private isSelectionValid(selection: NodeEntry | Array<NodeEntry>) {
|
||||
return selection || (selection instanceof Array && selection.length > 0);
|
||||
}
|
||||
|
||||
private downloadFile(node: NodeEntry) {
|
||||
if (node && node.entry) {
|
||||
// nodeId for Shared node
|
||||
const id = (node.entry as any).nodeId || node.entry.id;
|
||||
|
||||
let url;
|
||||
let fileName;
|
||||
if (this.version) {
|
||||
url = this.contentApi.getVersionContentUrl(id, this.version.entry.id, true);
|
||||
fileName = this.version.entry.name;
|
||||
} else {
|
||||
url = this.contentApi.getContentUrl(id, true);
|
||||
fileName = node.entry.name;
|
||||
}
|
||||
|
||||
this.downloadService.downloadUrl(url, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
private downloadZip(selection: Array<NodeEntry>) {
|
||||
if (selection && selection.length > 0) {
|
||||
// nodeId for Shared node
|
||||
const nodeIds = selection.map((node: any) => (node.entry.nodeId || node.entry.id));
|
||||
|
||||
this.dialog.open(DownloadZipDialogComponent, {
|
||||
width: '600px',
|
||||
disableClose: true,
|
||||
data: {
|
||||
nodeIds
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@@ -19,7 +19,8 @@
|
||||
|
||||
import { Directive, ElementRef, Renderer2, HostListener, Input, AfterViewInit } from '@angular/core';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
import { AllowableOperationsEnum, ContentService } from '@alfresco/adf-core';
|
||||
import { ContentService } from '../common/services/content.service';
|
||||
import { AllowableOperationsEnum } from '../common/models/allowable-operations.enum';
|
||||
import { ContentNodeDialogService } from '../content-node-selector/content-node-dialog.service';
|
||||
|
||||
@Directive({
|
||||
|
@@ -25,3 +25,4 @@ export * from './library-membership.directive';
|
||||
export * from './node-delete.directive';
|
||||
export * from './node-favorite.directive';
|
||||
export * from './node-restore.directive';
|
||||
export * from './node-download.directive';
|
||||
|
Reference in New Issue
Block a user