diff --git a/ng2-components/ng2-activiti-form/src/services/activiti-content-service.ts b/ng2-components/ng2-activiti-form/src/services/activiti-content-service.ts index 194c510cb2..36dd1d1e2b 100644 --- a/ng2-components/ng2-activiti-form/src/services/activiti-content-service.ts +++ b/ng2-components/ng2-activiti-form/src/services/activiti-content-service.ts @@ -123,4 +123,9 @@ export class ActivitiContentService { let icon = this.mimeTypeIcons[mimeType]; return icon || ActivitiContentService.DEFAULT_MIME_TYPE_ICON; } + + createTaskRelatedContent(taskId: string, file: any) { + return Observable.fromPromise(this.apiService.getInstance().activiti.contentApi.createRelatedContentOnTask(taskId, file)) + .catch(err => this.handleError(err)); + } } diff --git a/ng2-components/ng2-activiti-tasklist/README.md b/ng2-components/ng2-activiti-tasklist/README.md index aae994f3f8..4d8a0931c9 100644 --- a/ng2-components/ng2-activiti-tasklist/README.md +++ b/ng2-components/ng2-activiti-tasklist/README.md @@ -401,6 +401,58 @@ The component shows all the available filters. ``` +### Task Attachment List component + +This component displays attached documents on a specified task + +```html + +``` +![task-attachment-list-sample](docs/assets/task-attachment-list.png) + +#### Options + + +| Name | Description | +| --- | --- | +| `taskId` | (required): The numeric ID of the task to display | + +#### Events + + +| Name | Description | +| --- | --- | +| `attachmentClick` | Emitted when the attachment double clicked or selected view option from context menu by the user from within the component | + + +### Create Task Attachment component + +This component displays Upload Component(Drag and Click) to upload the attachment to a specified task + +```html + +``` + +![task-create-attachment](docs/assets/task-create-attachment.png) + +#### Options + + +| Name | Description | +| --- | --- | +| `taskId` | (required): The numeric ID of the task to display | + +#### Events + + +| Name | Description | +| --- | --- | +| `error` | Emitted when the error occured while creating/uploading the attachment by the user from within the component | +| `success` | Emitted when the attachement created/uploaded successfully from within the component | + ## Build from sources Alternatively you can build component from sources with the following commands: diff --git a/ng2-components/ng2-activiti-tasklist/docs/assets/task-attachment-list.png b/ng2-components/ng2-activiti-tasklist/docs/assets/task-attachment-list.png new file mode 100644 index 0000000000..23d902bfb4 Binary files /dev/null and b/ng2-components/ng2-activiti-tasklist/docs/assets/task-attachment-list.png differ diff --git a/ng2-components/ng2-activiti-tasklist/docs/assets/task-create-attachment.png b/ng2-components/ng2-activiti-tasklist/docs/assets/task-create-attachment.png new file mode 100644 index 0000000000..f755633f7c Binary files /dev/null and b/ng2-components/ng2-activiti-tasklist/docs/assets/task-create-attachment.png differ diff --git a/ng2-components/ng2-activiti-tasklist/index.ts b/ng2-components/ng2-activiti-tasklist/index.ts index 862d666d25..111c2c9862 100644 --- a/ng2-components/ng2-activiti-tasklist/index.ts +++ b/ng2-components/ng2-activiti-tasklist/index.ts @@ -35,7 +35,8 @@ import { ActivitiTaskHeader, ActivitiStartTaskButton, ActivitiPeopleSearch, - TaskAttachmentListComponent + TaskAttachmentListComponent, + ActivitiCreateTaskAttachmentComponent } from './src/components/index'; export * from './src/components/index'; @@ -54,7 +55,8 @@ export const ACTIVITI_TASKLIST_DIRECTIVES: any[] = [ ActivitiTaskHeader, ActivitiStartTaskButton, ActivitiPeopleSearch, - TaskAttachmentListComponent + TaskAttachmentListComponent, + ActivitiCreateTaskAttachmentComponent ]; export const ACTIVITI_TASKLIST_PROVIDERS: any[] = [ diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-create-task-attachment.component.css b/ng2-components/ng2-activiti-tasklist/src/components/activiti-create-task-attachment.component.css new file mode 100644 index 0000000000..7371ee4215 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-create-task-attachment.component.css @@ -0,0 +1,19 @@ +.upload-attachment-container { + border: 1px solid rgb(224, 224, 224); + background: #fff; + text-align: left; + border-top: none; + padding: 10px; + text-align: center; +} + +.drag-area { + border: 1px solid #eee; + padding: 100px 10px; + margin-bottom: 10px; +} + +.upload-attachment-container button { + color: rgb(253, 145, 0); + opacity: 0.64; +} \ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-create-task-attachment.component.html b/ng2-components/ng2-activiti-tasklist/src/components/activiti-create-task-attachment.component.html new file mode 100644 index 0000000000..e1d5f20345 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-create-task-attachment.component.html @@ -0,0 +1,15 @@ +
+
+ Drop Files Here... +
+ +
\ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-create-task-attachment.component.spec.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-create-task-attachment.component.spec.ts new file mode 100644 index 0000000000..defcaf09a4 --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-create-task-attachment.component.spec.ts @@ -0,0 +1,102 @@ +/*! + * @license + * Copyright 2016 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 { SimpleChange } from '@angular/core'; +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { Observable } from 'rxjs/Rx'; + +import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core'; +import { ActivitiContentService } from 'ng2-activiti-form'; + +import { ActivitiCreateTaskAttachmentComponent } from './activiti-create-task-attachment.component'; + +describe('Activiti Task Create Attachment', () => { + + let componentHandler: any; + let service: ActivitiContentService; + let component: ActivitiCreateTaskAttachmentComponent; + let fixture: ComponentFixture; + let createTaskRelatedContentSpy: jasmine.Spy; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + CoreModule.forRoot() + ], + declarations: [ + ActivitiCreateTaskAttachmentComponent + ], + providers: [ + { provide: AlfrescoTranslationService }, + ActivitiContentService + ] + }).compileComponents(); + })); + + beforeEach(() => { + + fixture = TestBed.createComponent(ActivitiCreateTaskAttachmentComponent); + component = fixture.componentInstance; + service = fixture.debugElement.injector.get(ActivitiContentService); + + createTaskRelatedContentSpy = spyOn(service, 'createTaskRelatedContent').and.returnValue(Observable.of( + { + status: true + })); + + componentHandler = jasmine.createSpyObj('componentHandler', [ + 'upgradeAllRegistered', + 'upgradeElement' + ]); + window['componentHandler'] = componentHandler; + }); + + it('should not call createTaskRelatedContent service when taskId changed', () => { + let change = new SimpleChange(null, '123', true); + component.ngOnChanges({ 'taskId': change }); + expect(createTaskRelatedContentSpy).not.toHaveBeenCalled(); + }); + + it('should not call createTaskRelatedContent service when there is no file uploaded', () => { + let change = new SimpleChange(null, '123', true); + component.ngOnChanges({ 'taskId': change }); + let customEvent = { + detail: { + files: [ + ] + } + }; + component.onFileUpload(customEvent); + expect(createTaskRelatedContentSpy).not.toHaveBeenCalled(); + }); + + it('should call createTaskRelatedContent service when there is a file uploaded', () => { + let change = new SimpleChange(null, '123', true); + component.ngOnChanges({ 'taskId': change }); + let file = new File([new Blob()], 'Test'); + let customEvent = { + detail: { + files: [ + file + ] + } + }; + component.onFileUpload(customEvent); + expect(createTaskRelatedContentSpy).toHaveBeenCalled(); + }); +}); diff --git a/ng2-components/ng2-activiti-tasklist/src/components/activiti-create-task-attachment.component.ts b/ng2-components/ng2-activiti-tasklist/src/components/activiti-create-task-attachment.component.ts new file mode 100644 index 0000000000..5160aea40a --- /dev/null +++ b/ng2-components/ng2-activiti-tasklist/src/components/activiti-create-task-attachment.component.ts @@ -0,0 +1,67 @@ +/*! + * @license + * Copyright 2016 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 { Component, OnChanges, Input, SimpleChanges, Output, EventEmitter } from '@angular/core'; +import { AlfrescoTranslationService } from 'ng2-alfresco-core'; +import { ActivitiContentService } from 'ng2-activiti-form'; + +@Component({ + selector: 'activiti-create-task-attachment', + styleUrls: ['./activiti-create-task-attachment.component.css'], + templateUrl: './activiti-create-task-attachment.component.html' +}) +export class ActivitiCreateTaskAttachmentComponent implements OnChanges { + + @Input() + taskId: string; + + @Output() + error: EventEmitter = new EventEmitter(); + + @Output() + success: EventEmitter = new EventEmitter(); + + constructor(private translateService: AlfrescoTranslationService, + private activitiContentService: ActivitiContentService) { + + if (translateService) { + translateService.addTranslationFolder('ng2-activiti-tasklist', 'node_modules/ng2-activiti-tasklist/src'); + } + } + + ngOnChanges(changes: SimpleChanges) { + if (changes['taskId'] && changes['taskId'].currentValue) { + this.taskId = changes['taskId'].currentValue; + } + } + + onFileUpload(event: any) { + let files: File[] = event.detail.files; + + for (let i = 0; i < files.length; i++) { + let file: File = files[i]; + this.activitiContentService.createTaskRelatedContent(this.taskId, file).subscribe( + (res) => { + this.success.emit(res); + }, + (err) => { + this.error.emit(err); + } + ); + } + } +} diff --git a/ng2-components/ng2-activiti-tasklist/src/components/adf-task-attachment-list.component.css b/ng2-components/ng2-activiti-tasklist/src/components/adf-task-attachment-list.component.css index 67458ff066..908e599c81 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/adf-task-attachment-list.component.css +++ b/ng2-components/ng2-activiti-tasklist/src/components/adf-task-attachment-list.component.css @@ -6,3 +6,12 @@ alfresco-datatable >>> .column-header { alfresco-datatable >>> .data-cell { cursor: pointer !important; } + +.no-attachment-message { + border: 1px solid rgb(224, 224, 224); + background: #fff; + text-align: left; + border-top: none; + padding: 10px; + text-align: center; +} \ No newline at end of file diff --git a/ng2-components/ng2-activiti-tasklist/src/components/adf-task-attachment-list.component.html b/ng2-components/ng2-activiti-tasklist/src/components/adf-task-attachment-list.component.html index 8eaadbb56f..ec0aaf4c1b 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/adf-task-attachment-list.component.html +++ b/ng2-components/ng2-activiti-tasklist/src/components/adf-task-attachment-list.component.html @@ -1,3 +1,6 @@ +
+ No Attachments Found +
= new EventEmitter(); + attachments: any[] = []; constructor(private translateService: AlfrescoTranslationService, - private activitiContentService: ActivitiContentService) { + private activitiContentService: ActivitiContentService, + private contentService: ContentService) { if (translateService) { translateService.addTranslationFolder('ng2-activiti-tasklist', 'node_modules/ng2-activiti-tasklist/src'); @@ -90,31 +94,63 @@ export class TaskAttachmentListComponent implements OnChanges { } onShowRowActionsMenu(event: any) { - let myAction = { - title: 'Delete', - name: 'delete' + let viewAction = { + title: 'View', + name: 'view' }; + + let removeAction = { + title: 'Remove', + name: 'remove' + }; + + let downloadAction = { + title: 'Download', + name: 'download' + }; + event.value.actions = [ - myAction + viewAction, + removeAction, + downloadAction ]; } onExecuteRowAction(event: any) { let args = event.value; let action = args.action; - if (action.name === 'delete') { + if (action.name === 'view') { + this.emitDocumentContent(args.row.obj); + } else if (action.name === 'remove') { this.deleteAttachmentById(args.row.obj.id); + } else if (action.name === 'download') { + this.downloadContent(args.row.obj); } } openContent(event: any): void { let content = event.value.obj; + this.emitDocumentContent(content); + } + + emitDocumentContent(content: any) { this.activitiContentService.getFileRawContent(content.id).subscribe( (blob: Blob) => { content.contentBlob = blob; this.attachmentClick.emit(content); + }, + (err) => { + this.error.emit(err); } ); } + downloadContent(content: any): void { + this.activitiContentService.getFileRawContent(content.id).subscribe( + (blob: Blob) => this.contentService.downloadBlob(blob, content.name), + (err) => { + this.error.emit(err); + } + ); + } } diff --git a/ng2-components/ng2-activiti-tasklist/src/components/index.ts b/ng2-components/ng2-activiti-tasklist/src/components/index.ts index 2f7a94872f..ce820f1b0b 100644 --- a/ng2-components/ng2-activiti-tasklist/src/components/index.ts +++ b/ng2-components/ng2-activiti-tasklist/src/components/index.ts @@ -27,3 +27,4 @@ export * from './activiti-filters.component'; export * from './activiti-task-details.component'; export * from './activiti-start-task.component'; export * from './activiti-people-search.component'; +export * from './activiti-create-task-attachment.component';