mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-19 17:14:57 +00:00
Merge branch 'development' into dev-denys-dts
# Conflicts: # demo-shell-ng2/systemjs.config.js # ng2-components/ng2-alfresco-upload/src/services/upload.service.spec.ts # ng2-components/ng2-alfresco-upload/src/services/upload.service.ts # ng2-components/ng2-alfresco-viewer/src/componets/viewer.component.spec.t s # ng2-components/ng2-alfresco-viewer/src/componets/viewer.component.ts
This commit is contained in:
commit
c037b91c9c
10
.travis.yml
10
.travis.yml
@ -28,8 +28,8 @@ env:
|
|||||||
- MODULE=ng2-alfresco-viewer
|
- MODULE=ng2-alfresco-viewer
|
||||||
- MODULE=ng2-alfresco-webscript
|
- MODULE=ng2-alfresco-webscript
|
||||||
- MODULE=ng2-activiti-form
|
- MODULE=ng2-activiti-form
|
||||||
- MODULE=ng2-activiti-processlist
|
|
||||||
- MODULE=ng2-activiti-tasklist
|
- MODULE=ng2-activiti-tasklist
|
||||||
|
- MODULE=ng2-activiti-processlist
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- if ([ "$MODULE" != "ng2-alfresco-core" ]); then
|
- if ([ "$MODULE" != "ng2-alfresco-core" ]); then
|
||||||
@ -38,9 +38,12 @@ before_script:
|
|||||||
- if ([ "$MODULE" == "ng2-alfresco-documentlist" ] || [ "$MODULE" == "ng2-alfresco-webscript" ] || [ "$MODULE" == "ng2-activiti-processlist" ] || [ "$MODULE" == "ng2-activiti-tasklist" ]); then
|
- if ([ "$MODULE" == "ng2-alfresco-documentlist" ] || [ "$MODULE" == "ng2-alfresco-webscript" ] || [ "$MODULE" == "ng2-activiti-processlist" ] || [ "$MODULE" == "ng2-activiti-tasklist" ]); then
|
||||||
(cd ng2-components/ng2-alfresco-datatable; npm link ng2-alfresco-core; npm install; npm link);
|
(cd ng2-components/ng2-alfresco-datatable; npm link ng2-alfresco-core; npm install; npm link);
|
||||||
fi
|
fi
|
||||||
- if ([ "$MODULE" == "ng2-activiti-tasklist" ]); then
|
- if ([ "$MODULE" == "ng2-activiti-tasklist" ] || [ "$MODULE" == "ng2-activiti-processlist" ]); then
|
||||||
(cd ng2-components/ng2-activiti-form; npm link ng2-alfresco-core; npm install; npm link);
|
(cd ng2-components/ng2-activiti-form; npm link ng2-alfresco-core; npm install; npm link);
|
||||||
fi
|
fi
|
||||||
|
- if ([ "$MODULE" == "ng2-activiti-processlist" ]); then
|
||||||
|
(cd ng2-components/ng2-activiti-tasklist; npm link ng2-alfresco-core; npm link ng2-alfresco-datatable; npm link ng2-activiti-form; npm install; npm link);
|
||||||
|
fi
|
||||||
- cd ng2-components/$MODULE;
|
- cd ng2-components/$MODULE;
|
||||||
- if ([ "$MODULE" != "ng2-alfresco-core" ]); then
|
- if ([ "$MODULE" != "ng2-alfresco-core" ]); then
|
||||||
npm link ng2-alfresco-core;
|
npm link ng2-alfresco-core;
|
||||||
@ -51,6 +54,9 @@ before_script:
|
|||||||
- if ([ "$MODULE" == "ng2-activiti-tasklist" ]); then
|
- if ([ "$MODULE" == "ng2-activiti-tasklist" ]); then
|
||||||
npm link ng2-activiti-form;
|
npm link ng2-activiti-form;
|
||||||
fi
|
fi
|
||||||
|
- if ([ "$MODULE" == "ng2-activiti-processlist" ]); then
|
||||||
|
npm link ng2-activiti-tasklist;
|
||||||
|
fi
|
||||||
- npm install;
|
- npm install;
|
||||||
- npm run travis
|
- npm run travis
|
||||||
- ls -ltrh ./node_modules/
|
- ls -ltrh ./node_modules/
|
||||||
|
@ -52,6 +52,8 @@ The following is a list of some of the components that you can use when building
|
|||||||
- [Core library](ng2-components/ng2-alfresco-core/README.md)
|
- [Core library](ng2-components/ng2-alfresco-core/README.md)
|
||||||
- [DataTable](ng2-components/ng2-alfresco-datatable/README.md)
|
- [DataTable](ng2-components/ng2-alfresco-datatable/README.md)
|
||||||
- [DocumentList](ng2-components/ng2-alfresco-documentlist/README.md)
|
- [DocumentList](ng2-components/ng2-alfresco-documentlist/README.md)
|
||||||
|
- Activiti [ProcessList](ng2-components/ng2-activiti-processlist/README.md) and [TaskList](ng2-components/ng2-activiti-tasklist/README.md)
|
||||||
|
- [Activiti Form](ng2-components/ng2-activiti-form/README.md)
|
||||||
- [Viewer](ng2-components/ng2-alfresco-viewer/README.md)
|
- [Viewer](ng2-components/ng2-alfresco-viewer/README.md)
|
||||||
- [Login](ng2-components/ng2-alfresco-login/README.md)
|
- [Login](ng2-components/ng2-alfresco-login/README.md)
|
||||||
- [Upload](ng2-components/ng2-alfresco-upload/README.md)
|
- [Upload](ng2-components/ng2-alfresco-upload/README.md)
|
||||||
|
@ -27,6 +27,8 @@ install:
|
|||||||
- IF %COMPONENT_NAME% NEQ ng2-alfresco-core (cd ng2-components/ng2-alfresco-core && npm install && npm link && cd ../../)
|
- IF %COMPONENT_NAME% NEQ ng2-alfresco-core (cd ng2-components/ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-documentlist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
- IF %COMPONENT_NAME% EQU ng2-alfresco-documentlist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||||
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||||
|
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (cd ng2-components/ng2-activiti-form && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||||
|
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (cd ng2-components/ng2-activiti-tasklist && npm link ng2-alfresco-core && npm link ng2-alfresco-datatable && npm link ng2-activiti-form && npm install && npm link && cd ../../)
|
||||||
- IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
- IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||||
- IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (cd ng2-components/ng2-activiti-form && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
- IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (cd ng2-components/ng2-activiti-form && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-webscript (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
- IF %COMPONENT_NAME% EQU ng2-alfresco-webscript (cd ng2-components/ng2-alfresco-datatable && npm link ng2-alfresco-core && npm install && npm link && cd ../../)
|
||||||
@ -34,6 +36,7 @@ install:
|
|||||||
- IF %COMPONENT_NAME% NEQ ng2-alfresco-core (npm link ng2-alfresco-core)
|
- IF %COMPONENT_NAME% NEQ ng2-alfresco-core (npm link ng2-alfresco-core)
|
||||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-documentlist (npm link ng2-alfresco-datatable)
|
- IF %COMPONENT_NAME% EQU ng2-alfresco-documentlist (npm link ng2-alfresco-datatable)
|
||||||
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (npm link ng2-alfresco-datatable)
|
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (npm link ng2-alfresco-datatable)
|
||||||
|
- IF %COMPONENT_NAME% EQU ng2-activiti-processlist (npm link ng2-activiti-tasklist)
|
||||||
- IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (npm link ng2-alfresco-datatable && npm link ng2-activiti-form)
|
- IF %COMPONENT_NAME% EQU ng2-activiti-tasklist (npm link ng2-alfresco-datatable && npm link ng2-activiti-form)
|
||||||
- IF %COMPONENT_NAME% EQU ng2-alfresco-webscript (npm link ng2-alfresco-datatable)
|
- IF %COMPONENT_NAME% EQU ng2-alfresco-webscript (npm link ng2-alfresco-datatable)
|
||||||
- npm install
|
- npm install
|
||||||
|
@ -28,6 +28,7 @@ import {
|
|||||||
AboutComponent,
|
AboutComponent,
|
||||||
FormViewer
|
FormViewer
|
||||||
} from './components/index';
|
} from './components/index';
|
||||||
|
import { FormNodeViewer } from './components/activiti/form-node-viewer.component';
|
||||||
|
|
||||||
export const routes: RouterConfig = [
|
export const routes: RouterConfig = [
|
||||||
{ path: 'home', component: FilesComponent },
|
{ path: 'home', component: FilesComponent },
|
||||||
@ -39,6 +40,7 @@ export const routes: RouterConfig = [
|
|||||||
{ path: 'search', component: SearchComponent },
|
{ path: 'search', component: SearchComponent },
|
||||||
{ path: 'activiti', component: ActivitiDemoComponent },
|
{ path: 'activiti', component: ActivitiDemoComponent },
|
||||||
{ path: 'activiti/tasks/:id', component: FormViewer },
|
{ path: 'activiti/tasks/:id', component: FormViewer },
|
||||||
|
{ path: 'activiti/tasksnode/:id', component: FormNodeViewer },
|
||||||
{ path: 'webscript', component: WebscriptComponent },
|
{ path: 'webscript', component: WebscriptComponent },
|
||||||
{ path: 'about', component: AboutComponent }
|
{ path: 'about', component: AboutComponent }
|
||||||
];
|
];
|
||||||
|
@ -13,16 +13,17 @@
|
|||||||
<div class="mdl-grid">
|
<div class="mdl-grid">
|
||||||
<div class="mdl-cell mdl-cell--2-col task-column mdl-shadow--2dp">
|
<div class="mdl-cell mdl-cell--2-col task-column mdl-shadow--2dp">
|
||||||
<span>Task Filters</span>
|
<span>Task Filters</span>
|
||||||
<activiti-filters (filterClick)="onFilterClick($event)"></activiti-filters>
|
<activiti-filters (filterClick)="onTaskFilterClick($event)"></activiti-filters>
|
||||||
</div>
|
</div>
|
||||||
<div class="mdl-cell mdl-cell--3-col task-column mdl-shadow--2dp">
|
<div class="mdl-cell mdl-cell--3-col task-column mdl-shadow--2dp">
|
||||||
<span>Task List</span>
|
<span>Task List</span>
|
||||||
<activiti-tasklist *ngIf="isTaskListSelected()" [taskFilter]="taskFilter" [schemaColumn]="schemaColumn"
|
<activiti-tasklist *ngIf="isTaskListSelected()" [taskFilter]="taskFilter" [schemaColumn]="taskSchemaColumns"
|
||||||
(rowClick)="onRowClick($event)" #activititasklist></activiti-tasklist>
|
(rowClick)="onTaskRowClick($event)" #activititasklist></activiti-tasklist>
|
||||||
</div>
|
</div>
|
||||||
<div class="mdl-cell mdl-cell--7-col task-column mdl-shadow--2dp">
|
<div class="mdl-cell mdl-cell--7-col task-column mdl-shadow--2dp">
|
||||||
<span>Task Details</span>
|
<span>Task Details</span>
|
||||||
<activiti-task-details [taskId]="currentTaskId" #activitidetails></activiti-task-details>
|
<activiti-task-details [taskId]="currentTaskId" (formCompleted)="onFormCompleted($event)"
|
||||||
|
#activitidetails></activiti-task-details>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -33,12 +34,17 @@
|
|||||||
<div class="mdl-grid">
|
<div class="mdl-grid">
|
||||||
<div class="mdl-cell mdl-cell--2-col task-column">
|
<div class="mdl-cell mdl-cell--2-col task-column">
|
||||||
<span>Process Filters</span>
|
<span>Process Filters</span>
|
||||||
|
<activiti-start-process [appId]="appId"></activiti-start-process>
|
||||||
|
<activiti-process-filters (filterClick)="onProcessFilterClick($event)"></activiti-process-filters>
|
||||||
</div>
|
</div>
|
||||||
<div class="mdl-cell mdl-cell--3-col task-column">
|
<div class="mdl-cell mdl-cell--3-col task-column">
|
||||||
<span>Process List</span>
|
<span>Process List</span>
|
||||||
|
<activiti-process-instance-list [filter]="processFilter" [schemaColumn]="processSchemaColumns"
|
||||||
|
(rowClick)="onProcessRowClick($event)" #activitiprocesslist></activiti-process-instance-list>
|
||||||
</div>
|
</div>
|
||||||
<div class="mdl-cell mdl-cell--7-col task-column">
|
<div class="mdl-cell mdl-cell--7-col task-column">
|
||||||
<span>Process Details</span>
|
<span>Process Details</span>
|
||||||
|
<activiti-process-instance-details [processInstanceId]="currentProcessInstanceId" (taskFormCompleted)="taskFormCompleted()" (processCancelled)="processCancelled()" #activitiprocessdetails></activiti-process-instance-details>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, AfterViewChecked, ViewChild } from '@angular/core';
|
import { Component, AfterViewChecked, ViewChild, Input } from '@angular/core';
|
||||||
import { ALFRESCO_TASKLIST_DIRECTIVES } from 'ng2-activiti-tasklist';
|
import { ALFRESCO_TASKLIST_DIRECTIVES } from 'ng2-activiti-tasklist';
|
||||||
|
import { ACTIVITI_PROCESSLIST_DIRECTIVES } from 'ng2-activiti-processlist';
|
||||||
import { ActivitiForm } from 'ng2-activiti-form';
|
import { ActivitiForm } from 'ng2-activiti-form';
|
||||||
|
|
||||||
declare let __moduleName: string;
|
declare let __moduleName: string;
|
||||||
@ -27,7 +28,7 @@ declare var componentHandler;
|
|||||||
selector: 'activiti-demo',
|
selector: 'activiti-demo',
|
||||||
templateUrl: './activiti-demo.component.html',
|
templateUrl: './activiti-demo.component.html',
|
||||||
styleUrls: ['./activiti-demo.component.css'],
|
styleUrls: ['./activiti-demo.component.css'],
|
||||||
directives: [ALFRESCO_TASKLIST_DIRECTIVES, ActivitiForm]
|
directives: [ALFRESCO_TASKLIST_DIRECTIVES, ACTIVITI_PROCESSLIST_DIRECTIVES, ActivitiForm]
|
||||||
})
|
})
|
||||||
export class ActivitiDemoComponent implements AfterViewChecked {
|
export class ActivitiDemoComponent implements AfterViewChecked {
|
||||||
|
|
||||||
@ -39,11 +40,23 @@ export class ActivitiDemoComponent implements AfterViewChecked {
|
|||||||
@ViewChild('activititasklist')
|
@ViewChild('activititasklist')
|
||||||
activititasklist: any;
|
activititasklist: any;
|
||||||
|
|
||||||
currentTaskId: string;
|
@ViewChild('activitiprocesslist')
|
||||||
|
activitiprocesslist: any;
|
||||||
|
|
||||||
schemaColumn: any [] = [];
|
@ViewChild('activitiprocessdetails')
|
||||||
|
activitiprocessdetails: any;
|
||||||
|
|
||||||
|
currentTaskId: string;
|
||||||
|
currentProcessInstanceId: string;
|
||||||
|
|
||||||
|
taskSchemaColumns: any [] = [];
|
||||||
|
processSchemaColumns: any [] = [];
|
||||||
|
|
||||||
taskFilter: any;
|
taskFilter: any;
|
||||||
|
processFilter: any;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
appId: string;
|
||||||
|
|
||||||
setChoice($event) {
|
setChoice($event) {
|
||||||
this.currentChoice = $event.target.value;
|
this.currentChoice = $event.target.value;
|
||||||
@ -58,23 +71,50 @@ export class ActivitiDemoComponent implements AfterViewChecked {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
console.log('Activiti demo component');
|
this.taskSchemaColumns = [
|
||||||
this.schemaColumn = [
|
|
||||||
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true}
|
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true}
|
||||||
// {type: 'text', key: 'created', title: 'Created', sortable: true}
|
// {type: 'text', key: 'created', title: 'Created', sortable: true}
|
||||||
];
|
];
|
||||||
|
this.processSchemaColumns = [
|
||||||
|
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
onFilterClick(event: any) {
|
onTaskFilterClick(event: any) {
|
||||||
this.taskFilter = event;
|
this.taskFilter = event;
|
||||||
this.activititasklist.load(this.taskFilter);
|
this.activititasklist.load(this.taskFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
onRowClick(taskId) {
|
onProcessFilterClick(event: any) {
|
||||||
|
this.processFilter = event.filter;
|
||||||
|
this.activitiprocesslist.load(this.processFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
onTaskRowClick(taskId) {
|
||||||
this.currentTaskId = taskId;
|
this.currentTaskId = taskId;
|
||||||
this.activitidetails.loadDetails(this.currentTaskId);
|
this.activitidetails.loadDetails(this.currentTaskId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onProcessRowClick(processInstanceId) {
|
||||||
|
this.currentProcessInstanceId = processInstanceId;
|
||||||
|
this.activitiprocessdetails.load(this.currentProcessInstanceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
processCancelled(data: any) {
|
||||||
|
this.currentProcessInstanceId = null;
|
||||||
|
this.activitiprocesslist.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
taskFormCompleted(data: any) {
|
||||||
|
this.activitiprocesslist.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
onFormCompleted(form) {
|
||||||
|
this.activititasklist.load(this.taskFilter);
|
||||||
|
this.currentTaskId = null;
|
||||||
|
this.activitidetails.loadDetails(this.currentTaskId);
|
||||||
|
}
|
||||||
|
|
||||||
ngAfterViewChecked() {
|
ngAfterViewChecked() {
|
||||||
// workaround for MDL issues with dynamic components
|
// workaround for MDL issues with dynamic components
|
||||||
if (componentHandler) {
|
if (componentHandler) {
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
.activiti-form-viewer {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
<div class="activiti-form-viewer" *ngIf="nodeId">
|
||||||
|
<activiti-form [nodeId]="nodeId"
|
||||||
|
[saveMetadata]="true"
|
||||||
|
[path]="'/Sites/swsdp/documentLibrary'">
|
||||||
|
</activiti-form>
|
||||||
|
</div>
|
@ -0,0 +1,62 @@
|
|||||||
|
/*!
|
||||||
|
* @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, OnInit, OnDestroy, AfterViewChecked } from '@angular/core';
|
||||||
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
import { ActivitiForm, FormService, EcmModelService, NodeService } from 'ng2-activiti-form';
|
||||||
|
import { Subscription } from 'rxjs/Rx';
|
||||||
|
|
||||||
|
declare let __moduleName: string;
|
||||||
|
declare var componentHandler;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
moduleId: __moduleName,
|
||||||
|
selector: 'form-node-viewer',
|
||||||
|
templateUrl: './form-node-viewer.component.html',
|
||||||
|
styleUrls: ['./form-node-viewer.component.css'],
|
||||||
|
directives: [ActivitiForm],
|
||||||
|
providers: [FormService, EcmModelService, NodeService]
|
||||||
|
})
|
||||||
|
export class FormNodeViewer implements OnInit, OnDestroy, AfterViewChecked {
|
||||||
|
|
||||||
|
nodeId: string;
|
||||||
|
|
||||||
|
private sub: Subscription;
|
||||||
|
|
||||||
|
constructor(private formService: FormService,
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private router: Router) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.sub = this.route.params.subscribe(params => {
|
||||||
|
this.nodeId = params['id'];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.sub.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewChecked() {
|
||||||
|
// workaround for MDL issues with dynamic components
|
||||||
|
if (componentHandler) {
|
||||||
|
componentHandler.upgradeAllRegistered();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,3 +1,11 @@
|
|||||||
<div class="activiti-form-viewer" *ngIf="taskId">
|
<div class="activiti-form-viewer" *ngIf="taskId">
|
||||||
<activiti-form [taskId]="taskId"></activiti-form>
|
<activiti-form [taskId]="taskId"></activiti-form>
|
||||||
|
<!--<activiti-form [formName]="'activitiForms:patientFolder'"-->
|
||||||
|
<!--[saveMetadata]="true"-->
|
||||||
|
<!--[path]="'/Sites/swsdp/documentLibrary'"-->
|
||||||
|
<!--[nameNode]="'test'"></activiti-form>-->
|
||||||
|
<!--<activiti-form [nodeId]="'e280be3a-6584-45a1-8bb5-89bfe070262e'"-->
|
||||||
|
<!--[saveMetadata]="true"-->
|
||||||
|
<!--[path]="'/Sites/swsdp/documentLibrary'">-->
|
||||||
|
<!--</activiti-form>-->
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import { Component, OnInit, OnDestroy, AfterViewChecked } from '@angular/core';
|
import { Component, OnInit, OnDestroy, AfterViewChecked } from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { ActivitiForm, FormService } from 'ng2-activiti-form';
|
import { ActivitiForm, FormService, EcmModelService, NodeService } from 'ng2-activiti-form';
|
||||||
import { Subscription } from 'rxjs/Rx';
|
import { Subscription } from 'rxjs/Rx';
|
||||||
|
|
||||||
declare let __moduleName: string;
|
declare let __moduleName: string;
|
||||||
@ -29,7 +29,7 @@ declare var componentHandler;
|
|||||||
templateUrl: './form-viewer.component.html',
|
templateUrl: './form-viewer.component.html',
|
||||||
styleUrls: ['./form-viewer.component.css'],
|
styleUrls: ['./form-viewer.component.css'],
|
||||||
directives: [ActivitiForm],
|
directives: [ActivitiForm],
|
||||||
providers: [FormService]
|
providers: [FormService, EcmModelService, NodeService]
|
||||||
})
|
})
|
||||||
export class FormViewer implements OnInit, OnDestroy, AfterViewChecked {
|
export class FormViewer implements OnInit, OnDestroy, AfterViewChecked {
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
[showUploadDialog]="true"
|
[showUploadDialog]="true"
|
||||||
[currentFolderPath]="currentPath"
|
[currentFolderPath]="currentPath"
|
||||||
[uploaddirectory]=""
|
[uploaddirectory]=""
|
||||||
|
[versioning] = "versioning"
|
||||||
(onSuccess)="documentList.reload()">
|
(onSuccess)="documentList.reload()">
|
||||||
<alfresco-document-list-breadcrumb
|
<alfresco-document-list-breadcrumb
|
||||||
[currentFolderPath]="currentPath"
|
[currentFolderPath]="currentPath"
|
||||||
@ -91,7 +92,7 @@
|
|||||||
handler="delete">
|
handler="delete">
|
||||||
</content-action>
|
</content-action>
|
||||||
<content-action
|
<content-action
|
||||||
target="document"
|
target="folder"
|
||||||
title="Activiti: View Form"
|
title="Activiti: View Form"
|
||||||
(execute)="viewActivitiForm($event)">
|
(execute)="viewActivitiForm($event)">
|
||||||
</content-action>
|
</content-action>
|
||||||
@ -147,6 +148,13 @@
|
|||||||
</label>
|
</label>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p style="width:250px;margin: 20px;">
|
||||||
|
<label for="switch-versioning" class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
|
||||||
|
<input type="checkbox" id="switch-versioning" class="mdl-switch__input" (change)="toggleVersioning()">
|
||||||
|
<span class="mdl-switch__label">Versioning</span>
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
|
||||||
<h5>Upload</h5>
|
<h5>Upload</h5>
|
||||||
<br>
|
<br>
|
||||||
<div *ngIf="acceptedFilesTypeShow">
|
<div *ngIf="acceptedFilesTypeShow">
|
||||||
@ -160,6 +168,7 @@
|
|||||||
[currentFolderPath]="currentPath"
|
[currentFolderPath]="currentPath"
|
||||||
[multipleFiles]="multipleFileUpload"
|
[multipleFiles]="multipleFileUpload"
|
||||||
[uploadFolders]="folderUpload"
|
[uploadFolders]="folderUpload"
|
||||||
|
[versioning] = "versioning"
|
||||||
(onSuccess)="documentList.reload()">
|
(onSuccess)="documentList.reload()">
|
||||||
<div class="mdl-spinner mdl-js-spinner is-active"></div>
|
<div class="mdl-spinner mdl-js-spinner is-active"></div>
|
||||||
</alfresco-upload-button>
|
</alfresco-upload-button>
|
||||||
@ -171,6 +180,7 @@
|
|||||||
acceptedFilesType="{{acceptedFilesType}}"
|
acceptedFilesType="{{acceptedFilesType}}"
|
||||||
[multipleFiles]="multipleFileUpload"
|
[multipleFiles]="multipleFileUpload"
|
||||||
[uploadFolders]="folderUpload"
|
[uploadFolders]="folderUpload"
|
||||||
|
[versioning] = "versioning"
|
||||||
(onSuccess)="documentList.reload()">
|
(onSuccess)="documentList.reload()">
|
||||||
<div class="mdl-spinner mdl-js-spinner is-active"></div>
|
<div class="mdl-spinner mdl-js-spinner is-active"></div>
|
||||||
</alfresco-upload-button>
|
</alfresco-upload-button>
|
||||||
|
@ -63,6 +63,7 @@ export class FilesComponent implements OnInit {
|
|||||||
multipleFileUpload: boolean = false;
|
multipleFileUpload: boolean = false;
|
||||||
folderUpload: boolean = false;
|
folderUpload: boolean = false;
|
||||||
acceptedFilesTypeShow: boolean = false;
|
acceptedFilesTypeShow: boolean = false;
|
||||||
|
versioning: boolean = false;
|
||||||
|
|
||||||
acceptedFilesType: string = '.jpg,.pdf,.js';
|
acceptedFilesType: string = '.jpg,.pdf,.js';
|
||||||
|
|
||||||
@ -119,6 +120,11 @@ export class FilesComponent implements OnInit {
|
|||||||
return this.acceptedFilesTypeShow;
|
return this.acceptedFilesTypeShow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleVersioning() {
|
||||||
|
this.versioning = !this.versioning;
|
||||||
|
return this.versioning;
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.formService.getProcessDefinitions().subscribe(
|
this.formService.getProcessDefinitions().subscribe(
|
||||||
defs => this.setupBpmActions(defs || []),
|
defs => this.setupBpmActions(defs || []),
|
||||||
@ -127,7 +133,7 @@ export class FilesComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewActivitiForm(event?: any) {
|
viewActivitiForm(event?: any) {
|
||||||
this.router.navigate(['/activiti/tasks', '1']);
|
this.router.navigate(['/activiti/tasksnode', event.value.entry.id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupBpmActions(actions: any[]) {
|
private setupBpmActions(actions: any[]) {
|
||||||
|
@ -16,13 +16,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, EventEmitter, Output } from '@angular/core';
|
import { Component, EventEmitter, Output } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
|
||||||
import { ALFRESCO_SEARCH_DIRECTIVES } from 'ng2-alfresco-search';
|
import { ALFRESCO_SEARCH_DIRECTIVES } from 'ng2-alfresco-search';
|
||||||
import { VIEWERCOMPONENT } from 'ng2-alfresco-viewer';
|
import { VIEWERCOMPONENT } from 'ng2-alfresco-viewer';
|
||||||
import {
|
import { AlfrescoAuthenticationService } from 'ng2-alfresco-core';
|
||||||
AlfrescoAuthenticationService,
|
|
||||||
AlfrescoContentService
|
|
||||||
} from 'ng2-alfresco-core';
|
|
||||||
|
|
||||||
declare let __moduleName: string;
|
declare let __moduleName: string;
|
||||||
|
|
||||||
@ -30,52 +26,36 @@ declare let __moduleName: string;
|
|||||||
moduleId: __moduleName,
|
moduleId: __moduleName,
|
||||||
selector: 'search-bar',
|
selector: 'search-bar',
|
||||||
templateUrl: './search-bar.component.html',
|
templateUrl: './search-bar.component.html',
|
||||||
styles: [`
|
|
||||||
`],
|
|
||||||
directives: [ALFRESCO_SEARCH_DIRECTIVES, VIEWERCOMPONENT]
|
directives: [ALFRESCO_SEARCH_DIRECTIVES, VIEWERCOMPONENT]
|
||||||
})
|
})
|
||||||
export class SearchBarComponent {
|
export class SearchBarComponent {
|
||||||
|
|
||||||
urlFile: string;
|
fileNodeId: string;
|
||||||
fileName: string;
|
|
||||||
mimeType: string;
|
|
||||||
fileShowed: boolean = false;
|
fileShowed: boolean = false;
|
||||||
|
searchTerm: string = '';
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
expand = new EventEmitter();
|
expand = new EventEmitter();
|
||||||
|
|
||||||
constructor(
|
constructor(public auth: AlfrescoAuthenticationService) {
|
||||||
public router: Router,
|
|
||||||
public auth: AlfrescoAuthenticationService,
|
|
||||||
public contentService: AlfrescoContentService
|
|
||||||
|
|
||||||
) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isLoggedIn(): boolean {
|
isLoggedIn(): boolean {
|
||||||
return this.auth.isLoggedIn();
|
return this.auth.isLoggedIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a new search term is submitted
|
|
||||||
*
|
|
||||||
* @param params Parameters relating to the search
|
|
||||||
*/
|
|
||||||
searchTermChange(params) {
|
|
||||||
this.router.navigate(['Search', {
|
|
||||||
q: params.value
|
|
||||||
}]);
|
|
||||||
}
|
|
||||||
|
|
||||||
onFileClicked(event) {
|
onFileClicked(event) {
|
||||||
if (event.value.entry.isFile) {
|
if (event.value.entry.isFile) {
|
||||||
this.fileName = event.value.entry.name;
|
this.fileNodeId = event.value.entry.id;
|
||||||
this.mimeType = event.value.entry.content.mimeType;
|
|
||||||
this.urlFile = this.contentService.getContentUrl(event.value);
|
|
||||||
this.fileShowed = true;
|
this.fileShowed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
searchTermChange(event) {
|
||||||
|
console.log('Search term changed', event);
|
||||||
|
this.searchTerm = event.value;
|
||||||
|
}
|
||||||
|
|
||||||
onExpandToggle(event) {
|
onExpandToggle(event) {
|
||||||
this.expand.emit(event);
|
this.expand.emit(event);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
<alfresco-search (preview)="onFileClicked($event)"></alfresco-search>
|
<alfresco-search (preview)="onFileClicked($event)"></alfresco-search>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<alfresco-viewer [(showViewer)]="previewActive" [urlFile]="previewContentUrl" [fileName]="previewName" [mimeType]="previewMimeType" [overlayMode]="true">
|
<alfresco-viewer [(showViewer)]="fileShowed" [fileNodeId]="fileNodeId" [overlayMode]="true">
|
||||||
<div class="mdl-spinner mdl-js-spinner is-active"></div>
|
<div class="mdl-spinner mdl-js-spinner is-active"></div>
|
||||||
</alfresco-viewer>
|
</alfresco-viewer>
|
||||||
|
@ -52,10 +52,7 @@ declare let __moduleName: string;
|
|||||||
})
|
})
|
||||||
export class SearchComponent {
|
export class SearchComponent {
|
||||||
|
|
||||||
previewContentUrl: string;
|
fileShowed: boolean = false;
|
||||||
previewName: string;
|
|
||||||
previewMimeType: string;
|
|
||||||
previewActive: boolean = false;
|
|
||||||
fileNodeId: string;
|
fileNodeId: string;
|
||||||
|
|
||||||
constructor(public contentService: AlfrescoContentService) {
|
constructor(public contentService: AlfrescoContentService) {
|
||||||
@ -64,7 +61,7 @@ export class SearchComponent {
|
|||||||
onFileClicked(event) {
|
onFileClicked(event) {
|
||||||
if (event.value.entry.isFile) {
|
if (event.value.entry.isFile) {
|
||||||
this.fileNodeId = event.value.entry.id;
|
this.fileNodeId = event.value.entry.id;
|
||||||
this.previewActive = true;
|
this.fileShowed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,9 @@ import { bootstrap } from '@angular/platform-browser-dynamic';
|
|||||||
import { HTTP_PROVIDERS } from '@angular/http';
|
import { HTTP_PROVIDERS } from '@angular/http';
|
||||||
import { ALFRESCO_SEARCH_PROVIDERS } from 'ng2-alfresco-search';
|
import { ALFRESCO_SEARCH_PROVIDERS } from 'ng2-alfresco-search';
|
||||||
import { ALFRESCO_CORE_PROVIDERS } from 'ng2-alfresco-core';
|
import { ALFRESCO_CORE_PROVIDERS } from 'ng2-alfresco-core';
|
||||||
|
import { ATIVITI_FORM_PROVIDERS } from 'ng2-activiti-form';
|
||||||
import { UploadService } from 'ng2-alfresco-upload';
|
import { UploadService } from 'ng2-alfresco-upload';
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
import { appRouterProviders } from './app.routes';
|
import { appRouterProviders } from './app.routes';
|
||||||
|
|
||||||
bootstrap(AppComponent, [
|
bootstrap(AppComponent, [
|
||||||
@ -29,5 +29,6 @@ bootstrap(AppComponent, [
|
|||||||
HTTP_PROVIDERS,
|
HTTP_PROVIDERS,
|
||||||
ALFRESCO_CORE_PROVIDERS,
|
ALFRESCO_CORE_PROVIDERS,
|
||||||
ALFRESCO_SEARCH_PROVIDERS,
|
ALFRESCO_SEARCH_PROVIDERS,
|
||||||
UploadService
|
UploadService,
|
||||||
|
ATIVITI_FORM_PROVIDERS
|
||||||
]).catch(err => console.error(err));
|
]).catch(err => console.error(err));
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"DOCUMENT_LIST": {
|
"DOCUMENT_LIST": {
|
||||||
"COLUMNS": {
|
"COLUMNS": {
|
||||||
"DISPLAY_NAME": "Display name",
|
"DISPLAY_NAME": "Display name",
|
||||||
"CREATED_BY": "mario",
|
"CREATED_BY": "Created by",
|
||||||
"CREATED_ON": "Created on"
|
"CREATED_ON": "Created on"
|
||||||
},
|
},
|
||||||
"ACTIONS": {
|
"ACTIONS": {
|
||||||
|
@ -16,6 +16,10 @@
|
|||||||
<link href="node_modules/flag-icon-css/css/flag-icon.min.css" rel="stylesheet">
|
<link href="node_modules/flag-icon-css/css/flag-icon.min.css" rel="stylesheet">
|
||||||
|
|
||||||
<!-- 1. Load libraries -->
|
<!-- 1. Load libraries -->
|
||||||
|
<!-- Polyfill(s) for Safari (pre-10.x) -->
|
||||||
|
<script src="node_modules/intl/dist/Intl.min.js"></script>
|
||||||
|
<script src="node_modules/intl/locale-data/jsonp/en.js"></script>
|
||||||
|
|
||||||
<!-- Polyfill(s) for older browsers -->
|
<!-- Polyfill(s) for older browsers -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Alfresco-Angular2-Demo",
|
"name": "Alfresco-Angular2-Demo",
|
||||||
"description": "Demo shell for Alfresco Angular2 components",
|
"description": "Demo shell for Alfresco Angular2 components",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"author": "Alfresco Software, Ltd.",
|
"author": "Alfresco Software, Ltd.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "typings install",
|
"postinstall": "typings install",
|
||||||
@ -73,18 +73,20 @@
|
|||||||
"material-design-icons": "2.2.3",
|
"material-design-icons": "2.2.3",
|
||||||
"material-design-lite": "1.1.3",
|
"material-design-lite": "1.1.3",
|
||||||
"ng2-translate": "2.2.0",
|
"ng2-translate": "2.2.0",
|
||||||
"pdfjs-dist": "1.5.258",
|
"pdfjs-dist": "1.5.404",
|
||||||
"flag-icon-css": "2.3.0",
|
"flag-icon-css": "2.3.0",
|
||||||
"ng2-alfresco-core": "0.2.0",
|
"intl": "1.2.4",
|
||||||
"ng2-alfresco-datatable": "0.2.0",
|
"ng2-alfresco-core": "0.3.0",
|
||||||
"ng2-alfresco-documentlist": "0.2.0",
|
"ng2-alfresco-datatable": "0.3.0",
|
||||||
"ng2-alfresco-login": "0.2.0",
|
"ng2-alfresco-documentlist": "0.3.0",
|
||||||
"ng2-alfresco-search": "0.2.0",
|
"ng2-alfresco-login": "0.3.0",
|
||||||
"ng2-alfresco-upload": "0.2.0",
|
"ng2-alfresco-search": "0.3.0",
|
||||||
"ng2-alfresco-viewer": "0.2.0",
|
"ng2-alfresco-upload": "0.3.0",
|
||||||
"ng2-activiti-form": "0.2.0",
|
"ng2-alfresco-viewer": "0.3.0",
|
||||||
"ng2-activiti-tasklist": "0.2.0",
|
"ng2-activiti-form": "0.3.0",
|
||||||
"ng2-alfresco-webscript": "0.2.0"
|
"ng2-activiti-tasklist": "0.3.0",
|
||||||
|
"ng2-activiti-processlist": "0.3.0",
|
||||||
|
"ng2-alfresco-webscript": "0.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"concurrently": "2.0.0",
|
"concurrently": "2.0.0",
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
'ng2-alfresco-webscript': 'node_modules/ng2-alfresco-webscript/dist',
|
'ng2-alfresco-webscript': 'node_modules/ng2-alfresco-webscript/dist',
|
||||||
'ng2-activiti-tasklist': 'node_modules/ng2-activiti-tasklist/dist',
|
'ng2-activiti-tasklist': 'node_modules/ng2-activiti-tasklist/dist',
|
||||||
'alfresco-js-api': 'node_modules/alfresco-js-api/dist'
|
'alfresco-js-api': 'node_modules/alfresco-js-api/dist'
|
||||||
|
'ng2-activiti-processlist': 'node_modules/ng2-activiti-processlist/dist'
|
||||||
};
|
};
|
||||||
// packages tells the System loader how to load when no filename and/or no extension
|
// packages tells the System loader how to load when no filename and/or no extension
|
||||||
var packages = {
|
var packages = {
|
||||||
@ -39,6 +40,7 @@
|
|||||||
'ng2-alfresco-upload': { main: 'index.js', defaultExtension: 'js'},
|
'ng2-alfresco-upload': { main: 'index.js', defaultExtension: 'js'},
|
||||||
'ng2-alfresco-viewer': { main: 'index.js', defaultExtension: 'js'},
|
'ng2-alfresco-viewer': { main: 'index.js', defaultExtension: 'js'},
|
||||||
'ng2-activiti-form': { main: 'index.js', defaultExtension: 'js'},
|
'ng2-activiti-form': { main: 'index.js', defaultExtension: 'js'},
|
||||||
|
'ng2-activiti-processlist': { main: 'index.js', defaultExtension: 'js'},
|
||||||
'ng2-activiti-tasklist': { main: 'index.js', defaultExtension: 'js'},
|
'ng2-activiti-tasklist': { main: 'index.js', defaultExtension: 'js'},
|
||||||
'ng2-alfresco-webscript': { main: 'index.js', defaultExtension: 'js'},
|
'ng2-alfresco-webscript': { main: 'index.js', defaultExtension: 'js'},
|
||||||
'alfresco-js-api': { main: 'alfresco-js-api.js', defaultExtension: 'js'}
|
'alfresco-js-api': { main: 'alfresco-js-api.js', defaultExtension: 'js'}
|
||||||
|
@ -78,6 +78,38 @@ Only form definition will be fetched
|
|||||||
</activiti-form>
|
</activiti-form>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Display form definition by ECM nodeId, in this case the metadata of the node are showed in an activiti Form. If there are no form
|
||||||
|
definied in activiti for the type of the node, a new form will be automaticaly created in activiti.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<activiti-form
|
||||||
|
[nodeId]="'e280be3a-6584-45a1-8bb5-89bfe070262e'">
|
||||||
|
</activiti-form>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Display form definition by form name, and store the form field as metadata. The param nameNode is optional.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<activiti-form
|
||||||
|
[formName]="'activitiForms:patientFolder'"
|
||||||
|
[saveMetadata]="true"
|
||||||
|
[path]="'/Sites/swsdp/documentLibrary'"
|
||||||
|
[nameNode]="'test'">
|
||||||
|
</activiti-form>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Display form definition by ECM nodeId, in this case the metadata of the node are showed in an activiti Form, and store the form field
|
||||||
|
as metadata. The param nameNode is optional.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<activiti-form
|
||||||
|
[nodeId]="'e280be3a-6584-45a1-8bb5-89bfe070262e'"
|
||||||
|
[saveMetadata]="true"
|
||||||
|
[path]="'/Sites/swsdp/documentLibrary'"
|
||||||
|
[nameNode]="'test'">
|
||||||
|
</activiti-form>
|
||||||
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
### Properties
|
### Properties
|
||||||
@ -95,7 +127,14 @@ The recommended set of properties can be found in the following table:
|
|||||||
| showSaveButton | boolean | true | Toggle rendering of the `Save` outcome button. |
|
| showSaveButton | boolean | true | Toggle rendering of the `Save` outcome button. |
|
||||||
| readOnly | boolean | false | Toggle readonly state of the form. Enforces all form widgets render readonly if enabled. |
|
| readOnly | boolean | false | Toggle readonly state of the form. Enforces all form widgets render readonly if enabled. |
|
||||||
| showRefreshButton | boolean | true | Toggle rendering of the `Refresh` button. |
|
| showRefreshButton | boolean | true | Toggle rendering of the `Refresh` button. |
|
||||||
|
| saveMetadata | boolean | false | Store the value of the form as metadata. |
|
||||||
|
| path | string | | Path of the folder where to store the metadata. |
|
||||||
|
| nameNode (optional) | string | true | Name to assign to the new node where the metadata are stored. |
|
||||||
|
|
||||||
|
|
||||||
|
* {path} string - path of the folder where the to store the metadata
|
||||||
|
*
|
||||||
|
* {nameNode} string (optional) - name of the node stored, if not defined the node will be sotred with an uuid as name
|
||||||
#### Advanced properties
|
#### Advanced properties
|
||||||
|
|
||||||
The following properties are for complex customisation purposes:
|
The following properties are for complex customisation purposes:
|
||||||
@ -120,7 +159,7 @@ All `form*` events receive an instance of the `FormModel` as event argument for
|
|||||||
```html
|
```html
|
||||||
<activiti-form
|
<activiti-form
|
||||||
[taskId]="selectedTask?.id"
|
[taskId]="selectedTask?.id"
|
||||||
formSaved="onFormSaved($event)">
|
(formSaved)="onFormSaved($event)">
|
||||||
</activiti-form>
|
</activiti-form>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -15,6 +15,19 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { FormService } from './src/services/form.service';
|
||||||
|
import { EcmModelService } from './src/services/ecm-model.service';
|
||||||
|
import { NodeService } from './src/services/node.service';
|
||||||
|
|
||||||
export * from './src/components/activiti-form.component';
|
export * from './src/components/activiti-form.component';
|
||||||
export * from './src/services/form.service';
|
export * from './src/services/form.service';
|
||||||
export * from './src/components/widgets/index';
|
export * from './src/components/widgets/index';
|
||||||
|
export * from './src/services/ecm-model.service';
|
||||||
|
export * from './src/services/node.service';
|
||||||
|
|
||||||
|
|
||||||
|
export const ATIVITI_FORM_PROVIDERS: [any] = [
|
||||||
|
FormService,
|
||||||
|
EcmModelService,
|
||||||
|
NodeService
|
||||||
|
];
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ng2-activiti-form",
|
"name": "ng2-activiti-form",
|
||||||
"description": "Alfresco Activiti Form Component for Angular 2",
|
"description": "Alfresco Activiti Form Component for Angular 2",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"author": "Alfresco Software, Ltd.",
|
"author": "Alfresco Software, Ltd.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "typings install",
|
"postinstall": "typings install",
|
||||||
@ -65,7 +65,7 @@
|
|||||||
"rxjs": "5.0.0-beta.6",
|
"rxjs": "5.0.0-beta.6",
|
||||||
"zone.js": "0.6.12",
|
"zone.js": "0.6.12",
|
||||||
"ng2-translate": "2.2.2",
|
"ng2-translate": "2.2.2",
|
||||||
"ng2-alfresco-core": "0.2.0"
|
"ng2-alfresco-core": "0.3.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"material-design-icons": "^2.2.3",
|
"material-design-icons": "^2.2.3",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<div>
|
<div>
|
||||||
<div *ngIf="!hasForm()">
|
<div *ngIf="!hasForm()">
|
||||||
<h3 style="text-align: center">Please select a Visit</h3>
|
<h3 style="text-align: center">Please select a Task</h3>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="hasForm()">
|
<div *ngIf="hasForm()">
|
||||||
<div class="mdl-card mdl-shadow--2dp activiti-form-container">
|
<div class="mdl-card mdl-shadow--2dp activiti-form-container">
|
||||||
|
@ -40,8 +40,8 @@ describe('ActivitiForm', () => {
|
|||||||
]);
|
]);
|
||||||
window['componentHandler'] = componentHandler;
|
window['componentHandler'] = componentHandler;
|
||||||
|
|
||||||
formService = new FormService(null);
|
formService = new FormService(null, null);
|
||||||
formComponent = new ActivitiForm(formService, visibilityService);
|
formComponent = new ActivitiForm(formService, visibilityService, null, null, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should upgrade MDL content on view checked', () => {
|
it('should upgrade MDL content on view checked', () => {
|
||||||
|
@ -23,9 +23,10 @@ import {
|
|||||||
Output,
|
Output,
|
||||||
EventEmitter
|
EventEmitter
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { MATERIAL_DESIGN_DIRECTIVES } from 'ng2-alfresco-core';
|
import { MATERIAL_DESIGN_DIRECTIVES, AlfrescoAuthenticationService } from 'ng2-alfresco-core';
|
||||||
|
import { EcmModelService } from './../services/ecm-model.service';
|
||||||
import { FormService } from './../services/form.service';
|
import { FormService } from './../services/form.service';
|
||||||
|
import { NodeService } from './../services/node.service';
|
||||||
import { FormModel, FormOutcomeModel, FormValues, FormFieldModel, FormOutcomeEvent } from './widgets/core/index';
|
import { FormModel, FormOutcomeModel, FormValues, FormFieldModel, FormOutcomeEvent } from './widgets/core/index';
|
||||||
|
|
||||||
import { TabsWidget } from './widgets/tabs/tabs.widget';
|
import { TabsWidget } from './widgets/tabs/tabs.widget';
|
||||||
@ -38,19 +39,23 @@ import { WidgetVisibilityService } from './../services/widget-visibility.servic
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @Input
|
* @Input
|
||||||
* ActivitiForm can show 3 forms searching by 3 type of params:
|
* ActivitiForm can show 4 types of forms searching by 4 type of params:
|
||||||
* 1) Form attached to a task passing the {taskId}.
|
* 1) Form attached to a task passing the {taskId}.
|
||||||
|
*
|
||||||
* 2) Form that are only defined with the {formId} (in this case you receive only the form definition and the form will not be
|
* 2) Form that are only defined with the {formId} (in this case you receive only the form definition and the form will not be
|
||||||
* attached to any process, useful in case you want to use ActivitiForm as form designer), in this case you can pass also other 2
|
* attached to any process, useful in case you want to use ActivitiForm as form designer), in this case you can pass also other 2
|
||||||
* parameters:
|
* parameters:
|
||||||
* - {saveOption} as parameter to tell what is the function to call on the save action.
|
* - {saveOption} as parameter to tell what is the function to call on the save action.
|
||||||
* - {data} to fill the form field with some data, the id of the form must to match the name of the field of the provided data object.
|
* - {data} to fill the form field with some data, the id of the form must to match the name of the field of the provided data object.
|
||||||
|
*
|
||||||
* 3) Form that are only defined with the {formName} (in this case you receive only the form definition and the form will not be
|
* 3) Form that are only defined with the {formName} (in this case you receive only the form definition and the form will not be
|
||||||
* attached to any process, useful in case you want to use ActivitiForm as form designer),
|
* attached to any process, useful in case you want to use ActivitiForm as form designer),
|
||||||
* in this case you can pass also other 2 parameters:
|
* in this case you can pass also other 2 parameters:
|
||||||
* - {saveOption} as parameter to tell what is the function to call on the save action.
|
* - {saveOption} as parameter to tell what is the function to call on the save action.
|
||||||
* - {data} to fill the form field with some data, the id of the form must to match the name of the field of the provided data object.
|
* - {data} to fill the form field with some data, the id of the form must to match the name of the field of the provided data object.
|
||||||
*
|
*
|
||||||
|
* 4) Form that show the metadata of a {nodeId}
|
||||||
|
*
|
||||||
* {showTitle} boolean - to hide the title of the form pass false, default true;
|
* {showTitle} boolean - to hide the title of the form pass false, default true;
|
||||||
*
|
*
|
||||||
* {showRefreshButton} boolean - to hide the refresh button of the form pass false, default true;
|
* {showRefreshButton} boolean - to hide the refresh button of the form pass false, default true;
|
||||||
@ -59,6 +64,12 @@ import { WidgetVisibilityService } from './../services/widget-visibility.servic
|
|||||||
*
|
*
|
||||||
* {showSaveButton} boolean - to hide the save button of the form pass false, default true;
|
* {showSaveButton} boolean - to hide the save button of the form pass false, default true;
|
||||||
*
|
*
|
||||||
|
* {saveMetadata} boolean - store the value of the form as metadata, default false;
|
||||||
|
*
|
||||||
|
* {path} string - path of the folder where to store the metadata;
|
||||||
|
*
|
||||||
|
* {nameNode} string (optional) - Name to assign to the new node where the metadata are stored;
|
||||||
|
*
|
||||||
* @Output
|
* @Output
|
||||||
* {formLoaded} EventEmitter - This event is fired when the form is loaded, it pass all the value in the form.
|
* {formLoaded} EventEmitter - This event is fired when the form is loaded, it pass all the value in the form.
|
||||||
* {formSaved} EventEmitter - This event is fired when the form is saved, it pass all the value in the form.
|
* {formSaved} EventEmitter - This event is fired when the form is saved, it pass all the value in the form.
|
||||||
@ -72,7 +83,7 @@ import { WidgetVisibilityService } from './../services/widget-visibility.servic
|
|||||||
templateUrl: './activiti-form.component.html',
|
templateUrl: './activiti-form.component.html',
|
||||||
styleUrls: ['./activiti-form.component.css'],
|
styleUrls: ['./activiti-form.component.css'],
|
||||||
directives: [MATERIAL_DESIGN_DIRECTIVES, ContainerWidget, TabsWidget],
|
directives: [MATERIAL_DESIGN_DIRECTIVES, ContainerWidget, TabsWidget],
|
||||||
providers: [FormService, WidgetVisibilityService]
|
providers: [EcmModelService, FormService, WidgetVisibilityService, NodeService]
|
||||||
})
|
})
|
||||||
export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||||
|
|
||||||
@ -83,15 +94,27 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
|||||||
@Input()
|
@Input()
|
||||||
taskId: string;
|
taskId: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
nodeId: string;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
formId: string;
|
formId: string;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
formName: string;
|
formName: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
saveMetadata: boolean = false;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
data: FormValues;
|
data: FormValues;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
path: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
nameNode: string;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
showTitle: boolean = true;
|
showTitle: boolean = true;
|
||||||
|
|
||||||
@ -124,7 +147,10 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
|||||||
debugMode: boolean = false;
|
debugMode: boolean = false;
|
||||||
|
|
||||||
constructor(private formService: FormService,
|
constructor(private formService: FormService,
|
||||||
private visibilityService: WidgetVisibilityService) {
|
private visibilityService: WidgetVisibilityService,
|
||||||
|
private authService: AlfrescoAuthenticationService,
|
||||||
|
private ecmModelService: EcmModelService,
|
||||||
|
private nodeService: NodeService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
hasForm(): boolean {
|
hasForm(): boolean {
|
||||||
@ -154,8 +180,12 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
if (this.nodeId) {
|
||||||
|
this.loadActivitiFormForEcmNode();
|
||||||
|
} else {
|
||||||
this.loadForm();
|
this.loadForm();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngAfterViewChecked() {
|
ngAfterViewChecked() {
|
||||||
this.setupMaterialComponents();
|
this.setupMaterialComponents();
|
||||||
@ -208,6 +238,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
|||||||
|
|
||||||
if (outcome.id === ActivitiForm.CUSTOM_OUTCOME_ID) {
|
if (outcome.id === ActivitiForm.CUSTOM_OUTCOME_ID) {
|
||||||
this.formSaved.emit(this.form);
|
this.formSaved.emit(this.form);
|
||||||
|
this.storeFormAsMetadata();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -275,7 +306,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
|||||||
.getFormDefinitionById(formId)
|
.getFormDefinitionById(formId)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
form => {
|
form => {
|
||||||
// console.log('Get Form By definition Id', form);
|
this.formName = form.name;
|
||||||
this.form = this.parseForm(form);
|
this.form = this.parseForm(form);
|
||||||
this.formLoaded.emit(this.form);
|
this.formLoaded.emit(this.form);
|
||||||
},
|
},
|
||||||
@ -306,7 +337,10 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
|||||||
this.formService
|
this.formService
|
||||||
.saveTaskForm(this.form.taskId, this.form.values)
|
.saveTaskForm(this.form.taskId, this.form.values)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
() => this.formSaved.emit(this.form),
|
() => {
|
||||||
|
this.formSaved.emit(this.form);
|
||||||
|
this.storeFormAsMetadata();
|
||||||
|
},
|
||||||
this.handleError
|
this.handleError
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -317,13 +351,16 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
|||||||
this.formService
|
this.formService
|
||||||
.completeTaskForm(this.form.taskId, this.form.values, outcome)
|
.completeTaskForm(this.form.taskId, this.form.values, outcome)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
() => this.formCompleted.emit(this.form),
|
() => {
|
||||||
|
this.formCompleted.emit(this.form);
|
||||||
|
this.storeFormAsMetadata();
|
||||||
|
},
|
||||||
this.handleError
|
this.handleError
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleError(err: any) {
|
handleError(err: any): any {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,4 +391,41 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
|||||||
this.visibilityService.updateVisibilityForForm(field.form);
|
this.visibilityService.updateVisibilityForForm(field.form);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private loadActivitiFormForEcmNode(): void {
|
||||||
|
this.nodeService.getNodeMetadata(this.nodeId).subscribe(data => {
|
||||||
|
this.data = data.metadata;
|
||||||
|
this.loadFormFromActiviti(data.nodeType);
|
||||||
|
},
|
||||||
|
this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
public loadFormFromActiviti(nodeType: string): any {
|
||||||
|
this.formService.searchFrom(nodeType).subscribe(
|
||||||
|
form => {
|
||||||
|
if (!form) {
|
||||||
|
this.formService.createFormFromNodeType(nodeType).subscribe(formMetadata => {
|
||||||
|
this.loadFormFromFormId(formMetadata.id);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.loadFormFromFormId(form.id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
this.handleError
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadFormFromFormId(formId: string) {
|
||||||
|
this.formId = formId;
|
||||||
|
this.loadForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
private storeFormAsMetadata() {
|
||||||
|
if (this.saveMetadata) {
|
||||||
|
this.ecmModelService.createEcmTypeForActivitiForm(this.formName, this.form).subscribe(type => {
|
||||||
|
this.nodeService.createNodeMetadata(type.nodeType || type.entry.prefixedName, EcmModelService.MODEL_NAMESPACE, this.form.values, this.path, this.nameNode);
|
||||||
|
}, this.handleError
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,9 @@
|
|||||||
<div *ngSwitchCase="'readonly-text'">
|
<div *ngSwitchCase="'readonly-text'">
|
||||||
<display-text-widget [field]="field" (fieldChanged)="fieldChanged($event);"></display-text-widget>
|
<display-text-widget [field]="field" (fieldChanged)="fieldChanged($event);"></display-text-widget>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngSwitchCase="'upload'">
|
||||||
|
<upload-widget [field]="field" (fieldChanged)="fieldChanged($event);"></upload-widget>
|
||||||
|
</div>
|
||||||
<div *ngSwitchDefault>
|
<div *ngSwitchDefault>
|
||||||
<span>UNKNOWN WIDGET TYPE: {{field.type}}</span>
|
<span>UNKNOWN WIDGET TYPE: {{field.type}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -23,6 +23,7 @@ export class FormFieldTypes {
|
|||||||
static RADIO_BUTTONS: string = 'radio-buttons';
|
static RADIO_BUTTONS: string = 'radio-buttons';
|
||||||
static DISPLAY_VALUE: string = 'readonly';
|
static DISPLAY_VALUE: string = 'readonly';
|
||||||
static READONLY_TEXT: string = 'readonly-text';
|
static READONLY_TEXT: string = 'readonly-text';
|
||||||
|
static UPLOAD: string = 'upload';
|
||||||
|
|
||||||
static READONLY_TYPES: string[] = [
|
static READONLY_TYPES: string[] = [
|
||||||
FormFieldTypes.HYPERLINK,
|
FormFieldTypes.HYPERLINK,
|
||||||
|
@ -129,7 +129,9 @@ export class FormFieldModel extends FormWidgetModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateForm() {
|
updateForm() {
|
||||||
if (this.type === FormFieldTypes.DROPDOWN) {
|
|
||||||
|
switch (this.type) {
|
||||||
|
case FormFieldTypes.DROPDOWN:
|
||||||
/*
|
/*
|
||||||
This is needed due to Activiti reading dropdown values as string
|
This is needed due to Activiti reading dropdown values as string
|
||||||
but saving back as object: { id: <id>, name: <name> }
|
but saving back as object: { id: <id>, name: <name> }
|
||||||
@ -142,7 +144,8 @@ export class FormFieldModel extends FormWidgetModel {
|
|||||||
this.form.values[this.id] = entry[0];
|
this.form.values[this.id] = entry[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (this.type === FormFieldTypes.RADIO_BUTTONS) {
|
break;
|
||||||
|
case FormFieldTypes.RADIO_BUTTONS:
|
||||||
/*
|
/*
|
||||||
This is needed due to Activiti issue related to reading radio button values as value string
|
This is needed due to Activiti issue related to reading radio button values as value string
|
||||||
but saving back as object: { id: <id>, name: <name> }
|
but saving back as object: { id: <id>, name: <name> }
|
||||||
@ -153,7 +156,15 @@ export class FormFieldModel extends FormWidgetModel {
|
|||||||
} else if (this.options.length > 0) {
|
} else if (this.options.length > 0) {
|
||||||
this.form.values[this.id] = this.options[0];
|
this.form.values[this.id] = this.options[0];
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case FormFieldTypes.UPLOAD:
|
||||||
|
if (this.value && this.value.length > 0) {
|
||||||
|
this.form.values[this.id] = `${this.value[0].id}`;
|
||||||
} else {
|
} else {
|
||||||
|
this.form.values[this.id] = null;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
if (!FormFieldTypes.isReadOnlyType(this.type)) {
|
if (!FormFieldTypes.isReadOnlyType(this.type)) {
|
||||||
this.form.values[this.id] = this.value;
|
this.form.values[this.id] = this.value;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<div class="dropdown-widget">
|
<div class="dropdown-widget">
|
||||||
|
<label [attr.for]="field.id">{{field.name}}</label>
|
||||||
<select [(ngModel)]="field.value" (ngModelChange)="checkVisibility(field)">
|
<select [(ngModel)]="field.value" (ngModelChange)="checkVisibility(field)">
|
||||||
<option *ngFor="let opt of field.options" [value]="opt.id">{{opt.name}}</option>
|
<option *ngFor="let opt of field.options" [value]="opt.id">{{opt.name}}</option>
|
||||||
</select>
|
</select>
|
||||||
|
@ -27,6 +27,7 @@ import { HyperlinkWidget } from './hyperlink/hyperlink.widget';
|
|||||||
import { RadioButtonsWidget } from './radio-buttons/radio-buttons.widget';
|
import { RadioButtonsWidget } from './radio-buttons/radio-buttons.widget';
|
||||||
import { DisplayValueWidget } from './display-value/display-value.widget';
|
import { DisplayValueWidget } from './display-value/display-value.widget';
|
||||||
import { DisplayTextWidget } from './display-text/display-text.widget';
|
import { DisplayTextWidget } from './display-text/display-text.widget';
|
||||||
|
import { UploadWidget } from './upload/upload.widget';
|
||||||
|
|
||||||
// core
|
// core
|
||||||
export * from './widget.component';
|
export * from './widget.component';
|
||||||
@ -46,6 +47,7 @@ export * from './hyperlink/hyperlink.widget';
|
|||||||
export * from './radio-buttons/radio-buttons.widget';
|
export * from './radio-buttons/radio-buttons.widget';
|
||||||
export * from './display-value/display-value.widget';
|
export * from './display-value/display-value.widget';
|
||||||
export * from './display-text/display-text.widget';
|
export * from './display-text/display-text.widget';
|
||||||
|
export * from './upload/upload.widget';
|
||||||
|
|
||||||
export const CONTAINER_WIDGET_DIRECTIVES: [any] = [
|
export const CONTAINER_WIDGET_DIRECTIVES: [any] = [
|
||||||
TabsWidget,
|
TabsWidget,
|
||||||
@ -61,7 +63,8 @@ export const PRIMITIVE_WIDGET_DIRECTIVES: [any] = [
|
|||||||
HyperlinkWidget,
|
HyperlinkWidget,
|
||||||
RadioButtonsWidget,
|
RadioButtonsWidget,
|
||||||
DisplayValueWidget,
|
DisplayValueWidget,
|
||||||
DisplayTextWidget
|
DisplayTextWidget,
|
||||||
|
UploadWidget
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
.upload-widget {
|
||||||
|
width:100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-widget__icon {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-widget__file {
|
||||||
|
float: left;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-widget__reset {
|
||||||
|
float: left;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
<div class="upload-widget">
|
||||||
|
|
||||||
|
<label [attr.for]="field.id">{{field.name}}</label>
|
||||||
|
<div>
|
||||||
|
<i class="material-icons upload-widget__icon">image</i>
|
||||||
|
<span *ngIf="hasFile" class="upload-widget__file">{{getUploadedFileName()}}</span>
|
||||||
|
<input *ngIf="!hasFile"
|
||||||
|
#file
|
||||||
|
type="file"
|
||||||
|
[attr.id]="field.id"
|
||||||
|
class="upload-widget__file"
|
||||||
|
(change)="onFileChanged($event)">
|
||||||
|
<button *ngIf="hasFile" (click)="reset(file);" class="upload-widget__reset">X</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,105 @@
|
|||||||
|
/*!
|
||||||
|
* @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, OnInit } from '@angular/core';
|
||||||
|
import { WidgetComponent } from './../widget.component';
|
||||||
|
import { AlfrescoSettingsService, AlfrescoAuthenticationService } from 'ng2-alfresco-core';
|
||||||
|
|
||||||
|
declare let __moduleName: string;
|
||||||
|
declare var componentHandler;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
moduleId: __moduleName,
|
||||||
|
selector: 'upload-widget',
|
||||||
|
templateUrl: './upload.widget.html',
|
||||||
|
styleUrls: ['./upload.widget.css']
|
||||||
|
})
|
||||||
|
export class UploadWidget extends WidgetComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor(private settingsService: AlfrescoSettingsService,
|
||||||
|
private authService: AlfrescoAuthenticationService) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
hasFile: boolean;
|
||||||
|
fileName: string;
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (this.field &&
|
||||||
|
this.field.value &&
|
||||||
|
this.field.value.length > 0) {
|
||||||
|
this.hasFile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getUploadedFileName(): string {
|
||||||
|
let result = this.fileName;
|
||||||
|
|
||||||
|
if (this.field &&
|
||||||
|
this.field.value &&
|
||||||
|
this.field.value.length > 0) {
|
||||||
|
let file = this.field.value[0];
|
||||||
|
result = file.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.field.value = null;
|
||||||
|
this.field.json.value = null;
|
||||||
|
this.hasFile = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onFileChanged(event: any) {
|
||||||
|
let files = event.srcElement.files;
|
||||||
|
if (files && files.length > 0) {
|
||||||
|
|
||||||
|
let file = files[0];
|
||||||
|
|
||||||
|
this.hasFile = true;
|
||||||
|
this.fileName = file.name;
|
||||||
|
|
||||||
|
let formData: FormData = new FormData();
|
||||||
|
formData.append('file', file, file.name);
|
||||||
|
|
||||||
|
let xhr: XMLHttpRequest = new XMLHttpRequest();
|
||||||
|
|
||||||
|
xhr.withCredentials = true;
|
||||||
|
|
||||||
|
xhr.onreadystatechange = () => {
|
||||||
|
if (xhr.readyState === 4) {
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
let jsonFile = JSON.parse(xhr.response);
|
||||||
|
console.log(jsonFile);
|
||||||
|
this.field.value = [jsonFile];
|
||||||
|
this.field.json.value = [jsonFile];
|
||||||
|
} else {
|
||||||
|
console.error(xhr.response);
|
||||||
|
window.alert('Error uploading file. See console output for more details.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let url = `${this.settingsService.bpmHost}/activiti-app/app/rest/content/raw`;
|
||||||
|
xhr.open('POST', url, true);
|
||||||
|
xhr.setRequestHeader('Authorization', this.authService.getTicketBpm());
|
||||||
|
xhr.send(formData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
/*!
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class FormDefinitionModel {
|
||||||
|
reusable: boolean = false;
|
||||||
|
newVersion: boolean = false;
|
||||||
|
formRepresentation: any;
|
||||||
|
formImageBase64: string = '';
|
||||||
|
|
||||||
|
constructor(id: string, name: any, lastUpdatedByFullName: string, lastUpdated: string, metadata: any) {
|
||||||
|
|
||||||
|
this.formRepresentation = {
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
description: '',
|
||||||
|
version: 1,
|
||||||
|
lastUpdatedBy: 1,
|
||||||
|
lastUpdatedByFullName: lastUpdatedByFullName,
|
||||||
|
lastUpdated: lastUpdated,
|
||||||
|
stencilSetId: 0,
|
||||||
|
referenceId: null,
|
||||||
|
formDefinition: {
|
||||||
|
fields: [{
|
||||||
|
name: 'Label',
|
||||||
|
type: 'container',
|
||||||
|
fieldType: 'ContainerRepresentation',
|
||||||
|
numberOfColumns: 2,
|
||||||
|
required: false,
|
||||||
|
readOnly: false,
|
||||||
|
sizeX: 2,
|
||||||
|
sizeY: 1,
|
||||||
|
row: -1,
|
||||||
|
col: -1,
|
||||||
|
fields: {'1': this.metadataToFields(metadata)}
|
||||||
|
}],
|
||||||
|
gridsterForm: false,
|
||||||
|
javascriptEvents: [],
|
||||||
|
metadata: {},
|
||||||
|
outcomes: [],
|
||||||
|
className: '',
|
||||||
|
style: '',
|
||||||
|
tabs: [],
|
||||||
|
variables: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private metadataToFields(metadata: any): any[] {
|
||||||
|
let fields = [];
|
||||||
|
if (metadata) {
|
||||||
|
metadata.forEach(function(property) {
|
||||||
|
if (property) {
|
||||||
|
let field = {
|
||||||
|
type: 'text',
|
||||||
|
id: property.name,
|
||||||
|
name: property.name,
|
||||||
|
required: false,
|
||||||
|
readOnly: false,
|
||||||
|
sizeX: 1,
|
||||||
|
sizeY: 1,
|
||||||
|
row: -1,
|
||||||
|
col: -1,
|
||||||
|
colspan: 1,
|
||||||
|
params: {
|
||||||
|
existingColspan: 1,
|
||||||
|
maxColspan: 2
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
colspan: 1,
|
||||||
|
row: -1,
|
||||||
|
column: -1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fields.push(field);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*!
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class NodeMetadata {
|
||||||
|
metadata: any;
|
||||||
|
nodeType: string;
|
||||||
|
|
||||||
|
constructor(metadata: any, nodeType: string) {
|
||||||
|
this.metadata = metadata;
|
||||||
|
this.nodeType = nodeType;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,262 @@
|
|||||||
|
/*!
|
||||||
|
* @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 { Injectable } from '@angular/core';
|
||||||
|
import { AlfrescoAuthenticationService, AlfrescoSettingsService } from 'ng2-alfresco-core';
|
||||||
|
import { Observable } from 'rxjs/Rx';
|
||||||
|
import { Response, Http, Headers, RequestOptions } from '@angular/http';
|
||||||
|
import { FormModel } from '../components/widgets/core/form.model';
|
||||||
|
import { NodeService } from './node.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class EcmModelService {
|
||||||
|
|
||||||
|
public static MODEL_NAMESPACE: string = 'activitiForms';
|
||||||
|
public static MODEL_NAME: string = 'activitiFormsModel';
|
||||||
|
public static TYPE_MODEL: string = 'cm:folder';
|
||||||
|
|
||||||
|
constructor(private authService: AlfrescoAuthenticationService,
|
||||||
|
private http: Http,
|
||||||
|
public alfrescoSettingsService: AlfrescoSettingsService,
|
||||||
|
private nodeService: NodeService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public createEcmTypeForActivitiForm(formName: string, form: FormModel): Observable<any> {
|
||||||
|
return Observable.create(observer => {
|
||||||
|
this.seachActivitiEcmModel().subscribe(
|
||||||
|
model => {
|
||||||
|
if (!model) {
|
||||||
|
this.createActivitiEcmModel(formName, form).subscribe(typeForm => {
|
||||||
|
observer.next(typeForm);
|
||||||
|
observer.complete();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.createFomType(formName, form).subscribe(typeForm => {
|
||||||
|
observer.next(typeForm);
|
||||||
|
observer.complete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
this.handleError
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private seachActivitiEcmModel() {
|
||||||
|
return this.getEcmModels().map(function (ecmModels: any) {
|
||||||
|
return ecmModels.list.entries.find(model => model.entry.name === EcmModelService.MODEL_NAME);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private createActivitiEcmModel(formName: string, form: FormModel): Observable<any> {
|
||||||
|
return Observable.create(observer => {
|
||||||
|
this.createEcmModel(EcmModelService.MODEL_NAME, EcmModelService.MODEL_NAMESPACE).subscribe(
|
||||||
|
model => {
|
||||||
|
console.log('model created', model);
|
||||||
|
this.activeEcmModel(EcmModelService.MODEL_NAME).subscribe(
|
||||||
|
modelActive => {
|
||||||
|
console.log('model active', modelActive);
|
||||||
|
this.createEcmTypeWithProperties(formName, form).subscribe(typeCreated => {
|
||||||
|
observer.next(typeCreated);
|
||||||
|
observer.complete();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
this.handleError
|
||||||
|
);
|
||||||
|
},
|
||||||
|
this.handleError
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private createFomType(formName: string, form: FormModel): Observable<any> {
|
||||||
|
return Observable.create(observer => {
|
||||||
|
this.searchEcmType(formName, EcmModelService.MODEL_NAME).subscribe(
|
||||||
|
ecmType => {
|
||||||
|
console.log('custom types', ecmType);
|
||||||
|
if (!ecmType) {
|
||||||
|
this.createEcmTypeWithProperties(formName, form).subscribe(typeCreated => {
|
||||||
|
observer.next(typeCreated);
|
||||||
|
observer.complete();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
observer.next(ecmType);
|
||||||
|
observer.complete();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
this.handleError
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public createEcmTypeWithProperties(formName: string, form: FormModel): Observable<any> {
|
||||||
|
return Observable.create(observer => {
|
||||||
|
this.createEcmType(formName, EcmModelService.MODEL_NAME, EcmModelService.TYPE_MODEL).subscribe(
|
||||||
|
typeCreated => {
|
||||||
|
console.log('type Created', typeCreated);
|
||||||
|
this.addPropertyToAType(EcmModelService.MODEL_NAME, formName, form).subscribe(
|
||||||
|
properyAdded => {
|
||||||
|
console.log('property Added', properyAdded);
|
||||||
|
observer.next(typeCreated);
|
||||||
|
observer.complete();
|
||||||
|
},
|
||||||
|
this.handleError);
|
||||||
|
},
|
||||||
|
this.handleError);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public searchEcmType(typeName: string, modelName: string): Observable<any> {
|
||||||
|
return this.getEcmType(modelName).map(function (customTypes: any) {
|
||||||
|
return customTypes.list.entries.find(type => type.entry.prefixedName === typeName || type.entry.title === typeName);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public activeEcmModel(modelName: string): Observable<any> {
|
||||||
|
let url = `${this.alfrescoSettingsService.ecmHost}/alfresco/api/-default-/private/alfresco/versions/1/cmm/${modelName}?select=status`;
|
||||||
|
let options = this.getRequestOptions();
|
||||||
|
|
||||||
|
|
||||||
|
let body = {status: 'ACTIVE'};
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.put(url, body, options)
|
||||||
|
.map(this.toJson)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
public createEcmModel(modelName: string, nameSpace: string): Observable<any> {
|
||||||
|
let url = `${this.alfrescoSettingsService.ecmHost}/alfresco/api/-default-/private/alfresco/versions/1/cmm`;
|
||||||
|
let options = this.getRequestOptions();
|
||||||
|
|
||||||
|
|
||||||
|
let body = {
|
||||||
|
status: 'DRAFT', namespaceUri: modelName, namespacePrefix: nameSpace, name: modelName, description: '', author: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.post(url, body, options)
|
||||||
|
.map(this.toJson)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getEcmModels(): Observable<any> {
|
||||||
|
let url = `${this.alfrescoSettingsService.ecmHost}/alfresco/api/-default-/private/alfresco/versions/1/cmm`;
|
||||||
|
let options = this.getRequestOptions();
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.get(url, options)
|
||||||
|
.map(this.toJson)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public getEcmType(modelName: string): Observable<any> {
|
||||||
|
let url = `${this.alfrescoSettingsService.ecmHost}/alfresco/api/-default-/private/alfresco/versions/1/cmm/${modelName}/types`;
|
||||||
|
let options = this.getRequestOptions();
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.get(url, options)
|
||||||
|
.map(this.toJson)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
public createEcmType(typeName: string, modelName: string, parentType: string): Observable<any> {
|
||||||
|
let name = this.cleanNameType(typeName);
|
||||||
|
let url = `${this.alfrescoSettingsService.ecmHost}/alfresco/api/-default-/private/alfresco/versions/1/cmm/${modelName}/types`;
|
||||||
|
let options = this.getRequestOptions();
|
||||||
|
|
||||||
|
let body = {
|
||||||
|
name: name,
|
||||||
|
parentName: parentType,
|
||||||
|
title: typeName,
|
||||||
|
description: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.post(url, body, options)
|
||||||
|
.map(this.toJson)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
public addPropertyToAType(modelName: string, typeName: string, formFields: any) {
|
||||||
|
let name = this.cleanNameType(typeName);
|
||||||
|
let url = `${this.alfrescoSettingsService.ecmHost}/alfresco/api/-default-/private/alfresco/versions/1/cmm/${modelName}/types/${name}?select=props`;
|
||||||
|
let options = this.getRequestOptions();
|
||||||
|
|
||||||
|
let properties = [];
|
||||||
|
if (formFields && formFields.values) {
|
||||||
|
for (let key in formFields.values) {
|
||||||
|
if (key) {
|
||||||
|
properties.push({
|
||||||
|
name: key,
|
||||||
|
title: key,
|
||||||
|
description: key,
|
||||||
|
dataType: 'd:text',
|
||||||
|
multiValued: false,
|
||||||
|
mandatory: false,
|
||||||
|
mandatoryEnforced: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let body = {
|
||||||
|
name: name,
|
||||||
|
properties: properties
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.put(url, body, options)
|
||||||
|
.map(this.toJson)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
public cleanNameType(name: string): string {
|
||||||
|
let cleanName = name;
|
||||||
|
if (name.indexOf(':') !== -1) {
|
||||||
|
cleanName = name.split(':')[1];
|
||||||
|
}
|
||||||
|
return cleanName.replace(/[^a-zA-Z ]/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getHeaders(): Headers {
|
||||||
|
return new Headers({
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': this.authService.getTicketEcmBase64()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getRequestOptions(): RequestOptions {
|
||||||
|
let headers = this.getHeaders();
|
||||||
|
return new RequestOptions({headers: headers});
|
||||||
|
}
|
||||||
|
|
||||||
|
toJson(res: Response) {
|
||||||
|
if (res) {
|
||||||
|
let body = res.json();
|
||||||
|
return body || {};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
handleError(err: any): any {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
}
|
@ -17,8 +17,10 @@
|
|||||||
|
|
||||||
import { it, inject, describe, expect, beforeEach, beforeEachProviders, afterEach } from '@angular/core/testing';
|
import { it, inject, describe, expect, beforeEach, beforeEachProviders, afterEach } from '@angular/core/testing';
|
||||||
import { AlfrescoAuthenticationService, AlfrescoSettingsService } from 'ng2-alfresco-core';
|
import { AlfrescoAuthenticationService, AlfrescoSettingsService } from 'ng2-alfresco-core';
|
||||||
import { Response, ResponseOptions } from '@angular/http';
|
import { HTTP_PROVIDERS, Response, ResponseOptions } from '@angular/http';
|
||||||
import { FormService } from './form.service';
|
import { FormService } from './form.service';
|
||||||
|
import { EcmModelService } from './ecm-model.service';
|
||||||
|
import { NodeService } from './node.service';
|
||||||
|
|
||||||
declare let jasmine: any;
|
declare let jasmine: any;
|
||||||
|
|
||||||
@ -30,7 +32,10 @@ describe('FormService', () => {
|
|||||||
return [
|
return [
|
||||||
FormService,
|
FormService,
|
||||||
AlfrescoSettingsService,
|
AlfrescoSettingsService,
|
||||||
AlfrescoAuthenticationService
|
AlfrescoAuthenticationService,
|
||||||
|
EcmModelService,
|
||||||
|
HTTP_PROVIDERS,
|
||||||
|
NodeService
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ import {Injectable} from '@angular/core';
|
|||||||
import { Observable } from 'rxjs/Rx';
|
import { Observable } from 'rxjs/Rx';
|
||||||
import { AlfrescoAuthenticationService } from 'ng2-alfresco-core';
|
import { AlfrescoAuthenticationService } from 'ng2-alfresco-core';
|
||||||
import { FormValues } from './../components/widgets/core/index';
|
import { FormValues } from './../components/widgets/core/index';
|
||||||
|
import { FormDefinitionModel } from '../models/form-definition.model';
|
||||||
|
import { EcmModelService } from './ecm-model.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FormService {
|
export class FormService {
|
||||||
@ -26,28 +28,127 @@ export class FormService {
|
|||||||
static UNKNOWN_ERROR_MESSAGE: string = 'Unknown error';
|
static UNKNOWN_ERROR_MESSAGE: string = 'Unknown error';
|
||||||
static GENERIC_ERROR_MESSAGE: string = 'Server error';
|
static GENERIC_ERROR_MESSAGE: string = 'Server error';
|
||||||
|
|
||||||
constructor(private authService: AlfrescoAuthenticationService) {
|
constructor(private authService: AlfrescoAuthenticationService,
|
||||||
|
private ecmModelService: EcmModelService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
getProcessDefinitions(): Observable<any> {
|
/**
|
||||||
|
* Create a Form with a fields for each metadata properties
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
public createFormFromNodeType(formName: string): Observable<any> {
|
||||||
|
return Observable.create(observer => {
|
||||||
|
this.createForm(formName).subscribe(
|
||||||
|
form => {
|
||||||
|
this.ecmModelService.searchEcmType(formName, EcmModelService.MODEL_NAME).subscribe(
|
||||||
|
customType => {
|
||||||
|
let formDefinitionModel = new FormDefinitionModel(form.id, form.name, form.lastUpdatedByFullName, form.lastUpdated, customType.entry.properties);
|
||||||
|
this.addFieldsNodeTypePropertiesToTheForm(form.id, formDefinitionModel).subscribe(formData => {
|
||||||
|
observer.next(formData);
|
||||||
|
observer.complete();
|
||||||
|
}, this.handleError);
|
||||||
|
},
|
||||||
|
this.handleError);
|
||||||
|
}, this.handleError);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Form
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
public createForm(formName: string): Observable<any> {
|
||||||
|
let dataModel = {
|
||||||
|
name: formName,
|
||||||
|
description: '',
|
||||||
|
modelType: 2,
|
||||||
|
stencilSet: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.modelsApi.createModel(dataModel));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add Fields to A form from a metadata properties
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
public addFieldsNodeTypePropertiesToTheForm(formId: string, formDefinitionModel: FormDefinitionModel): Observable<any> {
|
||||||
|
return this.addFieldsToAForm(formId, formDefinitionModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add Fileds to A form
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
public addFieldsToAForm(formId: string, formModel: FormDefinitionModel): Observable<any> {
|
||||||
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.editorApi.saveForm(formId, formModel));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search For A Form by name
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
public searchFrom(name: string): Observable<any> {
|
||||||
|
let opts = {
|
||||||
|
'modelType': 2
|
||||||
|
};
|
||||||
|
|
||||||
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.modelsApi.getModels(opts)).map(function (forms: any) {
|
||||||
|
return forms.data.find(formdata => formdata.name === name);
|
||||||
|
}).catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get All the forms
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
public getForms(): Observable<any> {
|
||||||
|
let opts = {
|
||||||
|
'modelType': 2
|
||||||
|
};
|
||||||
|
|
||||||
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.modelsApi.getModels(opts));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Process Definition
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
public getProcessDefinitions(): Observable<any> {
|
||||||
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.processApi.getProcessDefinitions({}))
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.processApi.getProcessDefinitions({}))
|
||||||
.map(this.toJsonArray)
|
.map(this.toJsonArray)
|
||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTasks(): Observable<any> {
|
/**
|
||||||
|
* Get All the Tasks
|
||||||
|
* @param taskId Task Id
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
public getTasks(): Observable<any> {
|
||||||
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.taskApi.listTasks({}))
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.taskApi.listTasks({}))
|
||||||
.map(this.toJsonArray)
|
.map(this.toJsonArray)
|
||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTask(taskId: string): Observable<any> {
|
/**
|
||||||
|
* Get Task
|
||||||
|
* @param taskId Task Id
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
public getTask(taskId: string): Observable<any> {
|
||||||
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.taskApi.getTask(taskId))
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.taskApi.getTask(taskId))
|
||||||
.map(this.toJson)
|
.map(this.toJson)
|
||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveTaskForm(taskId: string, formValues: FormValues): Observable<any> {
|
/**
|
||||||
|
* Save Task Form
|
||||||
|
* @param taskId Task Id
|
||||||
|
* @param formValues Form Values
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
public saveTaskForm(taskId: string, formValues: FormValues): Observable<any> {
|
||||||
let body = JSON.stringify({values: formValues});
|
let body = JSON.stringify({values: formValues});
|
||||||
|
|
||||||
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.taskApi.saveTaskForm(taskId, body))
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.taskApi.saveTaskForm(taskId, body))
|
||||||
@ -59,9 +160,9 @@ export class FormService {
|
|||||||
* @param taskId Task Id
|
* @param taskId Task Id
|
||||||
* @param formValues Form Values
|
* @param formValues Form Values
|
||||||
* @param outcome Form Outcome
|
* @param outcome Form Outcome
|
||||||
* @returns {any}
|
* @returns {Observable<any>}
|
||||||
*/
|
*/
|
||||||
completeTaskForm(taskId: string, formValues: FormValues, outcome?: string): Observable<any> {
|
public completeTaskForm(taskId: string, formValues: FormValues, outcome?: string): Observable<any> {
|
||||||
let data: any = {values: formValues};
|
let data: any = {values: formValues};
|
||||||
if (outcome) {
|
if (outcome) {
|
||||||
data.outcome = outcome;
|
data.outcome = outcome;
|
||||||
@ -72,13 +173,23 @@ export class FormService {
|
|||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTaskForm(taskId: string): Observable<any> {
|
/**
|
||||||
|
* Get Form related to a taskId
|
||||||
|
* @param taskId Task Id
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
public getTaskForm(taskId: string): Observable<any> {
|
||||||
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.taskApi.getTaskForm(taskId))
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.taskApi.getTaskForm(taskId))
|
||||||
.map(this.toJson)
|
.map(this.toJson)
|
||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
getFormDefinitionById(formId: string): Observable<any> {
|
/**
|
||||||
|
* Get Form Definition
|
||||||
|
* @param formId Form Id
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
public getFormDefinitionById(formId: string): Observable<any> {
|
||||||
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.editorApi.getForm(formId))
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.editorApi.getForm(formId))
|
||||||
.map(this.toJson)
|
.map(this.toJson)
|
||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
@ -89,7 +200,7 @@ export class FormService {
|
|||||||
* @param name
|
* @param name
|
||||||
* @returns {Promise<T>|Promise<ErrorObservable>}
|
* @returns {Promise<T>|Promise<ErrorObservable>}
|
||||||
*/
|
*/
|
||||||
getFormDefinitionByName(name: string): Observable<any> {
|
public getFormDefinitionByName(name: string): Observable<any> {
|
||||||
let opts = {
|
let opts = {
|
||||||
'filter': 'myReusableForms',
|
'filter': 'myReusableForms',
|
||||||
'filterText': name,
|
'filterText': name,
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
/*!
|
||||||
|
* @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 { Injectable } from '@angular/core';
|
||||||
|
import { AlfrescoAuthenticationService } from 'ng2-alfresco-core';
|
||||||
|
import { Observable } from 'rxjs/Rx';
|
||||||
|
import { NodeMetadata } from '../models/node-metadata.model';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NodeService {
|
||||||
|
|
||||||
|
constructor(private authService: AlfrescoAuthenticationService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get All the metadata and the nodeType for a nodeId cleaned by the prefix
|
||||||
|
* @param nodeId Node Id
|
||||||
|
* @returns NodeMetadata
|
||||||
|
*/
|
||||||
|
public getNodeMetadata(nodeId: string): Observable<NodeMetadata> {
|
||||||
|
return Observable.fromPromise(this.authService.getAlfrescoApi().nodes.getNodeInfo(nodeId)).map(this.cleanMetadataFromSemicolon);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Node from form metadata
|
||||||
|
* @param path path
|
||||||
|
* @param nodeType node type
|
||||||
|
* @param nameSpace namespace node
|
||||||
|
* @param data data to store
|
||||||
|
* @returns NodeMetadata
|
||||||
|
*/
|
||||||
|
public createNodeMetadata(nodeType: string, nameSpace: any, data: any, path: string, name?: string): Observable<any> {
|
||||||
|
let properties = {};
|
||||||
|
for (let key in data) {
|
||||||
|
if (data[key]) {
|
||||||
|
properties[nameSpace + ':' + key] = data[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.createNode(name || this.generateUuid(), nodeType, properties, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Node from form metadata
|
||||||
|
* @param name path
|
||||||
|
* @param nodeType node type
|
||||||
|
* @param properties namespace node
|
||||||
|
* @param path path
|
||||||
|
* @returns NodeMetadata
|
||||||
|
*/
|
||||||
|
public createNode(name: string, nodeType: string, properties: any, path: string): Observable<any> {
|
||||||
|
let body = {
|
||||||
|
name: name,
|
||||||
|
nodeType: nodeType,
|
||||||
|
properties: properties,
|
||||||
|
relativePath: path
|
||||||
|
};
|
||||||
|
|
||||||
|
return Observable.fromPromise(this.authService.getAlfrescoApi().nodes.addNode('-root-', body, {}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private generateUuid() {
|
||||||
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||||
|
let r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||||
|
return v.toString(16);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private cleanMetadataFromSemicolon(data: any): NodeMetadata {
|
||||||
|
let metadata = {};
|
||||||
|
|
||||||
|
if (data && data.properties) {
|
||||||
|
for (let key in data.properties) {
|
||||||
|
if (key) {
|
||||||
|
metadata [key.split(':')[1]] = data.properties[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new NodeMetadata(metadata, data.nodeType);
|
||||||
|
}
|
||||||
|
}
|
@ -236,6 +236,7 @@ describe('WidgetVisibilityService', () => {
|
|||||||
expect(varValue).toBe('form_value_test');
|
expect(varValue).toBe('form_value_test');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
it('should return null if the variable does not exist', (done) => {
|
it('should return null if the variable does not exist', (done) => {
|
||||||
service.getTaskProcessVariableModelsForTask(9999).subscribe(
|
service.getTaskProcessVariableModelsForTask(9999).subscribe(
|
||||||
(res: TaskProcessVariableModel[]) => {
|
(res: TaskProcessVariableModel[]) => {
|
||||||
@ -252,6 +253,7 @@ describe('WidgetVisibilityService', () => {
|
|||||||
|
|
||||||
expect(varValue).toBe(null);
|
expect(varValue).toBe(null);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
it('should be able to retrieve a field value searching in the form', () => {
|
it('should be able to retrieve a field value searching in the form', () => {
|
||||||
let stubFormWithFields = new FormModel(fakeFormJson);
|
let stubFormWithFields = new FormModel(fakeFormJson);
|
||||||
@ -360,6 +362,7 @@ describe('WidgetVisibilityService', () => {
|
|||||||
expect(rightValue).toBe(null);
|
expect(rightValue).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
it('should retrieve the value for the left field when it is a process variable', (variableUpdated) => {
|
it('should retrieve the value for the left field when it is a process variable', (variableUpdated) => {
|
||||||
service.getTaskProcessVariableModelsForTask(9999).subscribe(
|
service.getTaskProcessVariableModelsForTask(9999).subscribe(
|
||||||
(res: TaskProcessVariableModel[]) => {
|
(res: TaskProcessVariableModel[]) => {
|
||||||
@ -379,6 +382,7 @@ describe('WidgetVisibilityService', () => {
|
|||||||
expect(rightValue).not.toBe(null);
|
expect(rightValue).not.toBe(null);
|
||||||
expect(rightValue).toBe('test_value_2');
|
expect(rightValue).toBe('test_value_2');
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
it('should retrieve the value for the left field when it is a form variable', () => {
|
it('should retrieve the value for the left field when it is a form variable', () => {
|
||||||
let fakeForm = new FormModel({variables: [
|
let fakeForm = new FormModel({variables: [
|
||||||
@ -484,6 +488,7 @@ describe('WidgetVisibilityService', () => {
|
|||||||
expect(isVisible).toBeTruthy();
|
expect(isVisible).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
it('should evaluate visibility with multiple conditions', (ready) => {
|
it('should evaluate visibility with multiple conditions', (ready) => {
|
||||||
service.getTaskProcessVariableModelsForTask(9999).subscribe(
|
service.getTaskProcessVariableModelsForTask(9999).subscribe(
|
||||||
(res: TaskProcessVariableModel[]) => {
|
(res: TaskProcessVariableModel[]) => {
|
||||||
@ -510,6 +515,7 @@ describe('WidgetVisibilityService', () => {
|
|||||||
|
|
||||||
expect(isVisible).toBeTruthy();
|
expect(isVisible).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
it('should return true when the visibility condition is not valid', () => {
|
it('should return true when the visibility condition is not valid', () => {
|
||||||
let visibilityObjTest = new WidgetVisibilityModel();
|
let visibilityObjTest = new WidgetVisibilityModel();
|
||||||
|
@ -10,4 +10,6 @@ src/**/*.d.ts
|
|||||||
demo/**/*.js
|
demo/**/*.js
|
||||||
demo/**/*.js.map
|
demo/**/*.js.map
|
||||||
demo/**/*.d.ts
|
demo/**/*.d.ts
|
||||||
|
index.js
|
||||||
|
index.js.map
|
||||||
!systemjs.config.js
|
!systemjs.config.js
|
||||||
|
@ -0,0 +1,123 @@
|
|||||||
|
/*!
|
||||||
|
* @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 { DatePipe } from '@angular/common';
|
||||||
|
import {
|
||||||
|
DataTableAdapter, ObjectDataTableAdapter, ObjectDataColumn,
|
||||||
|
DataRow, DataColumn, DataSorting
|
||||||
|
} from 'ng2-alfresco-datatable';
|
||||||
|
|
||||||
|
export class ProcessListDataTableAdapter extends ObjectDataTableAdapter implements DataTableAdapter {
|
||||||
|
|
||||||
|
ERR_ROW_NOT_FOUND: string = 'Row not found';
|
||||||
|
ERR_COL_NOT_FOUND: string = 'Column not found';
|
||||||
|
|
||||||
|
DEFAULT_DATE_FORMAT: string = 'medium';
|
||||||
|
|
||||||
|
private sorting: DataSorting;
|
||||||
|
private rows: DataRow[];
|
||||||
|
private columns: DataColumn[];
|
||||||
|
|
||||||
|
constructor(rows: any, schema: DataColumn[]) {
|
||||||
|
super(rows, schema);
|
||||||
|
this.rows = rows;
|
||||||
|
this.columns = schema || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
getRows(): Array<DataRow> {
|
||||||
|
return this.rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: disable this api
|
||||||
|
setRows(rows: Array<DataRow>) {
|
||||||
|
this.rows = rows || [];
|
||||||
|
this.sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
getColumns(): Array<DataColumn> {
|
||||||
|
return this.columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
setColumns(columns: Array<DataColumn>) {
|
||||||
|
this.columns = columns || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue(row: DataRow, col: DataColumn): any {
|
||||||
|
if (!row) {
|
||||||
|
throw new Error(this.ERR_ROW_NOT_FOUND);
|
||||||
|
}
|
||||||
|
if (!col) {
|
||||||
|
throw new Error(this.ERR_COL_NOT_FOUND);
|
||||||
|
}
|
||||||
|
let value = row.getValue(col.key);
|
||||||
|
|
||||||
|
if (col.type === 'date') {
|
||||||
|
let datePipe = new DatePipe();
|
||||||
|
let format = (<ActivitiDataColumn>(col)).format || this.DEFAULT_DATE_FORMAT;
|
||||||
|
try {
|
||||||
|
return datePipe.transform(value, format);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error parsing date ${value} to format ${format}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSorting(): DataSorting {
|
||||||
|
return this.sorting;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSorting(sorting: DataSorting): void {
|
||||||
|
this.sorting = sorting;
|
||||||
|
|
||||||
|
if (sorting && sorting.key && this.rows && this.rows.length > 0) {
|
||||||
|
this.rows.sort((a: DataRow, b: DataRow) => {
|
||||||
|
let left = a.getValue(sorting.key);
|
||||||
|
if (left) {
|
||||||
|
left = (left instanceof Date) ? left.valueOf().toString() : left.toString();
|
||||||
|
} else {
|
||||||
|
left = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
let right = b.getValue(sorting.key);
|
||||||
|
if (right) {
|
||||||
|
right = (right instanceof Date) ? right.valueOf().toString() : right.toString();
|
||||||
|
} else {
|
||||||
|
right = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return sorting.direction === 'asc'
|
||||||
|
? left.localeCompare(right)
|
||||||
|
: right.localeCompare(left);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort(key?: string, direction?: string): void {
|
||||||
|
let sorting = this.sorting || new DataSorting();
|
||||||
|
if (key) {
|
||||||
|
sorting.key = key;
|
||||||
|
sorting.direction = direction || 'asc';
|
||||||
|
}
|
||||||
|
this.setSorting(sorting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ActivitiDataColumn extends ObjectDataColumn {
|
||||||
|
format: string;
|
||||||
|
}
|
@ -39,7 +39,7 @@
|
|||||||
"reflect-metadata": "^0.1.3",
|
"reflect-metadata": "^0.1.3",
|
||||||
"rxjs": "5.0.0-beta.6",
|
"rxjs": "5.0.0-beta.6",
|
||||||
"zone.js": "^0.6.12",
|
"zone.js": "^0.6.12",
|
||||||
"ng2-activiti-processlist": "file:../",
|
"ng2-activiti-processlist": "^0.3.0",
|
||||||
"material-design-icons": "^2.2.3",
|
"material-design-icons": "^2.2.3",
|
||||||
"material-design-lite": "^1.1.3"
|
"material-design-lite": "^1.1.3"
|
||||||
},
|
},
|
||||||
|
@ -44,7 +44,7 @@ import {
|
|||||||
<label for="token"><b>Insert a servicePath</b></label><br>
|
<label for="token"><b>Insert a servicePath</b></label><br>
|
||||||
<input id="token" type="text" size="48" [(ngModel)]="servicePath"><br>
|
<input id="token" type="text" size="48" [(ngModel)]="servicePath"><br>
|
||||||
<div class="container" *ngIf="authenticated">
|
<div class="container" *ngIf="authenticated">
|
||||||
<activiti-processlist></activiti-processlist>
|
<activiti-process-instance-list></activiti-process-instance-list>
|
||||||
</div>`,
|
</div>`,
|
||||||
providers: [ACTIVITI_PROCESSLIST_PROVIDERS],
|
providers: [ACTIVITI_PROCESSLIST_PROVIDERS],
|
||||||
directives: [ACTIVITI_PROCESSLIST_DIRECTIVES]
|
directives: [ACTIVITI_PROCESSLIST_DIRECTIVES]
|
||||||
|
@ -15,17 +15,30 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ActivitiProcesslistComponent } from './src/components/activiti-processlist.component';
|
import { ActivitiProcessInstanceListComponent } from './src/components/activiti-processlist.component';
|
||||||
|
import { ActivitiProcessFilters } from './src/components/activiti-filters.component';
|
||||||
|
import { ActivitiProcessInstanceHeader } from './src/components/activiti-process-instance-header.component';
|
||||||
|
import { ActivitiProcessInstanceTasks } from './src/components/activiti-process-instance-tasks.component';
|
||||||
|
import { ActivitiComments } from './src/components/activiti-comments.component';
|
||||||
|
import { ActivitiProcessInstanceDetails } from './src/components/activiti-process-instance-details.component';
|
||||||
|
import { ActivitiStartProcessButton } from './src/components/activiti-start-process.component';
|
||||||
import { ActivitiProcessService } from './src/services/activiti-process.service';
|
import { ActivitiProcessService } from './src/services/activiti-process.service';
|
||||||
|
|
||||||
// components
|
// components
|
||||||
export * from './src/components/activiti-processlist.component';
|
export * from './src/components/activiti-processlist.component';
|
||||||
|
export * from './src/components/activiti-process-instance-details.component';
|
||||||
|
|
||||||
// services
|
// services
|
||||||
export * from './src/services/activiti-process.service';
|
export * from './src/services/activiti-process.service';
|
||||||
|
|
||||||
export const ACTIVITI_PROCESSLIST_DIRECTIVES: [any] = [
|
export const ACTIVITI_PROCESSLIST_DIRECTIVES: [any] = [
|
||||||
ActivitiProcesslistComponent
|
ActivitiProcessInstanceListComponent,
|
||||||
|
ActivitiProcessFilters,
|
||||||
|
ActivitiProcessInstanceDetails,
|
||||||
|
ActivitiProcessInstanceHeader,
|
||||||
|
ActivitiProcessInstanceTasks,
|
||||||
|
ActivitiComments,
|
||||||
|
ActivitiStartProcessButton
|
||||||
];
|
];
|
||||||
|
|
||||||
export const ACTIVITI_PROCESSLIST_PROVIDERS: [any] = [
|
export const ACTIVITI_PROCESSLIST_PROVIDERS: [any] = [
|
||||||
|
@ -20,6 +20,9 @@ module.exports = function (config) {
|
|||||||
{pattern: 'node_modules/ng2-alfresco-datatable/dist/**/*.js', included: false, served: true, watched: false},
|
{pattern: 'node_modules/ng2-alfresco-datatable/dist/**/*.js', included: false, served: true, watched: false},
|
||||||
{pattern: 'node_modules/ng2-alfresco-datatable/dist/**/*.html', included: false, served: true, watched: false},
|
{pattern: 'node_modules/ng2-alfresco-datatable/dist/**/*.html', included: false, served: true, watched: false},
|
||||||
{pattern: 'node_modules/ng2-alfresco-datatable/dist/**/*.css', included: false, served: true, watched: false},
|
{pattern: 'node_modules/ng2-alfresco-datatable/dist/**/*.css', included: false, served: true, watched: false},
|
||||||
|
{pattern: 'node_modules/ng2-activiti-tasklist/dist/**/*.js', included: false, served: true, watched: false},
|
||||||
|
{pattern: 'node_modules/ng2-activiti-tasklist/dist/**/*.html', included: false, served: true, watched: false},
|
||||||
|
{pattern: 'node_modules/ng2-activiti-tasklist/dist/**/*.css', included: false, served: true, watched: false},
|
||||||
{pattern: 'node_modules/ng2-translate/**/*.js', included: false, served: true, watched: false},
|
{pattern: 'node_modules/ng2-translate/**/*.js', included: false, served: true, watched: false},
|
||||||
{pattern: 'node_modules/alfresco-js-api/dist/alfresco-js-api.js', included: true, watched: false},
|
{pattern: 'node_modules/alfresco-js-api/dist/alfresco-js-api.js', included: true, watched: false},
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ng2-activiti-processlist",
|
"name": "ng2-activiti-processlist",
|
||||||
"description": "Show active processes from the Activiti BPM suite",
|
"description": "Show active processes from the Activiti BPM suite",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"author": "Alfresco Software, Ltd.",
|
"author": "Alfresco Software, Ltd.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "typings install",
|
"postinstall": "typings install",
|
||||||
@ -63,8 +63,9 @@
|
|||||||
"rxjs": "5.0.0-beta.6",
|
"rxjs": "5.0.0-beta.6",
|
||||||
"zone.js": "^0.6.12",
|
"zone.js": "^0.6.12",
|
||||||
"ng2-translate": "2.2.2",
|
"ng2-translate": "2.2.2",
|
||||||
"ng2-alfresco-core": "0.2.0",
|
"ng2-alfresco-core": "0.3.0",
|
||||||
"ng2-alfresco-datatable": "0.2.0"
|
"ng2-alfresco-datatable": "0.3.0",
|
||||||
|
"ng2-activiti-tasklist": "0.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"angular-cli": "1.0.0-beta.9",
|
"angular-cli": "1.0.0-beta.9",
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
:host {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activiti-label {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
<span class="activiti-label mdl-badge"
|
||||||
|
[attr.data-badge]="comments?.length">{{ 'DETAILS.LABELS.COMMENTS' |translate }}</span>
|
||||||
|
<div id="addComment" (click)="showDialog()" class="icon material-icons">add</div>
|
||||||
|
<div class="mdl-tooltip" for="addComment">
|
||||||
|
Add a comment
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="menu-container" *ngIf="comments?.length > 0">
|
||||||
|
<ul class='mdl-list'>
|
||||||
|
<li class="mdl-list__item" *ngFor="let comment of comments">
|
||||||
|
<span class="mdl-list__item-primary-content">
|
||||||
|
<i class="material-icons mdl-list__item-icon">comment</i>
|
||||||
|
{{comment.message}}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="comments?.length === 0">
|
||||||
|
{{ 'DETAILS.COMMENTS.NONE' | translate }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<dialog class="mdl-dialog" #dialog>
|
||||||
|
<h4 class="mdl-dialog__title">New comment</h4>
|
||||||
|
<div class="mdl-dialog__content">
|
||||||
|
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||||
|
<textarea class="mdl-textfield__input" type="text" [(ngModel)]="message" rows="1" id="commentText"></textarea>
|
||||||
|
<label class="mdl-textfield__label" for="commentText">Message</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mdl-dialog__actions">
|
||||||
|
<button type="button" (click)="add()" class="mdl-button">Add Comment</button>
|
||||||
|
<button type="button" (click)="cancel()" class="mdl-button close">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
@ -0,0 +1,121 @@
|
|||||||
|
/*!
|
||||||
|
* @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, Input, OnInit, ViewChild } from '@angular/core';
|
||||||
|
import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core';
|
||||||
|
import { ActivitiProcessService } from './../services/activiti-process.service';
|
||||||
|
import { Comment } from '../models/comment.model';
|
||||||
|
import { Observer } from 'rxjs/Observer';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
|
declare let componentHandler: any;
|
||||||
|
declare let __moduleName: string;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'activiti-comments',
|
||||||
|
moduleId: __moduleName,
|
||||||
|
templateUrl: './activiti-comments.component.html',
|
||||||
|
styleUrls: ['./activiti-comments.component.css'],
|
||||||
|
providers: [ActivitiProcessService],
|
||||||
|
pipes: [ AlfrescoPipeTranslate ]
|
||||||
|
|
||||||
|
})
|
||||||
|
export class ActivitiComments implements OnInit {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
processId: string;
|
||||||
|
|
||||||
|
@ViewChild('dialog')
|
||||||
|
dialog: any;
|
||||||
|
|
||||||
|
comments: Comment [] = [];
|
||||||
|
|
||||||
|
private commentObserver: Observer<Comment>;
|
||||||
|
comment$: Observable<Comment>;
|
||||||
|
|
||||||
|
message: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param auth
|
||||||
|
* @param translate
|
||||||
|
*/
|
||||||
|
constructor(private auth: AlfrescoAuthenticationService,
|
||||||
|
private translate: AlfrescoTranslationService,
|
||||||
|
private activitiProcess: ActivitiProcessService) {
|
||||||
|
|
||||||
|
if (translate) {
|
||||||
|
translate.addTranslationFolder('node_modules/ng2-activiti-processlist/src');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.comment$ = new Observable<Comment>(observer => this.commentObserver = observer).share();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.comment$.subscribe((comment: Comment) => {
|
||||||
|
this.comments.push(comment);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.processId) {
|
||||||
|
this.load(this.processId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public load(taskId: string) {
|
||||||
|
this.comments = [];
|
||||||
|
if (this.processId) {
|
||||||
|
this.activitiProcess.getProcessInstanceComments(this.processId).subscribe(
|
||||||
|
(res: Comment[]) => {
|
||||||
|
res.forEach((comment) => {
|
||||||
|
this.commentObserver.next(comment);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.comments = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public showDialog() {
|
||||||
|
if (this.dialog) {
|
||||||
|
this.dialog.nativeElement.showModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public add() {
|
||||||
|
this.activitiProcess.addProcessInstanceComment(this.processId, this.message).subscribe(
|
||||||
|
(res: Comment) => {
|
||||||
|
this.comments.push(res);
|
||||||
|
this.message = '';
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public cancel() {
|
||||||
|
if (this.dialog) {
|
||||||
|
this.dialog.nativeElement.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
.mdl-list__item {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
<div class="menu-container">
|
||||||
|
<ul class='mdl-list'>
|
||||||
|
<li class="mdl-list__item"(click)="selectFilter(filter)" *ngFor="let filter of filters">
|
||||||
|
<span class="mdl-list__item-primary-content">
|
||||||
|
<i class="material-icons mdl-list__item-icon">assignment</i>
|
||||||
|
{{filter.name}}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
@ -0,0 +1,131 @@
|
|||||||
|
/*!
|
||||||
|
* @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, Output, EventEmitter, OnInit, Input } from '@angular/core';
|
||||||
|
import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core';
|
||||||
|
import { ActivitiProcessService } from './../services/activiti-process.service';
|
||||||
|
import { FilterModel } from '../models/filter.model';
|
||||||
|
import { Observer } from 'rxjs/Observer';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
|
declare let componentHandler: any;
|
||||||
|
declare let __moduleName: string;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'activiti-process-filters',
|
||||||
|
moduleId: __moduleName,
|
||||||
|
templateUrl: './activiti-filters.component.html',
|
||||||
|
styleUrls: ['activiti-filters.component.css'],
|
||||||
|
providers: [ActivitiProcessService],
|
||||||
|
pipes: [AlfrescoPipeTranslate]
|
||||||
|
|
||||||
|
})
|
||||||
|
export class ActivitiProcessFilters implements OnInit {
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
filterClick: EventEmitter<FilterModel> = new EventEmitter<FilterModel>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
onSuccess: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
onError: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
appId: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
appName: string;
|
||||||
|
|
||||||
|
private filterObserver: Observer<FilterModel>;
|
||||||
|
filter$: Observable<FilterModel>;
|
||||||
|
|
||||||
|
currentFilter: FilterModel;
|
||||||
|
|
||||||
|
filters: FilterModel [] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param auth
|
||||||
|
* @param translate
|
||||||
|
* @param activiti
|
||||||
|
*/
|
||||||
|
constructor(private auth: AlfrescoAuthenticationService,
|
||||||
|
private translate: AlfrescoTranslationService,
|
||||||
|
public activiti: ActivitiProcessService) {
|
||||||
|
this.filter$ = new Observable<FilterModel>(observer => this.filterObserver = observer).share();
|
||||||
|
|
||||||
|
if (translate) {
|
||||||
|
translate.addTranslationFolder('node_modules/ng2-activiti-processlist/src');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.filter$.subscribe((filter: FilterModel) => {
|
||||||
|
this.filters.push(filter);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The method call the adapter data table component for render the task list
|
||||||
|
* @param tasks
|
||||||
|
*/
|
||||||
|
private load() {
|
||||||
|
if (this.appName) {
|
||||||
|
this.filterByAppName();
|
||||||
|
} else {
|
||||||
|
this.filterByAppId(this.appId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private filterByAppId(appId) {
|
||||||
|
this.activiti.getProcessFilters(appId).subscribe(
|
||||||
|
(res: FilterModel[]) => {
|
||||||
|
res.forEach((filter) => {
|
||||||
|
this.filterObserver.next(filter);
|
||||||
|
});
|
||||||
|
this.onSuccess.emit(res);
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err);
|
||||||
|
this.onError.emit(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private filterByAppName() {
|
||||||
|
this.activiti.getDeployedApplications(this.appName).subscribe(
|
||||||
|
application => {
|
||||||
|
this.filterByAppId(application.id);
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err);
|
||||||
|
this.onError.emit(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pass the selected filter as next
|
||||||
|
* @param filter
|
||||||
|
*/
|
||||||
|
public selectFilter(filter: FilterModel) {
|
||||||
|
this.currentFilter = filter;
|
||||||
|
this.filterClick.emit(filter);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
:host {
|
||||||
|
width: 100%;
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
<div *ngIf="!processInstanceDetails">{{ 'DETAILS.MESSAGES.NONE'|translate }}</div>
|
||||||
|
<div *ngIf="processInstanceDetails">
|
||||||
|
<h2 class="mdl-card__title-text">{{processInstanceDetails.name}}</h2>
|
||||||
|
<activiti-process-instance-header [processInstance]="processInstanceDetails" (processCancelled)="processCancelled()" #activitiprocessheader></activiti-process-instance-header>
|
||||||
|
<div class="mdl-grid">
|
||||||
|
<div class="mdl-cell mdl-cell--8-col">
|
||||||
|
<activiti-process-instance-tasks [processId]="processInstanceDetails.id" (taskFormCompleted)="taskFormCompleted()" #activitiprocesstasks></activiti-process-instance-tasks>
|
||||||
|
</div>
|
||||||
|
<div class="mdl-cell mdl-cell--4-col">
|
||||||
|
<activiti-comments [processId]="processInstanceDetails.id" #activitiprocesscomments></activiti-comments>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,108 @@
|
|||||||
|
/*!
|
||||||
|
* @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, Input, ViewChild, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core';
|
||||||
|
import { ActivitiProcessService } from './../services/activiti-process.service';
|
||||||
|
import { ActivitiProcessInstanceHeader } from './activiti-process-instance-header.component';
|
||||||
|
import { ActivitiProcessInstanceTasks } from './activiti-process-instance-tasks.component';
|
||||||
|
import { ActivitiComments } from './activiti-comments.component';
|
||||||
|
import { ProcessInstance } from '../models/process-instance';
|
||||||
|
|
||||||
|
|
||||||
|
declare let componentHandler: any;
|
||||||
|
declare let __moduleName: string;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'activiti-process-instance-details',
|
||||||
|
moduleId: __moduleName,
|
||||||
|
templateUrl: './activiti-process-instance-details.component.html',
|
||||||
|
styleUrls: ['./activiti-process-instance-details.component.css'],
|
||||||
|
providers: [ActivitiProcessService],
|
||||||
|
directives: [ActivitiProcessInstanceHeader, ActivitiComments, ActivitiProcessInstanceTasks],
|
||||||
|
pipes: [AlfrescoPipeTranslate]
|
||||||
|
|
||||||
|
})
|
||||||
|
export class ActivitiProcessInstanceDetails {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
processInstanceId: string;
|
||||||
|
|
||||||
|
@ViewChild('activitiprocessheader')
|
||||||
|
processInstanceHeader: ActivitiProcessInstanceHeader;
|
||||||
|
|
||||||
|
@ViewChild('activitiprocesstasks')
|
||||||
|
tasksList: ActivitiProcessInstanceTasks;
|
||||||
|
|
||||||
|
@ViewChild('activitiprocesscomments')
|
||||||
|
commentsList: ActivitiComments;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
showTitle: boolean = true;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
showRefreshButton: boolean = true;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
processCancelledEmitter = new EventEmitter();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
taskFormCompletedEmitter = new EventEmitter();
|
||||||
|
|
||||||
|
processInstanceDetails: ProcessInstance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param auth
|
||||||
|
* @param translate
|
||||||
|
* @param activitiProcess
|
||||||
|
*/
|
||||||
|
constructor(private auth: AlfrescoAuthenticationService,
|
||||||
|
private translate: AlfrescoTranslationService,
|
||||||
|
private activitiProcess: ActivitiProcessService) {
|
||||||
|
|
||||||
|
if (translate) {
|
||||||
|
translate.addTranslationFolder('node_modules/ng2-activiti-processlist/src');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
load(processId: string) {
|
||||||
|
if (processId) {
|
||||||
|
this.activitiProcess.getProcess(processId).subscribe(
|
||||||
|
(res: ProcessInstance) => {
|
||||||
|
this.processInstanceDetails = res;
|
||||||
|
if (this.processInstanceDetails) {
|
||||||
|
if (this.commentsList) {
|
||||||
|
this.commentsList.load(this.processInstanceDetails.id);
|
||||||
|
}
|
||||||
|
if (this.tasksList) {
|
||||||
|
this.tasksList.load(this.processInstanceDetails.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processCancelled(data: any) {
|
||||||
|
this.processCancelledEmitter.emit(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
taskFormCompleted(data: any) {
|
||||||
|
this.taskFormCompletedEmitter.emit(data);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
:host {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activiti-label {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
<div *ngIf="processInstance">
|
||||||
|
<div class="mdl-grid">
|
||||||
|
<div class="mdl-cell mdl-cell--4-col">
|
||||||
|
<span class="activiti-label">{{ 'DETAILS.LABELS.STARTED_BY' | translate }}</span>:
|
||||||
|
{{getStartedByFullName()}}
|
||||||
|
</div>
|
||||||
|
<div class="mdl-cell mdl-cell--4-col">
|
||||||
|
<span class="activiti-label">{{ 'DETAILS.LABELS.STARTED' | translate }}</span>:
|
||||||
|
{{getStartedDate() | date:'medium'}}
|
||||||
|
</div>
|
||||||
|
<div class="mdl-cell mdl-cell--4-col">
|
||||||
|
<button type="button" (click)="cancelProcess()" class="mdl-button">{{ 'DETAILS.BUTTON.CANCEL' | translate }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,73 @@
|
|||||||
|
/*!
|
||||||
|
* @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, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core';
|
||||||
|
import { ProcessInstance } from '../models/process-instance';
|
||||||
|
import { ActivitiProcessService } from './../services/activiti-process.service';
|
||||||
|
|
||||||
|
declare let componentHandler: any;
|
||||||
|
declare let __moduleName: string;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'activiti-process-instance-header',
|
||||||
|
moduleId: __moduleName,
|
||||||
|
templateUrl: './activiti-process-instance-header.component.html',
|
||||||
|
styleUrls: ['./activiti-process-instance-header.component.css'],
|
||||||
|
pipes: [ AlfrescoPipeTranslate ]
|
||||||
|
|
||||||
|
})
|
||||||
|
export class ActivitiProcessInstanceHeader {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
processInstance: ProcessInstance;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
processCancelled = new EventEmitter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param auth
|
||||||
|
* @param translate
|
||||||
|
* @param activitiProcess
|
||||||
|
*/
|
||||||
|
constructor(private auth: AlfrescoAuthenticationService,
|
||||||
|
private translate: AlfrescoTranslationService,
|
||||||
|
private activitiProcess: ActivitiProcessService) {
|
||||||
|
|
||||||
|
if (translate) {
|
||||||
|
translate.addTranslationFolder('node_modules/ng2-activiti-tasklist/src');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getStartedByFullName() {
|
||||||
|
if (this.processInstance && this.processInstance.startedBy) {
|
||||||
|
return (this.processInstance.startedBy.firstName && this.processInstance.startedBy.firstName !== 'null'
|
||||||
|
? this.processInstance.startedBy.firstName + ' ' : '') +
|
||||||
|
this.processInstance.startedBy.lastName;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
getStartedDate() {
|
||||||
|
return this.processInstance ? new Date(this.processInstance.started) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelProcess() {
|
||||||
|
this.processCancelled.emit(this.activitiProcess.cancelProcess(this.processInstance.id));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
:host {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activiti-label {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
.material-icons:hover {
|
||||||
|
color: rgb(255, 152, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-details-dialog {
|
||||||
|
width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.process-tasks-refresh {
|
||||||
|
float: right;
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
<div *ngIf="showRefreshButton" class="process-tasks-refresh" >
|
||||||
|
<button (click)="onRefreshClicked()"
|
||||||
|
class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect">
|
||||||
|
<i class="material-icons">refresh</i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span class="activiti-label mdl-badge"
|
||||||
|
[attr.data-badge]="activeTasks?.length">{{ 'DETAILS.LABELS.TASKS_ACTIVE'|translate }}</span>
|
||||||
|
|
||||||
|
<div class="menu-container" *ngIf="activeTasks?.length > 0">
|
||||||
|
<ul class='mdl-list'>
|
||||||
|
<li class="mdl-list__item mdl-list__item--two-line" *ngFor="let task of activeTasks">
|
||||||
|
<span class="mdl-list__item-primary-content" (click)="clickTask($event, task)">
|
||||||
|
<i class="material-icons mdl-list__item-icon">assignment</i>
|
||||||
|
<span>{{task.name}}</span>
|
||||||
|
<span class="mdl-list__item-sub-title">{{ 'DETAILS.LABELS.TASK_SUBTITLE' | translate:{user: getUserFullName(task.assignee), created: task.created | date:'mediumDate' } }}</span>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="activeTasks?.length === 0">
|
||||||
|
{{ 'DETAILS.TASKS.NO_ACTIVE' | translate }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span class="activiti-label mdl-badge"
|
||||||
|
[attr.data-badge]="completedTasks?.length">{{ 'DETAILS.LABELS.TASKS_COMPLETED'|translate }}</span>
|
||||||
|
|
||||||
|
<div class="menu-container" *ngIf="completedTasks?.length > 0">
|
||||||
|
<ul class='mdl-list'>
|
||||||
|
<li class="mdl-list__item mdl-list__item--two-line" *ngFor="let task of completedTasks">
|
||||||
|
<span class="mdl-list__item-primary-content" (click)="clickTask($event, task)">
|
||||||
|
<i class="material-icons mdl-list__item-icon">assignment</i>
|
||||||
|
<span>{{task.name}}</span>
|
||||||
|
<span class="mdl-list__item-sub-title">{{ 'DETAILS.LABELS.TASK_SUBTITLE' | translate:{user: getUserFullName(task.assignee), created: task.created | date:'mediumDate' } }}</span>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="completedTasks?.length === 0">
|
||||||
|
{{ 'DETAILS.TASKS.NO_COMPLETED' | translate }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<dialog class="mdl-dialog task-details-dialog" #dialog>
|
||||||
|
<h4 class="mdl-dialog__title">{{ 'DETAILS.TASKS.TASK_DETAILS' | translate }}</h4>
|
||||||
|
<div class="mdl-dialog__content">
|
||||||
|
<activiti-task-details [taskId]="selectedTaskId" (formCompleted)="taskFormCompleted()" #taskdetails></activiti-task-details>
|
||||||
|
</div>
|
||||||
|
<div class="mdl-dialog__actions">
|
||||||
|
<button type="button" (click)="cancelDialog()" class="mdl-button close">{{ 'DETAILS.TASKS.TASK_CLOSE' | translate }}</button>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
@ -0,0 +1,182 @@
|
|||||||
|
/*!
|
||||||
|
* @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, Input, OnInit, ViewChild, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core';
|
||||||
|
import { ActivitiProcessService } from './../services/activiti-process.service';
|
||||||
|
import { TaskDetailsModel } from '../models/task-details.model';
|
||||||
|
import { ALFRESCO_TASKLIST_DIRECTIVES } from 'ng2-activiti-tasklist';
|
||||||
|
import { Observer } from 'rxjs/Observer';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
|
declare let componentHandler: any;
|
||||||
|
declare let __moduleName: string;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'activiti-process-instance-tasks',
|
||||||
|
moduleId: __moduleName,
|
||||||
|
templateUrl: './activiti-process-instance-tasks.component.html',
|
||||||
|
styleUrls: ['./activiti-process-instance-tasks.component.css'],
|
||||||
|
providers: [ActivitiProcessService],
|
||||||
|
directives: [ ALFRESCO_TASKLIST_DIRECTIVES ],
|
||||||
|
pipes: [ AlfrescoPipeTranslate ]
|
||||||
|
|
||||||
|
})
|
||||||
|
export class ActivitiProcessInstanceTasks implements OnInit {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
processId: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
showRefreshButton: boolean = true;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
taskFormCompletedEmitter = new EventEmitter();
|
||||||
|
|
||||||
|
activeTasks: TaskDetailsModel[] = [];
|
||||||
|
completedTasks: TaskDetailsModel[] = [];
|
||||||
|
|
||||||
|
private taskObserver: Observer<TaskDetailsModel>;
|
||||||
|
private completedTaskObserver: Observer<TaskDetailsModel>;
|
||||||
|
|
||||||
|
task$: Observable<TaskDetailsModel>;
|
||||||
|
completedTask$: Observable<TaskDetailsModel>;
|
||||||
|
|
||||||
|
message: string;
|
||||||
|
|
||||||
|
selectedTaskId: string;
|
||||||
|
|
||||||
|
@ViewChild('dialog')
|
||||||
|
dialog: any;
|
||||||
|
|
||||||
|
@ViewChild('taskdetails')
|
||||||
|
taskdetails: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param auth
|
||||||
|
* @param translate
|
||||||
|
* @param activitiProcess
|
||||||
|
*/
|
||||||
|
constructor(private auth: AlfrescoAuthenticationService,
|
||||||
|
private translate: AlfrescoTranslationService,
|
||||||
|
private activitiProcess: ActivitiProcessService) {
|
||||||
|
|
||||||
|
if (translate) {
|
||||||
|
translate.addTranslationFolder('node_modules/ng2-activiti-processlist/src');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.task$ = new Observable<TaskDetailsModel>(observer => this.taskObserver = observer).share();
|
||||||
|
this.completedTask$ = new Observable<TaskDetailsModel>(observer => this.completedTaskObserver = observer).share();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.task$.subscribe((task: TaskDetailsModel) => {
|
||||||
|
this.activeTasks.push(task);
|
||||||
|
});
|
||||||
|
this.completedTask$.subscribe((task: TaskDetailsModel) => {
|
||||||
|
this.completedTasks.push(task);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.processId) {
|
||||||
|
this.load(this.processId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public load(processId: string) {
|
||||||
|
this.loadActive(processId);
|
||||||
|
this.loadCompleted(processId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public loadActive(processId: string) {
|
||||||
|
this.activeTasks = [];
|
||||||
|
if (processId) {
|
||||||
|
this.activitiProcess.getProcessTasks(processId, null).subscribe(
|
||||||
|
(res: TaskDetailsModel[]) => {
|
||||||
|
res.forEach((task) => {
|
||||||
|
this.taskObserver.next(task);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.activeTasks = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public loadCompleted(processId: string) {
|
||||||
|
this.completedTasks = [];
|
||||||
|
if (processId) {
|
||||||
|
this.activitiProcess.getProcessTasks(processId, 'completed').subscribe(
|
||||||
|
(res: TaskDetailsModel[]) => {
|
||||||
|
res.forEach((task) => {
|
||||||
|
this.completedTaskObserver.next(task);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.completedTasks = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getUserFullName(user: any) {
|
||||||
|
if (user) {
|
||||||
|
return (user.firstName && user.firstName !== 'null'
|
||||||
|
? user.firstName + ' ' : '') +
|
||||||
|
user.lastName;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public clickTask($event: any, task: TaskDetailsModel) {
|
||||||
|
this.selectedTaskId = task.id;
|
||||||
|
this.taskdetails.loadDetails(task.id);
|
||||||
|
this.showDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
public showDialog() {
|
||||||
|
if (this.dialog) {
|
||||||
|
this.dialog.nativeElement.showModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public cancelDialog() {
|
||||||
|
this.closeDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
private closeDialog() {
|
||||||
|
if (this.dialog) {
|
||||||
|
this.dialog.nativeElement.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public taskFormCompleted() {
|
||||||
|
this.closeDialog();
|
||||||
|
this.load(this.processId);
|
||||||
|
this.taskFormCompletedEmitter.emit(this.processId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public onRefreshClicked() {
|
||||||
|
this.load(this.processId);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,12 @@
|
|||||||
<h1>My Activiti Processes</h1>
|
<div *ngIf="!filter">{{ 'FILTERS.MESSAGES.NONE' | translate }}</div>
|
||||||
|
<div *ngIf="filter">
|
||||||
<p *ngIf="processInstances && processInstances.length == 0">{{ 'PROCESSLIST.NONE' | translate }}</p>
|
<div *ngIf="!isListEmpty()">
|
||||||
<alfresco-datatable
|
<alfresco-datatable
|
||||||
[data]="data">
|
[data]="data"
|
||||||
|
(rowClick)="onRowClick($event)">
|
||||||
</alfresco-datatable>
|
</alfresco-datatable>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="isListEmpty()">
|
||||||
|
{{ 'PROCESSLIST.NONE' | translate }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @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 {describe, expect, it, inject, beforeEachProviders, beforeEach} from '@angular/core/testing';
|
|
||||||
import {TestComponentBuilder} from '@angular/compiler/testing';
|
|
||||||
import {AlfrescoSettingsService, AlfrescoTranslationService, AlfrescoAuthenticationService} from 'ng2-alfresco-core';
|
|
||||||
import {ActivitiProcesslistComponent} from '../../src/components/activiti-processlist.component';
|
|
||||||
import {TranslationMock} from './../assets/translation.service.mock';
|
|
||||||
import {ActivitiProcessService} from '../services/activiti-process.service';
|
|
||||||
|
|
||||||
describe('ActivitiProcesslistComponent', () => {
|
|
||||||
|
|
||||||
let processlistComponentFixture, element, component;
|
|
||||||
|
|
||||||
|
|
||||||
beforeEachProviders(() => {
|
|
||||||
return [
|
|
||||||
ActivitiProcessService,
|
|
||||||
AlfrescoSettingsService,
|
|
||||||
AlfrescoAuthenticationService,
|
|
||||||
{provide: AlfrescoTranslationService, useClass: TranslationMock}
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
|
||||||
return tcb
|
|
||||||
.createAsync(ActivitiProcesslistComponent)
|
|
||||||
.then(fixture => {
|
|
||||||
processlistComponentFixture = fixture;
|
|
||||||
element = processlistComponentFixture.nativeElement;
|
|
||||||
component = processlistComponentFixture.componentInstance;
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should have a valid title', () => {
|
|
||||||
expect(element.querySelector('h1')).toBeDefined();
|
|
||||||
expect(element.getElementsByTagName('h1')[0].innerHTML).toEqual('My Activiti Processes');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should contain a list of processes', () => {
|
|
||||||
let componentHandler = jasmine.createSpyObj('componentHandler', [
|
|
||||||
'upgradeAllRegistered'
|
|
||||||
]);
|
|
||||||
window['componentHandler'] = componentHandler;
|
|
||||||
|
|
||||||
component.ngOnInit();
|
|
||||||
processlistComponentFixture.detectChanges();
|
|
||||||
expect(element.querySelector('table')).toBeDefined();
|
|
||||||
expect(element.querySelectorAll('table tbody tr').length).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
@ -15,17 +15,17 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Component, OnInit } from '@angular/core';
|
import {Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||||
import { AlfrescoPipeTranslate, AlfrescoTranslationService, CONTEXT_MENU_DIRECTIVES, CONTEXT_MENU_PROVIDERS } from 'ng2-alfresco-core';
|
import { AlfrescoPipeTranslate, AlfrescoTranslationService, CONTEXT_MENU_DIRECTIVES, CONTEXT_MENU_PROVIDERS } from 'ng2-alfresco-core';
|
||||||
import { ALFRESCO_DATATABLE_DIRECTIVES, ObjectDataTableAdapter } from 'ng2-alfresco-datatable';
|
import { ALFRESCO_DATATABLE_DIRECTIVES, ObjectDataTableAdapter, DataRowEvent } from 'ng2-alfresco-datatable';
|
||||||
import { ActivitiProcessService } from '../services/activiti-process.service';
|
import { ActivitiProcessService } from '../services/activiti-process.service';
|
||||||
import { ProcessInstance } from '../models/process-instance';
|
import { FilterModel } from '../models/filter.model';
|
||||||
|
|
||||||
declare let __moduleName: string;
|
declare let __moduleName: string;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
moduleId: __moduleName,
|
moduleId: __moduleName,
|
||||||
selector: 'activiti-processlist',
|
selector: 'activiti-process-instance-list',
|
||||||
styles: [
|
styles: [
|
||||||
`
|
`
|
||||||
:host h1 {
|
:host h1 {
|
||||||
@ -36,13 +36,33 @@ declare let __moduleName: string;
|
|||||||
templateUrl: './activiti-processlist.component.html',
|
templateUrl: './activiti-processlist.component.html',
|
||||||
directives: [ ALFRESCO_DATATABLE_DIRECTIVES, CONTEXT_MENU_DIRECTIVES ],
|
directives: [ ALFRESCO_DATATABLE_DIRECTIVES, CONTEXT_MENU_DIRECTIVES ],
|
||||||
pipes: [ AlfrescoPipeTranslate ],
|
pipes: [ AlfrescoPipeTranslate ],
|
||||||
providers: [ CONTEXT_MENU_PROVIDERS ]
|
providers: [ CONTEXT_MENU_PROVIDERS, ActivitiProcessService ]
|
||||||
})
|
})
|
||||||
export class ActivitiProcesslistComponent implements OnInit {
|
export class ActivitiProcessInstanceListComponent implements OnInit {
|
||||||
|
|
||||||
errorMessage: string;
|
errorMessage: string;
|
||||||
processInstances: ProcessInstance[];
|
|
||||||
data: ObjectDataTableAdapter;
|
data: ObjectDataTableAdapter;
|
||||||
|
currentProcessInstanceId: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
filter: FilterModel;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
schemaColumn: any[] = [
|
||||||
|
{type: 'text', key: 'id', title: 'Id', sortable: true},
|
||||||
|
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true},
|
||||||
|
{type: 'text', key: 'started', title: 'Started', sortable: true},
|
||||||
|
{type: 'text', key: 'startedBy.email', title: 'Started By', sortable: true}
|
||||||
|
];
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
rowClick: EventEmitter<string> = new EventEmitter<string>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
onSuccess: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
onError: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
constructor (private processService: ActivitiProcessService, private translate: AlfrescoTranslationService) {
|
constructor (private processService: ActivitiProcessService, private translate: AlfrescoTranslationService) {
|
||||||
if (translate !== null) {
|
if (translate !== null) {
|
||||||
@ -51,27 +71,77 @@ export class ActivitiProcesslistComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.getProcesses();
|
this.data = new ObjectDataTableAdapter(
|
||||||
|
[],
|
||||||
|
this.schemaColumn
|
||||||
|
);
|
||||||
|
if (this.filter) {
|
||||||
|
this.load(this.filter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getProcesses() {
|
load(filter: FilterModel) {
|
||||||
this.processService.getProcesses()
|
this.processService.getProcessInstances(filter)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
(processInstances) => {
|
(processInstances) => {
|
||||||
this.data = new ObjectDataTableAdapter(
|
this.renderProcessInstances(processInstances);
|
||||||
processInstances,
|
this.onSuccess.emit(processInstances);
|
||||||
[
|
|
||||||
{type: 'text', key: 'id', title: 'Id', sortable: true},
|
|
||||||
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true},
|
|
||||||
{type: 'text', key: 'started', title: 'Started', sortable: true},
|
|
||||||
{type: 'text', key: 'startedBy.email', title: 'Started By', sortable: true}
|
|
||||||
]
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
error => this.errorMessage = <any>error);
|
error => {
|
||||||
|
this.errorMessage = <any>error;
|
||||||
|
this.onError.emit(error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemClick(processInstance: ProcessInstance, event: any) {
|
reload() {
|
||||||
console.log(processInstance, event);
|
this.load(this.filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the process list
|
||||||
|
*
|
||||||
|
* @param processInstances
|
||||||
|
*/
|
||||||
|
private renderProcessInstances(processInstances: any[]) {
|
||||||
|
processInstances = this.optimizeProcessNames(processInstances);
|
||||||
|
this.data = new ObjectDataTableAdapter(
|
||||||
|
processInstances,
|
||||||
|
this.schemaColumn
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the list is empty
|
||||||
|
* @returns {ObjectDataTableAdapter|boolean}
|
||||||
|
*/
|
||||||
|
isListEmpty(): boolean {
|
||||||
|
return this.data === undefined ||
|
||||||
|
(this.data && this.data.getRows() && this.data.getRows().length === 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emit the event rowClick passing the current task id when the row is clicked
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
onRowClick(event: DataRowEvent) {
|
||||||
|
let item = event;
|
||||||
|
this.currentProcessInstanceId = item.value.getValue('id');
|
||||||
|
this.rowClick.emit(this.currentProcessInstanceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optimize process name field
|
||||||
|
* @param tasks
|
||||||
|
* @returns {any[]}
|
||||||
|
*/
|
||||||
|
private optimizeProcessNames(tasks: any[]) {
|
||||||
|
tasks = tasks.map(t => {
|
||||||
|
t.name = t.name || 'No name';
|
||||||
|
if (t.name.length > 50) {
|
||||||
|
t.name = t.name.substring(0, 50) + '...';
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
return tasks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
:host {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activiti-label {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
.material-icons:hover {
|
||||||
|
color: rgb(255, 152, 0);
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
<button type="button" (click)="showDialog()" class="mdl-button">{{'START_PROCESS.BUTTON'|translate}}</button>
|
||||||
|
|
||||||
|
<dialog class="mdl-dialog" #dialog>
|
||||||
|
<h4 class="mdl-dialog__title">{{'START_PROCESS.DIALOG.TITLE'|translate}}</h4>
|
||||||
|
<div class="mdl-dialog__content">
|
||||||
|
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||||
|
<select name="processDefinition" [(ngModel)]="processDefinition" id="processDefinition">
|
||||||
|
<option *ngFor="let processDef of processDefinitions" [value]="processDef.id">
|
||||||
|
{{processDef.name}}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<label class="mdl-textfield__label" for="processDefinition">{{'START_PROCESS.DIALOG.LABEL.TYPE'|translate}}</label>
|
||||||
|
</div>
|
||||||
|
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||||
|
<input class="mdl-textfield__input" type="text" [(ngModel)]="name" rows="1" id="processName" />
|
||||||
|
<label class="mdl-textfield__label" for="processName">{{'START_PROCESS.DIALOG.LABEL.NAME'|translate}}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mdl-dialog__actions">
|
||||||
|
<button type="button" (click)="startProcess()" class="mdl-button">{{'START_PROCESS.DIALOG.ACTION.START'|translate}}</button>
|
||||||
|
<button type="button" (click)="cancel()" class="mdl-button close">{{'START_PROCESS.DIALOG.ACTION.CANCEL'|translate}}</button>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
@ -0,0 +1,101 @@
|
|||||||
|
/*!
|
||||||
|
* @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, Input, OnInit, ViewChild } from '@angular/core';
|
||||||
|
import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoPipeTranslate } from 'ng2-alfresco-core';
|
||||||
|
import { ActivitiProcessService } from './../services/activiti-process.service';
|
||||||
|
|
||||||
|
declare let componentHandler: any;
|
||||||
|
declare let __moduleName: string;
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'activiti-start-process',
|
||||||
|
moduleId: __moduleName,
|
||||||
|
templateUrl: './activiti-start-process.component.html',
|
||||||
|
styleUrls: ['./activiti-start-process.component.css'],
|
||||||
|
providers: [ActivitiProcessService],
|
||||||
|
pipes: [ AlfrescoPipeTranslate ]
|
||||||
|
|
||||||
|
})
|
||||||
|
export class ActivitiStartProcessButton implements OnInit {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
appId: string;
|
||||||
|
|
||||||
|
@ViewChild('dialog')
|
||||||
|
dialog: any;
|
||||||
|
|
||||||
|
processDefinitions: any[] = [];
|
||||||
|
|
||||||
|
name: string;
|
||||||
|
processDefinition: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param auth
|
||||||
|
* @param translate
|
||||||
|
* @param activitiProcess
|
||||||
|
*/
|
||||||
|
constructor(private auth: AlfrescoAuthenticationService,
|
||||||
|
private translate: AlfrescoTranslationService,
|
||||||
|
private activitiProcess: ActivitiProcessService) {
|
||||||
|
|
||||||
|
if (translate) {
|
||||||
|
translate.addTranslationFolder('node_modules/ng2-activiti-processlist/src');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.load(this.appId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public load(appId: string) {
|
||||||
|
this.activitiProcess.getProcessDefinitions(this.appId).subscribe(
|
||||||
|
(res: any[]) => {
|
||||||
|
this.processDefinitions = res;
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public showDialog() {
|
||||||
|
if (this.dialog) {
|
||||||
|
this.dialog.nativeElement.showModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public startProcess() {
|
||||||
|
if (this.processDefinition && this.name) {
|
||||||
|
this.activitiProcess.startProcess(this.processDefinition, this.name).subscribe(
|
||||||
|
(res: any) => {
|
||||||
|
this.cancel();
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public cancel() {
|
||||||
|
if (this.dialog) {
|
||||||
|
this.dialog.nativeElement.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,54 @@
|
|||||||
{
|
{
|
||||||
"PROCESSLIST": {
|
"PROCESSLIST": {
|
||||||
"NONE": "No active processes were found",
|
"NONE": "No process instances were found",
|
||||||
"SUMMARY": "Found {{total}} active process instances",
|
"SUMMARY": "Found {{total}} process instances",
|
||||||
"ERROR": "An error occurred while loading the processes: {{errorMessage}}",
|
"ERROR": "An error occurred while loading the processes instances: {{errorMessage}}",
|
||||||
"COLUMN": {
|
"COLUMN": {
|
||||||
"NAME": "Name"
|
"NAME": "Name"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"FILTERS": {
|
||||||
|
"MESSAGES": {
|
||||||
|
"NONE": "No process instance filter selected."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DETAILS": {
|
||||||
|
"LABELS": {
|
||||||
|
"STARTED_BY": "Started by",
|
||||||
|
"STARTED": "Started",
|
||||||
|
"COMMENTS": "Comments",
|
||||||
|
"TASKS_ACTIVE": "Active Tasks",
|
||||||
|
"TASKS_COMPLETED": "Completed Tasks",
|
||||||
|
"TASK_SUBTITLE": "Assigned to {{user}}, created {{created}}"
|
||||||
|
},
|
||||||
|
"BUTTON": {
|
||||||
|
"CANCEL": "Cancel Process"
|
||||||
|
},
|
||||||
|
"MESSAGES": {
|
||||||
|
"NONE": "No process details found."
|
||||||
|
},
|
||||||
|
"TASKS": {
|
||||||
|
"NO_ACTIVE": "No tasks are currently active",
|
||||||
|
"NO_COMPLETED": "No tasks have been completed yet",
|
||||||
|
"TASK_DETAILS": "Task details",
|
||||||
|
"TASK_CLOSE": "Close"
|
||||||
|
},
|
||||||
|
"COMMENTS": {
|
||||||
|
"NONE": "No comments."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"START_PROCESS": {
|
||||||
|
"BUTTON": "Start Process",
|
||||||
|
"DIALOG": {
|
||||||
|
"TITLE": "Start Process",
|
||||||
|
"LABEL": {
|
||||||
|
"TYPE": "Type",
|
||||||
|
"NAME": "Name"
|
||||||
|
},
|
||||||
|
"ACTION": {
|
||||||
|
"START": "Start",
|
||||||
|
"CANCEL": "Cancel"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
/*!
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Comment submitted against a process
|
||||||
|
*
|
||||||
|
* @returns {Comment} .
|
||||||
|
*/
|
||||||
|
import { User } from './user.model';
|
||||||
|
|
||||||
|
export class Comment {
|
||||||
|
id: number;
|
||||||
|
message: string;
|
||||||
|
created: string;
|
||||||
|
createdBy: User;
|
||||||
|
|
||||||
|
constructor(id: number, message: string, created: string, createdBy: User) {
|
||||||
|
this.id = id;
|
||||||
|
this.message = message;
|
||||||
|
this.created = created;
|
||||||
|
this.createdBy = createdBy;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
/*!
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This object represent the filter.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @returns {FilterModel} .
|
||||||
|
*/
|
||||||
|
export class FilterModel {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
recent: boolean = false;
|
||||||
|
icon: string;
|
||||||
|
filter: FilterParamsModel;
|
||||||
|
appId: number;
|
||||||
|
|
||||||
|
constructor(name: string, recent: boolean, icon: string, query: string, state: string, assignment: string, appDefinitionId?: string) {
|
||||||
|
this.name = name;
|
||||||
|
this.recent = recent;
|
||||||
|
this.icon = icon;
|
||||||
|
this.filter = new FilterParamsModel(query, state, assignment, appDefinitionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This object represent the parameters of a filter.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @returns {FilterModel} .
|
||||||
|
*/
|
||||||
|
export class FilterParamsModel {
|
||||||
|
name: string;
|
||||||
|
sort: string;
|
||||||
|
state: string;
|
||||||
|
appDefinitionId: string;
|
||||||
|
|
||||||
|
constructor(query: string, sort: string, state: string, appDefinitionId?: string) {
|
||||||
|
this.name = query;
|
||||||
|
this.sort = sort;
|
||||||
|
this.state = state;
|
||||||
|
this.appDefinitionId = appDefinitionId;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
/*!
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This object represent the details of a task.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @returns {TaskDetailsModel} .
|
||||||
|
*/
|
||||||
|
import { User } from './user.model';
|
||||||
|
|
||||||
|
export class TaskDetailsModel {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
assignee: User;
|
||||||
|
priority: number;
|
||||||
|
adhocTaskCanBeReassigned: number;
|
||||||
|
category: string;
|
||||||
|
created: string;
|
||||||
|
description: string;
|
||||||
|
dueDate: string;
|
||||||
|
duration: string;
|
||||||
|
endDate: string;
|
||||||
|
executionId: string;
|
||||||
|
formKey: string;
|
||||||
|
initiatorCanCompleteTask: boolean = false;
|
||||||
|
managerOfCandidateGroup: boolean = false;
|
||||||
|
memberOfCandidateGroup: boolean = false;
|
||||||
|
memberOfCandidateUsers: boolean = false;
|
||||||
|
involvedPeople: User [];
|
||||||
|
parentTaskId: string;
|
||||||
|
parentTaskName: string;
|
||||||
|
processDefinitionCategory: string;
|
||||||
|
processDefinitionDeploymentId: string;
|
||||||
|
processDefinitionDescription: string;
|
||||||
|
processDefinitionId: string;
|
||||||
|
processDefinitionKey: string;
|
||||||
|
processDefinitionName: string;
|
||||||
|
processDefinitionVersion: number = 0;
|
||||||
|
processInstanceId: string;
|
||||||
|
processInstanceName: string;
|
||||||
|
processInstanceStartUserId: string;
|
||||||
|
taskDefinitionKey: string;
|
||||||
|
|
||||||
|
|
||||||
|
constructor(obj: any) {
|
||||||
|
this.id = obj.id;
|
||||||
|
this.name = obj.name;
|
||||||
|
this.priority = obj.priority;
|
||||||
|
this.assignee = new User(obj.assignee.id, obj.assignee.email, obj.assignee.firstName, obj.assignee.lastName);
|
||||||
|
this.adhocTaskCanBeReassigned = obj.adhocTaskCanBeReassigned;
|
||||||
|
this.created = obj.created;
|
||||||
|
this.description = obj.description;
|
||||||
|
this.dueDate = obj.dueDate;
|
||||||
|
this.duration = obj.duration;
|
||||||
|
this.endDate = obj.endDate;
|
||||||
|
this.executionId = obj.executionId;
|
||||||
|
this.formKey = obj.formKey;
|
||||||
|
this.initiatorCanCompleteTask = obj.initiatorCanCompleteTask;
|
||||||
|
this.managerOfCandidateGroup = obj.managerOfCandidateGroup;
|
||||||
|
this.memberOfCandidateGroup = obj.memberOfCandidateGroup;
|
||||||
|
this.memberOfCandidateUsers = obj.memberOfCandidateUsers;
|
||||||
|
this.involvedPeople = obj.involvedPeople;
|
||||||
|
this.parentTaskId = obj.parentTaskId;
|
||||||
|
this.parentTaskName = obj.parentTaskName;
|
||||||
|
this.processDefinitionCategory = obj.processDefinitionCategory;
|
||||||
|
this.processDefinitionDeploymentId = obj.processDefinitionDeploymentId;
|
||||||
|
this.processDefinitionDescription = obj.processDefinitionDescription;
|
||||||
|
this.processDefinitionId = obj.processDefinitionId;
|
||||||
|
this.processDefinitionKey = obj.processDefinitionKey;
|
||||||
|
this.processDefinitionName = obj.processDefinitionName;
|
||||||
|
this.processDefinitionVersion = obj.processDefinitionVersion;
|
||||||
|
this.processInstanceId = obj.processInstanceId;
|
||||||
|
this.processInstanceName = obj.processInstanceName;
|
||||||
|
this.processInstanceStartUserId = obj.processInstanceStartUserId;
|
||||||
|
this.taskDefinitionKey = obj.taskDefinitionKey;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*!
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This object represent the user.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @returns {User} .
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class User {
|
||||||
|
id: number;
|
||||||
|
email: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
|
||||||
|
constructor(id: number, email: string, firstName: string, lastName: string) {
|
||||||
|
this.id = id;
|
||||||
|
this.email = email;
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,9 @@
|
|||||||
|
|
||||||
import {AlfrescoAuthenticationService} from 'ng2-alfresco-core';
|
import {AlfrescoAuthenticationService} from 'ng2-alfresco-core';
|
||||||
import {ProcessInstance} from '../models/process-instance';
|
import {ProcessInstance} from '../models/process-instance';
|
||||||
|
import {FilterModel} from '../models/filter.model';
|
||||||
|
import {User} from '../models/user.model';
|
||||||
|
import {Comment} from '../models/comment.model';
|
||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {Observable} from 'rxjs/Observable';
|
import {Observable} from 'rxjs/Observable';
|
||||||
import 'rxjs/add/operator/map';
|
import 'rxjs/add/operator/map';
|
||||||
@ -28,6 +31,16 @@ export class ActivitiProcessService {
|
|||||||
constructor(public authService: AlfrescoAuthenticationService) {
|
constructor(public authService: AlfrescoAuthenticationService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrive all the Deployed app
|
||||||
|
* @returns {Observable<any>}
|
||||||
|
*/
|
||||||
|
getDeployedApplications(name: string): Observable<any> {
|
||||||
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.appsApi.getAppDefinitions())
|
||||||
|
.map((response: any) => response.data.find(p => p.name === name))
|
||||||
|
.do(data => console.log('Application: ' + JSON.stringify(data)));
|
||||||
|
}
|
||||||
|
|
||||||
getProcesses(): Observable<ProcessInstance[]> {
|
getProcesses(): Observable<ProcessInstance[]> {
|
||||||
let request = {'page': 0, 'sort': 'created-desc', 'state': 'all'};
|
let request = {'page': 0, 'sort': 'created-desc', 'state': 'all'};
|
||||||
|
|
||||||
@ -36,6 +49,109 @@ export class ActivitiProcessService {
|
|||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getProcessInstances(filter: FilterModel): Observable<ProcessInstance[]> {
|
||||||
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.processApi.getProcessInstances(filter))
|
||||||
|
.map(this.extractData)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
getProcessFilters(appId: string): Observable<any[]> {
|
||||||
|
let filterOpts = appId ? {
|
||||||
|
appId: appId
|
||||||
|
} : {};
|
||||||
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.userFiltersApi.getUserProcessInstanceFilters(filterOpts))
|
||||||
|
.map(this.extractData)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
getProcess(id: string): Observable<ProcessInstance> {
|
||||||
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.processApi.getProcessInstance(id))
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
getProcessTasks(id: string, state: string): Observable<any[]> {
|
||||||
|
let taskOpts = state ? {
|
||||||
|
processInstanceId: id,
|
||||||
|
state: state
|
||||||
|
} : {
|
||||||
|
processInstanceId: id
|
||||||
|
};
|
||||||
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.taskApi.listTasks(taskOpts))
|
||||||
|
.map(this.extractData)
|
||||||
|
.map(tasks => tasks.map((task: any) => {
|
||||||
|
task.created = new Date(task.created);
|
||||||
|
return task;
|
||||||
|
}))
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrive all the process instance's comments
|
||||||
|
* @param id - process instance ID
|
||||||
|
* @returns {<Comment[]>}
|
||||||
|
*/
|
||||||
|
getProcessInstanceComments(id: string): Observable<Comment[]> {
|
||||||
|
return Observable.fromPromise(this.authService.getAlfrescoApi().activiti.commentsApi.getProcessInstanceComments(id))
|
||||||
|
.map(res => res)
|
||||||
|
.map((response: any) => {
|
||||||
|
let comments: Comment[] = [];
|
||||||
|
response.data.forEach((comment) => {
|
||||||
|
let user = new User(
|
||||||
|
comment.createdBy.id, comment.createdBy.email, comment.createdBy.firstName, comment.createdBy.lastName);
|
||||||
|
comments.push(new Comment(comment.id, comment.message, comment.created, user));
|
||||||
|
});
|
||||||
|
return comments;
|
||||||
|
}).catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a comment to a process instance
|
||||||
|
* @param id - process instance Id
|
||||||
|
* @param message - content of the comment
|
||||||
|
* @returns {Comment}
|
||||||
|
*/
|
||||||
|
addProcessInstanceComment(id: string, message: string): Observable<Comment> {
|
||||||
|
return Observable.fromPromise(
|
||||||
|
this.authService.getAlfrescoApi().activiti.commentsApi.addProcessInstanceComment({message: message}, id)
|
||||||
|
)
|
||||||
|
.map(res => res)
|
||||||
|
.map((response: Comment) => {
|
||||||
|
return new Comment(response.id, response.message, response.created, response.createdBy);
|
||||||
|
}).catch(this.handleError);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
getProcessDefinitions(appId: string) {
|
||||||
|
let opts = appId ? {
|
||||||
|
latest: true,
|
||||||
|
appId: appId
|
||||||
|
} : {
|
||||||
|
latest: true
|
||||||
|
};
|
||||||
|
return Observable.fromPromise(
|
||||||
|
this.authService.getAlfrescoApi().activiti.processApi.getProcessDefinitions(opts)
|
||||||
|
)
|
||||||
|
.map(this.extractData)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
startProcess(processDefinitionId: string, name: string) {
|
||||||
|
let startRequest: any = {};
|
||||||
|
startRequest.name = name;
|
||||||
|
startRequest.processDefinitionId = processDefinitionId;
|
||||||
|
return Observable.fromPromise(
|
||||||
|
this.authService.getAlfrescoApi().activiti.processApi.startNewProcessInstance(startRequest)
|
||||||
|
)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelProcess(processInstanceId: string) {
|
||||||
|
return Observable.fromPromise(
|
||||||
|
this.authService.getAlfrescoApi().activiti.processApi.deleteProcessInstance(processInstanceId)
|
||||||
|
)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
private extractData(res: any) {
|
private extractData(res: any) {
|
||||||
return res.data || {};
|
return res.data || {};
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,8 @@
|
|||||||
"material-design-lite": "1.1.3",
|
"material-design-lite": "1.1.3",
|
||||||
"ng2-translate": "2.2.2",
|
"ng2-translate": "2.2.2",
|
||||||
"alfresco-js-api": "^0.3.0",
|
"alfresco-js-api": "^0.3.0",
|
||||||
"ng2-alfresco-datatable": "^0.1.12",
|
"ng2-alfresco-datatable": "^0.3.0",
|
||||||
"ng2-alfresco-core": "^0.1.36"
|
"ng2-alfresco-core": "^0.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"browser-sync": "2.10.0",
|
"browser-sync": "2.10.0",
|
||||||
|
@ -15,69 +15,70 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Component, OnInit} from '@angular/core';
|
|
||||||
import {ALFRESCO_CORE_PROVIDERS, AlfrescoAuthenticationService, AlfrescoSettingsService} from 'ng2-alfresco-core';
|
|
||||||
import { bootstrap } from '@angular/platform-browser-dynamic';
|
import { bootstrap } from '@angular/platform-browser-dynamic';
|
||||||
import {ActivitiTaskList} from 'ng2-activiti-tasklist';
|
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||||
import {ObjectDataTableAdapter, ObjectDataColumn} from 'ng2-alfresco-datatable';
|
import { ALFRESCO_CORE_PROVIDERS, AlfrescoAuthenticationService, AlfrescoSettingsService } from 'ng2-alfresco-core';
|
||||||
|
import { ALFRESCO_TASKLIST_DIRECTIVES } from 'ng2-activiti-tasklist';
|
||||||
import { HTTP_PROVIDERS } from '@angular/http';
|
import { HTTP_PROVIDERS } from '@angular/http';
|
||||||
|
import { ATIVITI_FORM_PROVIDERS } from 'ng2-activiti-form';
|
||||||
declare let AlfrescoApi: any;
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'activiti-tasklist-demo',
|
selector: 'activiti-tasklist-demo',
|
||||||
template: `label for="token"><b>Insert a valid access token / ticket:</b></label><br>
|
template: `<label for="token"><b>Insert a valid access token / ticket:</b></label><br>
|
||||||
<input id="token" type="text" size="48" (change)="updateToken();documentList.reload()" [(ngModel)]="token"><br>
|
<input id="token" type="text" size="48" (change)="updateToken();documentList.reload()" [(ngModel)]="token"><br>
|
||||||
<label for="token"><b>Insert the ip of your Alfresco instance:</b></label><br>
|
<label for="token"><b>Insert the ip of your Activiti instance:</b></label><br>
|
||||||
<input id="token" type="text" size="48" (change)="updateHost();documentList.reload()" [(ngModel)]="bpmHost"><br><br>
|
<input id="token" type="text" size="48" (change)="updateHost();documentList.reload()" [(ngModel)]="bpmHost"><br><br>
|
||||||
<div *ngIf="!authenticated" style="color:#FF2323">
|
<div *ngIf="!authenticated" style="color:#FF2323">
|
||||||
Authentication failed to ip {{ bpmHost }} with user: admin, admin, you can still try to add a valid token to perform
|
Authentication failed to ip {{ bpmHost }} with user: admin, admin, you can still try to add a valid token to perform
|
||||||
operations.
|
operations.
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<label for="token"><b>Insert a scriptPath</b></label><br>
|
|
||||||
<input id="token" type="text" size="48" [(ngModel)]="scriptPath"><br>
|
|
||||||
<label for="token"><b>Insert a contextRoot</b></label><br>
|
|
||||||
<input id="token" type="text" size="48" [(ngModel)]="contextRoot"><br>
|
|
||||||
<label for="token"><b>Insert a servicePath</b></label><br>
|
|
||||||
<input id="token" type="text" size="48" [(ngModel)]="servicePath"><br>
|
|
||||||
<div class="container" *ngIf="authenticated">
|
<div class="container" *ngIf="authenticated">
|
||||||
<activiti-tasklist></activiti-tasklist>
|
<span>Task Filters</span>
|
||||||
|
<activiti-filters (filterClick)="onFilterClick($event)"></activiti-filters>
|
||||||
|
<span>Tasks</span>
|
||||||
|
<activiti-tasklist [taskFilter]="taskFilter" [schemaColumn]="schemaColumn"
|
||||||
|
(rowClick)="onRowClick($event)" #activititasklist></activiti-tasklist>
|
||||||
|
<span>Task Details</span>
|
||||||
|
<activiti-task-details [taskId]="currentTaskId" #activitidetails></activiti-task-details>
|
||||||
</div>`,
|
</div>`,
|
||||||
styles: [
|
styles: [
|
||||||
':host > .container {padding: 10px}',
|
':host > .container {padding: 10px}',
|
||||||
'.p-10 { padding: 10px; }'
|
'.p-10 { padding: 10px; }'
|
||||||
],
|
],
|
||||||
directives: [ActivitiTaskList]
|
directives: [ALFRESCO_TASKLIST_DIRECTIVES]
|
||||||
})
|
})
|
||||||
class ActivitiTaskListDemo implements OnInit {
|
class ActivitiTaskListDemo implements OnInit {
|
||||||
|
|
||||||
|
@ViewChild('activititasklist')
|
||||||
|
activititasklist: any;
|
||||||
|
|
||||||
|
@ViewChild('activitidetails')
|
||||||
|
activitidetails: any;
|
||||||
|
|
||||||
bpmHost: string = 'http://127.0.0.1:9999';
|
bpmHost: string = 'http://127.0.0.1:9999';
|
||||||
|
|
||||||
token: string;
|
token: string;
|
||||||
|
|
||||||
data: ObjectDataTableAdapter;
|
|
||||||
|
|
||||||
authenticated: boolean;
|
authenticated: boolean;
|
||||||
|
|
||||||
|
schemaColumn: any [] = [];
|
||||||
|
|
||||||
|
currentTaskId: string;
|
||||||
|
|
||||||
|
taskFilter: any;
|
||||||
|
|
||||||
constructor(private authService: AlfrescoAuthenticationService,
|
constructor(private authService: AlfrescoAuthenticationService,
|
||||||
private settingsService: AlfrescoSettingsService) {
|
private settingsService: AlfrescoSettingsService) {
|
||||||
this.settingsService.setProviders('BPM');
|
this.settingsService.setProviders('BPM');
|
||||||
this.data = new ObjectDataTableAdapter([], []);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.login();
|
this.login();
|
||||||
|
|
||||||
let schema = [
|
this.schemaColumn = [
|
||||||
{type: 'text', key: 'id', title: 'Id'},
|
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true}
|
||||||
{type: 'text', key: 'name', title: 'Name', cssClass: 'full-width name-column', sortable: true},
|
|
||||||
{type: 'text', key: 'formKey', title: 'Form Key', sortable: true},
|
|
||||||
{type: 'text', key: 'created', title: 'Created', sortable: true}
|
|
||||||
];
|
];
|
||||||
|
|
||||||
let columns = schema.map(col => new ObjectDataColumn(col));
|
|
||||||
this.data.setColumns(columns);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
login() {
|
login() {
|
||||||
@ -92,9 +93,20 @@ class ActivitiTaskListDemo implements OnInit {
|
|||||||
this.authenticated = false;
|
this.authenticated = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onFilterClick(event: any) {
|
||||||
|
this.taskFilter = event;
|
||||||
|
this.activititasklist.load(this.taskFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
onRowClick(taskId) {
|
||||||
|
this.currentTaskId = taskId;
|
||||||
|
this.activitidetails.loadDetails(this.currentTaskId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bootstrap(ActivitiTaskListDemo, [
|
bootstrap(ActivitiTaskListDemo, [
|
||||||
HTTP_PROVIDERS,
|
HTTP_PROVIDERS,
|
||||||
|
ATIVITI_FORM_PROVIDERS,
|
||||||
ALFRESCO_CORE_PROVIDERS]
|
ALFRESCO_CORE_PROVIDERS]
|
||||||
);
|
);
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
'ng2-translate': 'node_modules/ng2-translate',
|
'ng2-translate': 'node_modules/ng2-translate',
|
||||||
'ng2-alfresco-core': 'node_modules/ng2-alfresco-core/dist',
|
'ng2-alfresco-core': 'node_modules/ng2-alfresco-core/dist',
|
||||||
'ng2-alfresco-datatable': 'node_modules/ng2-alfresco-datatable/dist',
|
'ng2-alfresco-datatable': 'node_modules/ng2-alfresco-datatable/dist',
|
||||||
|
'ng2-activiti-form': 'node_modules/ng2-activiti-form/dist',
|
||||||
'ng2-activiti-tasklist': 'node_modules/ng2-activiti-tasklist/dist'
|
'ng2-activiti-tasklist': 'node_modules/ng2-activiti-tasklist/dist'
|
||||||
};
|
};
|
||||||
// packages tells the System loader how to load when no filename and/or no extension
|
// packages tells the System loader how to load when no filename and/or no extension
|
||||||
@ -24,6 +25,7 @@
|
|||||||
'ng2-translate': { defaultExtension: 'js' },
|
'ng2-translate': { defaultExtension: 'js' },
|
||||||
'ng2-alfresco-core': { main: 'index.js', defaultExtension: 'js' },
|
'ng2-alfresco-core': { main: 'index.js', defaultExtension: 'js' },
|
||||||
'ng2-alfresco-datatable': { main: 'index.js', defaultExtension: 'js' },
|
'ng2-alfresco-datatable': { main: 'index.js', defaultExtension: 'js' },
|
||||||
|
'ng2-activiti-form': { main: 'index.js', defaultExtension: 'js' },
|
||||||
'ng2-activiti-tasklist': { main: 'index.js', defaultExtension: 'js' }
|
'ng2-activiti-tasklist': { main: 'index.js', defaultExtension: 'js' }
|
||||||
};
|
};
|
||||||
var ngPackageNames = [
|
var ngPackageNames = [
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ng2-activiti-tasklist",
|
"name": "ng2-activiti-tasklist",
|
||||||
"description": "Activiti Angular2 Task List Component",
|
"description": "Activiti Angular2 Task List Component",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"author": "Alfresco Software, Ltd.",
|
"author": "Alfresco Software, Ltd.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "typings install",
|
"postinstall": "typings install",
|
||||||
@ -67,9 +67,9 @@
|
|||||||
"rxjs": "5.0.0-beta.6",
|
"rxjs": "5.0.0-beta.6",
|
||||||
"zone.js": "0.6.12",
|
"zone.js": "0.6.12",
|
||||||
"ng2-translate": "2.2.2",
|
"ng2-translate": "2.2.2",
|
||||||
"ng2-alfresco-core": "0.2.0",
|
"ng2-alfresco-core": "0.3.0",
|
||||||
"ng2-alfresco-datatable": "0.2.0",
|
"ng2-alfresco-datatable": "0.3.0",
|
||||||
"ng2-activiti-form": "0.2.0",
|
"ng2-activiti-form": "0.3.0",
|
||||||
"alfresco-js-api": "^0.3.0"
|
"alfresco-js-api": "^0.3.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
@ -59,7 +59,7 @@ export class ActivitiChecklist implements OnInit {
|
|||||||
private activitiTaskList: ActivitiTaskListService) {
|
private activitiTaskList: ActivitiTaskListService) {
|
||||||
|
|
||||||
if (translate) {
|
if (translate) {
|
||||||
translate.addTranslationFolder('node_modules/ng2-activiti-tasklist');
|
translate.addTranslationFolder('node_modules/ng2-activiti-tasklist/src');
|
||||||
}
|
}
|
||||||
this.task$ = new Observable<TaskDetailsModel>(observer => this.taskObserver = observer).share();
|
this.task$ = new Observable<TaskDetailsModel>(observer => this.taskObserver = observer).share();
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ export class ActivitiComments implements OnInit {
|
|||||||
private activitiTaskList: ActivitiTaskListService) {
|
private activitiTaskList: ActivitiTaskListService) {
|
||||||
|
|
||||||
if (translate) {
|
if (translate) {
|
||||||
translate.addTranslationFolder('node_modules/ng2-activiti-tasklist');
|
translate.addTranslationFolder('node_modules/ng2-activiti-tasklist/src');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.comment$ = new Observable<Comment>(observer => this.commentObserver = observer).share();
|
this.comment$ = new Observable<Comment>(observer => this.commentObserver = observer).share();
|
||||||
|
@ -70,7 +70,7 @@ export class ActivitiFilters implements OnInit {
|
|||||||
this.filter$ = new Observable<FilterModel>(observer => this.filterObserver = observer).share();
|
this.filter$ = new Observable<FilterModel>(observer => this.filterObserver = observer).share();
|
||||||
|
|
||||||
if (translate) {
|
if (translate) {
|
||||||
translate.addTranslationFolder('node_modules/ng2-activiti-tasklist');
|
translate.addTranslationFolder('node_modules/ng2-activiti-tasklist/src');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ export class ActivitiPeople implements OnInit {
|
|||||||
private translate: AlfrescoTranslationService) {
|
private translate: AlfrescoTranslationService) {
|
||||||
|
|
||||||
if (translate) {
|
if (translate) {
|
||||||
translate.addTranslationFolder('node_modules/ng2-activiti-tasklist');
|
translate.addTranslationFolder('node_modules/ng2-activiti-tasklist/src');
|
||||||
}
|
}
|
||||||
this.people$ = new Observable<User>(observer => this.peopleObserver = observer).share();
|
this.people$ = new Observable<User>(observer => this.peopleObserver = observer).share();
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ export class ActivitiTaskDetails implements OnInit {
|
|||||||
private activitiTaskList: ActivitiTaskListService) {
|
private activitiTaskList: ActivitiTaskListService) {
|
||||||
|
|
||||||
if (translate) {
|
if (translate) {
|
||||||
translate.addTranslationFolder('node_modules/ng2-activiti-tasklist');
|
translate.addTranslationFolder('node_modules/ng2-activiti-tasklist/src');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,6 +125,8 @@ export class ActivitiTaskDetails implements OnInit {
|
|||||||
console.log(this.taskDetails);
|
console.log(this.taskDetails);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
this.taskDetails = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ export class ActivitiTaskHeader implements OnInit, OnChanges {
|
|||||||
private translate: AlfrescoTranslationService) {
|
private translate: AlfrescoTranslationService) {
|
||||||
|
|
||||||
if (translate) {
|
if (translate) {
|
||||||
translate.addTranslationFolder('node_modules/ng2-activiti-tasklist');
|
translate.addTranslationFolder('node_modules/ng2-activiti-tasklist/src');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ng2-alfresco-core",
|
"name": "ng2-alfresco-core",
|
||||||
"description": "Alfresco Angular 2 Components core",
|
"description": "Alfresco Angular 2 Components core",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"author": "Alfresco Software, Ltd.",
|
"author": "Alfresco Software, Ltd.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "typings install",
|
"postinstall": "typings install",
|
||||||
|
@ -33,9 +33,9 @@ export class AlfrescoSettingsService {
|
|||||||
|
|
||||||
private providers: string = 'ALL'; // ECM, BPM , ALL
|
private providers: string = 'ALL'; // ECM, BPM , ALL
|
||||||
|
|
||||||
bpmHostSubject: Subject<string> = new Subject<string>();
|
public bpmHostSubject: Subject<string> = new Subject<string>();
|
||||||
ecmHostSubject: Subject<string> = new Subject<string>();
|
public ecmHostSubject: Subject<string> = new Subject<string>();
|
||||||
providerSubject: Subject<string> = new Subject<string>();
|
public providerSubject: Subject<string> = new Subject<string>();
|
||||||
|
|
||||||
public get ecmHost(): string {
|
public get ecmHost(): string {
|
||||||
return this._ecmHost;
|
return this._ecmHost;
|
||||||
|
@ -41,8 +41,7 @@
|
|||||||
"license-check": "1.1.5",
|
"license-check": "1.1.5",
|
||||||
|
|
||||||
"material-design-icons": "2.2.3",
|
"material-design-icons": "2.2.3",
|
||||||
"material-design-lite": "1.1.3",
|
"material-design-lite": "1.1.3"
|
||||||
"ng2-activiti-processlist": "^0.1.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"browser-sync": "2.10.0",
|
"browser-sync": "2.10.0",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ng2-alfresco-datatable",
|
"name": "ng2-alfresco-datatable",
|
||||||
"description": "Alfresco Angular2 DataTable Component",
|
"description": "Alfresco Angular2 DataTable Component",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"author": "Alfresco Software, Ltd.",
|
"author": "Alfresco Software, Ltd.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "typings install",
|
"postinstall": "typings install",
|
||||||
@ -63,7 +63,7 @@
|
|||||||
"rxjs": "5.0.0-beta.6",
|
"rxjs": "5.0.0-beta.6",
|
||||||
"zone.js": "0.6.12",
|
"zone.js": "0.6.12",
|
||||||
"ng2-translate": "2.2.2",
|
"ng2-translate": "2.2.2",
|
||||||
"ng2-alfresco-core": "0.2.0"
|
"ng2-alfresco-core": "0.3.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"material-design-icons": "^2.2.3",
|
"material-design-icons": "^2.2.3",
|
||||||
|
@ -47,7 +47,11 @@
|
|||||||
[context-menu]="getContextMenuActions(row, col)">
|
[context-menu]="getContextMenuActions(row, col)">
|
||||||
<div *ngSwitchCase="'image'" class="cell-value">
|
<div *ngSwitchCase="'image'" class="cell-value">
|
||||||
<i *ngIf="isIconValue(row, col)" class="material-icons icon-cell">{{asIconValue(row, col)}}</i>
|
<i *ngIf="isIconValue(row, col)" class="material-icons icon-cell">{{asIconValue(row, col)}}</i>
|
||||||
<img *ngIf="!isIconValue(row, col)" class="image-cell" alt="{{iconAltTextKey(data.getValue(row, col))|translate}}" src="{{data.getValue(row, col)}}">
|
<img *ngIf="!isIconValue(row, col)"
|
||||||
|
class="image-cell"
|
||||||
|
alt="{{iconAltTextKey(data.getValue(row, col))|translate}}"
|
||||||
|
src="{{data.getValue(row, col)}}"
|
||||||
|
(error)="onImageLoadingError($event)">
|
||||||
</div>
|
</div>
|
||||||
<div *ngSwitchCase="'date'" class="cell-value" [attr.data-automation-id]="'date_' + data.getValue(row, col)">
|
<div *ngSwitchCase="'date'" class="cell-value" [attr.data-automation-id]="'date_' + data.getValue(row, col)">
|
||||||
{{data.getValue(row, col)}}
|
{{data.getValue(row, col)}}
|
||||||
|
@ -320,4 +320,29 @@ describe('DataTable', () => {
|
|||||||
expect(dataTable.isColumnSorted(<DataColumn> {key: 'column_1'}, 'asc')).toBeTruthy();
|
expect(dataTable.isColumnSorted(<DataColumn> {key: 'column_1'}, 'asc')).toBeTruthy();
|
||||||
expect(dataTable.isColumnSorted(<DataColumn> {key: 'column_2'}, 'desc')).toBeFalsy();
|
expect(dataTable.isColumnSorted(<DataColumn> {key: 'column_2'}, 'desc')).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should replace image source with fallback thumbnail on error', () => {
|
||||||
|
let event = <any> {
|
||||||
|
srcElement: {
|
||||||
|
src: 'missing-image'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dataTable.fallbackThumbnail = '<fallback>';
|
||||||
|
dataTable.onImageLoadingError(event);
|
||||||
|
expect(event.srcElement.src).toBe(dataTable.fallbackThumbnail);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should replace image source only when fallback available', () => {
|
||||||
|
const originalSrc = 'missing-image';
|
||||||
|
let event = <any> {
|
||||||
|
srcElement: {
|
||||||
|
src: originalSrc
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dataTable.fallbackThumbnail = null;
|
||||||
|
dataTable.onImageLoadingError(event);
|
||||||
|
expect(event.srcElement.src).toBe(originalSrc);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -63,6 +63,9 @@ export class DataTableComponent implements OnInit, AfterViewChecked {
|
|||||||
@Input()
|
@Input()
|
||||||
actions: boolean = false;
|
actions: boolean = false;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
fallbackThumbnail: string;
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
rowClick: EventEmitter<DataRowEvent> = new EventEmitter<DataRowEvent>();
|
rowClick: EventEmitter<DataRowEvent> = new EventEmitter<DataRowEvent>();
|
||||||
|
|
||||||
@ -155,6 +158,13 @@ export class DataTableComponent implements OnInit, AfterViewChecked {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onImageLoadingError(event: Event) {
|
||||||
|
if (event && this.fallbackThumbnail) {
|
||||||
|
let element = <any> event.srcElement;
|
||||||
|
element.src = this.fallbackThumbnail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
isIconValue(row: DataRow, col: DataColumn) {
|
isIconValue(row: DataRow, col: DataColumn) {
|
||||||
if (row && col) {
|
if (row && col) {
|
||||||
let value = row.getValue(col.key);
|
let value = row.getValue(col.key);
|
||||||
|
@ -12,6 +12,10 @@
|
|||||||
<link rel="stylesheet" href="node_modules/material-design-icons/iconfont/material-icons.css">
|
<link rel="stylesheet" href="node_modules/material-design-icons/iconfont/material-icons.css">
|
||||||
|
|
||||||
<!-- 1. Load libraries -->
|
<!-- 1. Load libraries -->
|
||||||
|
<!-- Polyfill(s) for Safari (pre-10.x) -->
|
||||||
|
<script src="node_modules/intl/dist/Intl.min.js"></script>
|
||||||
|
<script src="node_modules/intl/locale-data/jsonp/en.js"></script>
|
||||||
|
|
||||||
<!-- Polyfill(s) for older browsers -->
|
<!-- Polyfill(s) for older browsers -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||||
|
|
||||||
|
@ -36,10 +36,11 @@
|
|||||||
"material-design-icons": "2.2.3",
|
"material-design-icons": "2.2.3",
|
||||||
"material-design-lite": "1.1.3",
|
"material-design-lite": "1.1.3",
|
||||||
"ng2-translate": "2.2.2",
|
"ng2-translate": "2.2.2",
|
||||||
|
"intl": "1.2.4",
|
||||||
"alfresco-js-api": "^0.3.0",
|
"alfresco-js-api": "^0.3.0",
|
||||||
"ng2-alfresco-core": "^0.2.0",
|
"ng2-alfresco-core": "^0.3.0",
|
||||||
"ng2-alfresco-documentlist": "^0.2.0",
|
"ng2-alfresco-documentlist": "^0.3.0",
|
||||||
"ng2-alfresco-datatable": "^0.2.0"
|
"ng2-alfresco-datatable": "^0.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"concurrently": "2.0.0",
|
"concurrently": "2.0.0",
|
||||||
|
@ -37,17 +37,15 @@ import {
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'alfresco-documentlist-demo',
|
selector: 'alfresco-documentlist-demo',
|
||||||
template: `
|
template: `
|
||||||
<label for="token"><b>Insert a valid access token / ticket:</b></label><br>
|
<label for="ticket"><b>Insert a valid access ticket / ticket:</b></label><br>
|
||||||
<input id="token" type="text" size="48" (change)="updateToken();documentList.reload()" [(ngModel)]="token"><br>
|
<input id="ticket" type="text" size="48" (change)="updateTicket(); documentList.reload()" [(ngModel)]="ticket"><br>
|
||||||
<label for="token"><b>Insert the ip of your Alfresco instance:</b></label><br>
|
<label for="host"><b>Insert the ip of your Alfresco instance:</b></label><br>
|
||||||
<input id="token" type="text" size="48" (change)="updateHost();documentList.reload()" [(ngModel)]="host"><br><br>
|
<input id="host" type="text" size="48" (change)="updateHost(); documentList.reload()" [(ngModel)]="ecmHost"><br><br>
|
||||||
<div *ngIf="!authenticated" style="color:#FF2323">
|
<div *ngIf="!authenticated" style="color:#FF2323">
|
||||||
Authentication failed to ip {{ host }} with user: admin, admin, you can still try to add a valid token to perform
|
Authentication failed to ip {{ ecmHost }} with user: admin, admin, you can still try to add a valid ticket to perform
|
||||||
operations.
|
operations.
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="container" *ngIf="authenticated">
|
|
||||||
|
|
||||||
<alfresco-document-list-breadcrumb
|
<alfresco-document-list-breadcrumb
|
||||||
[currentFolderPath]="currentPath"
|
[currentFolderPath]="currentPath"
|
||||||
[target]="documentList">
|
[target]="documentList">
|
||||||
@ -57,7 +55,6 @@ import {
|
|||||||
[currentFolderPath]="currentPath"
|
[currentFolderPath]="currentPath"
|
||||||
[contextMenuActions]="true"
|
[contextMenuActions]="true"
|
||||||
[contentActions]="true"
|
[contentActions]="true"
|
||||||
[multiselect]="true"
|
|
||||||
(folderChange)="onFolderChanged($event)">
|
(folderChange)="onFolderChanged($event)">
|
||||||
<!--
|
<!--
|
||||||
<empty-folder-content>
|
<empty-folder-content>
|
||||||
@ -74,6 +71,12 @@ import {
|
|||||||
sortable="true"
|
sortable="true"
|
||||||
class="full-width ellipsis-cell">
|
class="full-width ellipsis-cell">
|
||||||
</content-column>
|
</content-column>
|
||||||
|
<!--
|
||||||
|
<content-column
|
||||||
|
title="Type"
|
||||||
|
source="content.mimeType">
|
||||||
|
</content-column>
|
||||||
|
-->
|
||||||
<content-column
|
<content-column
|
||||||
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_BY' | translate}}"
|
title="{{'DOCUMENT_LIST.COLUMNS.CREATED_BY' | translate}}"
|
||||||
key="createdByUser.displayName"
|
key="createdByUser.displayName"
|
||||||
@ -89,6 +92,7 @@ import {
|
|||||||
class="desktop-only">
|
class="desktop-only">
|
||||||
</content-column>
|
</content-column>
|
||||||
</content-columns>
|
</content-columns>
|
||||||
|
|
||||||
<content-actions>
|
<content-actions>
|
||||||
<!-- folder actions -->
|
<!-- folder actions -->
|
||||||
<content-action
|
<content-action
|
||||||
@ -106,7 +110,6 @@ import {
|
|||||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.DELETE' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.DELETE' | translate}}"
|
||||||
handler="delete">
|
handler="delete">
|
||||||
</content-action>
|
</content-action>
|
||||||
|
|
||||||
<!-- document actions -->
|
<!-- document actions -->
|
||||||
<content-action
|
<content-action
|
||||||
target="document"
|
target="document"
|
||||||
@ -128,10 +131,14 @@ import {
|
|||||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DELETE' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DELETE' | translate}}"
|
||||||
handler="delete">
|
handler="delete">
|
||||||
</content-action>
|
</content-action>
|
||||||
|
<content-action
|
||||||
|
target="folder"
|
||||||
|
title="Activiti: View Form"
|
||||||
|
(execute)="viewActivitiForm($event)">
|
||||||
|
</content-action>
|
||||||
</content-actions>
|
</content-actions>
|
||||||
</alfresco-document-list>
|
</alfresco-document-list>
|
||||||
<context-menu-holder></context-menu-holder>
|
<context-menu-holder></context-menu-holder>
|
||||||
</div>
|
|
||||||
`,
|
`,
|
||||||
styles: [':host > .container {padding: 10px}'],
|
styles: [':host > .container {padding: 10px}'],
|
||||||
directives: [DOCUMENT_LIST_DIRECTIVES, CONTEXT_MENU_DIRECTIVES],
|
directives: [DOCUMENT_LIST_DIRECTIVES, CONTEXT_MENU_DIRECTIVES],
|
||||||
@ -141,28 +148,27 @@ import {
|
|||||||
class DocumentListDemo implements OnInit {
|
class DocumentListDemo implements OnInit {
|
||||||
|
|
||||||
currentPath: string = '/';
|
currentPath: string = '/';
|
||||||
authenticated: boolean;
|
authenticated: boolean = false;
|
||||||
|
|
||||||
ecmHost: string = 'http://devproducts-platform.alfresco.me';
|
ecmHost: string = 'http://devproducts-platform.alfresco.me';
|
||||||
|
|
||||||
token: string;
|
ticket: string;
|
||||||
|
|
||||||
constructor(
|
constructor(private authService: AlfrescoAuthenticationService, private settingsService: AlfrescoSettingsService,
|
||||||
private authService: AlfrescoAuthenticationService,
|
translation: AlfrescoTranslationService, private documentActions: DocumentActionsService) {
|
||||||
private settingsService: AlfrescoSettingsService,
|
|
||||||
translation: AlfrescoTranslationService,
|
|
||||||
private documentActions: DocumentActionsService) {
|
|
||||||
|
|
||||||
settingsService.ecmHost = this.ecmHost;
|
settingsService.ecmHost = this.ecmHost;
|
||||||
if (this.authService.getTicket()) {
|
settingsService.setProviders('ECM');
|
||||||
this.token = this.authService.getTicket();
|
|
||||||
|
if (this.authService.getTicketEcm()) {
|
||||||
|
this.ticket = this.authService.getTicketEcm();
|
||||||
}
|
}
|
||||||
|
|
||||||
translation.addTranslationFolder();
|
translation.addTranslationFolder();
|
||||||
documentActions.setHandler('my-handler', this.myDocumentActionHandler.bind(this));
|
documentActions.setHandler('my-handler', this.myDocumentActionHandler.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateToken(): void {
|
public updateTicket(): void {
|
||||||
localStorage.setItem('token', this.token);
|
localStorage.setItem('ticket-ECM', this.ticket);
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateHost(): void {
|
public updateHost(): void {
|
||||||
@ -190,9 +196,9 @@ class DocumentListDemo implements OnInit {
|
|||||||
|
|
||||||
login() {
|
login() {
|
||||||
this.authService.login('admin', 'admin').subscribe(
|
this.authService.login('admin', 'admin').subscribe(
|
||||||
token => {
|
ticket => {
|
||||||
console.log(token);
|
console.log(ticket);
|
||||||
this.token = token;
|
this.ticket = this.authService.getTicketEcm();
|
||||||
this.authenticated = true;
|
this.authenticated = true;
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
|
@ -72,7 +72,7 @@ module.exports = function (config) {
|
|||||||
],
|
],
|
||||||
|
|
||||||
// Coverage reporter generates the coverage
|
// Coverage reporter generates the coverage
|
||||||
reporters: ['mocha', 'coverage', 'coveralls', 'kjhtml'],
|
reporters: ['mocha', 'coverage', 'kjhtml'],
|
||||||
|
|
||||||
// Source files that you wanna generate coverage for.
|
// Source files that you wanna generate coverage for.
|
||||||
// Do not include tests or libraries (these files will be instrumented by Istanbul)
|
// Do not include tests or libraries (these files will be instrumented by Istanbul)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ng2-alfresco-documentlist",
|
"name": "ng2-alfresco-documentlist",
|
||||||
"description": "Alfresco Angular2 Document List Component",
|
"description": "Alfresco Angular2 Document List Component",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"author": "Alfresco Software, Ltd.",
|
"author": "Alfresco Software, Ltd.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "typings install",
|
"postinstall": "typings install",
|
||||||
@ -70,8 +70,8 @@
|
|||||||
"rxjs": "5.0.0-beta.6",
|
"rxjs": "5.0.0-beta.6",
|
||||||
"zone.js": "0.6.12",
|
"zone.js": "0.6.12",
|
||||||
"ng2-translate": "2.2.2",
|
"ng2-translate": "2.2.2",
|
||||||
"ng2-alfresco-core": "0.2.0",
|
"ng2-alfresco-core": "0.3.0",
|
||||||
"ng2-alfresco-datatable": "0.2.0",
|
"ng2-alfresco-datatable": "0.3.0",
|
||||||
"alfresco-js-api": "^0.3.0"
|
"alfresco-js-api": "^0.3.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
.document-list_empty_template {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.document-list__this-space-is-empty {
|
||||||
|
height: 32px;
|
||||||
|
opacity: 0.26;
|
||||||
|
font-family: Muli, Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 1.33;
|
||||||
|
letter-spacing: -1px;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.document-list__drag-drop {
|
||||||
|
height: 56px;
|
||||||
|
opacity: 0.54;
|
||||||
|
font-family: Muli, Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 56px;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: -2px;
|
||||||
|
color: #000000;
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.document-list__any-files-here-to-add {
|
||||||
|
height: 24px;
|
||||||
|
opacity: 0.54;
|
||||||
|
font-family: Muli, Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.5;
|
||||||
|
letter-spacing: -0.4px;
|
||||||
|
color: #000000;
|
||||||
|
margin-top: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.document-list__empty_doc_lib {
|
||||||
|
width: 565px;
|
||||||
|
height: 161px;
|
||||||
|
object-fit: contain;
|
||||||
|
margin-top: 17px;
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
[data]="data"
|
[data]="data"
|
||||||
[actions]="contentActions"
|
[actions]="contentActions"
|
||||||
[multiselect]="multiselect"
|
[multiselect]="multiselect"
|
||||||
|
[fallbackThumbnail]="baseComponentPath + '/img/ft_ic_miscellaneous.svg'"
|
||||||
(showRowContextMenu)="onShowRowContextMenu($event)"
|
(showRowContextMenu)="onShowRowContextMenu($event)"
|
||||||
(showRowActionsMenu)="onShowRowActionsMenu($event)"
|
(showRowActionsMenu)="onShowRowActionsMenu($event)"
|
||||||
(executeRowAction)="onExecuteRowAction($event)"
|
(executeRowAction)="onExecuteRowAction($event)"
|
||||||
@ -9,7 +10,12 @@
|
|||||||
(rowDblClick)="onRowDblClick($event)">
|
(rowDblClick)="onRowDblClick($event)">
|
||||||
<no-content-template>
|
<no-content-template>
|
||||||
<template>
|
<template>
|
||||||
<img [src]="baseComponentPath + '/img/document-list.empty-folder.png'">
|
<div class="document-list_empty_template">
|
||||||
|
<div class="document-list__this-space-is-empty">This folder is empty</div>
|
||||||
|
<div class="document-list__drag-drop">Drag and Drop</div>
|
||||||
|
<div class="document-list__any-files-here-to-add">any files here to add</div>
|
||||||
|
<img [src]="baseComponentPath + '/img/empty_doc_lib.svg'" class="document-list__empty_doc_lib">
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</no-content-template>
|
</no-content-template>
|
||||||
</alfresco-datatable>
|
</alfresco-datatable>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user