mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-2340] add trashcan in demo shell and definitely delete in delete directive (#2976)
* add trashcan in demo shell and definetly delete in delete directive * fix delte directive test
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
"UPLOADER": "Uploader",
|
||||
"WEBSCRIPT": "Webscript",
|
||||
"TAG": "Tag",
|
||||
"TRASHCAN": "Trashcan",
|
||||
"SOCIAL": "Social",
|
||||
"SETTINGS": "Settings",
|
||||
"OVERLAY_VIEWER": "Overlay Viewer",
|
||||
@@ -33,6 +34,17 @@
|
||||
"SEARCH_CREATED_BY" : "Created By",
|
||||
"SEARCH_SERVICE_APPROACH": "Check this to disable the input property and configure using the service"
|
||||
},
|
||||
"TRASHCAN" :{
|
||||
"ACTIONS":{
|
||||
"DELETE_PERMANENT":"Delete permanent",
|
||||
"RESTORE":"Restore"
|
||||
},
|
||||
"EMPTY_STATE": {
|
||||
"TITLE": "Trash is empty",
|
||||
"FIRST_TEXT": "Items you delete are moved to the Trash.",
|
||||
"SECOND_TEXT": "Empty Trash to permanently delete items."
|
||||
}
|
||||
},
|
||||
"DOCUMENT_LIST": {
|
||||
"MULTISELECT_CHECKBOXES" :"Multiselect (with checkboxes)",
|
||||
"MULTIPLE_FILE_UPLOAD" :"Multiple File Upload",
|
||||
@@ -49,7 +61,10 @@
|
||||
"TAG": "Tag",
|
||||
"CREATED_BY": "Created by",
|
||||
"CREATED_ON": "Created on",
|
||||
"CREATED": "Created"
|
||||
"CREATED": "Created",
|
||||
"SIZE": "Size",
|
||||
"DELETED_ON": "Deleted",
|
||||
"DELETED_BY": "Deleted by"
|
||||
},
|
||||
"TOOLBAR": {
|
||||
"CARDVIEW":"Card view mode",
|
||||
|
@@ -29,6 +29,7 @@ import { FormViewerComponent } from './components/process-service/form-viewer.co
|
||||
import { FormNodeViewerComponent } from './components/process-service/form-node-viewer.component';
|
||||
import { AppsViewComponent } from './components/process-service/apps-view.component';
|
||||
import { DataTableComponent } from './components/datatable/datatable.component';
|
||||
import { TrashcanComponent } from './components/trashcan/trashcan.component';
|
||||
import { FilesComponent } from './components/files/files.component';
|
||||
import { FileViewComponent } from './components/file-view/file-view.component';
|
||||
import { WebscriptComponent } from './components/webscript/webscript.component';
|
||||
@@ -78,6 +79,7 @@ import { SharedLinkViewComponent } from './components/shared-link-view/shared-li
|
||||
DataTableComponent,
|
||||
FilesComponent,
|
||||
FileViewComponent,
|
||||
TrashcanComponent,
|
||||
FormComponent,
|
||||
FormListComponent,
|
||||
WebscriptComponent,
|
||||
|
@@ -30,6 +30,7 @@ import { FormNodeViewerComponent } from './components/process-service/form-node-
|
||||
import { AppsViewComponent } from './components/process-service/apps-view.component';
|
||||
import { SearchResultComponent } from './components/search/search-result.component';
|
||||
import { SearchExtendedComponent } from './components/search/search-extended.component';
|
||||
import { TrashcanComponent } from './components/trashcan/trashcan.component';
|
||||
|
||||
import { DataTableComponent } from './components/datatable/datatable.component';
|
||||
import { WebscriptComponent } from './components/webscript/webscript.component';
|
||||
@@ -65,8 +66,12 @@ export const appRoutes: Routes = [
|
||||
{
|
||||
path: 'home',
|
||||
component: HomeComponent
|
||||
}
|
||||
,
|
||||
},
|
||||
{
|
||||
path: 'trashcan',
|
||||
component: TrashcanComponent,
|
||||
canActivate: [AuthGuardEcm]
|
||||
},
|
||||
{
|
||||
path: 'files',
|
||||
component: FilesComponent,
|
||||
|
@@ -30,6 +30,7 @@ export class AppLayoutComponent {
|
||||
links: Array<any> = [
|
||||
{ href: '/home', icon: 'home', title: 'APP_LAYOUT.HOME' },
|
||||
{ href: '/files', icon: 'folder_open', title: 'APP_LAYOUT.CONTENT_SERVICES' },
|
||||
{ href: '/trashcan', icon: 'delete', title: 'APP_LAYOUT.TRASHCAN' },
|
||||
{ href: '/activiti', icon: 'device_hub', title: 'APP_LAYOUT.PROCESS_SERVICES' },
|
||||
{ href: '/login', icon: 'vpn_key', title: 'APP_LAYOUT.LOGIN' },
|
||||
{ href: '/dl-custom-sources', icon: 'extension', title: 'APP_LAYOUT.CUSTOM_SOURCES' },
|
||||
|
@@ -199,7 +199,7 @@
|
||||
-->
|
||||
<data-column
|
||||
key="content.sizeInBytes"
|
||||
title="Size"
|
||||
title="{{'DOCUMENT_LIST.COLUMNS.SIZE' | translate}}"
|
||||
type="fileSize">
|
||||
</data-column>
|
||||
<!-- Notes: has performance overhead due to multiple files/folders causing separate HTTP calls to get tags -->
|
||||
|
@@ -0,0 +1,96 @@
|
||||
<div class="inner-layout">
|
||||
<div class="inner-layout__header">
|
||||
<adf-breadcrumb [root]="'APP_LAYOUT.TRASHCAN' | translate">
|
||||
</adf-breadcrumb>
|
||||
|
||||
<adf-toolbar class="inline">
|
||||
<button
|
||||
mat-icon-button
|
||||
[adf-delete]="documentList.selection"
|
||||
(delete)="documentList.reload()"
|
||||
[permanent]="true"
|
||||
*ngIf="documentList.selection.length"
|
||||
title="{{ 'TRASHCAN.ACTIONS.DELETE_PERMANENT' | translate }}">
|
||||
<mat-icon>delete_forever</mat-icon>
|
||||
</button>
|
||||
|
||||
<button
|
||||
mat-icon-button
|
||||
(selection-node-restored)="refresh()"
|
||||
[adf-restore]="documentList.selection"
|
||||
*ngIf="documentList.selection.length"
|
||||
title="{{ 'TRASHCAN.ACTIONS.RESTORE' | translate }}">
|
||||
<mat-icon>restore</mat-icon>
|
||||
</button>
|
||||
</adf-toolbar>
|
||||
</div>
|
||||
|
||||
<div class="inner-layout__content">
|
||||
|
||||
<adf-document-list #documentList
|
||||
[attr.class]="documentList.isEmpty() ? 'empty-list' : ''"
|
||||
currentFolderId="-trashcan-"
|
||||
selectionMode="multiple"
|
||||
[navigate]="false"
|
||||
locationFormat="/files"
|
||||
[sorting]="[ 'archivedAt', 'desc' ]"
|
||||
[contextMenuActions]="true"
|
||||
[contentActions]="false">
|
||||
|
||||
<empty-folder-content>
|
||||
<ng-template>
|
||||
<div class="empty-list__block">
|
||||
<mat-icon>delete</mat-icon>
|
||||
<p class="empty-list__title">{{ 'TRASHCAN.EMPTY_STATE.TITLE' | translate }}</p>
|
||||
<p class="empty-list__text">{{ 'TRASHCAN.EMPTY_STATE.FIRST_TEXT' | translate }}</p>
|
||||
<p class="empty-list__text">{{ 'TRASHCAN.EMPTY_STATE.SECOND_TEXT' | translate }}</p>
|
||||
</div>
|
||||
</ng-template>
|
||||
</empty-folder-content>
|
||||
|
||||
<data-columns>
|
||||
|
||||
<data-column
|
||||
key="$thumbnail"
|
||||
type="image"
|
||||
[sortable]="false"
|
||||
class="image-table-cell">
|
||||
</data-column>
|
||||
|
||||
<data-column
|
||||
class="adf-data-table-cell--ellipsis__name"
|
||||
key="name"
|
||||
title="DOCUMENT_LIST.COLUMNS.DISPLAY_NAME">
|
||||
<ng-template let-value="value" let-context>
|
||||
<span class="adf-datatable-cell" title="{{ context?.row?.obj | adfNodeNameTooltip }}">{{ value }}</span>
|
||||
</ng-template>
|
||||
</data-column>
|
||||
|
||||
<data-column
|
||||
key="content.sizeInBytes"
|
||||
title="DOCUMENT_LIST.COLUMNS.SIZE"
|
||||
type="fileSize">
|
||||
</data-column>
|
||||
|
||||
<data-column
|
||||
key="archivedAt"
|
||||
title="DOCUMENT_LIST.COLUMNS.DELETED_ON">
|
||||
<ng-template let-value="value">
|
||||
<span title="{{ value | date:'medium' }}">{{ value | adfTimeAgo }}</span>
|
||||
</ng-template>
|
||||
</data-column>
|
||||
|
||||
<data-column
|
||||
class="adf-data-table-cell--ellipsis"
|
||||
key="archivedByUser.displayName"
|
||||
title="DOCUMENT_LIST.COLUMNS.DELETED_BY">
|
||||
</data-column>
|
||||
|
||||
</data-columns>
|
||||
|
||||
</adf-document-list>
|
||||
<adf-pagination [ngClass]="{ 'no-border' : documentList.isEmpty()}"
|
||||
[target]="documentList">
|
||||
</adf-pagination>
|
||||
</div>
|
||||
</div>
|
@@ -0,0 +1,35 @@
|
||||
.empty-list {
|
||||
.adf-data-table {
|
||||
height: 100%;
|
||||
|
||||
tr:hover, tr:focus {
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
&__block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
p {
|
||||
line-height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&__subtitle {
|
||||
font-size: 14px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
&__block > mat-icon {
|
||||
font-size: 52px;
|
||||
height: 52px;
|
||||
width: 52px;
|
||||
}
|
||||
}
|
43
demo-shell/src/app/components/trashcan/trashcan.component.ts
Normal file
43
demo-shell/src/app/components/trashcan/trashcan.component.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2017 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Component, ViewChild } from '@angular/core';
|
||||
import { DocumentListComponent } from '@alfresco/adf-content-services';
|
||||
|
||||
@Component({
|
||||
templateUrl: './trashcan.component.html',
|
||||
styleUrls: ['trashcan.component.scss']
|
||||
})
|
||||
export class TrashcanComponent {
|
||||
|
||||
@ViewChild(DocumentListComponent)
|
||||
documentList;
|
||||
|
||||
refresh() {
|
||||
this.documentList.loadTrashcan();
|
||||
this.documentList.resetSelection();
|
||||
}
|
||||
|
||||
}
|
@@ -25,7 +25,7 @@ Deletes multiple files and folders.
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| selection | `MinimalNodeEntity[]` | | Array of nodes to delete. |
|
||||
| selection | `MinimalNodeEntity[] | DeletedNodeEntity[]` | | Array of nodes to delete. |
|
||||
| permanent | `boolean` | `false` | If true then the nodes are deleted immediately rather than being put in the trash. |
|
||||
|
||||
### Events
|
||||
@@ -36,7 +36,7 @@ Deletes multiple files and folders.
|
||||
|
||||
## Details
|
||||
|
||||
See **Demo Shell**
|
||||
Note it the file is already in the trashcan so is a DeletedNodeEntity the performing of this action will delete the file premanently
|
||||
|
||||
## See also
|
||||
|
||||
|
@@ -36,7 +36,8 @@ class TestComponent {
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<div [adf-node-permission]="selection" [adf-delete]="selection"
|
||||
<div [adf-node-permission]="selection"
|
||||
[adf-delete]="selection"
|
||||
(delete)="done()">
|
||||
</div>`
|
||||
})
|
||||
@@ -46,13 +47,33 @@ class TestWithPermissionsComponent {
|
||||
done = jasmine.createSpy('done');
|
||||
}
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
delete permanent
|
||||
<div id="delete-permanent"
|
||||
[adf-delete]="selection"
|
||||
[permanent]="permanent"
|
||||
(delete)="done()">
|
||||
</div>`
|
||||
})
|
||||
class TestDeletePermanentComponent {
|
||||
selection = [];
|
||||
|
||||
permanent = true;
|
||||
|
||||
done = jasmine.createSpy('done');
|
||||
}
|
||||
|
||||
describe('NodeDeleteDirective', () => {
|
||||
let fixture: ComponentFixture<TestComponent>;
|
||||
let fixtureWithPermissions: ComponentFixture<TestWithPermissionsComponent>;
|
||||
let fixtureWithPermanentComponent: ComponentFixture<TestDeletePermanentComponent>;
|
||||
let element: DebugElement;
|
||||
let elementWithPermissions: DebugElement;
|
||||
let elementWithPermanentDelete: DebugElement;
|
||||
let component: TestComponent;
|
||||
let componentWithPermissions: TestWithPermissionsComponent;
|
||||
let componentWithPermanentDelete: TestDeletePermanentComponent;
|
||||
let alfrescoApi: AlfrescoApiService;
|
||||
let notification: NotificationService;
|
||||
let nodeApi;
|
||||
@@ -62,17 +83,23 @@ describe('NodeDeleteDirective', () => {
|
||||
|
||||
declarations: [
|
||||
TestComponent,
|
||||
TestWithPermissionsComponent
|
||||
TestWithPermissionsComponent,
|
||||
TestDeletePermanentComponent
|
||||
]
|
||||
})
|
||||
.compileComponents()
|
||||
.then(() => {
|
||||
fixture = TestBed.createComponent(TestComponent);
|
||||
fixtureWithPermissions = TestBed.createComponent(TestWithPermissionsComponent);
|
||||
fixtureWithPermanentComponent = TestBed.createComponent(TestDeletePermanentComponent);
|
||||
|
||||
component = fixture.componentInstance;
|
||||
componentWithPermissions = fixtureWithPermissions.componentInstance;
|
||||
componentWithPermanentDelete = fixtureWithPermanentComponent.componentInstance;
|
||||
|
||||
element = fixture.debugElement.query(By.directive(NodeDeleteDirective));
|
||||
elementWithPermissions = fixtureWithPermissions.debugElement.query(By.directive(NodeDeleteDirective));
|
||||
elementWithPermanentDelete = fixtureWithPermanentComponent.debugElement.query(By.directive(NodeDeleteDirective));
|
||||
|
||||
alfrescoApi = TestBed.get(AlfrescoApiService);
|
||||
nodeApi = alfrescoApi.getInstance().nodes;
|
||||
@@ -268,5 +295,43 @@ describe('NodeDeleteDirective', () => {
|
||||
expect(elementWithPermissions.nativeElement.disabled).toEqual(false);
|
||||
}));
|
||||
|
||||
describe('Permanent', () => {
|
||||
|
||||
it('should call the api with permamnet delete option if permanent directive input is true', fakeAsync(() => {
|
||||
let deleteApi = spyOn(nodeApi, 'deleteNode').and.returnValue(Promise.resolve());
|
||||
|
||||
fixtureWithPermanentComponent.detectChanges();
|
||||
|
||||
componentWithPermanentDelete.selection = [
|
||||
{ entry: { id: '1', name: 'name1'}
|
||||
];
|
||||
|
||||
fixtureWithPermanentComponent.detectChanges();
|
||||
|
||||
elementWithPermanentDelete.triggerEventHandler('click', null);
|
||||
tick();
|
||||
|
||||
expect(deleteApi).toHaveBeenCalledWith('1', { permanent: true });
|
||||
}));
|
||||
|
||||
it('should call the traschan api if permanent directive input is true and the file is already in the trashcan ', fakeAsync(() => {
|
||||
let deleteApi = spyOn(nodeApi, 'purgeDeletedNode').and.returnValue(Promise.resolve());
|
||||
|
||||
fixtureWithPermanentComponent.detectChanges();
|
||||
|
||||
componentWithPermanentDelete.selection = [
|
||||
{ entry: { id: '1', name: 'name1', archivedAt: 'archived' } }
|
||||
];
|
||||
|
||||
fixtureWithPermanentComponent.detectChanges();
|
||||
|
||||
elementWithPermanentDelete.triggerEventHandler('click', null);
|
||||
tick();
|
||||
|
||||
expect(deleteApi).toHaveBeenCalledWith('1');
|
||||
}));
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -18,7 +18,7 @@
|
||||
/* tslint:disable:no-input-rename */
|
||||
|
||||
import { Directive, ElementRef, EventEmitter, HostListener, Input, OnChanges, Output } from '@angular/core';
|
||||
import { MinimalNodeEntity, MinimalNodeEntryEntity } from 'alfresco-js-api';
|
||||
import { MinimalNodeEntity, MinimalNodeEntryEntity, DeletedNodeEntity, DeletedNodeMinimalEntry } from 'alfresco-js-api';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { AlfrescoApiService } from '../services/alfresco-api.service';
|
||||
import { NotificationService } from '../services/notification.service';
|
||||
@@ -28,7 +28,7 @@ import 'rxjs/observable/forkJoin';
|
||||
import 'rxjs/add/operator/catch';
|
||||
|
||||
interface ProcessedNodeData {
|
||||
entry: MinimalNodeEntryEntity;
|
||||
entry: MinimalNodeEntryEntity | DeletedNodeMinimalEntry;
|
||||
status: number;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ interface ProcessStatus {
|
||||
export class NodeDeleteDirective implements OnChanges {
|
||||
/** Array of nodes to delete. */
|
||||
@Input('adf-delete')
|
||||
selection: MinimalNodeEntity[];
|
||||
selection: MinimalNodeEntity[] | DeletedNodeEntity[];
|
||||
|
||||
/** If true then the nodes are deleted immediately rather than being
|
||||
* put in the trash.
|
||||
@@ -92,10 +92,8 @@ export class NodeDeleteDirective implements OnChanges {
|
||||
this.elementRef.nativeElement.disabled = disable;
|
||||
}
|
||||
|
||||
private process(selection: MinimalNodeEntity[]) {
|
||||
if (!selection.length) {
|
||||
return;
|
||||
}
|
||||
private process(selection: MinimalNodeEntity[] | DeletedNodeEntity[]) {
|
||||
if (selection && selection.length) {
|
||||
|
||||
const batch = this.getDeleteNodesBatch(selection);
|
||||
|
||||
@@ -110,15 +108,22 @@ export class NodeDeleteDirective implements OnChanges {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private getDeleteNodesBatch(selection: MinimalNodeEntity[]): Observable<ProcessedNodeData>[] {
|
||||
private getDeleteNodesBatch(selection: any): Observable<ProcessedNodeData>[] {
|
||||
return selection.map((node) => this.deleteNode(node));
|
||||
}
|
||||
|
||||
private deleteNode(node: MinimalNodeEntity): Observable<ProcessedNodeData> {
|
||||
private deleteNode(node: MinimalNodeEntity | DeletedNodeEntity): Observable<ProcessedNodeData> {
|
||||
const id = (<any> node.entry).nodeId || node.entry.id;
|
||||
|
||||
const promise = this.alfrescoApiService.getInstance().nodes.deleteNode(id, { permanent: this.permanent });
|
||||
let promise;
|
||||
|
||||
if (node.entry.hasOwnProperty('archivedAt')) {
|
||||
promise = this.alfrescoApiService.getInstance().nodes.purgeDeletedNode(id);
|
||||
} else {
|
||||
promise = this.alfrescoApiService.getInstance().nodes.deleteNode(id, { permanent: this.permanent });
|
||||
}
|
||||
|
||||
return Observable.fromPromise(promise)
|
||||
.map(() => ({
|
||||
|
@@ -23,7 +23,7 @@ import { Observable } from 'rxjs/Observable';
|
||||
import { ComponentTranslationModel } from '../models/component.model';
|
||||
import { ObjectUtils } from '../utils/object-utils';
|
||||
import { LogService } from './log.service';
|
||||
import { map } from 'rxjs/operators'
|
||||
import { map } from 'rxjs/operators';
|
||||
import 'rxjs/observable/forkJoin';
|
||||
import 'rxjs/add/observable/forkJoin';
|
||||
|
||||
|
Reference in New Issue
Block a user