mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-26 17:24:56 +00:00
[ADF-1711] The <adf-task-attachment-list component displays drag-and-drop area that is not working (#2658)
* [ADF-1711] The <adf-task-attachment-list component displays drag-and-drop area that is not working * Made the drag and drop area working in demo shell for task attachment * Provided a way to pass custom no content template for drag and drop to the user * Updated the task-attachment README file for the user to know how to use drag and drop component with task-attachment component * [ADF-1711] The <adf-task-attachment-list component displays drag-and-drop area that is not working * Made the drag and drop area working in demo shell for task attachment * Provided a way to pass custom no content template for drag and drop to the user * Updated the task-attachment README file for the user to know how to use drag and drop component with task-attachment component
This commit is contained in:
parent
bf6d0284e0
commit
aa8b2a28f3
@ -85,10 +85,20 @@
|
||||
</div>
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<adf-task-attachment-list
|
||||
[taskId]="currentTaskId"
|
||||
(attachmentClick)="onContentClick($event)">
|
||||
</adf-task-attachment-list>
|
||||
<adf-upload-drag-area
|
||||
[parentId]="currentTaskId"
|
||||
[showNotificationBar]="false">
|
||||
<adf-task-attachment-list #taskAttachList
|
||||
[taskId]="currentTaskId">
|
||||
<div adf-empty-list>
|
||||
<div adf-empty-list-header class="adf-empty-list-header"> {{'ADF_TASK_LIST.ATTACHMENT.EMPTY.HEADER' | translate}} </div>
|
||||
<div adf-empty-list-body>
|
||||
<div fxHide.lt-md="true" class="adf-empty-list-drag_drop">{{'ADF_TASK_LIST.ATTACHMENT.EMPTY.DRAG-AND-DROP.TITLE' | translate}}</div>
|
||||
<div fxHide.lt-md="true" class="adf-empty-list__any-files-here-to-add"> {{'ADF_TASK_LIST.ATTACHMENT.EMPTY.DRAG-AND-DROP.SUBTITLE' | translate}} </div>
|
||||
</div>
|
||||
</div>
|
||||
</adf-task-attachment-list>
|
||||
</adf-upload-drag-area>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
|
@ -49,10 +49,12 @@ import {
|
||||
TaskDetailsEvent,
|
||||
TaskFiltersComponent,
|
||||
TaskListComponent,
|
||||
TaskListService
|
||||
TaskListService,
|
||||
TaskAttachmentListComponent,
|
||||
ProcessUploadService
|
||||
} from '@alfresco/adf-process-services';
|
||||
import { LogService } from '@alfresco/adf-core';
|
||||
import { AlfrescoApiService } from '@alfresco/adf-core';
|
||||
import { AlfrescoApiService, UploadService } from '@alfresco/adf-core';
|
||||
import {
|
||||
DataSorting,
|
||||
ObjectDataRow,
|
||||
@ -69,6 +71,9 @@ const currentTaskIdNew = '__NEW__';
|
||||
selector: 'adf-activiti',
|
||||
templateUrl: './activiti.component.html',
|
||||
styleUrls: ['./activiti.component.scss'],
|
||||
providers: [
|
||||
{ provide: UploadService, useClass: ProcessUploadService }
|
||||
],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ActivitiComponent implements AfterViewInit, OnDestroy, OnInit {
|
||||
@ -79,6 +84,9 @@ export class ActivitiComponent implements AfterViewInit, OnDestroy, OnInit {
|
||||
@ViewChild(TaskListComponent)
|
||||
taskList: TaskListComponent;
|
||||
|
||||
@ViewChild(TaskAttachmentListComponent)
|
||||
taskAttachList: TaskAttachmentListComponent;
|
||||
|
||||
@ViewChild(ProcessFiltersComponent)
|
||||
activitiprocessfilter: ProcessFiltersComponent;
|
||||
|
||||
@ -147,7 +155,8 @@ export class ActivitiComponent implements AfterViewInit, OnDestroy, OnInit {
|
||||
private apiService: AlfrescoApiService,
|
||||
private logService: LogService,
|
||||
formRenderingService: FormRenderingService,
|
||||
formService: FormService) {
|
||||
formService: FormService,
|
||||
private uploadService: UploadService) {
|
||||
this.dataTasks = new ObjectDataTableAdapter();
|
||||
this.dataTasks.setSorting(new DataSorting('created', 'desc'));
|
||||
|
||||
@ -247,6 +256,7 @@ export class ActivitiComponent implements AfterViewInit, OnDestroy, OnInit {
|
||||
this.currentProcessInstanceId = null;
|
||||
});
|
||||
this.layoutType = AppsListComponent.LAYOUT_GRID;
|
||||
this.uploadService.fileUploadComplete.subscribe(value => this.onTaskFileUploadComplete(value.data));
|
||||
|
||||
}
|
||||
|
||||
@ -480,4 +490,8 @@ export class ActivitiComponent implements AfterViewInit, OnDestroy, OnInit {
|
||||
this.taskList.reload();
|
||||
this.currentTaskId = null;
|
||||
}
|
||||
|
||||
onTaskFileUploadComplete(content: any) {
|
||||
this.taskAttachList.add(content);
|
||||
}
|
||||
}
|
||||
|
BIN
docs/docassets/images/custom-no-content-drag-drop-template.png
Normal file
BIN
docs/docassets/images/custom-no-content-drag-drop-template.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
docs/docassets/images/default-no-content-template.png
Normal file
BIN
docs/docassets/images/default-no-content-template.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
@ -1,6 +1,6 @@
|
||||
# Task Attachment List Component
|
||||
|
||||
Displays attached documents on a specified task
|
||||
Displays attached documents on a specified task.
|
||||
|
||||

|
||||
|
||||
@ -9,6 +9,7 @@ Displays attached documents on a specified task
|
||||
<!-- toc -->
|
||||
|
||||
- [Basic Usage](#basic-usage)
|
||||
* [Drag and Drop Functionality](#how-to-add-drag-and-drop-functionality)
|
||||
* [Properties](#properties)
|
||||
* [Events](#events)
|
||||
|
||||
@ -24,6 +25,38 @@ Displays attached documents on a specified task
|
||||
(attachmentClick)="YOUR_HANDLER">
|
||||
</adf-task-attachment-list>
|
||||
```
|
||||
If the List is empty, a default no content template is displayed.
|
||||
|
||||

|
||||
|
||||
### How to Add Drag and Drop Functionality
|
||||
|
||||
If we want user to be able to upload attachments for empty lists, We can wrap our component with upload drag area component. In that case, We should also pass a custom *no content template* as shown below with our component urging the user to drag files to upload whenever the list is empty.
|
||||
|
||||
```html
|
||||
<adf-upload-drag-area
|
||||
[parentId]="YOUR_TASK_ID"
|
||||
[showNotificationBar]="BOOLEAN">
|
||||
<adf-task-attachment-list
|
||||
[taskId]="YOUR_TASK_ID"
|
||||
(attachmentClick)="YOUR_HANDLER">
|
||||
<div adf-empty-list> //no content template
|
||||
<adf-empty-list>
|
||||
<div adf-empty-list-header>{{This List is empty}}</div>
|
||||
<div adf-empty-list-body>{{Drag and drop to upload}}</div>
|
||||
<div adf-empty-list-footer>
|
||||
<img [src]="Your custom image URL"></div>
|
||||
</adf-empty-list>
|
||||
</div>
|
||||
</adf-task-attachment-list>
|
||||
</adf-upload-drag-area>
|
||||
```
|
||||
|
||||
[Upload Drag Area Component](./upload-drag-area.component.md)
|
||||
|
||||
If the List is empty, the custom no-content template we passed is displayed.
|
||||
|
||||

|
||||
|
||||
### Properties
|
||||
|
||||
|
@ -1,25 +1,29 @@
|
||||
<adf-datatable [rows]="attachments" [actions]="true" [loading]="isLoading" (rowDblClick)="openContent($event)" (showRowActionsMenu)="onShowRowActionsMenu($event)"
|
||||
(executeRowAction)="onExecuteRowAction($event)">
|
||||
<adf-empty-list *ngIf="isEmpty()">
|
||||
<div adf-empty-list-header class="adf-empty-list-header"> {{'ADF_TASK_LIST.ATTACHMENT.EMPTY.HEADER' | translate}} </div>
|
||||
<div adf-empty-list-body *ngIf="!isDisabled()">
|
||||
<div fxHide.lt-md="true" class="adf-empty-list-drag_drop">{{'ADF_TASK_LIST.ATTACHMENT.EMPTY.DRAG-AND-DROP.TITLE' | translate}}</div>
|
||||
<div fxHide.lt-md="true" class="adf-empty-list__any-files-here-to-add"> {{'ADF_TASK_LIST.ATTACHMENT.EMPTY.DRAG-AND-DROP.SUBTITLE' | translate}} </div>
|
||||
</div>
|
||||
<div adf-empty-list-footer *ngIf="!isDisabled()">
|
||||
<img class="adf-empty-list__empty_doc_lib" [src]="emptyListImageUrl">
|
||||
</div>
|
||||
</adf-empty-list>
|
||||
<data-columns>
|
||||
<data-column key="icon" type="image" srTitle="ADF_TASK_LIST.PROPERTIES.THUMBNAIL" [sortable]="false"></data-column>
|
||||
<data-column key="name" type="text" title="ADF_TASK_LIST.PROPERTIES.NAME" class="full-width ellipsis-cell" [sortable]="true"></data-column>
|
||||
<data-column key="created" type="date" format="shortDate" title="ADF_TASK_LIST.PROPERTIES.CREATED"></data-column>
|
||||
</data-columns>
|
||||
<loading-content-template>
|
||||
<ng-template>
|
||||
<!--Add your custom loading template here-->
|
||||
<mat-progress-spinner class="adf-attachment-list-loading-margin" [color]="'primary'" [mode]="'indeterminate'">
|
||||
</mat-progress-spinner>
|
||||
</ng-template>
|
||||
</loading-content-template>
|
||||
<adf-datatable [rows]="attachments"
|
||||
[actions]="true"
|
||||
[loading]="isLoading"
|
||||
(rowDblClick)="openContent($event)"
|
||||
(showRowActionsMenu)="onShowRowActionsMenu($event)"
|
||||
(executeRowAction)="onExecuteRowAction($event)">
|
||||
|
||||
<adf-empty-list *ngIf="isEmpty()">
|
||||
<div adf-empty-list-header class="adf-empty-list-header" *ngIf="!isCustomTemplateDefined()">
|
||||
{{'ADF_TASK_LIST.ATTACHMENT.EMPTY.HEADER' | translate}}
|
||||
</div>
|
||||
<div *ngIf="!isDisabled()" #customEmptyListTemplate class="adf-custom-empty-template">
|
||||
<ng-content select="[adf-empty-list]"></ng-content>
|
||||
</div>
|
||||
</adf-empty-list>
|
||||
|
||||
<data-columns>
|
||||
<data-column key="icon" type="icon" srTitle="ADF_TASK_LIST.PROPERTIES.THUMBNAIL" [sortable]="false"></data-column>
|
||||
<data-column key="name" type="text" title="ADF_TASK_LIST.PROPERTIES.NAME" class="full-width ellipsis-cell" [sortable]="true"></data-column>
|
||||
<data-column key="created" type="date" format="shortDate" title="ADF_TASK_LIST.PROPERTIES.CREATED"></data-column>
|
||||
</data-columns>
|
||||
<loading-content-template>
|
||||
<ng-template>
|
||||
<!--Add your custom loading template here-->
|
||||
<mat-progress-spinner class="adf-attachment-list-loading-margin" [color]="'primary'" [mode]="'indeterminate'">
|
||||
</mat-progress-spinner>
|
||||
</ng-template>
|
||||
</loading-content-template>
|
||||
</adf-datatable>
|
||||
|
@ -141,7 +141,54 @@ describe('TaskAttachmentList', () => {
|
||||
});
|
||||
}));
|
||||
|
||||
it('should display all actions if attachements are not read only', () => {
|
||||
it('emit document when a user wants to view the document', () => {
|
||||
component.emitDocumentContent(mockAttachment.data[1]);
|
||||
fixture.detectChanges();
|
||||
expect(getFileRawContentSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('download document when a user wants to view the document', () => {
|
||||
component.downloadContent(mockAttachment.data[1]);
|
||||
fixture.detectChanges();
|
||||
expect(getFileRawContentSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should show the empty list drag and drop component when the task is not completed', async(() => {
|
||||
getTaskRelatedContentSpy.and.returnValue(Observable.of({
|
||||
'size': 0,
|
||||
'total': 0,
|
||||
'start': 0,
|
||||
'data': []
|
||||
}));
|
||||
let change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({'taskId': change});
|
||||
component.disabled = false;
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.querySelector('.adf-custom-empty-template')).not.toBeNull();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should not show the empty list drag and drop component when is disabled', async(() => {
|
||||
getTaskRelatedContentSpy.and.returnValue(Observable.of({
|
||||
'size': 0,
|
||||
'total': 0,
|
||||
'start': 0,
|
||||
'data': []
|
||||
}));
|
||||
let change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({'taskId': change});
|
||||
component.disabled = true;
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.querySelector('.adf-custom-empty-template')).toBeNull();
|
||||
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim()).toEqual('ADF_TASK_LIST.ATTACHMENT.EMPTY.HEADER');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should display all actions if attachments are not read only', () => {
|
||||
let change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({'taskId': change});
|
||||
fixture.detectChanges();
|
||||
@ -190,40 +237,6 @@ describe('TaskAttachmentList', () => {
|
||||
});
|
||||
}));
|
||||
|
||||
it('should show the empty list drag and drop component when the task is not completed', async(() => {
|
||||
getTaskRelatedContentSpy.and.returnValue(Observable.of({
|
||||
'size': 0,
|
||||
'total': 0,
|
||||
'start': 0,
|
||||
'data': []
|
||||
}));
|
||||
let change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({'taskId': change});
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.querySelector('adf-empty-list .adf-empty-list-drag_drop').innerText.trim()).toEqual('ADF_TASK_LIST.ATTACHMENT.EMPTY.DRAG-AND-DROP.TITLE');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should not show the empty list drag and drop component when is disabled', async(() => {
|
||||
getTaskRelatedContentSpy.and.returnValue(Observable.of({
|
||||
'size': 0,
|
||||
'total': 0,
|
||||
'start': 0,
|
||||
'data': []
|
||||
}));
|
||||
let change = new SimpleChange(null, '123', true);
|
||||
component.ngOnChanges({'taskId': change});
|
||||
component.disabled = true;
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.querySelector('adf-empty-list .adf-empty-list-drag_drop')).toBeNull();
|
||||
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim()).toEqual('ADF_TASK_LIST.ATTACHMENT.EMPTY.HEADER');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should show the empty list component when the attachments list is empty for completed task', async(() => {
|
||||
getTaskRelatedContentSpy.and.returnValue(Observable.of({
|
||||
'size': 0,
|
||||
@ -270,7 +283,7 @@ describe('TaskAttachmentList', () => {
|
||||
expect(getTaskRelatedContentSpy).toHaveBeenCalledWith('456');
|
||||
});
|
||||
|
||||
it('should NOT fetch new attachments when empty changeset made', () => {
|
||||
it('should NOT fetch new attachments when empty change set made', () => {
|
||||
component.ngOnChanges({});
|
||||
expect(getTaskRelatedContentSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
@ -292,5 +305,11 @@ describe('TaskAttachmentList', () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
it('delete content by contentId', () => {
|
||||
component.deleteAttachmentById(5);
|
||||
fixture.detectChanges();
|
||||
expect(deleteContentSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
@ -16,17 +16,16 @@
|
||||
*/
|
||||
|
||||
import { ContentService, ThumbnailService } from '@alfresco/adf-core';
|
||||
import { Component, EventEmitter, Input, NgZone, OnChanges, Output, SimpleChanges } from '@angular/core';
|
||||
import { AfterViewInit, Component, ElementRef, EventEmitter, Input, NgZone, OnChanges, Output, SimpleChanges, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { ProcessContentService } from '@alfresco/adf-core';
|
||||
|
||||
declare var require: any;
|
||||
|
||||
@Component({
|
||||
selector: 'adf-task-attachment-list',
|
||||
styleUrls: ['./task-attachment-list.component.scss'],
|
||||
templateUrl: './task-attachment-list.component.html'
|
||||
templateUrl: './task-attachment-list.component.html',
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class TaskAttachmentListComponent implements OnChanges {
|
||||
export class TaskAttachmentListComponent implements OnChanges, AfterViewInit {
|
||||
|
||||
@Input()
|
||||
taskId: string;
|
||||
@ -43,8 +42,9 @@ export class TaskAttachmentListComponent implements OnChanges {
|
||||
@Output()
|
||||
error: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
@Input()
|
||||
emptyListImageUrl: string = require('../assets/images/empty_doc_lib.svg');
|
||||
hasCustomTemplate: boolean;
|
||||
|
||||
@ViewChild('customEmptyListTemplate') customTemplateRef: ElementRef;
|
||||
|
||||
attachments: any[] = [];
|
||||
isLoading: boolean = true;
|
||||
@ -61,6 +61,13 @@ export class TaskAttachmentListComponent implements OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
if (this.customTemplateRef && this.customTemplateRef.nativeElement &&
|
||||
this.customTemplateRef.nativeElement.children && this.customTemplateRef.nativeElement.children.length > 0) {
|
||||
this.hasCustomTemplate = true;
|
||||
}
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
this.attachments = [];
|
||||
}
|
||||
@ -110,7 +117,7 @@ export class TaskAttachmentListComponent implements OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
private deleteAttachmentById(contentId: number) {
|
||||
deleteAttachmentById(contentId: number) {
|
||||
if (contentId) {
|
||||
this.activitiContentService.deleteRelatedContent(contentId).subscribe(
|
||||
(res: any) => {
|
||||
@ -128,6 +135,10 @@ export class TaskAttachmentListComponent implements OnChanges {
|
||||
return this.attachments && this.attachments.length === 0;
|
||||
}
|
||||
|
||||
isCustomTemplateDefined(): boolean {
|
||||
return this.hasCustomTemplate;
|
||||
}
|
||||
|
||||
onShowRowActionsMenu(event: any) {
|
||||
let viewAction = {
|
||||
title: 'ADF_TASK_LIST.MENU_ACTIONS.VIEW_CONTENT',
|
||||
|
Loading…
x
Reference in New Issue
Block a user