mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-3538] [ADF-3547] Migration - Task Filters - Task List - New Process cloud page on demoshell (#3914)
* [ADF-3538] start creating new folder for cloud components * [ADF-3538] added new package to the script and the builds * [ADF-3538] added some more changes to scripts * [ADF-3538] - starting the new package * change index * fix package * Fix module structure with Cli * add basic structure * Create a library with angular cli * Add a cloud component as example * Skip the scss style * add the import scss * remove useless codes * Add i18n example * remove useless code * Simplify the hello component Fix the wrong path * add the app-list-cloud-component add the app-details-cloud-component * Expose and use the new component * Consume the new package and component from the demoshell * Fix process service cloud path * [ADF-3538] Alfresco Process Service Cloud - new package with CLI (#3872) * [ADF-3538] start creating new folder for cloud components * [ADF-3538] added new package to the script and the builds * [ADF-3538] added some more changes to scripts * [ADF-3538] - starting the new package * change index * fix package * Fix module structure with Cli * add basic structure * Create a library with angular cli * Add a cloud component as example * Skip the scss style * add the import scss * remove useless codes * Add i18n example * remove useless code * Simplify the hello component Fix the wrong path * Fix process service cloud path * Download process-service-cloud from the CS * [ADF-3538] generated task-list cloud by cli * [ADF-3550] Added Task Filter Cloud component * [ADF-3550] Task Filter Cloud component relocated * [ADF-3538] rebased task list cloud 2.0 * [ADF-3538] fixed ng-package.json * [ADF-3538] reverted worng changes * [ADF-3538] removed wrong rebased files * [ADF-3538] forcing update of app-list file * [ADF-3538] wrong file after rebase removed * [ADF-3538] wrong file after rebase fixe * Merge the applist component with task list * [ADF-3550] Added Task Filter Cloud component * emit the event * Add the route process cloud and fix the page issues * fixed wrong pagination initialisation * improved initialisation of page size * removed unused import * fixed tsconfig with double definition * Use standard name for scss * fix sorting issue and remove useless models * Fix tslint * Use 1 single testing module file * [ADF-3538] [ADF-3547] Fix selected task filter and unit tests * Fix unit tests and remove useless imports * Uncomment unit tests * Remove useless component * Use main module instead of submodules * Remove useless jsdoc and improve doc * Remove useless jsdoc * Remove useless interface * remove AfterViewInit import * remove js doc params
This commit is contained in:
committed by
Eugenio Romano
parent
ee7af9d797
commit
38f4916e06
@@ -61,6 +61,7 @@
|
||||
"NOTIFICATIONS": "Notifications",
|
||||
"TASK_LIST": "Task List",
|
||||
"PROCESS_LIST": "Process List",
|
||||
"PROCESS_CLOUD": "Process Cloud",
|
||||
"CARD_VIEW": "CardView",
|
||||
"PROCESS_SERVICES": "Process Services",
|
||||
"LOGIN": "Login",
|
||||
|
@@ -63,8 +63,9 @@ import { ContentModule } from '@alfresco/adf-content-services';
|
||||
import { InsightsModule } from '@alfresco/adf-insights';
|
||||
import { ProcessModule } from '@alfresco/adf-process-services';
|
||||
import { AuthBearerInterceptor } from './services';
|
||||
import { AppListCloudModule } from '@alfresco/adf-process-services-cloud';
|
||||
import { ProcessServicesCloudModule } from '@alfresco/adf-process-services-cloud';
|
||||
import { CloudComponent } from './components/cloud/cloud.component';
|
||||
import { TaskListCloudDemoComponent } from './components/task-list-cloud-demo/task-list-cloud-demo.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -83,7 +84,7 @@ import { CloudComponent } from './components/cloud/cloud.component';
|
||||
ThemePickerModule,
|
||||
ChartsModule,
|
||||
MonacoEditorModule.forRoot(),
|
||||
AppListCloudModule
|
||||
ProcessServicesCloudModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
@@ -113,7 +114,8 @@ import { CloudComponent } from './components/cloud/cloud.component';
|
||||
FormLoadingComponent,
|
||||
DemoPermissionComponent,
|
||||
FormLoadingComponent,
|
||||
ReportIssueComponent
|
||||
ReportIssueComponent,
|
||||
TaskListCloudDemoComponent
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
|
@@ -41,6 +41,7 @@ import { DemoPermissionComponent } from './components/permissions/demo-permissio
|
||||
import { ReportIssueComponent } from './components/report-issue/report-issue.component';
|
||||
import { AppComponent } from './app.component';
|
||||
import { CloudComponent } from './components/cloud/cloud.component';
|
||||
import { TaskListCloudDemoComponent } from './components/task-list-cloud-demo/task-list-cloud-demo.component';
|
||||
|
||||
export const appRoutes: Routes = [
|
||||
{ path: 'login', component: LoginComponent },
|
||||
@@ -135,8 +136,17 @@ export const appRoutes: Routes = [
|
||||
},
|
||||
{
|
||||
path: 'cloud',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: CloudComponent
|
||||
},
|
||||
{
|
||||
path: ':applicationName/tasks',
|
||||
component: TaskListCloudDemoComponent
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'node-selector',
|
||||
loadChildren: 'app/components/content-node-selector/content-node-selector.module#AppContentNodeSelectorModule'
|
||||
|
@@ -40,6 +40,7 @@ export class AppLayoutComponent implements OnInit {
|
||||
{ href: '/node-selector', icon: 'attachment', title: 'APP_LAYOUT.NODE-SELECTOR' },
|
||||
{ href: '/task-list', icon: 'assignment', title: 'APP_LAYOUT.TASK_LIST' },
|
||||
{ href: '/process-list', icon: 'assignment', title: 'APP_LAYOUT.PROCESS_LIST' },
|
||||
{ href: '/cloud', icon: 'cloud', title: 'APP_LAYOUT.PROCESS_CLOUD' },
|
||||
{ href: '/activiti', icon: 'device_hub', title: 'APP_LAYOUT.PROCESS_SERVICES' },
|
||||
{ href: '/login', icon: 'vpn_key', title: 'APP_LAYOUT.LOGIN' },
|
||||
{ href: '/trashcan', icon: 'delete', title: 'APP_LAYOUT.TRASHCAN' },
|
||||
|
@@ -1,2 +1,2 @@
|
||||
|
||||
<adf-cloud-app-list></adf-cloud-app-list>
|
||||
<adf-cloud-app-list (appClick)="onAppClick($event)"></adf-cloud-app-list>
|
||||
|
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { Router } from '@angular/router';
|
||||
@Component({
|
||||
selector: 'app-cloud',
|
||||
templateUrl: './cloud.component.html',
|
||||
@@ -24,9 +24,13 @@ import { Component, OnInit } from '@angular/core';
|
||||
})
|
||||
export class CloudComponent implements OnInit {
|
||||
|
||||
constructor() {
|
||||
constructor(private router: Router) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
onAppClick(app) {
|
||||
this.router.navigate([`/cloud/${app.name}/tasks/`]);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,86 @@
|
||||
<h2>TASK LIST CLOUD DEMO</h2>
|
||||
<adf-cloud-task-filters
|
||||
[appName]="'my-app'"
|
||||
[showIcons]="true"
|
||||
(filterClick)="onFilterSelected($event)">
|
||||
</adf-cloud-task-filters>
|
||||
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
{{filterName}}
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
Customise your filter
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<div class="task-cloud-demo-select">
|
||||
<mat-form-field style="margin: 8px;">
|
||||
<mat-select placeholder="Status" [(ngModel)]="status">
|
||||
<mat-option value="">
|
||||
ALL
|
||||
</mat-option>
|
||||
<mat-option value="CREATED">
|
||||
CREATED
|
||||
</mat-option>
|
||||
<mat-option value="CANCELLED">
|
||||
CANCELLED
|
||||
</mat-option>
|
||||
<mat-option value="ASSIGNED">
|
||||
ASSIGNED
|
||||
</mat-option>
|
||||
<mat-option value="SUSPENDED">
|
||||
SUSPENDED
|
||||
</mat-option>
|
||||
<mat-option value="COMPLETED">
|
||||
COMPLETED
|
||||
</mat-option>
|
||||
<mat-option value="DELETED">
|
||||
DELETED
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-select [formControl]="sortFormControl">
|
||||
<mat-option [value]="''">Select a column</mat-option>
|
||||
<mat-option *ngFor="let column of columns" [value]="column.key">
|
||||
{{column.label}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-select [formControl]="sortDirectionFormControl">
|
||||
<mat-option [value]="''">Select a direction</mat-option>
|
||||
<mat-option value="ASC">
|
||||
ASC
|
||||
</mat-option>
|
||||
<mat-option value="DESC">
|
||||
DESC
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
<div>
|
||||
<adf-cloud-task-list *ngIf="isFilterLoaded" #taskCloud
|
||||
[applicationName]="applicationName"
|
||||
[status]="status"
|
||||
[landingTaskId]="selectTask"
|
||||
[sorting]="sortArray"
|
||||
(rowClick)="onRowClick($event)">
|
||||
<data-columns>
|
||||
<data-column key="entry.id" title="Id"></data-column>
|
||||
<data-column key="entry.name" title="Name"></data-column>
|
||||
<data-column key="entry.status" title="Status"></data-column>
|
||||
<data-column key="entry.processDefinitionId" title="Process Definition Id"></data-column>
|
||||
<data-column key="entry.priority" title="Priority"></data-column>
|
||||
<data-column key="entry.createdDate" title="Created Date"></data-column>
|
||||
</data-columns>
|
||||
</adf-cloud-task-list>
|
||||
<adf-pagination [target]="taskCloud"
|
||||
(changePageSize)="onChangePageSize($event)">
|
||||
</adf-pagination>
|
||||
</div>
|
@@ -0,0 +1,15 @@
|
||||
.task-cloud-demo-select {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.task-cloud-demo-select .mat-expansion-panel-body {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.app-task-list-cloud-demo-selection{
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.task-row-clicked {
|
||||
align-self: center;
|
||||
}
|
@@ -0,0 +1,126 @@
|
||||
/*!
|
||||
* @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, ViewChild, OnInit } from '@angular/core';
|
||||
import { TaskListCloudComponent, TaskListCloudSortingModel } from '@alfresco/adf-process-services-cloud';
|
||||
import { UserPreferencesService } from '@alfresco/adf-core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { FormControl } from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-task-list-cloud-demo',
|
||||
templateUrl: 'task-list-cloud-demo.component.html',
|
||||
styleUrls: ['task-list-cloud-demo.component.scss']
|
||||
})
|
||||
export class TaskListCloudDemoComponent implements OnInit {
|
||||
|
||||
@ViewChild('taskCloud')
|
||||
taskCloud: TaskListCloudComponent;
|
||||
|
||||
sortFormControl: FormControl;
|
||||
sortDirectionFormControl: FormControl;
|
||||
|
||||
appDefinitionList: Observable<any>;
|
||||
applicationName: string = '';
|
||||
status: string = '';
|
||||
sort: string = '';
|
||||
isFilterLoaded = false;
|
||||
sortDirection: string = 'ASC';
|
||||
filterName: string;
|
||||
clickedRow: string = '';
|
||||
selectTask: string = '';
|
||||
sortArray: TaskListCloudSortingModel [];
|
||||
|
||||
columns = [
|
||||
{key: 'id', label: 'ID'},
|
||||
{key: 'name', label: 'NAME'},
|
||||
{key: 'createdDate', label: 'Created Date'},
|
||||
{key: 'priority', label: 'PRIORITY'},
|
||||
{key: 'processDefinitionId', label: 'PROCESS DEFINITION ID'}
|
||||
];
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private userPreference: UserPreferencesService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.isFilterLoaded = false;
|
||||
this.route.params.subscribe(params => {
|
||||
this.applicationName = params.applicationName;
|
||||
});
|
||||
|
||||
this.sortFormControl = new FormControl('');
|
||||
|
||||
this.sortFormControl.valueChanges.subscribe(
|
||||
(sortValue) => {
|
||||
this.sort = sortValue;
|
||||
|
||||
this.sortArray = [{
|
||||
orderBy: this.sort,
|
||||
direction: this.sortDirection
|
||||
}];
|
||||
}
|
||||
);
|
||||
this.sortDirectionFormControl = new FormControl('');
|
||||
|
||||
this.sortDirectionFormControl.valueChanges.subscribe(
|
||||
(sortDirectionValue) => {
|
||||
this.sortDirection = sortDirectionValue;
|
||||
|
||||
this.sortArray = [{
|
||||
orderBy: this.sort,
|
||||
direction: this.sortDirection
|
||||
}];
|
||||
}
|
||||
);
|
||||
|
||||
this.route.queryParams
|
||||
.subscribe(params => {
|
||||
if (params.status) {
|
||||
this.status = params.status;
|
||||
this.sort = params.sort;
|
||||
this.sortDirection = params.order;
|
||||
this.filterName = params.filterName;
|
||||
this.isFilterLoaded = true;
|
||||
this.sortDirectionFormControl.setValue(this.sortDirection);
|
||||
this.sortFormControl.setValue(this.sort);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onFilterSelected(filter) {
|
||||
const queryParams = {
|
||||
status: filter.query.state,
|
||||
filterName: filter.name,
|
||||
sort: filter.query.sort,
|
||||
order: filter.query.order
|
||||
};
|
||||
this.router.navigate([`/cloud/${this.applicationName}/tasks/`], {queryParams: queryParams});
|
||||
}
|
||||
|
||||
onChangePageSize(event) {
|
||||
this.userPreference.paginationSize = event.maxItems;
|
||||
}
|
||||
|
||||
onRowClick($event) {
|
||||
this.clickedRow = $event;
|
||||
}
|
||||
|
||||
}
|
217
docs/process-services-cloud/task-list-cloud.md
Normal file
217
docs/process-services-cloud/task-list-cloud.md
Normal file
@@ -0,0 +1,217 @@
|
||||
---
|
||||
Added: v2.0.0
|
||||
Status: Active
|
||||
Last reviewed: 2018-04-16
|
||||
---
|
||||
|
||||
# Task List component
|
||||
|
||||
Renders a list containing all the tasks matched by the parameters specified.
|
||||
|
||||
## Contents
|
||||
|
||||
- [Basic Usage](#basic-usage)
|
||||
- [Transclusions](#transclusions)
|
||||
- [Class members](#class-members)
|
||||
- [Properties](#properties)
|
||||
- [Events](#events)
|
||||
- [Details](#details)
|
||||
- [Setting the column schema](#setting-the-column-schema)
|
||||
- [Setting Sorting Order for the list](#setting-sorting-order-for-the-list)
|
||||
- [Pagination strategy](#pagination-strategy)
|
||||
- [DataTableAdapter example](#datatableadapter-example)
|
||||
- [DataColumn Features](#datacolumn-features)
|
||||
- [See also](#see-also)
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```html
|
||||
<adf-cloud-task-list
|
||||
[applicationName]="'APPLICATION-NAME'" >
|
||||
</adf-cloud-task-list>
|
||||
```
|
||||
|
||||
### [Transclusions](../user-guide/transclusion.md)
|
||||
|
||||
Any content inside an `<adf-empty-custom-content>` sub-component will be shown
|
||||
when the task list is empty:
|
||||
|
||||
```html
|
||||
<adf-cloud-task-list>
|
||||
<adf-empty-custom-content>
|
||||
Your Content
|
||||
</adf-empty-custom-content>
|
||||
<adf-cloud-task-list>
|
||||
```
|
||||
|
||||
## Class members
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| applicationName | `string` | | The name of the application. |
|
||||
| assignee | `string` | | The assigee of the process. Possible values are: "assignee" (the current user is the assignee), candidate (the current user is a task candidate", "group_x" (the task is assigned to a group where the current user is a member, no value(the current user is involved). |
|
||||
| createdDate | `Date` | | filter the tasks for the date when the task should have been created |
|
||||
| dueDate | `Date` | | Filter the tasks. Display only tasks with dueDate equal to the one insterted. |
|
||||
| id | `string` | | Filter the tasks. Display only tasks with id equal to the one insterted. |
|
||||
| name | `string` | | Filter the tasks. Display only tasks with name equal to the one insterted. |
|
||||
| parentTaskId | `string` | | Filter the tasks. Display only tasks with parentTaskId equal to the one insterted. |
|
||||
| processDefinitionId | `string` | | Filter the tasks. Display only tasks with processDefinitionId equal to the one insterted. |
|
||||
| processInstanceId | `string` | | Filter the tasks. Display only tasks with processInstanceId equal to the one insterted. |
|
||||
| status | `string` | | Filter the tasks. Display only tasks with status equal to the one insterted. |
|
||||
| processDefinitionId | `string` | | Filter the tasks. Display only tasks with processDefinitionId equal to the one insterted. |
|
||||
| landingTaskId | `string` | | Define which task id should be selected after reloading. If the task id doesn't exist or nothing is passed then the first task will be selected. |
|
||||
| selectFirstRow | `boolean` | true | Toggles default selection of the first row |
|
||||
| selectionMode | `string` | "single" | Row selection mode. Can be none, `single` or `multiple`. For `multiple` mode, you can use Cmd (macOS) or Ctrl (Win) modifier key to toggle selection for multiple rows. |
|
||||
| multiselect | `boolean` | false | Toggles multiple row selection, renders checkboxes at the beginning of each row |
|
||||
| sorting | `[TaskListCloudSortingModel]` | | This array of `TaskListCloudSortingModel` specify how the sorting on our table should be provided. This parameters are for BE sorting. |
|
||||
|
||||
### Events
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| error | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when an error occurs. |
|
||||
| rowClick | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<string>` | Emitted when a task in the list is clicked |
|
||||
| rowsSelected | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any[]>` | Emitted when rows are selected/unselected |
|
||||
| success | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when the task list is loaded |
|
||||
|
||||
## Details
|
||||
|
||||
This component displays lists of tasks related to the application name insterted. Extra filtering can be provided by applying extra input parameters
|
||||
|
||||
### Setting the column schema
|
||||
|
||||
You can use an HTML-based schema declaration to set a column schema for the tasklist as shown below :
|
||||
|
||||
```html
|
||||
<adf-cloud-task-list ...>
|
||||
<data-columns>
|
||||
<data-column key="name" title="NAME" class="full-width name-column"></data-column>
|
||||
<data-column key="created" title="Created" class="hidden"></data-column>
|
||||
</data-columns>
|
||||
</adf-cloud-task-list>
|
||||
```
|
||||
|
||||
You can also set a static custom schema declaration in `app.config.json` as shown below:
|
||||
|
||||
```json
|
||||
"adf-cloud-task-list": {
|
||||
"presets": {
|
||||
"customSchema": [
|
||||
{
|
||||
"key": "name",
|
||||
"type": "text",
|
||||
"title": "name",
|
||||
"sortable": true
|
||||
}],
|
||||
"default": [
|
||||
{
|
||||
"key": "name",
|
||||
"type": "text",
|
||||
"title": "name",
|
||||
"sortable": true
|
||||
}],
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```html
|
||||
<adf-cloud-task-list
|
||||
[appId]="'1'"
|
||||
[presetColumn]="'customSchema'">
|
||||
</adf-cloud-task-list>
|
||||
```
|
||||
|
||||
You can use an HTML-based schema and an `app.config.json` custom schema declaration at the same time:
|
||||
|
||||
```json
|
||||
"adf-cloud-task-list": {
|
||||
"presets": {
|
||||
"customSchema": [
|
||||
{
|
||||
"key": "id",
|
||||
"type": "text",
|
||||
"title": "Id",
|
||||
"sortable": true
|
||||
}],
|
||||
"default": [
|
||||
{
|
||||
"key": "name",
|
||||
"type": "text",
|
||||
"title": "name",
|
||||
"sortable": true
|
||||
}],
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!-- {% raw %} -->
|
||||
|
||||
```html
|
||||
<adf-cloud-task-list
|
||||
[applicationName]="'ApplicationName'">
|
||||
<data-columns>
|
||||
<data-column key="assignee" title="Assignee" class="full-width name-column">
|
||||
<ng-template let-entry="$implicit">
|
||||
<div>{{getFullName(entry.row.obj.assignee)}}</div>
|
||||
</ng-template>
|
||||
</data-column>
|
||||
</data-columns>
|
||||
</adf-cloud-task-list>
|
||||
```
|
||||
|
||||
### Setting Sorting Order for the list
|
||||
|
||||
you can pass sorting order as shown in the example below:
|
||||
|
||||
```ts
|
||||
let sorting = { orderBy: 'created', direction: 'desc' };
|
||||
```
|
||||
|
||||
```html
|
||||
<adf-cloud-task-list
|
||||
[appId]="'1'"
|
||||
[sorting]="[sorting]">
|
||||
</adf-cloud-task-list>
|
||||
```
|
||||
|
||||
<!-- {% endraw %} -->
|
||||
|
||||
### Pagination strategy
|
||||
|
||||
The Tasklist also supports pagination as shown in the example below:
|
||||
|
||||
```html
|
||||
<adf-cloud-task-list #taskCloud
|
||||
[applicationName]="'APPLICATION-NAME'">
|
||||
</adf-cloud-task-list>
|
||||
<adf-pagination [target]="taskCloud"
|
||||
(changePageSize)="onChangePageSize($event)">
|
||||
</adf-pagination>
|
||||
```
|
||||
|
||||
### DataTableAdapter example
|
||||
|
||||
See the [`DataTableAdapter`](../../lib/core/datatable/data/datatable-adapter.ts) page for full details of the interface and its standard
|
||||
implementation, [`ObjectDataTableAdapter`](../../lib/core/datatable/data/object-datatable-adapter.ts). Below is an example of how you can set up the adapter for a
|
||||
typical tasklist.
|
||||
|
||||
```json
|
||||
[
|
||||
{"type": "text", "key": "id", "title": "Id"},
|
||||
{"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}
|
||||
]
|
||||
```
|
||||
|
||||
### DataColumn Features
|
||||
|
||||
You can customize the styling of a column and also add features like tooltips and automatic translation of column titles. See the [`DataColumn`](../../lib/core/datatable/data/data-column.model.ts) page for more information about these features.
|
||||
|
||||
## See also
|
||||
|
||||
- [Data column component](../core/data-column.component.md)
|
||||
- [`DataTableAdapter`](../../lib/core/datatable/data/datatable-adapter.ts)
|
||||
- [Pagination component](../core/pagination.component.md)
|
19
lib/core/assets/images/ft_ic_link_folder.svg
Normal file
19
lib/core/assets/images/ft_ic_link_folder.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="20px" height="16px" viewBox="0 0 20 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>System Icon Links</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Style" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="icons" transform="translate(-289.000000, -4488.000000)">
|
||||
<g id="File" transform="translate(140.000000, 4130.000000)">
|
||||
<g id="Icon-Links-Folder" transform="translate(120.000000, 328.000000)">
|
||||
<g id="System-Icon-Links" transform="translate(28.000000, 30.000000)">
|
||||
<path d="M1.70933755,0.543276016 L1,1.924926 L1,14.8121399 L1.69466158,15.5150573 L1.69466158,15.5150573 C1.88252616,15.7051546 2.13866895,15.8121399 2.40593302,15.8121399 L19.6045166,15.8121399 L20.3116234,15.1050331 L20.3116234,15.1050331 C20.4991598,14.9174967 20.6045166,14.6631428 20.6045166,14.3979263 L20.6045166,3.00924449 L19.9015261,2.24697884 L19.9015261,2.24697884 C19.7122055,2.04169503 19.4456711,1.924926 19.1664154,1.924926 L10.1733882,1.924926 L10.1733882,1.924926 C9.85108856,1.924926 9.548546,1.76958526 9.36072924,1.50766556 L8.57882415,0.417260445 L8.57882415,0.417260445 C8.39100739,0.155340737 8.08846483,-6.31724684e-16 7.76616517,0 L2.59894601,0 L2.59894601,-1.11022302e-16 C2.2240117,-4.21479881e-17 1.88057904,0.209731289 1.70933755,0.543276016 Z" id="Path-2-Copy" fill="#000000" opacity="0.54"></path>
|
||||
<path d="M10,6 L7.6,6 L7.6,7.14 L10,7.14 C11.026,7.14 11.86,7.974 11.86,9 C11.86,10.026 11.026,10.86 10,10.86 L7.6,10.86 L7.6,12 L10,12 C11.656,12 13,10.656 13,9 C13,7.344 11.656,6 10,6 L10,6 Z M4.6,9.6 L9.4,9.6 L9.4,8.4 L4.6,8.4 L4.6,9.6 Z M2.14,9 C2.14,7.974 2.974,7.14 4,7.14 L6.4,7.14 L6.4,6 L4,6 C2.344,6 1,7.344 1,9 C1,10.656 2.344,12 4,12 L6.4,12 L6.4,10.86 L4,10.86 C2.974,10.86 2.14,10.026 2.14,9 L2.14,9 Z" id="Fill-2" fill="#FFFFFF" transform="translate(7.000000, 9.000000) rotate(-45.000000) translate(-7.000000, -9.000000) "></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
@@ -18,5 +18,6 @@
|
||||
export * from './context-menu-holder.component';
|
||||
export * from './context-menu.directive';
|
||||
export * from './context-menu.service';
|
||||
export * from './context-menu-overlay.service';
|
||||
|
||||
export * from './context-menu.module';
|
||||
|
@@ -1,30 +0,0 @@
|
||||
npm-debug.log
|
||||
.idea
|
||||
.npmrc
|
||||
|
||||
/.editorconfig
|
||||
/.travis.yml
|
||||
/*.json
|
||||
/karma-test-shim.js
|
||||
/karma.conf.js
|
||||
/gulpfile.ts
|
||||
/.npmignore
|
||||
/.happypack
|
||||
**/*.html
|
||||
**/*.js
|
||||
**/*.ts
|
||||
!**/*.d.ts
|
||||
!**/adf-process-services-cloud.js
|
||||
|
||||
**/*.scss
|
||||
**/*.css
|
||||
!**/_theming.scss
|
||||
|
||||
coverage/
|
||||
demo/
|
||||
dist/
|
||||
node_modules
|
||||
typings/
|
||||
fonts/
|
||||
i18n/
|
||||
assets/
|
@@ -15,4 +15,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './src/public_api';
|
||||
export * from './src/public-api';
|
||||
|
@@ -1,44 +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 { NgModule } from '@angular/core';
|
||||
import {
|
||||
MAT_LABEL_GLOBAL_OPTIONS, MatAutocompleteModule, MatButtonModule, MatCardModule, MatCheckboxModule,
|
||||
MatChipsModule, MatDatepickerModule, MatDialogModule, MatGridListModule, MatIconModule,
|
||||
MatInputModule, MatListModule, MatNativeDateModule, MatOptionModule, MatProgressSpinnerModule, MatRadioModule,
|
||||
MatRippleModule, MatSelectModule, MatSlideToggleModule, MatTableModule, MatTabsModule,
|
||||
MatTooltipModule, MatMenuModule
|
||||
} from '@angular/material';
|
||||
|
||||
export function modules() {
|
||||
return [
|
||||
MatAutocompleteModule, MatButtonModule, MatCardModule, MatDialogModule,
|
||||
MatCheckboxModule, MatDatepickerModule, MatGridListModule, MatIconModule, MatInputModule,
|
||||
MatListModule, MatOptionModule, MatRadioModule, MatSelectModule, MatSlideToggleModule, MatTableModule,
|
||||
MatTabsModule, MatProgressSpinnerModule, MatNativeDateModule, MatRippleModule, MatTooltipModule,
|
||||
MatChipsModule, MatMenuModule
|
||||
];
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
{provide: MAT_LABEL_GLOBAL_OPTIONS, useValue: { float: 'never' }}
|
||||
],
|
||||
imports: modules(),
|
||||
exports: modules()
|
||||
})
|
||||
export class MaterialModule {}
|
@@ -3,7 +3,7 @@
|
||||
"dest": "../dist/process-services-cloud",
|
||||
"lib": {
|
||||
"languageLevel": ["dom", "es2017"],
|
||||
"entryFile": "src/public_api.ts",
|
||||
"entryFile": "src/public-api.ts",
|
||||
"flatModuleFile": "adf-process-services-cloud",
|
||||
"umdModuleIds": {
|
||||
"alfresco-js-api": "alfresco-js-api"
|
||||
|
@@ -1,99 +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 { CommonModule } from '@angular/common';
|
||||
import { NgModule, ModuleWithProviders } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { CoreModule, TRANSLATION_PROVIDER } from '@alfresco/adf-core';
|
||||
|
||||
import { MaterialModule } from './material.module';
|
||||
import { HelloCloudModule } from './hello/hello.module';
|
||||
|
||||
export function providers() {
|
||||
return [
|
||||
];
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CoreModule.forChild(),
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
MaterialModule,
|
||||
HelloCloudModule
|
||||
],
|
||||
providers: [
|
||||
...providers(),
|
||||
{
|
||||
provide: TRANSLATION_PROVIDER,
|
||||
multi: true,
|
||||
useValue: {
|
||||
name: 'adf-process-services-cloud',
|
||||
source: 'assets/adf-process-services-cloud'
|
||||
}
|
||||
}
|
||||
],
|
||||
exports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
HelloCloudModule
|
||||
]
|
||||
})
|
||||
export class ProcessCloudModule {
|
||||
static forRoot(): ModuleWithProviders {
|
||||
return {
|
||||
ngModule: ProcessCloudModule,
|
||||
providers: [
|
||||
...providers(),
|
||||
{
|
||||
provide: TRANSLATION_PROVIDER,
|
||||
multi: true,
|
||||
useValue: {
|
||||
name: 'adf-process-services-cloud',
|
||||
source: 'assets/adf-process-services-cloud'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
static forChild(): ModuleWithProviders {
|
||||
return {
|
||||
ngModule: ProcessCloudModuleLazy
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CoreModule.forChild(),
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
MaterialModule,
|
||||
HelloCloudModule
|
||||
],
|
||||
exports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
HelloCloudModule
|
||||
]
|
||||
})
|
||||
export class ProcessCloudModuleLazy {}
|
@@ -20,7 +20,8 @@ import { setupTestBed } from '@alfresco/adf-core';
|
||||
|
||||
import { fakeApplicationInstance } from '../mock/app-model.mock';
|
||||
import { AppDetailsCloudComponent } from './app-details-cloud.component';
|
||||
import { AppListTestingModule } from '../testing/app-list.testing.module';
|
||||
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
|
||||
import { AppListCloudModule } from '../app-list-cloud.module';
|
||||
|
||||
describe('AppDetailsCloudComponent', () => {
|
||||
|
||||
@@ -28,7 +29,7 @@ describe('AppDetailsCloudComponent', () => {
|
||||
let fixture: ComponentFixture<AppDetailsCloudComponent>;
|
||||
|
||||
setupTestBed({
|
||||
imports: [AppListTestingModule]
|
||||
imports: [ProcessServiceCloudTestingModule, AppListCloudModule]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
@@ -23,8 +23,9 @@ import { of } from 'rxjs';
|
||||
import { fakeApplicationInstance } from '../mock/app-model.mock';
|
||||
import { AppListCloudComponent } from './app-list-cloud.component';
|
||||
import { AppsProcessCloudService } from '../services/apps-process-cloud.service';
|
||||
import { AppListTestingModule } from '../testing/app-list.testing.module';
|
||||
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
|
||||
import { ApplicationInstanceModel } from '../models/application-instance.model';
|
||||
import { AppListCloudModule } from '../app-list-cloud.module';
|
||||
|
||||
describe('AppListCloudComponent', () => {
|
||||
|
||||
@@ -34,7 +35,7 @@ describe('AppListCloudComponent', () => {
|
||||
let getAppsSpy: jasmine.Spy;
|
||||
|
||||
setupTestBed({
|
||||
imports: [AppListTestingModule],
|
||||
imports: [ProcessServiceCloudTestingModule, AppListCloudModule],
|
||||
providers: [AppsProcessCloudService]
|
||||
});
|
||||
|
||||
@@ -184,7 +185,7 @@ describe('Custom CustomEmptyAppListCloudTemplateComponent', () => {
|
||||
let fixture: ComponentFixture<CustomEmptyAppListCloudTemplateComponent>;
|
||||
|
||||
setupTestBed({
|
||||
imports: [AppListTestingModule],
|
||||
imports: [ProcessServiceCloudTestingModule],
|
||||
declarations: [CustomEmptyAppListCloudTemplateComponent],
|
||||
schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
|
||||
});
|
||||
|
@@ -17,4 +17,4 @@
|
||||
|
||||
export * from './components/app-list-cloud.component';
|
||||
export * from './models/application-instance.model';
|
||||
export * from './apps-list-cloud.module';
|
||||
export * from './app-list-cloud.module';
|
@@ -22,14 +22,14 @@ import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { AppsProcessCloudService } from './apps-process-cloud.service';
|
||||
import { fakeApplicationInstance } from '../mock/app-model.mock';
|
||||
import { ApplicationInstanceModel } from '../models/application-instance.model';
|
||||
import { AppListTestingModule } from '../testing/app-list.testing.module';
|
||||
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
|
||||
|
||||
describe('AppsProcessCloudService', () => {
|
||||
|
||||
let service: AppsProcessCloudService;
|
||||
|
||||
setupTestBed({
|
||||
imports: [AppListTestingModule],
|
||||
imports: [ProcessServiceCloudTestingModule],
|
||||
providers: [AppsProcessCloudService]
|
||||
});
|
||||
|
||||
|
@@ -1,4 +0,0 @@
|
||||
<p>
|
||||
hello cloud world!
|
||||
</p>
|
||||
|
@@ -1,25 +0,0 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HelloComponent } from './hello.component';
|
||||
|
||||
describe('HelloComponent', () => {
|
||||
let component: HelloComponent;
|
||||
let fixture: ComponentFixture<HelloComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ HelloComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(HelloComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -1,15 +0,0 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-cloud-hello',
|
||||
templateUrl: './hello.component.html',
|
||||
styleUrls: ['./hello.component.css']
|
||||
})
|
||||
export class HelloComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
import { HelloModule } from './hello.module';
|
||||
|
||||
describe('HelloModule', () => {
|
||||
let helloModule: HelloModule;
|
||||
|
||||
beforeEach(() => {
|
||||
helloModule = new HelloModule();
|
||||
});
|
||||
|
||||
it('should create an instance', () => {
|
||||
expect(helloModule).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -1,13 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { HelloComponent } from './hello.component';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
TranslateModule
|
||||
],
|
||||
declarations: [HelloComponent],
|
||||
exports: [HelloComponent]
|
||||
})
|
||||
export class HelloModule { }
|
@@ -1,10 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { TRANSLATION_PROVIDER } from '@alfresco/adf-core';
|
||||
import { AppListCloudModule } from './app-list-cloud/app-list-cloud.module';
|
||||
import { TaskListCloudModule } from './task-list-cloud/task-list-cloud.module';
|
||||
import { TaskCloudModule } from './task-cloud/task-cloud.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
AppListCloudModule
|
||||
AppListCloudModule,
|
||||
TaskListCloudModule,
|
||||
TaskCloudModule
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
@@ -17,6 +21,6 @@ import { AppListCloudModule } from './app-list-cloud/app-list-cloud.module';
|
||||
}
|
||||
],
|
||||
declarations: [],
|
||||
exports: [AppListCloudModule]
|
||||
exports: [AppListCloudModule, TaskListCloudModule, TaskCloudModule]
|
||||
})
|
||||
export class ProcessServicesCloudModule { }
|
||||
|
@@ -1,7 +1,9 @@
|
||||
@import './../app-list-cloud/components/app-details-cloud.component';
|
||||
@import './../app-list-cloud/components/app-list-cloud.component';
|
||||
@import './../task-cloud/task-filters-cloud/task-filters-cloud.component.scss';
|
||||
|
||||
@mixin adf-process-services-cloud-theme($theme) {
|
||||
@include adf-cloud-app-list-theme($theme);
|
||||
@include adf-cloud-app-details-theme($theme);
|
||||
@include adf-cloud-task-filters-theme($theme);
|
||||
}
|
||||
|
@@ -0,0 +1,267 @@
|
||||
/*!
|
||||
* @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 { FilterRepresentationModel, AppDefinitionRepresentationModel } from '../models/filter-cloud.model';
|
||||
|
||||
export let fakeFilters = {
|
||||
size: 2, total: 2, start: 0,
|
||||
data: [
|
||||
new AppDefinitionRepresentationModel(
|
||||
{
|
||||
id: 1, name: 'FakeInvolvedTasks', recent: false, icon: 'glyphicon-align-left',
|
||||
filter: { sort: 'created-desc', name: '', state: 'open', assignment: 'fake-involved' }
|
||||
}
|
||||
),
|
||||
{
|
||||
id: 2, name: 'FakeMyTasks', recent: false, icon: 'glyphicon-align-left',
|
||||
filter: { sort: 'created-desc', name: '', state: 'open', assignment: 'fake-assignee' }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export let fakeAppFilter = {
|
||||
size: 1, total: 1, start: 0,
|
||||
data: [
|
||||
{
|
||||
id: 1, name: 'FakeInvolvedTasks', recent: false, icon: 'glyphicon-align-left',
|
||||
filter: { sort: 'created-desc', name: '', state: 'open', assignment: 'fake-involved' }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export let fakeApps = {
|
||||
size: 2, total: 2, start: 0,
|
||||
data: [
|
||||
{
|
||||
id: 1, defaultAppId: null, name: 'Sales-Fakes-App', description: 'desc-fake1', modelId: 22,
|
||||
theme: 'theme-1-fake', icon: 'glyphicon-asterisk', 'deploymentId': '111', 'tenantId': null
|
||||
},
|
||||
{
|
||||
id: 2, defaultAppId: null, name: 'health-care-Fake', description: 'desc-fake2', modelId: 33,
|
||||
theme: 'theme-2-fake', icon: 'glyphicon-asterisk', 'deploymentId': '444', 'tenantId': null
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export let fakeFilter = {
|
||||
sort: 'created-desc', text: '', state: 'open', assignment: 'fake-assignee'
|
||||
};
|
||||
|
||||
export let fakeUser1 = { id: 1, email: 'fake-email@dom.com', firstName: 'firstName', lastName: 'lastName' };
|
||||
|
||||
export let fakeUser2 = { id: 1001, email: 'some-one@somegroup.com', firstName: 'some', lastName: 'one' };
|
||||
|
||||
export let fakeTaskList = {
|
||||
size: 1, total: 1, start: 0,
|
||||
data: [
|
||||
{
|
||||
id: '1', name: 'FakeNameTask', description: null, category: null,
|
||||
assignee: fakeUser1,
|
||||
created: '2016-07-15T11:19:17.440+0000'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export let fakeTaskListDifferentProcessDefinitionKey = {
|
||||
size: 2, total: 1, start: 0,
|
||||
data: [
|
||||
{
|
||||
id: '1', name: 'FakeNameTask', description: null, category: null,
|
||||
assignee: fakeUser1,
|
||||
processDefinitionKey: '1',
|
||||
created: '2016-07-15T11:19:17.440+0000'
|
||||
},
|
||||
{
|
||||
id: '2', name: 'FakeNameTask2', description: null, category: null,
|
||||
assignee: fakeUser1,
|
||||
processDefinitionKey: '2',
|
||||
created: '2016-07-15T11:19:17.440+0000'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export let secondFakeTaskList = {
|
||||
size: 1, total: 1, start: 0,
|
||||
data: [
|
||||
{
|
||||
id: '200', name: 'FakeNameTask', description: null, category: null,
|
||||
assignee: fakeUser1,
|
||||
created: '2016-07-15T11:19:17.440+0000'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export let mockErrorTaskList = {
|
||||
error: 'wrong request'
|
||||
};
|
||||
|
||||
export let fakeTaskDetails = { id: '999', name: 'fake-task-name', formKey: '99', assignee: fakeUser1 };
|
||||
|
||||
export let fakeTasksComment = {
|
||||
size: 2, total: 2, start: 0,
|
||||
data: [
|
||||
{
|
||||
id: 1, message: 'fake-message-1', created: '', createdBy: fakeUser1
|
||||
},
|
||||
{
|
||||
id: 2, message: 'fake-message-2', created: '', createdBy: fakeUser1
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export let fakeTasksChecklist = {
|
||||
size: 1, total: 1, start: 0,
|
||||
data: [
|
||||
{
|
||||
id: 1, name: 'FakeCheckTask1', description: null, category: null,
|
||||
assignee: fakeUser1,
|
||||
created: '2016-07-15T11:19:17.440+0000'
|
||||
},
|
||||
{
|
||||
id: 2, name: 'FakeCheckTask2', description: null, category: null,
|
||||
assignee: fakeUser1,
|
||||
created: '2016-07-15T11:19:17.440+0000'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export let fakeRepresentationFilter1: FilterRepresentationModel = new FilterRepresentationModel({
|
||||
appId: 1,
|
||||
name: 'CONTAIN FILTER',
|
||||
recent: true,
|
||||
icon: 'glyphicon-align-left',
|
||||
filter: {
|
||||
processDefinitionId: null,
|
||||
processDefinitionKey: null,
|
||||
name: null,
|
||||
state: 'open',
|
||||
sort: 'created-desc',
|
||||
assignment: 'involved',
|
||||
dueAfter: null,
|
||||
dueBefore: null
|
||||
}
|
||||
});
|
||||
|
||||
export let fakeRepresentationFilter2: FilterRepresentationModel = new FilterRepresentationModel({
|
||||
appId: 2,
|
||||
name: 'NO TASK FILTER',
|
||||
recent: false,
|
||||
icon: 'glyphicon-inbox',
|
||||
filter: {
|
||||
processDefinitionId: null,
|
||||
processDefinitionKey: null,
|
||||
name: null,
|
||||
state: 'open',
|
||||
sort: 'created-desc',
|
||||
assignment: 'assignee',
|
||||
dueAfter: null,
|
||||
dueBefore: null
|
||||
}
|
||||
});
|
||||
|
||||
export let fakeAppPromise = new Promise(function (resolve, reject) {
|
||||
resolve(fakeAppFilter);
|
||||
});
|
||||
|
||||
export let fakeFormList = {
|
||||
size: 2,
|
||||
total: 2,
|
||||
start: 0,
|
||||
data: [{
|
||||
id: 1,
|
||||
name: 'form with all widgets',
|
||||
description: '',
|
||||
createdBy: 2,
|
||||
createdByFullName: 'Admin Admin',
|
||||
lastUpdatedBy: 2,
|
||||
lastUpdatedByFullName: 'Admin Admin',
|
||||
lastUpdated: 1491400951205,
|
||||
latestVersion: true,
|
||||
version: 4,
|
||||
comment: null,
|
||||
stencilSet: null,
|
||||
referenceId: null,
|
||||
modelType: 2,
|
||||
favorite: null,
|
||||
permission: 'write',
|
||||
tenantId: null
|
||||
}, {
|
||||
id: 2,
|
||||
name: 'uppy',
|
||||
description: '',
|
||||
createdBy: 2,
|
||||
createdByFullName: 'Admin Admin',
|
||||
lastUpdatedBy: 2,
|
||||
lastUpdatedByFullName: 'Admin Admin',
|
||||
lastUpdated: 1490951054477,
|
||||
latestVersion: true,
|
||||
version: 2,
|
||||
comment: null,
|
||||
stencilSet: null,
|
||||
referenceId: null,
|
||||
modelType: 2,
|
||||
favorite: null,
|
||||
permission: 'write',
|
||||
tenantId: null
|
||||
}]
|
||||
};
|
||||
|
||||
export let fakeTaskOpen1 = {
|
||||
id: '1', name: 'FakeOpenTask1', description: null, category: null,
|
||||
assignee: fakeUser1,
|
||||
created: '2017-07-15T11:19:17.440+0000',
|
||||
dueDate: null,
|
||||
endDate: null
|
||||
};
|
||||
|
||||
export let fakeTaskOpen2 = {
|
||||
id: '1', name: 'FakeOpenTask2', description: null, category: null,
|
||||
assignee: { id: 1, email: 'fake-open-email@dom.com', firstName: 'firstName', lastName: 'lastName' },
|
||||
created: '2017-07-15T11:19:17.440+0000',
|
||||
dueDate: null,
|
||||
endDate: null
|
||||
};
|
||||
|
||||
export let fakeTaskCompleted1 = {
|
||||
id: '1', name: 'FakeCompletedTaskName1', description: null, category: null,
|
||||
assignee: { id: 1, email: 'fake-completed-email@dom.com', firstName: 'firstName', lastName: 'lastName' },
|
||||
created: '2016-07-15T11:19:17.440+0000',
|
||||
dueDate: null,
|
||||
endDate: '2016-11-03T15:25:42.749+0000'
|
||||
};
|
||||
|
||||
export let fakeTaskCompleted2 = {
|
||||
id: '1', name: 'FakeCompletedTaskName2', description: null, category: null,
|
||||
assignee: fakeUser1,
|
||||
created: null,
|
||||
dueDate: null,
|
||||
endDate: '2016-11-03T15:25:42.749+0000'
|
||||
};
|
||||
|
||||
export let fakeOpenTaskList = {
|
||||
size: 2,
|
||||
total: 2,
|
||||
start: 0,
|
||||
data: [fakeTaskOpen1, fakeTaskOpen2]
|
||||
};
|
||||
|
||||
export let fakeCompletedTaskList = {
|
||||
size: 2,
|
||||
total: 2,
|
||||
start: 0,
|
||||
data: [fakeTaskCompleted1, fakeTaskCompleted2]
|
||||
};
|
@@ -0,0 +1,52 @@
|
||||
/*!
|
||||
* @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 QueryModel {
|
||||
processDefinitionId: string;
|
||||
appName: string;
|
||||
state: string;
|
||||
sort: string;
|
||||
assignment: string;
|
||||
order: string;
|
||||
|
||||
constructor(obj?: any) {
|
||||
if (obj) {
|
||||
this.appName = obj.appName || null;
|
||||
this.processDefinitionId = obj.processDefinitionId || null;
|
||||
this.state = obj.state || null;
|
||||
this.sort = obj.sort || null;
|
||||
this.assignment = obj.assignment || null;
|
||||
this.order = obj.order || null;
|
||||
}
|
||||
}
|
||||
}
|
||||
export class FilterRepresentationModel {
|
||||
name: string;
|
||||
icon: string;
|
||||
query: QueryModel;
|
||||
|
||||
constructor(obj?: any) {
|
||||
if (obj) {
|
||||
this.name = obj.name || null;
|
||||
this.icon = obj.icon || null;
|
||||
this.query = new QueryModel(obj.query);
|
||||
}
|
||||
}
|
||||
|
||||
hasFilter() {
|
||||
return !!this.query;
|
||||
}
|
||||
}
|
@@ -15,4 +15,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './index';
|
||||
export * from './task-filters-cloud/task-filters-cloud.component';
|
||||
export * from './models/filter-cloud.model';
|
||||
export * from './task-cloud.module';
|
@@ -0,0 +1,181 @@
|
||||
/*!
|
||||
* @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 { LogService, StorageService } from '@alfresco/adf-core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, forkJoin } from 'rxjs';
|
||||
import { FilterRepresentationModel, QueryModel } from '../models/filter-cloud.model';
|
||||
|
||||
@Injectable()
|
||||
export class TaskFilterCloudService {
|
||||
|
||||
constructor(private logService: LogService,
|
||||
private storage: StorageService) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns the default filters for a process app.
|
||||
* @param appName Name of the target app
|
||||
* @returns Observable of default filters just created
|
||||
*/
|
||||
public createDefaultFilters(appName: string): Observable<FilterRepresentationModel[]> {
|
||||
let involvedTasksFilter = this.getInvolvedTasksFilterInstance(appName);
|
||||
let involvedObservable = this.addFilter(involvedTasksFilter);
|
||||
|
||||
let myTasksFilter = this.getMyTasksFilterInstance(appName);
|
||||
let myTaskObservable = this.addFilter(myTasksFilter);
|
||||
|
||||
let queuedTasksFilter = this.getQueuedTasksFilterInstance(appName);
|
||||
let queuedObservable = this.addFilter(queuedTasksFilter);
|
||||
|
||||
let completedTasksFilter = this.getCompletedTasksFilterInstance(appName);
|
||||
let completeObservable = this.addFilter(completedTasksFilter);
|
||||
|
||||
return new Observable(observer => {
|
||||
forkJoin(
|
||||
involvedObservable,
|
||||
myTaskObservable,
|
||||
queuedObservable,
|
||||
completeObservable
|
||||
).subscribe(
|
||||
(filters) => {
|
||||
observer.next(filters);
|
||||
observer.complete();
|
||||
},
|
||||
(err: any) => {
|
||||
this.logService.error(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all task filters for a process app.
|
||||
* @param appName Name of the target app
|
||||
* @returns Observable of task filter details
|
||||
*/
|
||||
getTaskListFilters(appName?: string): Observable<FilterRepresentationModel[]> {
|
||||
let key = 'task-filters-' + appName;
|
||||
const filters = JSON.parse(this.storage.getItem(key) || '[]');
|
||||
return new Observable(function(observer) {
|
||||
observer.next(filters);
|
||||
observer.complete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new task filter
|
||||
* @param filter The new filter to add
|
||||
* @returns Details of task filter just added
|
||||
*/
|
||||
addFilter(filter: FilterRepresentationModel): Observable<FilterRepresentationModel> {
|
||||
const key = 'task-filters-' + filter.query.appName || '0';
|
||||
let filters = JSON.parse(this.storage.getItem(key) || '[]');
|
||||
|
||||
filters.push(filter);
|
||||
|
||||
this.storage.setItem(key, JSON.stringify(filters));
|
||||
|
||||
return new Observable(function(observer) {
|
||||
observer.next(filter);
|
||||
observer.complete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a filter for "Involved" task instances.
|
||||
* @param appName Name of the target app
|
||||
* @returns The newly created filter
|
||||
*/
|
||||
getInvolvedTasksFilterInstance(appName: string): FilterRepresentationModel {
|
||||
return new FilterRepresentationModel({
|
||||
name: 'Cancelled Tasks',
|
||||
icon: 'view_headline',
|
||||
query: new QueryModel(
|
||||
{
|
||||
appName: appName,
|
||||
sort: 'id',
|
||||
state: 'CANCELLED',
|
||||
assignment: 'involved',
|
||||
order: 'DESC'
|
||||
}
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a filter for "My Tasks" task instances.
|
||||
* @param appName Name of the target app
|
||||
* @returns The newly created filter
|
||||
*/
|
||||
getMyTasksFilterInstance(appName: string): FilterRepresentationModel {
|
||||
return new FilterRepresentationModel({
|
||||
name: 'My Tasks',
|
||||
icon: 'inbox',
|
||||
query: new QueryModel(
|
||||
{
|
||||
appName: appName,
|
||||
sort: 'id',
|
||||
state: 'CREATED',
|
||||
assignment: 'assignee',
|
||||
order: 'ASC'
|
||||
}
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a filter for "Queued Tasks" task instances.
|
||||
* @param appName Name of the target app
|
||||
* @returns The newly created filter
|
||||
*/
|
||||
getQueuedTasksFilterInstance(appName: string): FilterRepresentationModel {
|
||||
return new FilterRepresentationModel({
|
||||
name: 'Suspended Tasks',
|
||||
icon: 'adjust',
|
||||
query: new QueryModel(
|
||||
{
|
||||
appName: appName,
|
||||
sort: 'createdDate',
|
||||
state: 'SUSPENDED',
|
||||
assignment: 'candidate',
|
||||
order: 'DESC'
|
||||
}
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a filter for "Completed" task instances.
|
||||
* @param appName Name of the target app
|
||||
* @returns The newly created filter
|
||||
*/
|
||||
getCompletedTasksFilterInstance(appName: string): FilterRepresentationModel {
|
||||
return new FilterRepresentationModel({
|
||||
name: 'Completed Tasks',
|
||||
icon: 'done',
|
||||
query: new QueryModel(
|
||||
{
|
||||
appName: appName,
|
||||
sort: 'createdDate',
|
||||
state: 'COMPLETED',
|
||||
assignment: 'involved',
|
||||
order: 'ASC'
|
||||
}
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
import { TaskCloudModule } from './task-cloud.module';
|
||||
|
||||
describe('TaskCloudModule', () => {
|
||||
let taskCloudModule: TaskCloudModule;
|
||||
|
||||
beforeEach(() => {
|
||||
taskCloudModule = new TaskCloudModule();
|
||||
});
|
||||
|
||||
it('should create an instance', () => {
|
||||
expect(taskCloudModule).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,26 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TaskFiltersCloudComponent } from './task-filters-cloud/task-filters-cloud.component';
|
||||
import { MaterialModule } from '../material.module';
|
||||
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
||||
import { TranslateLoaderService, LogService, StorageService } from '@alfresco/adf-core';
|
||||
import { TaskFilterCloudService } from './services/task-filter-cloud.service';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
@NgModule({
|
||||
imports: [
|
||||
HttpClientModule,
|
||||
CommonModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
}),
|
||||
MaterialModule
|
||||
],
|
||||
declarations: [TaskFiltersCloudComponent],
|
||||
|
||||
exports: [TaskFiltersCloudComponent],
|
||||
providers: [TaskFilterCloudService, LogService, StorageService]
|
||||
})
|
||||
export class TaskCloudModule { }
|
@@ -0,0 +1,17 @@
|
||||
<div class="menu-container">
|
||||
<mat-list class="adf-menu-list" *ngIf="filters$ | async; else loading">
|
||||
<mat-list-item (click)="selectFilterAndEmit(filter)" *ngFor="let filter of filters$ | async"
|
||||
class="adf-filters__entry" [class.active]="currentFilter === filter">
|
||||
<mat-icon *ngIf="showIcons && filter.icon" matListIcon class="adf-filters__entry-icon">{{filter.icon}}
|
||||
</mat-icon>
|
||||
<span matLine [attr.data-automation-id]="filter.name + '_filter'">{{filter.name}}</span>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
<ng-template #loading>
|
||||
<ng-container>
|
||||
<div class="adf-app-list-spinner">
|
||||
<mat-spinner></mat-spinner>
|
||||
</div>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</div>
|
@@ -0,0 +1,34 @@
|
||||
@mixin adf-cloud-task-filters-theme($theme) {
|
||||
$primary: map-get($theme, primary);
|
||||
|
||||
.adf {
|
||||
|
||||
&-filters__entry {
|
||||
cursor: pointer;
|
||||
font-size: 14px!important;
|
||||
font-weight: bold;
|
||||
opacity: .54;
|
||||
padding-left: 30px;
|
||||
|
||||
.mat-list-item-content {
|
||||
height: 34px;
|
||||
}
|
||||
}
|
||||
|
||||
&-filters__entry-icon {
|
||||
padding-right: 12px !important;
|
||||
padding-left: 0px !important;
|
||||
}
|
||||
|
||||
&-filters__entry {
|
||||
&.active, &:hover {
|
||||
color: mat-color($primary);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&-menu-list {
|
||||
padding-top: 0px!important;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,359 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { SimpleChange } from '@angular/core';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { setupTestBed } from '@alfresco/adf-core';
|
||||
import { from, Observable } from 'rxjs';
|
||||
import { FilterRepresentationModel } from '../models/filter-cloud.model';
|
||||
import { TaskFilterCloudService } from '../services/task-filter-cloud.service';
|
||||
import { TaskFiltersCloudComponent } from './task-filters-cloud.component';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
|
||||
import { TaskCloudModule } from '../task-cloud.module';
|
||||
|
||||
describe('TaskFiltersCloudComponent', () => {
|
||||
|
||||
let taskFilterService: TaskFilterCloudService;
|
||||
|
||||
let fakeGlobalFilter = [
|
||||
new FilterRepresentationModel({
|
||||
name: 'FakeInvolvedTasks',
|
||||
icon: 'adjust',
|
||||
id: 10,
|
||||
filter: {state: 'open', assignment: 'fake-involved'}
|
||||
}),
|
||||
new FilterRepresentationModel({
|
||||
name: 'FakeMyTasks1',
|
||||
icon: 'done',
|
||||
id: 11,
|
||||
filter: {state: 'open', assignment: 'fake-assignee'}
|
||||
}),
|
||||
new FilterRepresentationModel({
|
||||
name: 'FakeMyTasks2',
|
||||
icon: 'inbox',
|
||||
id: 12,
|
||||
filter: {state: 'open', assignment: 'fake-assignee'}
|
||||
})
|
||||
];
|
||||
|
||||
let fakeGlobalFilterObservable =
|
||||
new Observable(function(observer) {
|
||||
observer.next(fakeGlobalFilter);
|
||||
observer.complete();
|
||||
});
|
||||
|
||||
let fakeGlobalFilterPromise = new Promise(function (resolve, reject) {
|
||||
resolve(fakeGlobalFilter);
|
||||
});
|
||||
|
||||
let fakeGlobalEmptyFilter = {
|
||||
message: 'invalid data'
|
||||
};
|
||||
|
||||
let fakeGlobalEmptyFilterPromise = new Promise(function (resolve, reject) {
|
||||
resolve(fakeGlobalEmptyFilter);
|
||||
});
|
||||
|
||||
let mockErrorFilterList = {
|
||||
error: 'wrong request'
|
||||
};
|
||||
|
||||
let mockErrorFilterPromise = Promise.reject(mockErrorFilterList);
|
||||
|
||||
let component: TaskFiltersCloudComponent;
|
||||
let fixture: ComponentFixture<TaskFiltersCloudComponent>;
|
||||
|
||||
setupTestBed({
|
||||
imports: [ProcessServiceCloudTestingModule, TaskCloudModule],
|
||||
providers: [TaskFilterCloudService]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(TaskFiltersCloudComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
taskFilterService = TestBed.get(TaskFilterCloudService);
|
||||
});
|
||||
|
||||
it('should attach specific icon for each filter if hasIcon is true', async(() => {
|
||||
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||
let change = new SimpleChange(undefined, 'my-app-1', true);
|
||||
component.ngOnChanges({'appName': change});
|
||||
fixture.detectChanges();
|
||||
component.showIcons = true;
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(component.filters.length).toBe(3);
|
||||
let filters = fixture.nativeElement.querySelectorAll('.adf-filters__entry-icon');
|
||||
expect(filters.length).toBe(3);
|
||||
expect(filters[0].innerText).toContain('adjust');
|
||||
expect(filters[1].innerText).toContain('done');
|
||||
expect(filters[2].innerText).toContain('inbox');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should not attach icons for each filter if hasIcon is false', (done) => {
|
||||
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(fakeGlobalFilterPromise));
|
||||
|
||||
component.showIcons = false;
|
||||
let change = new SimpleChange(undefined, 'my-app-1', true);
|
||||
component.ngOnChanges({'appName': change});
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
let filters: any = fixture.debugElement.queryAll(By.css('.adf-filters__entry-icon'));
|
||||
expect(filters.length).toBe(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should display the filters', async(() => {
|
||||
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||
let change = new SimpleChange(undefined, 'my-app-1', true);
|
||||
component.ngOnChanges({'appName': change});
|
||||
fixture.detectChanges();
|
||||
component.showIcons = true;
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
let filters = fixture.debugElement.queryAll(By.css('mat-list-item[class*="adf-filters__entry"]'));
|
||||
expect(component.filters.length).toBe(3);
|
||||
expect(filters.length).toBe(3);
|
||||
expect(filters[0].nativeElement.innerText).toContain('FakeInvolvedTasks');
|
||||
expect(filters[1].nativeElement.innerText).toContain('FakeMyTasks1');
|
||||
expect(filters[2].nativeElement.innerText).toContain('FakeMyTasks2');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should emit an error with a bad response', (done) => {
|
||||
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(mockErrorFilterPromise));
|
||||
|
||||
const appName = 'my-app-1';
|
||||
let change = new SimpleChange(null, appName, true);
|
||||
component.ngOnChanges({'appName': change});
|
||||
|
||||
component.error.subscribe((err) => {
|
||||
expect(err).toBeDefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the filter task list', (done) => {
|
||||
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(fakeGlobalFilterPromise));
|
||||
const appName = 'my-app-1';
|
||||
let change = new SimpleChange(null, appName, true);
|
||||
component.ngOnChanges({ 'appName': change });
|
||||
|
||||
component.success.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(component.filters).toBeDefined();
|
||||
expect(component.filters.length).toEqual(3);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the filter task list, filtered By Name', (done) => {
|
||||
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(fakeGlobalFilterPromise));
|
||||
const appName = 'my-app-1';
|
||||
let change = new SimpleChange(null, appName, true);
|
||||
component.ngOnChanges({ 'appName': change });
|
||||
|
||||
component.success.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(component.filters).toBeDefined();
|
||||
expect(component.filters[0].name).toEqual('FakeInvolvedTasks');
|
||||
expect(component.filters[1].name).toEqual('FakeMyTasks1');
|
||||
expect(component.filters[2].name).toEqual('FakeMyTasks2');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should select the first filter as default', async(() => {
|
||||
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||
|
||||
const appName = 'my-app-1';
|
||||
let change = new SimpleChange(null, appName, true);
|
||||
|
||||
fixture.detectChanges();
|
||||
component.ngOnChanges({ 'appName': change });
|
||||
|
||||
component.success.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(component.currentFilter).toBeDefined();
|
||||
expect(component.currentFilter.name).toEqual('FakeInvolvedTasks');
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
it('should be able to fetch and select the default filters if the input filter is not valid', (done) => {
|
||||
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(from(fakeGlobalEmptyFilterPromise));
|
||||
spyOn(component, 'createFilters').and.callThrough();
|
||||
|
||||
const appName = 'my-app-1';
|
||||
let change = new SimpleChange(null, appName, true);
|
||||
component.ngOnChanges({ 'appName': change });
|
||||
|
||||
component.success.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(component.createFilters).not.toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should select the task filter based on the input by name param', async(() => {
|
||||
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||
|
||||
component.filterParam = new FilterRepresentationModel({ name: 'FakeMyTasks1' });
|
||||
const appName = 'my-app-1';
|
||||
let change = new SimpleChange(null, appName, true);
|
||||
|
||||
fixture.detectChanges();
|
||||
component.ngOnChanges({ 'appName': change });
|
||||
|
||||
component.success.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(component.currentFilter).toBeDefined();
|
||||
expect(component.currentFilter.name).toEqual('FakeMyTasks1');
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
it('should select the default task filter if filter input does not exist', async(() => {
|
||||
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||
|
||||
component.filterParam = new FilterRepresentationModel({ name: 'UnexistableFilter' });
|
||||
|
||||
const appName = 'my-app-1';
|
||||
let change = new SimpleChange(null, appName, true);
|
||||
|
||||
fixture.detectChanges();
|
||||
component.ngOnChanges({ 'appName': change });
|
||||
|
||||
component.success.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(component.currentFilter).toBeDefined();
|
||||
expect(component.currentFilter.name).toEqual('FakeInvolvedTasks');
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
it('should select the task filter based on the input by index param', async(() => {
|
||||
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||
|
||||
component.filterParam = new FilterRepresentationModel({ index: 2 });
|
||||
|
||||
const appName = 'my-app-1';
|
||||
let change = new SimpleChange(null, appName, true);
|
||||
|
||||
fixture.detectChanges();
|
||||
component.ngOnChanges({ 'appName': change });
|
||||
|
||||
component.success.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(component.currentFilter).toBeDefined();
|
||||
expect(component.currentFilter.name).toEqual('FakeMyTasks2');
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
it('should select the task filter based on the input by id param', async(() => {
|
||||
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||
|
||||
component.filterParam = new FilterRepresentationModel({ id: 12 });
|
||||
|
||||
const appName = 'my-app-1';
|
||||
let change = new SimpleChange(null, appName, true);
|
||||
|
||||
fixture.detectChanges();
|
||||
component.ngOnChanges({ 'appName': change });
|
||||
|
||||
component.success.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(component.currentFilter).toBeDefined();
|
||||
expect(component.currentFilter.name).toEqual('FakeMyTasks2');
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
it('should emit an event when a filter is selected', async(() => {
|
||||
spyOn(taskFilterService, 'getTaskListFilters').and.returnValue(fakeGlobalFilterObservable);
|
||||
|
||||
component.filterParam = new FilterRepresentationModel({ id: 12 });
|
||||
|
||||
const appName = 'my-app-1';
|
||||
let change = new SimpleChange(null, appName, true);
|
||||
component.ngOnChanges({ 'appName': change });
|
||||
|
||||
fixture.detectChanges();
|
||||
spyOn(component, 'selectFilterAndEmit').and.stub();
|
||||
let filterButton = fixture.debugElement.nativeElement.querySelector('span[data-automation-id="FakeMyTasks1_filter"]');
|
||||
filterButton.click();
|
||||
expect(component.selectFilterAndEmit).toHaveBeenCalledWith(fakeGlobalFilter[1]);
|
||||
}));
|
||||
|
||||
it('should reload filters by appName on binding changes', () => {
|
||||
spyOn(component, 'getFilters').and.stub();
|
||||
const appName = 'my-app-1';
|
||||
|
||||
let change = new SimpleChange(null, appName, true);
|
||||
component.ngOnChanges({ 'appName': change });
|
||||
|
||||
expect(component.getFilters).toHaveBeenCalledWith(appName);
|
||||
});
|
||||
|
||||
it('should not reload filters by appName null on binding changes', () => {
|
||||
spyOn(component, 'getFilters').and.stub();
|
||||
const appName = null;
|
||||
|
||||
let change = new SimpleChange(undefined, appName, true);
|
||||
component.ngOnChanges({ 'appName': change });
|
||||
|
||||
expect(component.getFilters).not.toHaveBeenCalledWith(appName);
|
||||
});
|
||||
|
||||
it('should change current filter when filterParam (name) changes', () => {
|
||||
component.filters = fakeGlobalFilter;
|
||||
component.currentFilter = null;
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
expect(component.currentFilter.name).toEqual(fakeGlobalFilter[2].name);
|
||||
});
|
||||
|
||||
const change = new SimpleChange(null, { name: fakeGlobalFilter[2].name }, true);
|
||||
component.ngOnChanges({ 'filterParam': change });
|
||||
});
|
||||
|
||||
it('should reload filters by app name on binding changes', () => {
|
||||
spyOn(component, 'getFilters').and.stub();
|
||||
const appName = 'fake-app-name';
|
||||
|
||||
let change = new SimpleChange(null, appName, true);
|
||||
component.ngOnChanges({ 'appName': change });
|
||||
|
||||
expect(component.getFilters).toHaveBeenCalledWith(appName);
|
||||
});
|
||||
|
||||
it('should return the current filter after one is selected', () => {
|
||||
let filter = fakeGlobalFilter[1];
|
||||
component.filters = fakeGlobalFilter;
|
||||
|
||||
expect(component.currentFilter).toBeUndefined();
|
||||
component.selectFilter(filter);
|
||||
expect(component.getCurrentFilter()).toBe(filter);
|
||||
});
|
||||
});
|
@@ -0,0 +1,156 @@
|
||||
/*!
|
||||
* @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, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { TaskFilterCloudService } from '../services/task-filter-cloud.service';
|
||||
import { FilterRepresentationModel } from '../models/filter-cloud.model';
|
||||
@Component({
|
||||
selector: 'adf-cloud-task-filters',
|
||||
templateUrl: './task-filters-cloud.component.html',
|
||||
styleUrls: ['task-filters-cloud.component.scss']
|
||||
})
|
||||
export class TaskFiltersCloudComponent implements OnChanges {
|
||||
|
||||
@Input()
|
||||
appName: string;
|
||||
|
||||
@Input()
|
||||
filterParam: FilterRepresentationModel;
|
||||
|
||||
@Input()
|
||||
showIcons: boolean = false;
|
||||
|
||||
@Output()
|
||||
filterClick: EventEmitter<FilterRepresentationModel> = new EventEmitter<FilterRepresentationModel>();
|
||||
|
||||
@Output()
|
||||
success: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
@Output()
|
||||
error: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
filters$: Observable<FilterRepresentationModel[]>;
|
||||
|
||||
currentFilter: FilterRepresentationModel;
|
||||
|
||||
filters: FilterRepresentationModel [] = [];
|
||||
|
||||
constructor(private taskFilterCloudService: TaskFilterCloudService) {
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
const appName = changes['appName'];
|
||||
const filter = changes['filterParam'];
|
||||
if (appName && appName.currentValue) {
|
||||
this.getFilters(appName.currentValue);
|
||||
} else if (filter && filter.currentValue !== filter.previousValue) {
|
||||
this.selectFilter(filter.currentValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filter list filtered by appName
|
||||
*/
|
||||
getFilters(appName: string) {
|
||||
this.filters$ = this.taskFilterCloudService.getTaskListFilters(appName);
|
||||
|
||||
this.filters$.subscribe(
|
||||
(res: FilterRepresentationModel[]) => {
|
||||
if (res.length === 0) {
|
||||
this.createFilters(appName);
|
||||
} else {
|
||||
this.resetFilter();
|
||||
this.filters = res;
|
||||
}
|
||||
this.selectFilterAndEmit(this.filterParam);
|
||||
this.success.emit(res);
|
||||
},
|
||||
(err: any) => {
|
||||
this.error.emit(err);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create default filters by appId
|
||||
*/
|
||||
createFilters(appName?: string) {
|
||||
this.filters$ = this.taskFilterCloudService.createDefaultFilters(appName);
|
||||
|
||||
this.filters$.subscribe(
|
||||
(resDefault: FilterRepresentationModel[]) => {
|
||||
this.resetFilter();
|
||||
this.filters = resDefault;
|
||||
},
|
||||
(errDefault: any) => {
|
||||
this.error.emit(errDefault);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass the selected filter as next
|
||||
*/
|
||||
public selectFilter(newFilter: FilterRepresentationModel) {
|
||||
if (newFilter) {
|
||||
this.currentFilter = this.filters.find((filter) =>
|
||||
(newFilter.name &&
|
||||
(newFilter.name.toLocaleLowerCase() === filter.name.toLocaleLowerCase())
|
||||
));
|
||||
}
|
||||
if (!this.currentFilter) {
|
||||
this.selectDefaultTaskFilter();
|
||||
}
|
||||
}
|
||||
|
||||
public selectFilterAndEmit(newFilter: FilterRepresentationModel) {
|
||||
this.selectFilter(newFilter);
|
||||
this.filterClick.emit(this.currentFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select as default task filter the first in the list
|
||||
*/
|
||||
public selectDefaultTaskFilter() {
|
||||
if (!this.isFilterListEmpty()) {
|
||||
this.currentFilter = this.filters[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current task
|
||||
*/
|
||||
getCurrentFilter(): FilterRepresentationModel {
|
||||
return this.currentFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the filter list is empty
|
||||
*/
|
||||
isFilterListEmpty(): boolean {
|
||||
return this.filters === undefined || (this.filters && this.filters.length === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the filters properties
|
||||
*/
|
||||
private resetFilter() {
|
||||
this.filters = [];
|
||||
this.currentFilter = undefined;
|
||||
}
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
.adf-cloud-task-list-loading-margin {
|
||||
margin-left: calc((100% - 100px) / 2);
|
||||
margin-right: calc((100% - 100px) / 2);
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
<div *ngIf="!rows">{{ 'ADF_TASK_LIST.FILTERS.MESSAGES.NONE' | translate }}</div>
|
||||
<ng-container *ngIf="rows">
|
||||
<adf-datatable
|
||||
[rows]="rows"
|
||||
[columns]="columns"
|
||||
[loading]="isLoading"
|
||||
[multiselect]="multiselect"
|
||||
[selectionMode]="selectionMode"
|
||||
(row-select)="onRowSelect($event)"
|
||||
(row-unselect)="onRowUnselect($event)"
|
||||
(rowClick)="onRowClick($event)"
|
||||
(row-keyup)="onRowKeyUp($event)">
|
||||
<loading-content-template>
|
||||
<ng-template>
|
||||
<!-- Add your custom loading template here -->
|
||||
<mat-progress-spinner class="adf-cloud-task-list-loading-margin"
|
||||
[color]="'primary'"
|
||||
[mode]="'indeterminate'">
|
||||
</mat-progress-spinner>
|
||||
</ng-template>
|
||||
</loading-content-template>
|
||||
<no-content-template>
|
||||
<ng-template>
|
||||
<adf-empty-content *ngIf="!emptyCustomContent"
|
||||
icon="assignment"
|
||||
[title]="'ADF_TASK_LIST.LIST.MESSAGES.TITLE' | translate"
|
||||
[subtitle]="'ADF_TASK_LIST.LIST.MESSAGES.SUBTITLE' | translate">
|
||||
</adf-empty-content>
|
||||
<ng-content select="adf-empty-custom-content"></ng-content>
|
||||
</ng-template>
|
||||
</no-content-template>
|
||||
</adf-datatable>
|
||||
</ng-container>
|
@@ -0,0 +1,312 @@
|
||||
/*!
|
||||
* @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, SimpleChange, ViewChild, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { AppConfigService, setupTestBed, CoreModule } from '@alfresco/adf-core';
|
||||
import { DataRowEvent, ObjectDataRow } from '@alfresco/adf-core';
|
||||
import { TaskListCloudService } from '../services/task-list-cloud.service';
|
||||
import { TaskListCloudComponent } from './task-list-cloud.component';
|
||||
import { fakeGlobalTask, fakeCustomSchema, fakeTaskCloudList } from '../mock/fakeTaskResponseMock';
|
||||
import { of } from 'rxjs';
|
||||
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
|
||||
import { TaskListCloudModule } from '../task-list-cloud.module';
|
||||
@Component({
|
||||
template: `
|
||||
<adf-cloud-task-list #taskListCloud>
|
||||
<data-columns>
|
||||
<data-column key="name" title="ADF_TASK_LIST.PROPERTIES.NAME" class="full-width name-column"></data-column>
|
||||
<data-column key="created" title="ADF_TASK_LIST.PROPERTIES.CREATED" class="hidden"></data-column>
|
||||
<data-column key="startedBy" title="ADF_TASK_LIST.PROPERTIES.CREATED" class="desktop-only dw-dt-col-3 ellipsis-cell">
|
||||
<ng-template let-entry="$implicit">
|
||||
<div>{{getFullName(entry.row.obj.startedBy)}}</div>
|
||||
</ng-template>
|
||||
</data-column>
|
||||
</data-columns>
|
||||
</adf-cloud-task-list>`
|
||||
})
|
||||
class CustomTaskListComponent {
|
||||
@ViewChild(TaskListCloudComponent)
|
||||
taskList: TaskListCloudComponent;
|
||||
}
|
||||
@Component({
|
||||
template: `
|
||||
<adf-tasklist>
|
||||
<adf-empty-content-holder>
|
||||
<p id="custom-id"></p>
|
||||
</adf-empty-content-holder>
|
||||
</adf-tasklist>
|
||||
`
|
||||
})
|
||||
class EmptyTemplateComponent {
|
||||
}
|
||||
describe('TaskListCloudComponent', () => {
|
||||
let component: TaskListCloudComponent;
|
||||
let fixture: ComponentFixture<TaskListCloudComponent>;
|
||||
let appConfig: AppConfigService;
|
||||
let taskListCloudService: TaskListCloudService;
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
ProcessServiceCloudTestingModule, TaskListCloudModule
|
||||
],
|
||||
providers: [TaskListCloudService]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
appConfig = TestBed.get(AppConfigService);
|
||||
taskListCloudService = TestBed.get(TaskListCloudService);
|
||||
fixture = TestBed.createComponent(TaskListCloudComponent);
|
||||
component = fixture.componentInstance;
|
||||
appConfig.config = Object.assign(appConfig.config, {
|
||||
'adf-cloud-task-list': {
|
||||
'presets': {
|
||||
'fakeCustomSchema': [
|
||||
{
|
||||
'key': 'fakeName',
|
||||
'type': 'text',
|
||||
'title': 'ADF_TASK_LIST.PROPERTIES.FAKE',
|
||||
'sortable': true
|
||||
},
|
||||
{
|
||||
'key': 'fakeTaskName',
|
||||
'type': 'text',
|
||||
'title': 'ADF_TASK_LIST.PROPERTIES.TASK_FAKE',
|
||||
'sortable': true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should use the default schemaColumn as default', () => {
|
||||
component.ngAfterContentInit();
|
||||
expect(component.columns).toBeDefined();
|
||||
expect(component.columns.length).toEqual(3);
|
||||
});
|
||||
|
||||
it('should use the custom schemaColumn from app.config.json', () => {
|
||||
component.presetColumn = 'fakeCustomSchema';
|
||||
component.ngAfterContentInit();
|
||||
fixture.detectChanges();
|
||||
expect(component.columns).toEqual(fakeCustomSchema);
|
||||
});
|
||||
|
||||
it('should fetch custom schemaColumn when the input presetColumn is defined', () => {
|
||||
component.presetColumn = 'fakeCustomSchema';
|
||||
fixture.detectChanges();
|
||||
expect(component.columns).toBeDefined();
|
||||
expect(component.columns.length).toEqual(2);
|
||||
});
|
||||
|
||||
it('should return an empty task list when no input parameters are passed', () => {
|
||||
component.ngAfterContentInit();
|
||||
expect(component.rows).toBeDefined();
|
||||
expect(component.isListEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return the results if an application name is given', (done) => {
|
||||
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTask));
|
||||
let appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||
component.success.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(component.rows).toBeDefined();
|
||||
expect(component.isListEmpty()).not.toBeTruthy();
|
||||
expect(component.rows.length).toEqual(1);
|
||||
expect(component.rows[0].entry['serviceName']).toEqual('test-ciprian2-rb');
|
||||
expect(component.rows[0].entry['serviceFullName']).toEqual('test-ciprian2-rb');
|
||||
expect(component.rows[0].entry['serviceVersion']).toBe('');
|
||||
expect(component.rows[0].entry['appName']).toBe('test-ciprian2');
|
||||
expect(component.rows[0].entry['appVersion']).toBe('');
|
||||
expect(component.rows[0].entry['serviceType']).toBeNull();
|
||||
expect(component.rows[0].entry['id']).toBe('11fe013d-c263-11e8-b75b-0a5864600540');
|
||||
expect(component.rows[0].entry['assignee']).toBeNull();
|
||||
expect(component.rows[0].entry['name']).toEqual('standalone-subtask');
|
||||
expect(component.rows[0].entry['description']).toBeNull();
|
||||
expect(component.rows[0].entry['createdDate']).toBe(1538059139420);
|
||||
expect(component.rows[0].entry['dueDate']).toBeNull();
|
||||
expect(component.rows[0].entry['claimedDate']).toBeNull();
|
||||
expect(component.rows[0].entry['priority']).toBe(0);
|
||||
expect(component.rows[0].entry['category']).toBeNull();
|
||||
expect(component.rows[0].entry['processDefinitionId']).toBeNull();
|
||||
expect(component.rows[0].entry['processInstanceId']).toBeNull();
|
||||
expect(component.rows[0].entry['status']).toBe('CREATED');
|
||||
expect(component.rows[0].entry['owner']).toBe('devopsuser');
|
||||
expect(component.rows[0].entry['parentTaskId']).toBe('71fda20b-c25b-11e8-b75b-0a5864600540');
|
||||
expect(component.rows[0].entry['lastModified']).toBe(1538059139420);
|
||||
expect(component.rows[0].entry['lastModifiedTo']).toBeNull();
|
||||
expect(component.rows[0].entry['lastModifiedFrom']).toBeNull();
|
||||
expect(component.rows[0].entry['standAlone']).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
component.applicationName = appName.currentValue;
|
||||
component.ngOnChanges({ 'appName': appName });
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should return a currentId null when the taskList is empty', () => {
|
||||
component.selectTask(null);
|
||||
expect(component.getCurrentId()).toBeNull();
|
||||
});
|
||||
|
||||
it('should return selected id for the selected task', () => {
|
||||
component.rows = [
|
||||
{ entry: { id: '999', name: 'Fake-name' } },
|
||||
{ entry: { id: '888', name: 'Fake-name-888' } }
|
||||
];
|
||||
component.selectTask('888');
|
||||
expect(component.rows).toBeDefined();
|
||||
expect(component.currentInstanceId).toEqual('888');
|
||||
});
|
||||
|
||||
it('should reload tasks when reload() is called', (done) => {
|
||||
component.applicationName = 'fake';
|
||||
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTask));
|
||||
component.success.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(component.rows).toBeDefined();
|
||||
expect(component.isListEmpty()).not.toBeTruthy();
|
||||
done();
|
||||
});
|
||||
fixture.detectChanges();
|
||||
component.reload();
|
||||
});
|
||||
|
||||
it('should emit row click event', (done) => {
|
||||
let row = new ObjectDataRow({
|
||||
entry: {
|
||||
id: '999'
|
||||
}
|
||||
});
|
||||
let rowEvent = new DataRowEvent(row, null);
|
||||
component.rowClick.subscribe(taskId => {
|
||||
expect(taskId).toEqual('999');
|
||||
expect(component.getCurrentId()).toEqual('999');
|
||||
done();
|
||||
});
|
||||
component.onRowClick(rowEvent);
|
||||
});
|
||||
|
||||
describe('component changes', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
component.rows = fakeGlobalTask.list.entries;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should NOT reload the tasks if the landingTaskId is the same of the current task', () => {
|
||||
spyOn(component, 'reload').and.stub();
|
||||
component.currentInstanceId = '999';
|
||||
component.rows = [{ entry: { id: '999', name: 'Fake-name' } }];
|
||||
const landingTaskId = '999';
|
||||
let change = new SimpleChange('999', landingTaskId, true);
|
||||
component.ngOnChanges({ 'landingTaskId': change });
|
||||
expect(component.reload).not.toHaveBeenCalled();
|
||||
expect(component.rows.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should reload the tasks if the loadingTaskId is different from the current task', (done) => {
|
||||
component.currentInstanceId = '999';
|
||||
component.rows = [{ id: '999', name: 'Fake-name' }];
|
||||
const landingTaskId = '888';
|
||||
let change = new SimpleChange(null, landingTaskId, true);
|
||||
component.applicationName = 'fake';
|
||||
spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeTaskCloudList));
|
||||
component.success.subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(component.rows).toBeDefined();
|
||||
expect(component.rows.length).toEqual(2);
|
||||
done();
|
||||
});
|
||||
component.ngOnChanges({ 'landingTaskId': change });
|
||||
});
|
||||
|
||||
it('should NOT reload the task list when no parameters changed', () => {
|
||||
component.rows = null;
|
||||
component.ngOnChanges({});
|
||||
fixture.detectChanges();
|
||||
expect(component.isListEmpty()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Injecting custom colums for tasklist - CustomTaskListComponent', () => {
|
||||
let fixtureCustom: ComponentFixture<CustomTaskListComponent>;
|
||||
let componentCustom: CustomTaskListComponent;
|
||||
|
||||
setupTestBed({
|
||||
imports: [CoreModule.forRoot()],
|
||||
declarations: [TaskListCloudComponent, CustomTaskListComponent],
|
||||
providers: [TaskListCloudService]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixtureCustom = TestBed.createComponent(CustomTaskListComponent);
|
||||
fixtureCustom.detectChanges();
|
||||
componentCustom = fixtureCustom.componentInstance;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixtureCustom.destroy();
|
||||
});
|
||||
|
||||
it('should create instance of CustomTaskListComponent', () => {
|
||||
expect(componentCustom instanceof CustomTaskListComponent).toBe(true, 'should create CustomTaskListComponent');
|
||||
});
|
||||
|
||||
it('should fetch custom schemaColumn from html', () => {
|
||||
fixture.detectChanges();
|
||||
expect(componentCustom.taskList.columnList).toBeDefined();
|
||||
expect(componentCustom.taskList.columns[0]['title']).toEqual('ADF_TASK_LIST.PROPERTIES.NAME');
|
||||
expect(componentCustom.taskList.columns[1]['title']).toEqual('ADF_TASK_LIST.PROPERTIES.CREATED');
|
||||
expect(componentCustom.taskList.columns.length).toEqual(3);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Creating an empty custom template - EmptyTemplateComponent', () => {
|
||||
let fixtureEmpty: ComponentFixture<EmptyTemplateComponent>;
|
||||
|
||||
setupTestBed({
|
||||
imports: [ProcessServiceCloudTestingModule, TaskListCloudModule],
|
||||
declarations: [EmptyTemplateComponent],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixtureEmpty = TestBed.createComponent(EmptyTemplateComponent);
|
||||
fixtureEmpty.detectChanges();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixtureEmpty.destroy();
|
||||
});
|
||||
|
||||
it('should render the custom template', async(() => {
|
||||
fixtureEmpty.whenStable().then(() => {
|
||||
fixtureEmpty.detectChanges();
|
||||
expect(fixtureEmpty.debugElement.query(By.css('#custom-id'))).not.toBeNull();
|
||||
expect(fixtureEmpty.debugElement.query(By.css('.adf-empty-content'))).toBeNull();
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
@@ -0,0 +1,260 @@
|
||||
/*!
|
||||
* @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, ViewEncapsulation, OnChanges, Input, SimpleChanges, Output, EventEmitter, ContentChild, AfterContentInit, SimpleChange } from '@angular/core';
|
||||
import { AppConfigService, UserPreferencesService,
|
||||
DataTableSchema, UserPreferenceValues,
|
||||
PaginatedComponent, PaginationModel,
|
||||
DataRowEvent, EmptyCustomContentDirective } from '@alfresco/adf-core';
|
||||
import { taskPresetsCloudDefaultModel } from '../models/task-preset-cloud.model';
|
||||
import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { TaskListCloudService } from '../services/task-list-cloud.service';
|
||||
import { MinimalNodeEntity } from 'alfresco-js-api';
|
||||
import { TaskListCloudSortingModel } from '../models/task-list-sorting.model';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-cloud-task-list',
|
||||
templateUrl: './task-list-cloud.component.html',
|
||||
styleUrls: ['./task-list-cloud.component.css'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
|
||||
export class TaskListCloudComponent extends DataTableSchema implements OnChanges, AfterContentInit, PaginatedComponent {
|
||||
|
||||
static PRESET_KEY = 'adf-cloud-task-list.presets';
|
||||
|
||||
@ContentChild(EmptyCustomContentDirective)
|
||||
emptyCustomContent: EmptyCustomContentDirective;
|
||||
|
||||
@Input()
|
||||
applicationName: string = '';
|
||||
|
||||
@Input()
|
||||
assignee: string = '';
|
||||
|
||||
@Input()
|
||||
createdDate: string = '';
|
||||
|
||||
@Input()
|
||||
dueDate: string = '';
|
||||
|
||||
@Input()
|
||||
id: string = '';
|
||||
|
||||
@Input()
|
||||
name: string = '';
|
||||
|
||||
@Input()
|
||||
parentTaskId: string = '';
|
||||
|
||||
@Input()
|
||||
processDefinitionId: string = '';
|
||||
|
||||
@Input()
|
||||
processInstanceId: string = '';
|
||||
|
||||
@Input()
|
||||
status: string = '';
|
||||
|
||||
@Input()
|
||||
selectFirstRow: boolean = true;
|
||||
|
||||
@Input()
|
||||
landingTaskId: string;
|
||||
|
||||
@Input()
|
||||
selectionMode: string = 'single'; // none|single|multiple
|
||||
|
||||
/** Toggles multiple row selection, renders checkboxes at the beginning of each row */
|
||||
@Input()
|
||||
multiselect: boolean = false;
|
||||
|
||||
@Input()
|
||||
sorting: TaskListCloudSortingModel[];
|
||||
|
||||
/** Emitted when a task in the list is clicked */
|
||||
@Output()
|
||||
rowClick: EventEmitter<string> = new EventEmitter<string>();
|
||||
|
||||
/** Emitted when rows are selected/unselected */
|
||||
@Output()
|
||||
rowsSelected: EventEmitter<any[]> = new EventEmitter<any[]>();
|
||||
|
||||
/** Emitted when the task list is loaded */
|
||||
@Output()
|
||||
success: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
/** Emitted when an error occurs. */
|
||||
@Output()
|
||||
error: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
pagination: BehaviorSubject<PaginationModel>;
|
||||
|
||||
requestNode: TaskQueryCloudRequestModel;
|
||||
rows: any[] = [];
|
||||
size: number;
|
||||
skipCount: number = 0;
|
||||
currentInstanceId: any;
|
||||
isLoading = false;
|
||||
selectedInstances: any[];
|
||||
|
||||
constructor(private taskListCloudService: TaskListCloudService,
|
||||
appConfigService: AppConfigService,
|
||||
private userPreferences: UserPreferencesService) {
|
||||
super(appConfigService, TaskListCloudComponent.PRESET_KEY, taskPresetsCloudDefaultModel);
|
||||
this.size = userPreferences.paginationSize;
|
||||
this.userPreferences.select(UserPreferenceValues.PaginationSize).subscribe((pageSize) => {
|
||||
this.size = pageSize;
|
||||
});
|
||||
|
||||
this.pagination = new BehaviorSubject<PaginationModel>(<PaginationModel> {
|
||||
maxItems: this.size,
|
||||
skipCount: 0,
|
||||
totalItems: 0
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (this.isPropertyChanged(changes) &&
|
||||
!this.isEqualToCurrentId(changes['landingTaskId'])) {
|
||||
this.reload();
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterContentInit() {
|
||||
this.createDatatableSchema();
|
||||
}
|
||||
|
||||
getCurrentId(): string {
|
||||
return this.currentInstanceId;
|
||||
}
|
||||
|
||||
isEqualToCurrentId(landingTaskChanged: SimpleChange): boolean {
|
||||
return landingTaskChanged && this.currentInstanceId === landingTaskChanged.currentValue;
|
||||
}
|
||||
|
||||
private isPropertyChanged(changes: SimpleChanges): boolean {
|
||||
for (let property in changes) {
|
||||
if (changes.hasOwnProperty(property)) {
|
||||
if (changes[property] &&
|
||||
(changes[property].currentValue !== changes[property].previousValue)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
reload() {
|
||||
this.requestNode = this.createRequestNode();
|
||||
if (this.requestNode.appName) {
|
||||
this.load(this.requestNode);
|
||||
} else {
|
||||
this.rows = [];
|
||||
}
|
||||
}
|
||||
|
||||
private load(requestNode: TaskQueryCloudRequestModel) {
|
||||
this.isLoading = true;
|
||||
this.taskListCloudService.getTaskByRequest(requestNode).subscribe(
|
||||
(tasks) => {
|
||||
this.rows = tasks.list.entries;
|
||||
this.selectTask(this.landingTaskId);
|
||||
this.success.emit(tasks);
|
||||
this.isLoading = false;
|
||||
this.pagination.next(tasks.list.pagination);
|
||||
}, (error) => {
|
||||
this.error.emit(error);
|
||||
this.isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
selectTask(taskIdSelected: string) {
|
||||
if (!this.isListEmpty()) {
|
||||
let dataRow: any = null;
|
||||
if (taskIdSelected) {
|
||||
dataRow = this.rows.find((currentRow: MinimalNodeEntity) => {
|
||||
return currentRow.entry.id === taskIdSelected;
|
||||
});
|
||||
}
|
||||
if (!dataRow && this.selectFirstRow) {
|
||||
dataRow = this.rows[0];
|
||||
}
|
||||
if (dataRow) {
|
||||
dataRow.isSelected = true;
|
||||
this.currentInstanceId = dataRow.entry.id;
|
||||
}
|
||||
} else {
|
||||
this.currentInstanceId = null;
|
||||
}
|
||||
}
|
||||
|
||||
isListEmpty(): boolean {
|
||||
return !this.rows || this.rows.length === 0;
|
||||
}
|
||||
|
||||
updatePagination(pagination: PaginationModel) {
|
||||
this.size = pagination.maxItems;
|
||||
this.skipCount = pagination.skipCount;
|
||||
this.pagination.next(pagination);
|
||||
this.reload();
|
||||
}
|
||||
|
||||
onRowClick(item: DataRowEvent) {
|
||||
this.currentInstanceId = item.value.getValue('entry.id');
|
||||
this.rowClick.emit(this.currentInstanceId);
|
||||
}
|
||||
|
||||
onRowSelect(event: CustomEvent) {
|
||||
this.selectedInstances = [...event.detail.selection];
|
||||
this.rowsSelected.emit(this.selectedInstances);
|
||||
}
|
||||
|
||||
onRowUnselect(event: CustomEvent) {
|
||||
this.selectedInstances = [...event.detail.selection];
|
||||
this.rowsSelected.emit(this.selectedInstances);
|
||||
}
|
||||
|
||||
onRowKeyUp(event: CustomEvent) {
|
||||
if (event.detail.keyboardEvent.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
this.currentInstanceId = event.detail.row.getValue('entry.id');
|
||||
this.rowClick.emit(this.currentInstanceId);
|
||||
}
|
||||
}
|
||||
|
||||
private createRequestNode() {
|
||||
|
||||
let requestNode = {
|
||||
appName: this.applicationName,
|
||||
assignee: this.assignee,
|
||||
id: this.id,
|
||||
name: this.name,
|
||||
parentTaskId: this.parentTaskId,
|
||||
processDefinitionId: this.processDefinitionId,
|
||||
processInstanceId: this.processInstanceId,
|
||||
status: this.status,
|
||||
maxItems: this.size,
|
||||
skipCount: this.skipCount,
|
||||
sorting: this.sorting
|
||||
};
|
||||
return new TaskQueryCloudRequestModel(requestNode);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,145 @@
|
||||
/*!
|
||||
* @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 { ObjectDataColumn } from '@alfresco/adf-core';
|
||||
|
||||
export const fakeTaskCloudList = {
|
||||
list: {
|
||||
entries: [
|
||||
{
|
||||
entry: {
|
||||
serviceName: 'maurizio-test-rb',
|
||||
serviceFullName: 'maurizio-test-rb',
|
||||
serviceVersion: '',
|
||||
appName: 'save-the-cheerleader',
|
||||
appVersion: '',
|
||||
serviceType: null,
|
||||
id: '890b0e1c-c252-11e8-b5c5-0a58646004c7',
|
||||
assignee: null,
|
||||
name: 'SimpleStandaloneTask',
|
||||
description: 'Task description',
|
||||
createdDate: 1538052037711,
|
||||
dueDate: null,
|
||||
claimedDate: null,
|
||||
priority: 0,
|
||||
category: null,
|
||||
processDefinitionId: null,
|
||||
processInstanceId: null,
|
||||
status: 'CREATED',
|
||||
owner: 'superadminuser',
|
||||
parentTaskId: null,
|
||||
lastModified: 1538052037711,
|
||||
lastModifiedTo: null,
|
||||
lastModifiedFrom: null,
|
||||
standAlone: true
|
||||
}
|
||||
},
|
||||
{
|
||||
entry: {
|
||||
serviceName: 'maurizio-test-rb',
|
||||
serviceFullName: 'maurizio-test-rb',
|
||||
serviceVersion: '',
|
||||
appName: 'save-the-cheerleader',
|
||||
appVersion: '',
|
||||
serviceType: null,
|
||||
id: '8962cb0e-c252-11e8-b5c5-0a58646004c7',
|
||||
assignee: null,
|
||||
name: 'SimpleStandaloneTask',
|
||||
description: 'Task description',
|
||||
createdDate: 1538052038286,
|
||||
dueDate: null,
|
||||
claimedDate: null,
|
||||
priority: 0,
|
||||
category: null,
|
||||
processDefinitionId: null,
|
||||
processInstanceId: null,
|
||||
status: 'CREATED',
|
||||
owner: 'superadminuser',
|
||||
parentTaskId: null,
|
||||
lastModified: 1538052038286,
|
||||
lastModifiedTo: null,
|
||||
lastModifiedFrom: null,
|
||||
standAlone: true
|
||||
}
|
||||
}
|
||||
],
|
||||
pagination: {
|
||||
skipCount: 0,
|
||||
maxItems: 100,
|
||||
count: 2,
|
||||
hasMoreItems: false,
|
||||
totalItems: 2
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export let fakeGlobalTask = {
|
||||
list: {
|
||||
entries: [
|
||||
{
|
||||
entry: {
|
||||
serviceName: 'test-ciprian2-rb',
|
||||
serviceFullName: 'test-ciprian2-rb',
|
||||
serviceVersion: '',
|
||||
appName: 'test-ciprian2',
|
||||
appVersion: '',
|
||||
serviceType: null,
|
||||
id: '11fe013d-c263-11e8-b75b-0a5864600540',
|
||||
assignee: null,
|
||||
name: 'standalone-subtask',
|
||||
description: null,
|
||||
createdDate: 1538059139420,
|
||||
dueDate: null,
|
||||
claimedDate: null,
|
||||
priority: 0,
|
||||
category: null,
|
||||
processDefinitionId: null,
|
||||
processInstanceId: null,
|
||||
status: 'CREATED',
|
||||
owner: 'devopsuser',
|
||||
parentTaskId: '71fda20b-c25b-11e8-b75b-0a5864600540',
|
||||
lastModified: 1538059139420,
|
||||
lastModifiedTo: null,
|
||||
lastModifiedFrom: null,
|
||||
standAlone: true
|
||||
}
|
||||
}
|
||||
],
|
||||
pagination: {
|
||||
skipCount: 0,
|
||||
maxItems: 100,
|
||||
count: 1,
|
||||
hasMoreItems: false,
|
||||
totalItems: 1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export let fakeCustomSchema =
|
||||
[
|
||||
new ObjectDataColumn({
|
||||
'key': 'fakeName',
|
||||
'type': 'text',
|
||||
'title': 'ADF_TASK_LIST.PROPERTIES.FAKE',
|
||||
'sortable': true
|
||||
}),
|
||||
new ObjectDataColumn({
|
||||
'key': 'fakeTaskName',
|
||||
'type': 'text',
|
||||
'title': 'ADF_TASK_LIST.PROPERTIES.TASK_FAKE',
|
||||
'sortable': true
|
||||
})
|
||||
];
|
@@ -0,0 +1,70 @@
|
||||
/*!
|
||||
* @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 { TaskListCloudSortingModel } from './task-list-sorting.model';
|
||||
|
||||
export class TaskQueryCloudRequestModel {
|
||||
appName: string;
|
||||
appVersion?: string;
|
||||
assignee?: string;
|
||||
claimedDate?: string;
|
||||
createdDate?: Date;
|
||||
description?: string;
|
||||
dueDate?: null;
|
||||
id?: string;
|
||||
name?: string;
|
||||
owner?: string;
|
||||
parentTaskId?: string;
|
||||
priority?: number;
|
||||
processDefinitionId?: string;
|
||||
processInstanceId?: string;
|
||||
serviceFullName?: string;
|
||||
serviceName?: string;
|
||||
serviceType?: string;
|
||||
serviceVersion?: string;
|
||||
status?: string;
|
||||
maxItems: number;
|
||||
skipCount: number;
|
||||
sorting?: TaskListCloudSortingModel[];
|
||||
|
||||
constructor(obj?: any) {
|
||||
if (obj) {
|
||||
this.appName = obj.appName;
|
||||
this.appVersion = obj.appVersion;
|
||||
this.assignee = obj.assignee;
|
||||
this.claimedDate = obj.claimedDate;
|
||||
this.createdDate = obj.createdDate;
|
||||
this.description = obj.description;
|
||||
this.dueDate = obj.dueDate;
|
||||
this.id = obj.id;
|
||||
this.name = obj.name;
|
||||
this.owner = obj.owner;
|
||||
this.parentTaskId = obj.parentTaskId;
|
||||
this.priority = obj.priority;
|
||||
this.processDefinitionId = obj.processDefinitionId;
|
||||
this.processInstanceId = obj.processInstanceId;
|
||||
this.serviceFullName = obj.serviceFullName;
|
||||
this.serviceName = obj.serviceName;
|
||||
this.serviceType = obj.serviceType;
|
||||
this.serviceVersion = obj.serviceVersion;
|
||||
this.status = obj.status;
|
||||
this.maxItems = obj.maxItems;
|
||||
this.skipCount = obj.skipCount;
|
||||
this.sorting = obj.sorting;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
/*!
|
||||
* @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 TaskListCloudSortingModel {
|
||||
orderBy: string;
|
||||
direction: string;
|
||||
|
||||
constructor(obj: any) {
|
||||
if (obj) {
|
||||
this.orderBy = obj.orderBy;
|
||||
this.direction = obj.direction;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
/*!
|
||||
* @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 let taskPresetsCloudDefaultModel = {
|
||||
'default': [
|
||||
{
|
||||
'key': 'name',
|
||||
'type': 'text',
|
||||
'title': 'ADF_TASK_LIST.PROPERTIES.NAME',
|
||||
'sortable': true
|
||||
},
|
||||
{
|
||||
'key': 'created',
|
||||
'type': 'text',
|
||||
'title': 'ADF_TASK_LIST.PROPERTIES.CREATED',
|
||||
'cssClass': 'hidden',
|
||||
'sortable': true
|
||||
},
|
||||
{
|
||||
'key': 'assignee',
|
||||
'type': 'text',
|
||||
'title': 'ADF_TASK_LIST.PROPERTIES.ASSIGNEE',
|
||||
'cssClass': 'hidden',
|
||||
'sortable': true
|
||||
}
|
||||
]
|
||||
};
|
@@ -0,0 +1,24 @@
|
||||
/*!
|
||||
* @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 * from './components/task-list-cloud.component';
|
||||
|
||||
export * from './models/filter-cloud-model';
|
||||
export * from './models/task-list-sorting.model';
|
||||
export * from './models/task-preset-cloud.model';
|
||||
|
||||
export * from './task-list-cloud.module';
|
@@ -0,0 +1,134 @@
|
||||
/*!
|
||||
* @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 { async } from '@angular/core/testing';
|
||||
import { setupTestBed } from '@alfresco/adf-core';
|
||||
import { fakeTaskCloudList } from '../mock/fakeTaskResponseMock';
|
||||
import { AlfrescoApiServiceMock, LogService, AppConfigService, StorageService, CoreModule } from '@alfresco/adf-core';
|
||||
import { TaskListCloudService } from './task-list-cloud.service';
|
||||
import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model';
|
||||
|
||||
describe('Activiti TaskList Cloud Service', () => {
|
||||
|
||||
let service: TaskListCloudService;
|
||||
let alfrescoApiMock: AlfrescoApiServiceMock;
|
||||
|
||||
function returFakeTaskListResults() {
|
||||
return {
|
||||
oauth2Auth: {
|
||||
callCustomApi : () => {
|
||||
return Promise.resolve(fakeTaskCloudList);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function returnCallQueryParameters() {
|
||||
return {
|
||||
oauth2Auth: {
|
||||
callCustomApi : (queryUrl, operation, context, queryParams) => {
|
||||
return Promise.resolve(queryParams);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function returnCallUrl() {
|
||||
return {
|
||||
oauth2Auth: {
|
||||
callCustomApi : (queryUrl, operation, context, queryParams) => {
|
||||
return Promise.resolve(queryUrl);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
CoreModule.forRoot()
|
||||
]
|
||||
});
|
||||
|
||||
beforeEach(async(() => {
|
||||
alfrescoApiMock = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService() );
|
||||
service = new TaskListCloudService(alfrescoApiMock,
|
||||
new AppConfigService(null),
|
||||
new LogService(new AppConfigService(null)));
|
||||
}));
|
||||
|
||||
it('should return the tasks', (done) => {
|
||||
let taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: 'fakeName' };
|
||||
spyOn(alfrescoApiMock, 'getInstance').and.callFake(returFakeTaskListResults);
|
||||
service.getTaskByRequest(taskRequest).subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res).not.toBeNull();
|
||||
expect(res.list.entries.length).toBe(2);
|
||||
expect(res.list.entries[0].entry.appName).toBe('save-the-cheerleader');
|
||||
expect(res.list.entries[1].entry.appName).toBe('save-the-cheerleader');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should append to the call all the parameters', (done) => {
|
||||
let taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service' };
|
||||
spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnCallQueryParameters);
|
||||
service.getTaskByRequest(taskRequest).subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res).not.toBeNull();
|
||||
expect(res.skipCount).toBe(0);
|
||||
expect(res.maxItems).toBe(20);
|
||||
expect(res.service).toBe('fake-service');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should concat the app name to the request url', (done) => {
|
||||
let taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service' };
|
||||
spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnCallUrl);
|
||||
service.getTaskByRequest(taskRequest).subscribe((requestUrl) => {
|
||||
expect(requestUrl).toBeDefined();
|
||||
expect(requestUrl).not.toBeNull();
|
||||
expect(requestUrl).toContain('/fakeName-query/v1/tasks');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should concat the sorting to append as parameters', (done) => {
|
||||
let taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: 'fakeName', skipCount: 0, maxItems: 20, service: 'fake-service',
|
||||
sorting: [{ orderBy: 'NAME', direction: 'DESC'}, { orderBy: 'TITLE', direction: 'ASC'}] };
|
||||
spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnCallQueryParameters);
|
||||
service.getTaskByRequest(taskRequest).subscribe((res) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res).not.toBeNull();
|
||||
expect(res.sort).toBe('NAME,DESC&TITLE,ASC');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an error when app name is not specified', (done) => {
|
||||
let taskRequest: TaskQueryCloudRequestModel = <TaskQueryCloudRequestModel> { appName: null };
|
||||
spyOn(alfrescoApiMock, 'getInstance').and.callFake(returnCallUrl);
|
||||
service.getTaskByRequest(taskRequest).subscribe(
|
||||
() => { },
|
||||
(error) => {
|
||||
expect(error).toBe('Appname not configured');
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
});
|
@@ -0,0 +1,92 @@
|
||||
/*!
|
||||
* @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 { AlfrescoApiService, AppConfigService, LogService } from '@alfresco/adf-core';
|
||||
import { TaskQueryCloudRequestModel } from '../models/filter-cloud-model';
|
||||
import { Observable, from, throwError } from 'rxjs';
|
||||
import { TaskListCloudSortingModel } from '../models/task-list-sorting.model';
|
||||
|
||||
@Injectable()
|
||||
export class TaskListCloudService {
|
||||
|
||||
constructor(private apiService: AlfrescoApiService,
|
||||
private appConfigService: AppConfigService,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
contentTypes = ['application/json'];
|
||||
accepts = ['application/json'];
|
||||
|
||||
getTaskByRequest(requestNode: TaskQueryCloudRequestModel): Observable<any> {
|
||||
if (requestNode.appName) {
|
||||
let queryUrl = this.buildQueryUrl(requestNode);
|
||||
let queryParams = this.buildQueryParams(requestNode);
|
||||
let sortingParams = this.buildSortingParam(requestNode.sorting);
|
||||
if (sortingParams) {
|
||||
queryParams['sort'] = sortingParams;
|
||||
}
|
||||
return from(this.apiService.getInstance()
|
||||
.oauth2Auth.callCustomApi(queryUrl, 'GET',
|
||||
null, queryParams, null,
|
||||
null, null, null, ['application/json'],
|
||||
['application/json'], Object, null, null)
|
||||
);
|
||||
} else {
|
||||
this.logService.error('Appname is mandatory for querying task');
|
||||
return throwError('Appname not configured');
|
||||
}
|
||||
}
|
||||
|
||||
private buildQueryUrl(requestNode: TaskQueryCloudRequestModel) {
|
||||
return `${this.appConfigService.get('bpmHost', '')}/${requestNode.appName}-query/v1/tasks`;
|
||||
}
|
||||
|
||||
private buildQueryParams(requestNode: TaskQueryCloudRequestModel) {
|
||||
let queryParam = {};
|
||||
for (let property in requestNode) {
|
||||
if (requestNode.hasOwnProperty(property) &&
|
||||
!this.isExcludedField(property) &&
|
||||
this.isPropertyValueValid(requestNode, property)) {
|
||||
queryParam[property] = requestNode[property];
|
||||
}
|
||||
}
|
||||
return queryParam;
|
||||
}
|
||||
|
||||
private isExcludedField(property) {
|
||||
return property === 'appName' || property === 'sorting';
|
||||
}
|
||||
|
||||
private isPropertyValueValid(requestNode, property) {
|
||||
return requestNode[property] !== '' && requestNode[property] !== null && requestNode[property] !== undefined;
|
||||
}
|
||||
|
||||
private buildSortingParam(sortings: TaskListCloudSortingModel[]): string {
|
||||
let finalSorting: string = '';
|
||||
if (sortings) {
|
||||
for (let sort of sortings) {
|
||||
if (!finalSorting) {
|
||||
finalSorting = `${sort.orderBy},${sort.direction}`;
|
||||
} else {
|
||||
finalSorting = `${finalSorting}&${sort.orderBy},${sort.direction}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
return encodeURI(finalSorting);
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
import { TaskListCloudModule } from './task-list-cloud.module';
|
||||
|
||||
describe('TaskListCloudModule', () => {
|
||||
let taskListCloudModule: TaskListCloudModule;
|
||||
|
||||
beforeEach(() => {
|
||||
taskListCloudModule = new TaskListCloudModule();
|
||||
});
|
||||
|
||||
it('should create an instance', () => {
|
||||
expect(taskListCloudModule).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,26 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MaterialModule } from '../material.module';
|
||||
import { TaskListCloudComponent } from './components/task-list-cloud.component';
|
||||
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
||||
import { TranslateLoaderService, DataTableModule, TemplateModule } from '@alfresco/adf-core';
|
||||
import { TaskListCloudService } from './services/task-list-cloud.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
}),
|
||||
MaterialModule,
|
||||
DataTableModule,
|
||||
TemplateModule
|
||||
],
|
||||
declarations: [TaskListCloudComponent],
|
||||
exports: [TaskListCloudComponent],
|
||||
providers: [TaskListCloudService]
|
||||
})
|
||||
export class TaskListCloudModule { }
|
@@ -0,0 +1,51 @@
|
||||
/*!
|
||||
* @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 { NgModule } from '@angular/core';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { TaskListCloudModule } from '../task-list-cloud.module';
|
||||
import {
|
||||
AlfrescoApiService,
|
||||
AlfrescoApiServiceMock,
|
||||
AppConfigService,
|
||||
AppConfigServiceMock,
|
||||
StorageService,
|
||||
LogService,
|
||||
TranslationService,
|
||||
TranslationMock,
|
||||
UserPreferencesService,
|
||||
ContextMenuModule
|
||||
} from '@alfresco/adf-core';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
HttpClientModule,
|
||||
NoopAnimationsModule,
|
||||
TaskListCloudModule,
|
||||
ContextMenuModule
|
||||
],
|
||||
providers: [
|
||||
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
|
||||
{ provide: AppConfigService, useClass: AppConfigServiceMock },
|
||||
{ provide: TranslationService, useClass: TranslationMock },
|
||||
StorageService,
|
||||
LogService,
|
||||
UserPreferencesService
|
||||
]
|
||||
})
|
||||
export class TaskListTestingModule {}
|
@@ -18,7 +18,6 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { AppListCloudModule } from '../app-list-cloud.module';
|
||||
import {
|
||||
AlfrescoApiService,
|
||||
AlfrescoApiServiceMock,
|
||||
@@ -27,21 +26,24 @@ import {
|
||||
StorageService,
|
||||
LogService,
|
||||
TranslationService,
|
||||
TranslationMock
|
||||
TranslationMock,
|
||||
UserPreferencesService,
|
||||
ContextMenuModule
|
||||
} from '@alfresco/adf-core';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
HttpClientModule,
|
||||
NoopAnimationsModule,
|
||||
AppListCloudModule
|
||||
ContextMenuModule
|
||||
],
|
||||
providers: [
|
||||
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
|
||||
{ provide: AppConfigService, useClass: AppConfigServiceMock },
|
||||
{ provide: TranslationService, useClass: TranslationMock },
|
||||
StorageService,
|
||||
LogService
|
||||
LogService,
|
||||
UserPreferencesService
|
||||
]
|
||||
})
|
||||
export class AppListTestingModule {}
|
||||
export class ProcessServiceCloudTestingModule {}
|
@@ -16,4 +16,6 @@
|
||||
*/
|
||||
|
||||
export * from './lib/process-services-cloud.module';
|
||||
export * from './lib/app-list-cloud/app-list-cloud.module';
|
||||
export * from './lib/app-list-cloud/public-api';
|
||||
export * from './lib/task-list-cloud/public-api';
|
||||
export * from './lib/task-cloud/public-api';
|
@@ -1,41 +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 'core-js/es7/reflect';
|
||||
import 'zone.js/dist/zone';
|
||||
import 'zone.js/dist/zone-testing';
|
||||
import { getTestBed } from '@angular/core/testing';
|
||||
import {
|
||||
BrowserDynamicTestingModule,
|
||||
platformBrowserDynamicTesting
|
||||
} from '@angular/platform-browser-dynamic/testing';
|
||||
|
||||
declare const require: any;
|
||||
|
||||
// First, initialize the Angular testing environment.
|
||||
getTestBed().initTestEnvironment(
|
||||
BrowserDynamicTestingModule,
|
||||
platformBrowserDynamicTesting()
|
||||
);
|
||||
|
||||
declare const pdfjsLib: any;
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc = 'node_modules/pdfjs-dist/build/pdf.worker.min.js';
|
||||
|
||||
// Then we find all the tests.
|
||||
const context = require.context('./', true, /\.spec\.ts$/);
|
||||
// And load the modules.
|
||||
context.keys().map(context);
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../out-tsc/spec",
|
||||
"types": [
|
||||
|
Reference in New Issue
Block a user