mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-06-30 18:15:11 +00:00
[ADF-3540] Start Task Cloud by cli (#3954)
* [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 * Add a cloud component as example * Skip the scss style * 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 * Fix process service cloud path * Remove useless file * [ADF-3540] Start Task Component APS2 * Generated startTaskCloudModule * Generated start-task-cloud component by cli * Used start-task-cloud in the demo shell * * Added FormModule instead of CoreModule * Added StartTaskTestingModule * Refactored startTaskCloud Component * * Used FlexLayout * Used Keylock api to fetch users * Removed all css * Refactored start-task-cloud component * Removed form field from the starttask form * Created UsedCloud model * Added unit test to the recent changes * Added mock objects * * Added unit test to the startTaskCloud component * * Added documentation about startTaskCLoud component * Changed runtimeBundle to appName * Changed defaultTaskName to name * * Generated people-cloud component * Created initialUserName pipe * * Fetching roles by userId * Filtering Users with required roles * Removed duplicates * Generated initial-user-name pipe * Generated people-cloud component * Created roleCloud module * * Rebased with development branch * Created start-task-cloud-demo component in the demo-shell * * Added unit tests to the start-task-cloud service * Added unit test to the people-cloud component and userInitail pipe * Updated start-task unit tests to the recent changes * Created mock data * * Updated people-cloud component with error message* Updated unit tests * * Included StartTaskCloud component in the demoShell* Created startTask demo component* Added create task button in the tasklist demo component * * Added lodash * * Fixed lodash import * Add the start task into the cloud demo * Fix the lodash import and @type * Show the My task once the task has been created * first change * [ADF-3540] Improved start task component * [ADF-3540] Fixed expression changed error * [ADF-3540] Refactored code * [ADF-3540] Fix lodash import error * [ADF-3540] Remove lodash dependency * [ADF-3540] Refatored code * tmp * [ADF-3540] Show/Hide current user as part of list * [ADF-3340] Assign new task to current user when no assignee selected * [ADF-3540] Rebased the latest changes * [ADF-3540] Refactored code * [ADF-3540] Improved user search logic for people component * [ADF-3540] Moved user services to Core module * [ADF-3540] Modified translation keys * Add process-services-cloud into the license rule * Fix wrong import for prod build * Add license header * Fix unit tests * Fix proxy karma for content * Fix proxy karma for process services * Fix proxy karma for process cloud
This commit is contained in:
parent
5bea17fa6c
commit
2f0f33643b
@ -121,7 +121,8 @@ import { AppExtensionsModule } from './extensions/extensions.module';
|
||||
ReportIssueComponent,
|
||||
TaskListCloudDemoComponent,
|
||||
ProcessListCloudExampleComponent,
|
||||
TreeViewSampleComponent
|
||||
TreeViewSampleComponent,
|
||||
TaskListCloudDemoComponent
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
|
@ -141,11 +141,13 @@ export const appRoutes: Routes = [
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: CloudComponent
|
||||
component: CloudComponent,
|
||||
canActivate: [AuthGuard]
|
||||
},
|
||||
{
|
||||
path: ':applicationName/tasks',
|
||||
component: TaskListCloudDemoComponent
|
||||
component: TaskListCloudDemoComponent,
|
||||
canActivate: [AuthGuard]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -15,21 +15,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
@Component({
|
||||
selector: 'app-cloud',
|
||||
templateUrl: './cloud.component.html',
|
||||
styleUrls: ['./cloud.component.scss']
|
||||
})
|
||||
export class CloudComponent implements OnInit {
|
||||
export class CloudComponent {
|
||||
|
||||
constructor(private router: Router) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
onAppClick(app) {
|
||||
this.router.navigate([`/cloud/${app.name}/tasks/`]);
|
||||
}
|
||||
|
@ -1,15 +1,31 @@
|
||||
<h2>TASK LIST CLOUD DEMO</h2>
|
||||
<adf-cloud-task-filters
|
||||
[appName]="applicationName"
|
||||
[showIcons]="true"
|
||||
(filterClick)="onFilterSelected($event)">
|
||||
</adf-cloud-task-filters>
|
||||
<div fxLayout="row" fxLayout.xs="column">
|
||||
<div fxFlexOrder="1" fxFlex="15%">
|
||||
<adf-sidebar-action-menu [expanded]="true" [width]="205" title="{{'ADF_SIDEBAR_ACTION_MENU.BUTTON.CREATE' | translate}}">
|
||||
<mat-icon sidebar-menu-title-icon>arrow_drop_down</mat-icon>
|
||||
<div sidebar-menu-options>
|
||||
<button mat-menu-item data-automation-id="btn-start-task" (click)="onStartTask()">
|
||||
<mat-icon>assessment</mat-icon>
|
||||
<span>{{'ADF_SIDEBAR_ACTION_MENU.BUTTON.NEW_TASK' | translate}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</adf-sidebar-action-menu>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="showStartTask">
|
||||
<adf-cloud-start-task [appName]="applicationName" (success)="onStartTaskSuccess()" (cancel)="onCancelStartTask()">
|
||||
</adf-cloud-start-task>
|
||||
</div>
|
||||
<div *ngIf="!showStartTask">
|
||||
<adf-cloud-task-filters [appName]="applicationName" [filterParam]="filterTaskParam" [showIcons]="true" (filterClick)="onFilterSelected($event)">
|
||||
</adf-cloud-task-filters>
|
||||
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
{{filterName}}
|
||||
{{filterName | translate}}
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
Customise your filter
|
||||
@ -62,25 +78,21 @@
|
||||
</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>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
<div *ngIf="isFilterLoaded">
|
||||
<adf-cloud-task-list #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" class="full-width name-column ellipsis-cell"></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" type="date" title="Created Date" [format]="'timeAgo'"></data-column>
|
||||
</data-columns>
|
||||
</adf-cloud-task-list>
|
||||
<adf-pagination [target]="taskCloud" (changePageSize)="onChangePageSize($event)">
|
||||
</adf-pagination>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -21,6 +21,7 @@ import { UserPreferencesService } from '@alfresco/adf-core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material';
|
||||
|
||||
@Component({
|
||||
selector: 'app-task-list-cloud-demo',
|
||||
@ -36,14 +37,16 @@ export class TaskListCloudDemoComponent implements OnInit {
|
||||
sortDirectionFormControl: FormControl;
|
||||
|
||||
appDefinitionList: Observable<any>;
|
||||
applicationName: string = '';
|
||||
applicationName;
|
||||
status: string = '';
|
||||
sort: string = '';
|
||||
isFilterLoaded = false;
|
||||
showStartTask = false;
|
||||
sortDirection: string = 'ASC';
|
||||
filterName: string;
|
||||
clickedRow: string = '';
|
||||
selectTask: string = '';
|
||||
filterTaskParam;
|
||||
sortArray: TaskListCloudSortingModel [];
|
||||
|
||||
columns = [
|
||||
@ -55,13 +58,13 @@ export class TaskListCloudDemoComponent implements OnInit {
|
||||
];
|
||||
|
||||
constructor(
|
||||
public dialog: MatDialog,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private userPreference: UserPreferencesService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.isFilterLoaded = false;
|
||||
this.route.params.subscribe(params => {
|
||||
this.applicationName = params.applicationName;
|
||||
});
|
||||
@ -117,6 +120,19 @@ export class TaskListCloudDemoComponent implements OnInit {
|
||||
this.router.navigate([`/cloud/${this.applicationName}/tasks/`], {queryParams: queryParams});
|
||||
}
|
||||
|
||||
onStartTask() {
|
||||
this.showStartTask = true;
|
||||
}
|
||||
|
||||
onStartTaskSuccess() {
|
||||
this.showStartTask = false;
|
||||
this.filterTaskParam = { name: 'My tasks'};
|
||||
}
|
||||
|
||||
onCancelStartTask() {
|
||||
this.showStartTask = false;
|
||||
}
|
||||
|
||||
onChangePageSize(event) {
|
||||
this.userPreference.paginationSize = event.maxItems;
|
||||
}
|
||||
@ -124,5 +140,4 @@ export class TaskListCloudDemoComponent implements OnInit {
|
||||
onRowClick($event) {
|
||||
this.clickedRow = $event;
|
||||
}
|
||||
|
||||
}
|
||||
|
BIN
docs/docassets/images/adf-cloud-start-task.png
Normal file
BIN
docs/docassets/images/adf-cloud-start-task.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
37
docs/process-services-cloud/start-task-cloud.component.md
Normal file
37
docs/process-services-cloud/start-task-cloud.component.md
Normal file
@ -0,0 +1,37 @@
|
||||
---
|
||||
Added: v3.0.0
|
||||
Status: Active
|
||||
Last reviewed: 2018-23-10
|
||||
---
|
||||
|
||||
# Start Task Cloud Component
|
||||
|
||||
Creates/Starts new task for the specified app
|
||||
|
||||

|
||||
|
||||
## Basic Usage
|
||||
|
||||
```html
|
||||
<adf-cloud-start-task
|
||||
[appName]="YOUR_APP_NAME">
|
||||
</adf-cloud-start-task>
|
||||
```
|
||||
|
||||
## Class members
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| ---- | ---- | ------------- | ----------- |
|
||||
| appName | `string` | | (required) The name of the app. |
|
||||
| name | `string` | | Name of the task. |
|
||||
| maxNameLength | `number` | 255 | Maximum length of the task name. |
|
||||
|
||||
### Events
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| cancel | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<void>` | Emitted when the cancel button is clicked by the user. |
|
||||
| error | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when an error occurs. |
|
||||
| success | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<any>` | Emitted when the task is successfully created. |
|
@ -3,32 +3,32 @@
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
basePath: '../../',
|
||||
|
||||
files: [
|
||||
{pattern: '../../node_modules/core-js/client/core.js', included: true, watched: false},
|
||||
{pattern: '../../node_modules/tslib/tslib.js', included: true, watched: false},
|
||||
{pattern: '../../node_modules/hammerjs/hammer.min.js', included: true, watched: false},
|
||||
{pattern: '../../node_modules/hammerjs/hammer.min.js.map', included: false, watched: false},
|
||||
{pattern: 'node_modules/core-js/client/core.js', included: true, watched: false},
|
||||
{pattern: 'node_modules/tslib/tslib.js', included: true, watched: false},
|
||||
{pattern: 'node_modules/hammerjs/hammer.min.js', included: true, watched: false},
|
||||
{pattern: 'node_modules/hammerjs/hammer.min.js.map', included: false, watched: false},
|
||||
|
||||
// pdf-js
|
||||
{pattern: '../../node_modules/pdfjs-dist/build/pdf.js', included: true, watched: false},
|
||||
{pattern: '../../node_modules/pdfjs-dist/build/pdf.worker.js', included: true, watched: false},
|
||||
{pattern: '../../node_modules/pdfjs-dist/web/pdf_viewer.js', included: true, watched: false},
|
||||
{pattern: 'node_modules/pdfjs-dist/build/pdf.js', included: true, watched: false},
|
||||
{pattern: 'node_modules/pdfjs-dist/build/pdf.worker.js', included: true, watched: false},
|
||||
{pattern: 'node_modules/pdfjs-dist/web/pdf_viewer.js', included: true, watched: false},
|
||||
|
||||
{
|
||||
pattern: '../../node_modules/@angular/material/prebuilt-themes/indigo-pink.css',
|
||||
pattern: 'node_modules/@angular/material/prebuilt-themes/indigo-pink.css',
|
||||
included: true,
|
||||
watched: false
|
||||
},
|
||||
|
||||
{pattern: '../../node_modules/alfresco-js-api/dist/alfresco-js-api.min.js', included: true, watched: false},
|
||||
{pattern: '../../node_modules/moment/min/moment.min.js', included: true, watched: false},
|
||||
{pattern: 'node_modules/alfresco-js-api/dist/alfresco-js-api.min.js', included: true, watched: false},
|
||||
{pattern: 'node_modules/moment/min/moment.min.js', included: true, watched: false},
|
||||
|
||||
{pattern: '../content-services/i18n/**/en.json', included: false, served: true, watched: false},
|
||||
{pattern: '../core/i18n/**/en.json', included: false, served: true, watched: false},
|
||||
{pattern: '../content-services/**/*.ts', included: false, served: true, watched: false},
|
||||
{pattern: '../config/app.config.json', included: false, served: true, watched: false},
|
||||
{pattern: 'lib/content-services/i18n/**/en.json', included: false, served: true, watched: false},
|
||||
{pattern: 'lib/core/i18n/**/en.json', included: false, served: true, watched: false},
|
||||
{pattern: 'lib/content-services/**/*.ts', included: false, served: true, watched: false},
|
||||
{pattern: 'lib/config/app.config.json', included: false, served: true, watched: false},
|
||||
],
|
||||
|
||||
frameworks: ['jasmine-ajax', 'jasmine', '@angular-devkit/build-angular'],
|
||||
|
28
lib/core/userinfo/models/identity-role.model.ts
Normal file
28
lib/core/userinfo/models/identity-role.model.ts
Normal file
@ -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 IdentityRoleModel {
|
||||
|
||||
id: string;
|
||||
name: string;
|
||||
|
||||
constructor(obj?: any) {
|
||||
if (obj) {
|
||||
this.id = obj.id || null;
|
||||
this.name = obj.name || null;
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
export class IdentityUserModel {
|
||||
|
||||
id: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
|
@ -22,5 +22,6 @@ export * from './services/identity-user.service';
|
||||
export * from './models/bpm-user.model';
|
||||
export * from './models/ecm-user.model';
|
||||
export * from './models/identity-user.model';
|
||||
export * from './models/identity-role.model';
|
||||
|
||||
export * from './userinfo.module';
|
||||
|
@ -16,13 +16,31 @@
|
||||
*/
|
||||
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { throwError, of } from 'rxjs';
|
||||
import { IdentityUserService } from '../services/identity-user.service';
|
||||
import { setupTestBed } from '../../testing/setupTestBed';
|
||||
import { CoreModule } from '../../core.module';
|
||||
import { mockToken } from './../../mock/jwt-helper.service.spec';
|
||||
import { IdentityUserModel } from '../models/identity-user.model';
|
||||
import { IdentityRoleModel } from '../models/identity-role.model';
|
||||
|
||||
describe('IdentityUserService', () => {
|
||||
|
||||
const mockUsers = [
|
||||
{ id: 'fake-id-1', username: 'first-name-1 last-name-1', firstName: 'first-name-1', lastName: 'last-name-1', email: 'abc@xyz.com' },
|
||||
{ id: 'fake-id-2', username: 'first-name-2 last-name-2', firstName: 'first-name-2', lastName: 'last-name-2', email: 'abcd@xyz.com'},
|
||||
{ id: 'fake-id-3', username: 'first-name-3 last-name-3', firstName: 'first-name-3', lastName: 'last-name-3', email: 'abcde@xyz.com' }
|
||||
];
|
||||
|
||||
const mockRoles = [
|
||||
{ id: 'id-1', name: 'MOCK-ADMIN-ROLE'},
|
||||
{ id: 'id-2', name: 'MOCK-USER-ROLE'},
|
||||
{ id: 'id-3', name: 'MOCK_MODELER-ROLE' },
|
||||
{ id: 'id-4', name: 'MOCK-ROLE-1' },
|
||||
{ id: 'id-5', name: 'MOCK-ROLE-2'}
|
||||
];
|
||||
|
||||
let service: IdentityUserService;
|
||||
|
||||
setupTestBed({
|
||||
@ -46,7 +64,7 @@ describe('IdentityUserService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should able to fetch identity user info from Jwt token', (done) => {
|
||||
it('should fetch identity user info from Jwt token', (done) => {
|
||||
localStorage.setItem('access_token', mockToken);
|
||||
service.getCurrentUserInfo().subscribe(
|
||||
(user) => {
|
||||
@ -58,4 +76,149 @@ describe('IdentityUserService', () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fetch users ', (done) => {
|
||||
spyOn(service, 'getUsers').and.returnValue(of(mockUsers));
|
||||
service.getUsers().subscribe(
|
||||
(res: IdentityUserModel[]) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res[0].id).toEqual('fake-id-1');
|
||||
expect(res[0].username).toEqual('first-name-1 last-name-1');
|
||||
expect(res[1].id).toEqual('fake-id-2');
|
||||
expect(res[1].username).toEqual('first-name-2 last-name-2');
|
||||
expect(res[2].id).toEqual('fake-id-3');
|
||||
expect(res[2].username).toEqual('first-name-3 last-name-3');
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('Should not fetch users if error occurred', (done) => {
|
||||
const errorResponse = new HttpErrorResponse({
|
||||
error: 'Mock Error',
|
||||
status: 404, statusText: 'Not Found'
|
||||
});
|
||||
|
||||
spyOn(service, 'getUsers').and.returnValue(throwError(errorResponse));
|
||||
service.getUsers()
|
||||
.subscribe(
|
||||
() => {
|
||||
fail('expected an error, not users');
|
||||
},
|
||||
(error) => {
|
||||
expect(error.status).toEqual(404);
|
||||
expect(error.statusText).toEqual('Not Found');
|
||||
expect(error.error).toEqual('Mock Error');
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should fetch roles by userId', (done) => {
|
||||
spyOn(service, 'getUserRoles').and.returnValue(of(mockRoles));
|
||||
service.getUserRoles('mock-user-id').subscribe(
|
||||
(res: IdentityRoleModel[]) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res[0].name).toEqual('MOCK-ADMIN-ROLE');
|
||||
expect(res[1].name).toEqual('MOCK-USER-ROLE');
|
||||
expect(res[4].name).toEqual('MOCK-ROLE-2');
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('Should not fetch roles if error occurred', (done) => {
|
||||
const errorResponse = new HttpErrorResponse({
|
||||
error: 'Mock Error',
|
||||
status: 404, statusText: 'Not Found'
|
||||
});
|
||||
|
||||
spyOn(service, 'getUserRoles').and.returnValue(throwError(errorResponse));
|
||||
|
||||
service.getUserRoles('mock-user-id')
|
||||
.subscribe(
|
||||
() => {
|
||||
fail('expected an error, not users');
|
||||
},
|
||||
(error) => {
|
||||
expect(error.status).toEqual(404);
|
||||
expect(error.statusText).toEqual('Not Found');
|
||||
expect(error.error).toEqual('Mock Error');
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should fetch users by roles', (done) => {
|
||||
spyOn(service, 'getUsers').and.returnValue(of(mockUsers));
|
||||
spyOn(service, 'getUserRoles').and.returnValue(of(mockRoles));
|
||||
|
||||
service.getUsersByRolesWithCurrentUser([mockRoles[0].name]).then(
|
||||
(res: IdentityUserModel[]) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res[0].id).toEqual('fake-id-1');
|
||||
expect(res[0].username).toEqual('first-name-1 last-name-1');
|
||||
expect(res[1].id).toEqual('fake-id-2');
|
||||
expect(res[1].username).toEqual('first-name-2 last-name-2');
|
||||
expect(res[2].id).toEqual('fake-id-3');
|
||||
expect(res[2].username).toEqual('first-name-3 last-name-3');
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('Should not fetch users by roles if error occurred', (done) => {
|
||||
const errorResponse = new HttpErrorResponse({
|
||||
error: 'Mock Error',
|
||||
status: 404, statusText: 'Not Found'
|
||||
});
|
||||
|
||||
spyOn(service, 'getUsers').and.returnValue(throwError(errorResponse));
|
||||
|
||||
service.getUsersByRolesWithCurrentUser([mockRoles[0].name])
|
||||
.catch(
|
||||
(error) => {
|
||||
expect(error.status).toEqual(404);
|
||||
expect(error.statusText).toEqual('Not Found');
|
||||
expect(error.error).toEqual('Mock Error');
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should fetch users by roles without current user', (done) => {
|
||||
spyOn(service, 'getUsers').and.returnValue(of(mockUsers));
|
||||
spyOn(service, 'getUserRoles').and.returnValue(of(mockRoles));
|
||||
spyOn(service, 'getCurrentUserInfo').and.returnValue(of(mockUsers[0]));
|
||||
|
||||
service.getUsersByRolesWithoutCurrentUser([mockRoles[0].name]).then(
|
||||
(res: IdentityUserModel[]) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res[0].id).toEqual('fake-id-2');
|
||||
expect(res[0].username).toEqual('first-name-2 last-name-2');
|
||||
expect(res[1].id).toEqual('fake-id-3');
|
||||
expect(res[1].username).toEqual('first-name-3 last-name-3');
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('Should not fetch users by roles without current user if error occurred', (done) => {
|
||||
const errorResponse = new HttpErrorResponse({
|
||||
error: 'Mock Error',
|
||||
status: 404, statusText: 'Not Found'
|
||||
});
|
||||
|
||||
spyOn(service, 'getCurrentUserInfo').and.returnValue(throwError(errorResponse));
|
||||
|
||||
service.getUsersByRolesWithoutCurrentUser([mockRoles[0].name])
|
||||
.catch(
|
||||
(error) => {
|
||||
expect(error.status).toEqual(404);
|
||||
expect(error.statusText).toEqual('Not Found');
|
||||
expect(error.error).toEqual('Mock Error');
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -16,9 +16,14 @@
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { of, Observable } from 'rxjs';
|
||||
import { of, Observable, from } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { IdentityUserModel } from '../models/identity-user.model';
|
||||
import { JwtHelperService } from './../../services/jwt-helper.service';
|
||||
import { JwtHelperService } from '../../services/jwt-helper.service';
|
||||
import { AppConfigService } from '../../app-config/app-config.service';
|
||||
import { AlfrescoApiService } from '../../services/alfresco-api.service';
|
||||
import { IdentityRoleModel } from '../models/identity-role.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@ -30,7 +35,10 @@ export class IdentityUserService {
|
||||
static USER_ACCESS_TOKEN = 'access_token';
|
||||
static USER_PREFERRED_USERNAME = 'preferred_username';
|
||||
|
||||
constructor(private helper: JwtHelperService) {}
|
||||
constructor(
|
||||
private helper: JwtHelperService,
|
||||
private apiService: AlfrescoApiService,
|
||||
private appConfigService: AppConfigService) {}
|
||||
|
||||
getCurrentUserInfo(): Observable<IdentityUserModel> {
|
||||
const fullName = this.getValueFromToken<string>(IdentityUserService.USER_NAME);
|
||||
@ -50,4 +58,93 @@ export class IdentityUserService {
|
||||
}
|
||||
return <T> value;
|
||||
}
|
||||
|
||||
getUsers(): Observable<IdentityUserModel[]> {
|
||||
const url = this.buildUserUrl();
|
||||
const httpMethod = 'GET', pathParams = {}, queryParams = {}, bodyParam = {}, headerParams = {},
|
||||
formParams = {}, authNames = [], contentTypes = ['application/json'], accepts = ['application/json'];
|
||||
|
||||
return from(this.apiService.getInstance().oauth2Auth.callCustomApi(
|
||||
url, httpMethod, pathParams, queryParams,
|
||||
headerParams, formParams, bodyParam, authNames,
|
||||
contentTypes, accepts, Object, null, null)
|
||||
).pipe(
|
||||
map((response: IdentityUserModel[]) => {
|
||||
return response;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
getUserRoles(userId: string): Observable<IdentityRoleModel[]> {
|
||||
const url = this.buildRolesUrl(userId);
|
||||
const httpMethod = 'GET', pathParams = {}, queryParams = {}, bodyParam = {}, headerParams = {},
|
||||
formParams = {}, authNames = [], contentTypes = ['application/json'], accepts = ['application/json'];
|
||||
|
||||
return from(this.apiService.getInstance().oauth2Auth.callCustomApi(
|
||||
url, httpMethod, pathParams, queryParams,
|
||||
headerParams, formParams, bodyParam, authNames,
|
||||
contentTypes, accepts, Object, null, null)
|
||||
).pipe(
|
||||
map((response: IdentityRoleModel[]) => {
|
||||
return response;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
async getUsersByRolesWithCurrentUser(roleNames: string[]): Promise<IdentityUserModel[]> {
|
||||
const filteredUsers: IdentityUserModel[] = [];
|
||||
if (roleNames && roleNames.length > 0) {
|
||||
const users = await this.getUsers().toPromise();
|
||||
|
||||
for (let i = 0; i < users.length; i++) {
|
||||
const hasAnyRole = await this.userHasAnyRole(users[i].id, roleNames);
|
||||
if (hasAnyRole) {
|
||||
filteredUsers.push(users[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filteredUsers;
|
||||
}
|
||||
|
||||
async getUsersByRolesWithoutCurrentUser(roleNames: string[]): Promise<IdentityUserModel[]> {
|
||||
const filteredUsers: IdentityUserModel[] = [];
|
||||
if (roleNames && roleNames.length > 0) {
|
||||
const currentUser = await this.getCurrentUserInfo().toPromise();
|
||||
let users = await this.getUsers().toPromise();
|
||||
|
||||
users = users.filter((user) => { return user.username !== currentUser.username; });
|
||||
|
||||
for (let i = 0; i < users.length; i++) {
|
||||
const hasAnyRole = await this.userHasAnyRole(users[i].id, roleNames);
|
||||
if (hasAnyRole) {
|
||||
filteredUsers.push(users[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filteredUsers;
|
||||
}
|
||||
|
||||
private async userHasAnyRole(userId: string, roleNames: string[]): Promise<boolean> {
|
||||
const userRoles = await this.getUserRoles(userId).toPromise();
|
||||
const hasAnyRole = roleNames.some((roleName) => {
|
||||
const filteredRoles = userRoles.filter((userRole) => {
|
||||
return userRole.name.toLocaleLowerCase() === roleName.toLocaleLowerCase();
|
||||
});
|
||||
|
||||
return filteredRoles.length > 0;
|
||||
});
|
||||
|
||||
return hasAnyRole;
|
||||
}
|
||||
|
||||
private buildUserUrl(): any {
|
||||
return `${this.appConfigService.get('bpmHost')}/auth/admin/realms/springboot/users`;
|
||||
}
|
||||
|
||||
private buildRolesUrl(userId: string): any {
|
||||
return `${this.appConfigService.get('bpmHost')}/auth/admin/realms/springboot/users/${userId}/role-mappings/realm/composite`;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,8 +3,17 @@
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
basePath: '../../',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
files: [
|
||||
{pattern: 'lib/core/i18n/**/en.json', included: false, served: true, watched: false},
|
||||
{pattern: 'lib/config/app.config.json', included: false, served: true, watched: false},
|
||||
],
|
||||
proxies: {
|
||||
'/base/assets/': '/base/lib/process-services-cloud/src/lib/assets/',
|
||||
'/assets/adf-core/i18n/en.json': '/base/lib/core/i18n/en.json',
|
||||
'/app.config.json': '/base/lib/config/app.config.json'
|
||||
},
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*!
|
||||
* @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 { AppListCloudModule } from './app-list-cloud.module';
|
||||
|
||||
describe('AppListCloudModule', () => {
|
||||
|
@ -14,5 +14,13 @@
|
||||
"ALL_PROCESSES": "All Processes",
|
||||
"RUNNING_PROCESSES": "Running Processes",
|
||||
"COMPLETED_PROCESSES": "Completed Processes"
|
||||
},
|
||||
"ADF_CLOUD_START_TASK": {
|
||||
"ERROR": {
|
||||
"MESSAGE": "Enter a different value",
|
||||
"REQUIRED": "Field required",
|
||||
"DATE": "Date format DD/MM/YYYY",
|
||||
"MAXIMUM_LENGTH": "Length exceeded, {{characters}} characters max."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*!
|
||||
* @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, AfterContentInit, ContentChild, Output, EventEmitter, SimpleChanges, SimpleChange, Input } from '@angular/core';
|
||||
import { DataTableSchema, PaginatedComponent,
|
||||
EmptyCustomContentDirective, AppConfigService,
|
||||
|
@ -2,14 +2,14 @@
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License);
|
||||
* 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,
|
||||
* 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.
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*!
|
||||
* @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 { ProcessListCloudModule } from './process-list-cloud.module';
|
||||
|
||||
describe('ProcessListCloudModule', () => {
|
||||
|
@ -1,3 +1,20 @@
|
||||
/*!
|
||||
* @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 { CommonModule } from '@angular/common';
|
||||
import { ProcessListCloudComponent } from './components/process-list-cloud.component';
|
||||
|
@ -22,6 +22,7 @@ import { TaskListCloudModule } from './task-list-cloud/task-list-cloud.module';
|
||||
import { TaskCloudModule } from './task-cloud/task-cloud.module';
|
||||
import { ProcessListCloudModule } from './process-list-cloud/process-list-cloud.module';
|
||||
import { ProcessCloudModule } from './process-cloud/process-cloud.module';
|
||||
import { StartTaskCloudModule } from './start-task-cloud/start-task-cloud.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -29,7 +30,8 @@ import { ProcessCloudModule } from './process-cloud/process-cloud.module';
|
||||
TaskListCloudModule,
|
||||
TaskCloudModule,
|
||||
ProcessListCloudModule,
|
||||
ProcessCloudModule
|
||||
ProcessCloudModule,
|
||||
StartTaskCloudModule
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
@ -41,12 +43,13 @@ import { ProcessCloudModule } from './process-cloud/process-cloud.module';
|
||||
}
|
||||
}
|
||||
],
|
||||
declarations: [],
|
||||
exports: [
|
||||
AppListCloudModule,
|
||||
TaskListCloudModule,
|
||||
TaskCloudModule,
|
||||
ProcessListCloudModule,
|
||||
ProcessCloudModule]
|
||||
ProcessCloudModule,
|
||||
StartTaskCloudModule
|
||||
]
|
||||
})
|
||||
export class ProcessServicesCloudModule { }
|
||||
|
@ -0,0 +1,29 @@
|
||||
<form>
|
||||
<mat-form-field class="adf-people-cloud">
|
||||
<mat-label id="assignee-id">{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.ASSIGNEE' | translate}}</mat-label>
|
||||
<input #inputValue
|
||||
matInput
|
||||
class="adf-cloud-input"
|
||||
data-automation-id="adf-people-cloud-search-input"
|
||||
type="text"
|
||||
[formControl]="searchUser"
|
||||
[matAutocomplete]="auto">
|
||||
<mat-autocomplete autoActiveFirstOption class="adf-people-cloud-list"
|
||||
#auto="matAutocomplete"
|
||||
(optionSelected)="onSelect($event.option.value)"
|
||||
[displayWith]="getDisplayName">
|
||||
<mat-option *ngFor="let user of users$ | async; let i = index" [value]="user">
|
||||
<div class="adf-people-cloud-row" id="adf-people-cloud-user-{{i}}">
|
||||
<div [outerHTML]="user | usernameInitials:'adf-people-widget-pic'"></div>
|
||||
<span class="adf-people-label-name"> {{user | fullName}}</span>
|
||||
</div>
|
||||
</mat-option>
|
||||
</mat-autocomplete>
|
||||
</mat-form-field>
|
||||
<div class="adf-start-task-cloud-error">
|
||||
<div *ngIf="dataError" fxLayout="row" fxLayoutAlign="start start" [@transitionMessages]="_subscriptAnimationState">
|
||||
<div class="adf-start-task-cloud-error-message">{{ 'ADF_CLOUD_START_TASK.ERROR.MESSAGE' | translate }}</div>
|
||||
<mat-icon class="adf-start-task-cloud-error-icon">warning</mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
@ -0,0 +1,62 @@
|
||||
@mixin adf-cloud-people-theme($theme) {
|
||||
$warn: map-get($theme, warn);
|
||||
$primary: map-get($theme, primary);
|
||||
$background: map-get($theme, background);
|
||||
$foreground: map-get($theme, foreground);
|
||||
|
||||
.adf {
|
||||
|
||||
&-people-cloud {
|
||||
width: 100%;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
&-people-cloud-list {
|
||||
margin: 5px 0;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
&-people-cloud-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&-people-cloud-pic {
|
||||
background: mat-color($primary);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 100px;
|
||||
color: mat-color($foreground, text);
|
||||
font-weight: bolder;
|
||||
font-size: 18px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
&-start-task-cloud-error {
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
&-start-task-cloud-error {
|
||||
position: absolute;
|
||||
height: 20px;
|
||||
|
||||
&-message {
|
||||
padding-right: 8px;
|
||||
height: 16px;
|
||||
font-size: 12px;
|
||||
line-height: 1.33;
|
||||
color: mat-color($warn);
|
||||
width: auto;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
font-size: 17px;
|
||||
color: mat-color($warn);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
/*!
|
||||
* @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 { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { PeopleCloudComponent } from './people-cloud.component';
|
||||
import { StartTaskCloudTestingModule } from '../../testing/start-task-cloud.testing.module';
|
||||
import { LogService, setupTestBed, IdentityUserService, IdentityUserModel } from '@alfresco/adf-core';
|
||||
import { mockUsers, mockRoles } from '../../mock/user-cloud.mock';
|
||||
import { of } from 'rxjs';
|
||||
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
||||
|
||||
describe('PeopleCloudComponent', () => {
|
||||
let component: PeopleCloudComponent;
|
||||
let fixture: ComponentFixture<PeopleCloudComponent>;
|
||||
let element: HTMLElement;
|
||||
let identityService: IdentityUserService;
|
||||
let getRolesByUserIdSpy: jasmine.Spy;
|
||||
let getUserSpy: jasmine.Spy;
|
||||
|
||||
setupTestBed({
|
||||
imports: [ProcessServiceCloudTestingModule, StartTaskCloudTestingModule],
|
||||
providers: [IdentityUserService, LogService]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PeopleCloudComponent);
|
||||
component = fixture.componentInstance;
|
||||
element = fixture.nativeElement;
|
||||
identityService = TestBed.get(IdentityUserService);
|
||||
getRolesByUserIdSpy = spyOn(identityService, 'getUserRoles').and.returnValue(of(mockRoles));
|
||||
getUserSpy = spyOn(identityService, 'getUsers').and.returnValue(of(mockUsers));
|
||||
});
|
||||
|
||||
it('should create PeopleCloudComponent', () => {
|
||||
expect(component instanceof PeopleCloudComponent).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should able to fetch users', () => {
|
||||
fixture.detectChanges();
|
||||
expect(getUserSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should able to fetch roles by user id', async(() => {
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(getRolesByUserIdSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should not list the current logged in user when showCurrentUser is false', async(() => {
|
||||
spyOn(identityService, 'getCurrentUserInfo').and.returnValue(of(mockUsers[1]));
|
||||
component.showCurrentUser = false;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
const currentUser = component.users.find((user) => {
|
||||
return user.username === mockUsers[1].username;
|
||||
});
|
||||
expect(currentUser).toBeUndefined();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should show the users if the typed result match', async(() => {
|
||||
component.users$ = of(<IdentityUserModel[]> mockUsers);
|
||||
fixture.detectChanges();
|
||||
let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input');
|
||||
inputHTMLElement.focus();
|
||||
inputHTMLElement.dispatchEvent(new Event('input'));
|
||||
inputHTMLElement.dispatchEvent(new Event('keyup'));
|
||||
inputHTMLElement.dispatchEvent(new Event('keydown'));
|
||||
inputHTMLElement.value = 'M';
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(fixture.debugElement.query(By.css('mat-option'))).toBeDefined();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should hide result list if input is empty', () => {
|
||||
fixture.detectChanges();
|
||||
let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input');
|
||||
inputHTMLElement.focus();
|
||||
inputHTMLElement.value = '';
|
||||
inputHTMLElement.dispatchEvent(new Event('keyup'));
|
||||
inputHTMLElement.dispatchEvent(new Event('input'));
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(fixture.debugElement.query(By.css('mat-option'))).toBeNull();
|
||||
expect(fixture.debugElement.query(By.css('#adf-people-cloud-user-0'))).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
it('should emit selectedUser if option is valid', async() => {
|
||||
fixture.detectChanges();
|
||||
let selectEmitSpy = spyOn(component.selectedUser, 'emit');
|
||||
component.onSelect(new IdentityUserModel({ username: 'username'}));
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(selectEmitSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should show an error message if the user is invalid', async(() => {
|
||||
getUserSpy.and.returnValue(of([]));
|
||||
getRolesByUserIdSpy.and.returnValue(of([]));
|
||||
component.dataError = true;
|
||||
fixture.detectChanges();
|
||||
let inputHTMLElement: HTMLInputElement = <HTMLInputElement> element.querySelector('input');
|
||||
inputHTMLElement.focus();
|
||||
inputHTMLElement.dispatchEvent(new Event('input'));
|
||||
inputHTMLElement.dispatchEvent(new Event('keyup'));
|
||||
inputHTMLElement.dispatchEvent(new Event('keydown'));
|
||||
inputHTMLElement.value = 'ZZZ';
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
const errorMessage = element.querySelector('.adf-start-task-cloud-error-message');
|
||||
expect(element.querySelector('.adf-start-task-cloud-error')).not.toBeNull();
|
||||
expect(errorMessage.textContent).toContain('ADF_CLOUD_START_TASK.ERROR.MESSAGE');
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
@ -0,0 +1,110 @@
|
||||
/*!
|
||||
* @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 { FormControl } from '@angular/forms';
|
||||
import { Component, OnInit, Output, EventEmitter, ViewEncapsulation, Input } from '@angular/core';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { FullNamePipe, IdentityUserModel, IdentityUserService } from '@alfresco/adf-core';
|
||||
import { trigger, state, style, transition, animate } from '@angular/animations';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-cloud-people',
|
||||
templateUrl: './people-cloud.component.html',
|
||||
styleUrls: ['./people-cloud.component.scss'],
|
||||
animations: [
|
||||
trigger('transitionMessages', [
|
||||
state('enter', style({opacity: 1, transform: 'translateY(0%)'})),
|
||||
transition('void => enter', [
|
||||
style({opacity: 0, transform: 'translateY(-100%)'}),
|
||||
animate('300ms cubic-bezier(0.55, 0, 0.55, 0.2)')
|
||||
])
|
||||
])
|
||||
],
|
||||
providers: [FullNamePipe],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
|
||||
export class PeopleCloudComponent implements OnInit {
|
||||
|
||||
static ROLE_ACTIVITI_ADMIN = 'ACTIVITI_ADMIN';
|
||||
static ROLE_ACTIVITI_USER = 'ACTIVITI_USER';
|
||||
static ROLE_ACTIVITI_MODELER = 'ACTIVITI_MODELER';
|
||||
|
||||
/** Show current user in the list or not. */
|
||||
@Input()
|
||||
showCurrentUser: boolean = true;
|
||||
|
||||
/** Emitted when a user is selected. */
|
||||
@Output()
|
||||
selectedUser: EventEmitter<IdentityUserModel> = new EventEmitter<IdentityUserModel>();
|
||||
|
||||
/** Emitted when an error occurs. */
|
||||
@Output()
|
||||
error: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
users$: Observable<IdentityUserModel[]>;
|
||||
|
||||
searchUser: FormControl = new FormControl();
|
||||
|
||||
_subscriptAnimationState: string = 'enter';
|
||||
|
||||
users: IdentityUserModel[] = [];
|
||||
|
||||
dataError = false;
|
||||
|
||||
currentUser: IdentityUserModel;
|
||||
|
||||
constructor(private identityUserService: IdentityUserService) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.loadUsers();
|
||||
this.initSearch();
|
||||
}
|
||||
|
||||
initSearch() {
|
||||
this.searchUser.valueChanges.subscribe((keyword) => {
|
||||
this.users$ = this.searchUsers(keyword);
|
||||
});
|
||||
}
|
||||
|
||||
private async loadUsers() {
|
||||
const roles = [PeopleCloudComponent.ROLE_ACTIVITI_ADMIN, PeopleCloudComponent.ROLE_ACTIVITI_MODELER, PeopleCloudComponent.ROLE_ACTIVITI_USER];
|
||||
if (this.showCurrentUser) {
|
||||
this.users = await this.identityUserService.getUsersByRolesWithCurrentUser(roles);
|
||||
} else {
|
||||
this.users = await this.identityUserService.getUsersByRolesWithoutCurrentUser(roles);
|
||||
}
|
||||
}
|
||||
|
||||
private searchUsers(keyword: string): Observable<IdentityUserModel[]> {
|
||||
const filteredUsers = this.users.filter((user) => {
|
||||
return user.username.toLowerCase().indexOf(keyword.toString().toLowerCase()) !== -1;
|
||||
});
|
||||
this.dataError = filteredUsers.length === 0;
|
||||
return of(filteredUsers);
|
||||
}
|
||||
|
||||
onSelect(selectedUser: IdentityUserModel) {
|
||||
this.selectedUser.emit(selectedUser);
|
||||
this.dataError = false;
|
||||
}
|
||||
|
||||
getDisplayName(user): string {
|
||||
return FullNamePipe.prototype.transform(user);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
<mat-card>
|
||||
<mat-card-header fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="10px" class="adf-cloud-start-task-heading">
|
||||
<mat-card-title>{{'ADF_TASK_LIST.START_TASK.FORM.TITLE' | translate}}</mat-card-title>
|
||||
</mat-card-header>
|
||||
<form [formGroup]="taskForm" fxLayout="column" (ngSubmit)="saveTask()">
|
||||
|
||||
<mat-card-content>
|
||||
<div class="adf-task-name">
|
||||
<mat-form-field fxFlex>
|
||||
<mat-label>{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.NAME' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
id="name_id"
|
||||
class="form-control"
|
||||
formControlName="name">
|
||||
<mat-error *ngIf="nameController.hasError('required')">
|
||||
{{ 'ADF_CLOUD_START_TASK.ERROR.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="nameController.hasError('maxlength')">
|
||||
{{ 'ADF_CLOUD_START_TASK.ERROR.MAXIMUM_LENGTH' | translate : { characters : maxNameLength } }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="input-row" fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutGap.lt-md="0px">
|
||||
<mat-form-field fxFlex>
|
||||
<mat-label>{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.DESCRIPTION' | translate}}</mat-label>
|
||||
<textarea
|
||||
matInput
|
||||
class="form-control"
|
||||
id="description_id"
|
||||
formControlName="description">
|
||||
</textarea>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field fxFlex>
|
||||
<div style="height: 40px;">
|
||||
<input matInput type="number" placeholder="Priority" formControlName="priority">
|
||||
</div>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="input-row" fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="20px" fxLayoutGap.lt-md="0px">
|
||||
<mat-form-field fxFlex>
|
||||
<input matInput
|
||||
[matDatepicker]="taskDatePicker"
|
||||
(keydown)="true"
|
||||
(focusout)="onDateChanged($event.srcElement.value)"
|
||||
placeholder="{{'ADF_TASK_LIST.START_TASK.FORM.LABEL.DATE'|translate}}"
|
||||
[(ngModel)]="dueDate"
|
||||
[ngModelOptions]="{standalone: true}"
|
||||
id="date_id">
|
||||
<mat-datepicker-toggle matSuffix [for]="taskDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #taskDatePicker
|
||||
[touchUi]="true"
|
||||
(dateChanged)="onDateChanged($event)">
|
||||
</mat-datepicker>
|
||||
<div class="adf-error-text-container">
|
||||
<div *ngIf="dateError">
|
||||
<div class="adf-error-text">{{'ADF_CLOUD_START_TASK.ERROR.DATE' | translate}}</div>
|
||||
<mat-icon class="adf-error-icon">warning</mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
</mat-form-field>
|
||||
|
||||
<div fxFlex>
|
||||
<adf-cloud-people (selectedUser)="onAssigneeSelect($event)"></adf-cloud-people>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions>
|
||||
<div class="adf-cloud-start-task-footer" fxLayout="row" fxLayoutAlign="end end" >
|
||||
<button
|
||||
mat-button
|
||||
type="button"
|
||||
(click)="onCancel()"
|
||||
id="button-cancel">
|
||||
{{'ADF_TASK_LIST.START_TASK.FORM.ACTION.CANCEL'|translate}}
|
||||
</button>
|
||||
<button
|
||||
color="primary"
|
||||
type="submit" [disabled]="dateError || !taskForm.valid || submitted"
|
||||
mat-button
|
||||
id="button-start">
|
||||
{{'ADF_TASK_LIST.START_TASK.FORM.ACTION.START'|translate}}
|
||||
</button>
|
||||
</div>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
@ -0,0 +1,34 @@
|
||||
@mixin adf-start-task-cloud-theme($theme) {
|
||||
$primary: map-get($theme, primary);
|
||||
$accent: map-get($theme, accent);
|
||||
$warn: map-get($theme, warn);
|
||||
$foreground: map-get($theme, foreground);
|
||||
$header-border: 1px solid mat-color($foreground, divider);
|
||||
|
||||
.adf-cloud-start-task-heading {
|
||||
border-bottom: $header-border;
|
||||
margin-bottom: 10px;
|
||||
.mat-card-title {
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.adf-cloud-start-task-footer {
|
||||
padding: 4px;
|
||||
font-size: 18px;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
adf-cloud-start-task {
|
||||
.adf {
|
||||
|
||||
&-cloud-start-task-footer {
|
||||
.mat-button {
|
||||
text-transform: uppercase !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,240 @@
|
||||
/*!
|
||||
* @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, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { setupTestBed, IdentityUserService } from '@alfresco/adf-core';
|
||||
import {
|
||||
AlfrescoApiService,
|
||||
AppConfigService,
|
||||
LogService,
|
||||
StorageService,
|
||||
UserPreferencesService,
|
||||
IdentityUserModel
|
||||
} from '@alfresco/adf-core';
|
||||
import { StartTaskCloudService } from '../services/start-task-cloud.service';
|
||||
import { StartTaskCloudComponent } from './start-task-cloud.component';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { taskDetailsMock } from '../mock/task-details.mock';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { ProcessServiceCloudTestingModule } from './../../testing/process-service-cloud.testing.module';
|
||||
import { StartTaskCloudTestingModule } from '../testing/start-task-cloud.testing.module';
|
||||
import { mockRoles, mockUsers } from '../mock/user-cloud.mock';
|
||||
import { TaskDetailsCloudModel } from '../models/task-details-cloud.model';
|
||||
|
||||
describe('StartTaskCloudComponent', () => {
|
||||
|
||||
let component: StartTaskCloudComponent;
|
||||
let fixture: ComponentFixture<StartTaskCloudComponent>;
|
||||
let service: StartTaskCloudService;
|
||||
let identityService: IdentityUserService;
|
||||
let element: HTMLElement;
|
||||
let createNewTaskSpy: jasmine.Spy;
|
||||
let getRolesByUserIdSpy: jasmine.Spy;
|
||||
let getUserSpy: jasmine.Spy;
|
||||
|
||||
setupTestBed({
|
||||
imports: [ProcessServiceCloudTestingModule, StartTaskCloudTestingModule],
|
||||
providers: [StartTaskCloudService, AlfrescoApiService, AppConfigService, LogService, StorageService, UserPreferencesService],
|
||||
schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
|
||||
});
|
||||
|
||||
beforeEach(async(() => {
|
||||
fixture = TestBed.createComponent(StartTaskCloudComponent);
|
||||
component = fixture.componentInstance;
|
||||
element = fixture.nativeElement;
|
||||
|
||||
service = TestBed.get(StartTaskCloudService);
|
||||
identityService = TestBed.get(IdentityUserService);
|
||||
createNewTaskSpy = spyOn(service, 'createNewTask').and.returnValue(of(taskDetailsMock));
|
||||
getRolesByUserIdSpy = spyOn(identityService, 'getUserRoles').and.returnValue(of(mockRoles));
|
||||
getUserSpy = spyOn(identityService, 'getUsers').and.returnValue(of(mockUsers));
|
||||
spyOn(identityService, 'getCurrentUserInfo').and.returnValue(of(new IdentityUserModel({username: 'currentUser'})));
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should create instance of StartTaskCloudComponent', () => {
|
||||
expect(component instanceof StartTaskCloudComponent).toBe(true, 'should create StartTaskCloudComponent');
|
||||
});
|
||||
|
||||
it('should defined adf-cloud-people and fetch users ', () => {
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
const peopleElement = fixture.debugElement.nativeElement.querySelector('adf-cloud-people');
|
||||
expect(peopleElement).toBeDefined();
|
||||
expect(getRolesByUserIdSpy).toHaveBeenCalled();
|
||||
expect(getUserSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('create task', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
createNewTaskSpy.and.returnValue(of(
|
||||
{
|
||||
id: 91,
|
||||
name: 'fakeName',
|
||||
assignee: 'fake-assignee'
|
||||
}
|
||||
));
|
||||
});
|
||||
|
||||
it('should create new task when start button is clicked', async(() => {
|
||||
let successSpy = spyOn(component.success, 'emit');
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
createTaskButton.click();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(createNewTaskSpy).toHaveBeenCalled();
|
||||
expect(successSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should send on success event when the task is started', async(() => {
|
||||
let successSpy = spyOn(component.success, 'emit');
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
component.assigneeName = 'fake-assignee';
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
createTaskButton.click();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(successSpy).toHaveBeenCalledWith({
|
||||
id: 91,
|
||||
name: 'fakeName',
|
||||
assignee: 'fake-assignee'
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('should send on success event when only name is given', async(() => {
|
||||
let successSpy = spyOn(component.success, 'emit');
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
createTaskButton.click();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(successSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should not emit success event when data not present', () => {
|
||||
let successSpy = spyOn(component.success, 'emit');
|
||||
component.taskForm.controls['name'].setValue('');
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
createTaskButton.click();
|
||||
expect(createNewTaskSpy).not.toHaveBeenCalled();
|
||||
expect(successSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should assign task when an assignee is selected', async(() => {
|
||||
let successSpy = spyOn(component.success, 'emit');
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
component.assigneeName = 'fake-assignee';
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
createTaskButton.click();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(successSpy).toHaveBeenCalledWith({
|
||||
id: 91,
|
||||
name: 'fakeName',
|
||||
assignee: 'fake-assignee'
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('should assign task to the logged in user when assignee is not selected', async(() => {
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
createTaskButton.click();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
const taskRequest = new TaskDetailsCloudModel({ name: 'fakeName', assignee: 'currentUser'});
|
||||
expect(createNewTaskSpy).toHaveBeenCalledWith(taskRequest);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should show start task button', () => {
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
fixture.detectChanges();
|
||||
expect(element.querySelector('#button-start')).toBeDefined();
|
||||
expect(element.querySelector('#button-start')).not.toBeNull();
|
||||
expect(element.querySelector('#button-start').textContent).toContain('ADF_TASK_LIST.START_TASK.FORM.ACTION.START');
|
||||
});
|
||||
|
||||
it('should disable start button if name is empty', () => {
|
||||
component.taskForm.controls['name'].setValue('');
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = fixture.nativeElement.querySelector('#button-start');
|
||||
expect(createTaskButton.disabled).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should cancel start task on cancel button click', () => {
|
||||
fixture.detectChanges();
|
||||
let emitSpy = spyOn(component.cancel, 'emit');
|
||||
let cancelTaskButton = fixture.nativeElement.querySelector('#button-cancel');
|
||||
cancelTaskButton.click();
|
||||
expect(emitSpy).not.toBeNull();
|
||||
expect(emitSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should enable start button if name is filled out', () => {
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
fixture.detectChanges();
|
||||
let createTaskButton = fixture.nativeElement.querySelector('#button-start');
|
||||
expect(createTaskButton.disabled).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should emit error when there is an error while creating task', () => {
|
||||
component.taskForm.controls['name'].setValue('fakeName');
|
||||
let errorSpy = spyOn(component.error, 'emit');
|
||||
createNewTaskSpy.and.returnValue(throwError({}));
|
||||
let createTaskButton = <HTMLElement> element.querySelector('#button-start');
|
||||
fixture.detectChanges();
|
||||
createTaskButton.click();
|
||||
expect(errorSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should emit error when task name exceeds maximum length', () => {
|
||||
component.maxNameLength = 2;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
let name = component.taskForm.controls['name'];
|
||||
name.setValue('task');
|
||||
fixture.detectChanges();
|
||||
expect(name.valid).toBeFalsy();
|
||||
name.setValue('ta');
|
||||
fixture.detectChanges();
|
||||
expect(name.valid).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should emit error when task name field is empty', () => {
|
||||
fixture.detectChanges();
|
||||
let name = component.taskForm.controls['name'];
|
||||
name.setValue('');
|
||||
fixture.detectChanges();
|
||||
expect(name.valid).toBeFalsy();
|
||||
name.setValue('task');
|
||||
fixture.detectChanges();
|
||||
expect(name.valid).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,197 @@
|
||||
/*!
|
||||
* @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, OnInit, Output, ViewEncapsulation, OnDestroy } from '@angular/core';
|
||||
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
|
||||
import { MOMENT_DATE_FORMATS, MomentDateAdapter } from '@alfresco/adf-core';
|
||||
import moment from 'moment-es6';
|
||||
import { Moment } from 'moment';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { FormBuilder, AbstractControl, Validators, FormGroup, FormControl } from '@angular/forms';
|
||||
import { StartTaskCloudService } from '../services/start-task-cloud.service';
|
||||
import { TaskDetailsCloudModel } from '../models/task-details-cloud.model';
|
||||
import {
|
||||
LogService,
|
||||
UserPreferencesService,
|
||||
IdentityUserService,
|
||||
IdentityUserModel
|
||||
} from '@alfresco/adf-core';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-cloud-start-task',
|
||||
templateUrl: './start-task-cloud.component.html',
|
||||
styleUrls: ['./start-task-cloud.component.scss'],
|
||||
providers: [
|
||||
{ provide: DateAdapter, useClass: MomentDateAdapter },
|
||||
{ provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS }],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
|
||||
export class StartTaskCloudComponent implements OnInit, OnDestroy {
|
||||
|
||||
static MAX_NAME_LENGTH = 255;
|
||||
|
||||
public DATE_FORMAT: string = 'DD/MM/YYYY';
|
||||
|
||||
/** (required) Name of the app. */
|
||||
@Input()
|
||||
appName: string;
|
||||
|
||||
/** Maximum length of the task name. */
|
||||
@Input()
|
||||
maxNameLength: number = StartTaskCloudComponent.MAX_NAME_LENGTH;
|
||||
|
||||
/** Name of the task. */
|
||||
@Input()
|
||||
name: string = '';
|
||||
|
||||
/** Emitted when the task is successfully created. */
|
||||
@Output()
|
||||
success: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
/** Emitted when the cancel button is clicked by the user. */
|
||||
@Output()
|
||||
cancel: EventEmitter<void> = new EventEmitter<void>();
|
||||
|
||||
/** Emitted when an error occurs. */
|
||||
@Output()
|
||||
error: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
users$: Observable<any[]>;
|
||||
|
||||
taskId: string;
|
||||
|
||||
dueDate: Date;
|
||||
|
||||
submitted = false;
|
||||
|
||||
assigneeName: string;
|
||||
|
||||
dateError: boolean;
|
||||
|
||||
taskForm: FormGroup;
|
||||
|
||||
currentUser: IdentityUserModel;
|
||||
|
||||
private localeSub: Subscription;
|
||||
private createTaskSub: Subscription;
|
||||
|
||||
constructor(private taskService: StartTaskCloudService,
|
||||
private dateAdapter: DateAdapter<Moment>,
|
||||
private preferences: UserPreferencesService,
|
||||
private formBuilder: FormBuilder,
|
||||
private identityUserService: IdentityUserService,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.localeSub = this.preferences.locale$.subscribe((locale) => {
|
||||
this.dateAdapter.setLocale(locale);
|
||||
});
|
||||
this.loadCurrentUser();
|
||||
this.buildForm();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.localeSub) {
|
||||
this.localeSub.unsubscribe();
|
||||
}
|
||||
|
||||
if (this.createTaskSub) {
|
||||
this.createTaskSub.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
buildForm() {
|
||||
this.taskForm = this.formBuilder.group({
|
||||
name: new FormControl(this.name, [Validators.required, Validators.maxLength(this.getMaxNameLength())]),
|
||||
priority: new FormControl(),
|
||||
description: new FormControl()
|
||||
});
|
||||
}
|
||||
|
||||
private getMaxNameLength(): number {
|
||||
return this.maxNameLength > StartTaskCloudComponent.MAX_NAME_LENGTH ?
|
||||
StartTaskCloudComponent.MAX_NAME_LENGTH : this.maxNameLength;
|
||||
}
|
||||
|
||||
private async loadCurrentUser() {
|
||||
this.currentUser = await this.identityUserService.getCurrentUserInfo().toPromise();
|
||||
}
|
||||
|
||||
public saveTask() {
|
||||
this.submitted = true;
|
||||
const newTask = Object.assign(this.taskForm.value);
|
||||
newTask.appName = this.getAppName();
|
||||
newTask.dueDate = this.getDueDate();
|
||||
newTask.assignee = this.getAssigneeName();
|
||||
this.createNewTask(new TaskDetailsCloudModel(newTask));
|
||||
}
|
||||
|
||||
private createNewTask(newTask: TaskDetailsCloudModel) {
|
||||
this.createTaskSub = this.taskService.createNewTask(newTask)
|
||||
.subscribe(
|
||||
(res: any) => {
|
||||
this.submitted = false;
|
||||
this.success.emit(res);
|
||||
},
|
||||
(err) => {
|
||||
this.submitted = false;
|
||||
this.error.emit(err);
|
||||
this.logService.error('An error occurred while creating new task');
|
||||
});
|
||||
}
|
||||
|
||||
public onCancel() {
|
||||
this.cancel.emit();
|
||||
}
|
||||
|
||||
private getDueDate(): Date {
|
||||
return this.dueDate;
|
||||
}
|
||||
|
||||
private getAppName(): string {
|
||||
return this.appName ? this.appName : '';
|
||||
}
|
||||
|
||||
private getAssigneeName(): string {
|
||||
return this.assigneeName ? this.assigneeName : this.currentUser.username;
|
||||
}
|
||||
|
||||
onDateChanged(newDateValue) {
|
||||
this.dateError = false;
|
||||
|
||||
if (newDateValue) {
|
||||
let momentDate = moment(newDateValue, this.DATE_FORMAT, true);
|
||||
if (!momentDate.isValid()) {
|
||||
this.dateError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onAssigneeSelect(assignee: IdentityUserModel) {
|
||||
this.assigneeName = assignee ? assignee.username : '';
|
||||
}
|
||||
|
||||
get nameController(): AbstractControl {
|
||||
return this.taskForm.get('name');
|
||||
}
|
||||
|
||||
get priorityController(): AbstractControl {
|
||||
return this.taskForm.get('priority');
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/*!
|
||||
* @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 { TaskDetailsCloudModel } from '../models/task-details-cloud.model';
|
||||
|
||||
export let taskDetailsMock = new TaskDetailsCloudModel({ assignee: 'fake-assigne', name: 'fake-name' });
|
@ -0,0 +1,30 @@
|
||||
/*!
|
||||
* @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 const mockUsers = [
|
||||
{ id: 'fake-id-1', username: 'first-name-1 last-name-1', firstName: 'first-name-1', lastName: 'last-name-1', email: 'abc@xyz.com' },
|
||||
{ id: 'fake-id-2', username: 'first-name-2 last-name-2', firstName: 'first-name-2', lastName: 'last-name-2', email: 'abcd@xyz.com'},
|
||||
{ id: 'fake-id-3', username: 'first-name-3 last-name-3', firstName: 'first-name-3', lastName: 'last-name-3', email: 'abcde@xyz.com' }
|
||||
];
|
||||
|
||||
export const mockRoles = [
|
||||
{ id: 'id-1', name: 'MOCK-ADMIN-ROLE'},
|
||||
{ id: 'id-2', name: 'MOCK-USER-ROLE'},
|
||||
{ id: 'id-3', name: 'MOCK_MODELER-ROLE' },
|
||||
{ id: 'id-4', name: 'MOCK-ROLE-1' },
|
||||
{ id: 'id-5', name: 'MOCK-ROLE-2'}
|
||||
];
|
@ -0,0 +1,36 @@
|
||||
/*!
|
||||
* @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 StartTaskCloudRequestModel {
|
||||
|
||||
name: string;
|
||||
description: string;
|
||||
assignee: string;
|
||||
priority: string;
|
||||
dueDate: Date;
|
||||
payloadType: string;
|
||||
|
||||
constructor(obj?: any) {
|
||||
if (obj) {
|
||||
this.name = obj.name || null;
|
||||
this.description = obj.description || null;
|
||||
this.assignee = obj.assignee || null;
|
||||
this.priority = obj.priority || null;
|
||||
this.dueDate = obj.dueDate || null;
|
||||
this.payloadType = 'CreateTaskPayload';
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
/*!
|
||||
* @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 TaskDetailsCloudModel {
|
||||
|
||||
id: string;
|
||||
name: string;
|
||||
appName: string;
|
||||
assignee: string;
|
||||
appVersion: string;
|
||||
createdDate: Date;
|
||||
claimedDate: Date;
|
||||
formKey: any;
|
||||
category: any;
|
||||
description: string;
|
||||
dueDate: Date;
|
||||
lastModified: Date;
|
||||
lastModifiedTo: Date;
|
||||
lastModifiedFrom: Date;
|
||||
owner: any;
|
||||
parentTaskId: number;
|
||||
priority: number;
|
||||
processDefinitionId: string;
|
||||
processInstanceId: string;
|
||||
serviceType: any;
|
||||
status: string;
|
||||
standAlone: boolean;
|
||||
serviceName: string;
|
||||
serviceFullName: string;
|
||||
serviceVersion: string;
|
||||
|
||||
constructor(obj?: any) {
|
||||
if (obj) {
|
||||
this.id = obj.id || null;
|
||||
this.name = obj.name || null;
|
||||
this.appName = obj.appName || null;
|
||||
this.assignee = obj.assignee || null;
|
||||
this.appVersion = obj.appVersion || null;
|
||||
this.createdDate = obj.createdDate || null;
|
||||
this.claimedDate = obj.claimedDate || null;
|
||||
this.formKey = obj.formKey || null;
|
||||
this.description = obj.description || null;
|
||||
this.dueDate = obj.dueDate || null;
|
||||
this.lastModified = obj.lastModified || null;
|
||||
this.lastModifiedTo = obj.lastModifiedTo || null;
|
||||
this.lastModifiedFrom = obj.lastModifiedFrom || null;
|
||||
this.owner = obj.owner || null;
|
||||
this.parentTaskId = obj.parentTaskId || null;
|
||||
this.priority = obj.priority || null;
|
||||
this.processDefinitionId = obj.processDefinitionId || null;
|
||||
this.processInstanceId = obj.processInstanceId || null;
|
||||
this.serviceType = obj.serviceType || null;
|
||||
this.status = obj.status || null;
|
||||
this.standAlone = obj.standAlone || null;
|
||||
this.serviceName = obj.serviceName || null;
|
||||
this.serviceName = obj.serviceName || null;
|
||||
this.serviceFullName = obj.serviceFullName || null;
|
||||
this.serviceVersion = obj.serviceVersion || null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface StartTaskCloudResponseModel {
|
||||
entry: TaskDetailsCloudModel;
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*!
|
||||
* @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 './models/task-details-cloud.model';
|
||||
export * from './services/start-task-cloud.service';
|
||||
export * from './components/start-task-cloud.component';
|
||||
export * from './components/people-cloud/people-cloud.component';
|
||||
export * from './start-task-cloud.module';
|
@ -0,0 +1,78 @@
|
||||
/*!
|
||||
* @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 { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { setupTestBed } from '@alfresco/adf-core';
|
||||
import { StartTaskCloudService } from './start-task-cloud.service';
|
||||
import { StartTaskCloudTestingModule } from '../testing/start-task-cloud.testing.module';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { taskDetailsMock } from '../mock/task-details.mock';
|
||||
import { TaskDetailsCloudModel } from '../models/task-details-cloud.model';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import {
|
||||
AlfrescoApiService,
|
||||
AppConfigService,
|
||||
LogService,
|
||||
StorageService
|
||||
} from '@alfresco/adf-core';
|
||||
|
||||
describe('StartTaskCloudService', () => {
|
||||
|
||||
let service: StartTaskCloudService;
|
||||
|
||||
setupTestBed({
|
||||
imports: [StartTaskCloudTestingModule],
|
||||
providers: [StartTaskCloudService, AlfrescoApiService, AppConfigService, LogService, StorageService]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.get(StartTaskCloudService);
|
||||
});
|
||||
|
||||
it('should able to create a new task ', (done) => {
|
||||
spyOn(service, 'createNewTask').and.returnValue(of({id: 'fake-id', name: 'fake-name'}));
|
||||
service.createNewTask(taskDetailsMock).subscribe(
|
||||
(res: TaskDetailsCloudModel) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.id).toEqual('fake-id');
|
||||
expect(res.name).toEqual('fake-name');
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('Should not able to create a task if error occurred', () => {
|
||||
const errorResponse = new HttpErrorResponse({
|
||||
error: 'Mock Error',
|
||||
status: 404, statusText: 'Not Found'
|
||||
});
|
||||
|
||||
spyOn(service, 'createNewTask').and.returnValue(throwError(errorResponse));
|
||||
service.createNewTask(taskDetailsMock)
|
||||
.subscribe(
|
||||
() => {
|
||||
fail('expected an error, not applications');
|
||||
},
|
||||
(error) => {
|
||||
expect(error.status).toEqual(404);
|
||||
expect(error.statusText).toEqual('Not Found');
|
||||
expect(error.error).toEqual('Mock Error');
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
@ -0,0 +1,71 @@
|
||||
/*!
|
||||
* @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 { from, Observable, throwError } from 'rxjs';
|
||||
import { StartTaskCloudRequestModel } from '../models/start-task-cloud-request.model';
|
||||
import { TaskDetailsCloudModel, StartTaskCloudResponseModel } from '../models/task-details-cloud.model';
|
||||
import { map, catchError } from 'rxjs/operators';
|
||||
|
||||
@Injectable()
|
||||
export class StartTaskCloudService {
|
||||
|
||||
constructor(
|
||||
private apiService: AlfrescoApiService,
|
||||
private appConfigService: AppConfigService,
|
||||
private logService: LogService
|
||||
) {}
|
||||
|
||||
createNewTask(taskDetails: TaskDetailsCloudModel): Observable<TaskDetailsCloudModel> {
|
||||
let queryUrl = this.buildCreateTaskUrl(taskDetails.appName);
|
||||
const bodyParam = JSON.stringify(this.buildRequestBody(taskDetails));
|
||||
const httpMethod = 'POST', pathParams = {}, queryParams = {}, headerParams = {},
|
||||
formParams = {}, authNames = [], contentTypes = ['application/json'], accepts = ['application/json'];
|
||||
|
||||
return from(
|
||||
this.apiService
|
||||
.getInstance()
|
||||
.oauth2Auth.callCustomApi(
|
||||
queryUrl, httpMethod, pathParams, queryParams,
|
||||
headerParams, formParams, bodyParam, authNames,
|
||||
contentTypes, accepts, Object, null, null)
|
||||
).pipe(
|
||||
map((response: StartTaskCloudResponseModel) => {
|
||||
return new TaskDetailsCloudModel(response.entry);
|
||||
}),
|
||||
catchError((err) => this.handleError(err))
|
||||
);
|
||||
}
|
||||
|
||||
private buildCreateTaskUrl(appName: string): any {
|
||||
return `${this.appConfigService.get('bpmHost')}/${appName}-rb/v1/tasks`;
|
||||
}
|
||||
|
||||
private buildRequestBody(taskDetails: any) {
|
||||
return new StartTaskCloudRequestModel(taskDetails);
|
||||
}
|
||||
|
||||
private handleError(error: any) {
|
||||
this.logService.error(error);
|
||||
return throwError(error || 'Server error');
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/*!
|
||||
* @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 { CommonModule } from '@angular/common';
|
||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
import { MaterialModule } from '../material.module';
|
||||
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
||||
import { TemplateModule, TranslateLoaderService, FormModule, PipeModule } from '@alfresco/adf-core';
|
||||
import { StartTaskCloudComponent } from './components/start-task-cloud.component';
|
||||
import { StartTaskCloudService } from './services/start-task-cloud.service';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { PeopleCloudComponent } from './components/people-cloud/people-cloud.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
PipeModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
}),
|
||||
TemplateModule,
|
||||
FlexLayoutModule,
|
||||
MaterialModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
FormModule
|
||||
],
|
||||
declarations: [StartTaskCloudComponent, PeopleCloudComponent],
|
||||
providers: [
|
||||
StartTaskCloudService
|
||||
],
|
||||
exports: [
|
||||
StartTaskCloudComponent,
|
||||
PeopleCloudComponent
|
||||
]
|
||||
})
|
||||
export class StartTaskCloudModule { }
|
@ -0,0 +1,49 @@
|
||||
/*!
|
||||
* @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 { CommonModule } from '@angular/common';
|
||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
import { MaterialModule } from '../../material.module';
|
||||
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
||||
import { TemplateModule, TranslateLoaderService, FormModule, PipeModule } from '@alfresco/adf-core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
import { StartTaskCloudModule } from '../start-task-cloud.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
NoopAnimationsModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
}),
|
||||
TemplateModule,
|
||||
FlexLayoutModule,
|
||||
MaterialModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
FormModule,
|
||||
PipeModule,
|
||||
StartTaskCloudModule
|
||||
]
|
||||
})
|
||||
export class StartTaskCloudTestingModule { }
|
@ -2,10 +2,15 @@
|
||||
@import './../app-list-cloud/components/app-list-cloud.component';
|
||||
@import './../task-cloud/task-filters-cloud/task-filters-cloud.component.scss';
|
||||
@import './../process-list-cloud/components/process-list-cloud.component.scss';
|
||||
@import './../start-task-cloud/components/start-task-cloud.component';
|
||||
@import './../start-task-cloud/components/people-cloud/people-cloud.component';
|
||||
|
||||
|
||||
@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);
|
||||
@include adf-process-filters-cloud-theme($theme);
|
||||
@include adf-start-task-cloud-theme($theme);
|
||||
@include adf-cloud-people-theme($theme);
|
||||
}
|
||||
|
@ -1,3 +1,20 @@
|
||||
/*!
|
||||
* @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 { TaskCloudModule } from './task-cloud.module';
|
||||
|
||||
describe('TaskCloudModule', () => {
|
||||
|
@ -1,3 +1,20 @@
|
||||
/*!
|
||||
* @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 { CommonModule } from '@angular/common';
|
||||
import { TaskFiltersCloudComponent } from './task-filters-cloud/task-filters-cloud.component';
|
||||
|
@ -2,18 +2,19 @@
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License);
|
||||
* 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,
|
||||
* 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 = {
|
||||
|
@ -1,3 +1,20 @@
|
||||
/*!
|
||||
* @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 { TaskListCloudModule } from './task-list-cloud.module';
|
||||
|
||||
describe('TaskListCloudModule', () => {
|
||||
|
@ -1,3 +1,20 @@
|
||||
/*!
|
||||
* @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 { CommonModule } from '@angular/common';
|
||||
import { MaterialModule } from '../material.module';
|
||||
|
@ -20,3 +20,4 @@ export * from './lib/app-list-cloud/public-api';
|
||||
export * from './lib/task-list-cloud/public-api';
|
||||
export * from './lib/task-cloud/public-api';
|
||||
export * from './lib/process-list-cloud/public_api';
|
||||
export * from './lib/start-task-cloud/public-api';
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||
|
||||
import 'core-js/es7/reflect';
|
||||
|
@ -3,45 +3,45 @@
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
basePath: '../../',
|
||||
files: [
|
||||
{ pattern: '../../node_modules/core-js/client/core.js', included: true, watched: false },
|
||||
{ pattern: '../../node_modules/tslib/tslib.js', included: true, watched: false },
|
||||
{ pattern: '../../node_modules/hammerjs/hammer.min.js', included: true, watched: false },
|
||||
{ pattern: '../../node_modules/hammerjs/hammer.min.js.map', included: false, watched: false },
|
||||
{ pattern: 'node_modules/core-js/client/core.js', included: true, watched: false },
|
||||
{ pattern: 'node_modules/tslib/tslib.js', included: true, watched: false },
|
||||
{ pattern: 'node_modules/hammerjs/hammer.min.js', included: true, watched: false },
|
||||
{ pattern: 'node_modules/hammerjs/hammer.min.js.map', included: false, watched: false },
|
||||
|
||||
// pdf-js
|
||||
{ pattern: '../../node_modules/pdfjs-dist/build/pdf.js', included: true, watched: false },
|
||||
{ pattern: '../../node_modules/pdfjs-dist/build/pdf.worker.js', included: true, watched: false },
|
||||
{ pattern: '../../node_modules/pdfjs-dist/web/pdf_viewer.js', included: true, watched: false },
|
||||
{ pattern: 'node_modules/pdfjs-dist/build/pdf.js', included: true, watched: false },
|
||||
{ pattern: 'node_modules/pdfjs-dist/build/pdf.worker.js', included: true, watched: false },
|
||||
{ pattern: 'node_modules/pdfjs-dist/web/pdf_viewer.js', included: true, watched: false },
|
||||
|
||||
{
|
||||
pattern: '../../node_modules/@angular/material/prebuilt-themes/indigo-pink.css',
|
||||
pattern: 'node_modules/@angular/material/prebuilt-themes/indigo-pink.css',
|
||||
included: true,
|
||||
watched: false
|
||||
},
|
||||
|
||||
{ pattern: '../../node_modules/chart.js/dist/Chart.js', included: true, watched: false },
|
||||
{ pattern: '../../node_modules/raphael/raphael.min.js', included: true, watched: false },
|
||||
{ pattern: 'node_modules/chart.js/dist/Chart.js', included: true, watched: false },
|
||||
{ pattern: 'node_modules/raphael/raphael.min.js', included: true, watched: false },
|
||||
{
|
||||
pattern: '../../node_modules/ng2-charts/bundles/ng2-charts.umd.js',
|
||||
pattern: 'node_modules/ng2-charts/bundles/ng2-charts.umd.js',
|
||||
included: false,
|
||||
served: true,
|
||||
watched: false
|
||||
},
|
||||
|
||||
{ pattern: '../../node_modules/alfresco-js-api/dist/alfresco-js-api.min.js', included: true, watched: false },
|
||||
{ pattern: '../../node_modules/moment/min/moment.min.js', included: true, watched: false },
|
||||
{ pattern: 'node_modules/alfresco-js-api/dist/alfresco-js-api.min.js', included: true, watched: false },
|
||||
{ pattern: 'node_modules/moment/min/moment.min.js', included: true, watched: false },
|
||||
|
||||
{ pattern: '../core/i18n/**/en.json', included: false, served: true, watched: false },
|
||||
{ pattern: '../content-services/i18n/**/en.json', included: false, served: true, watched: false },
|
||||
{ pattern: '../process-services/i18n/**/en.json', included: false, served: true, watched: false },
|
||||
{ pattern: '../process-services/**/*.ts', included: false, served: true, watched: false },
|
||||
{ pattern: '../config/app.config.json', included: false, served: true, watched: false }
|
||||
{ pattern: 'lib/core/i18n/**/en.json', included: false, served: true, watched: false },
|
||||
{ pattern: 'lib/content-services/i18n/**/en.json', included: false, served: true, watched: false },
|
||||
{ pattern: 'lib/process-services/i18n/**/en.json', included: false, served: true, watched: false },
|
||||
{ pattern: 'lib/process-services/**/*.ts', included: false, served: true, watched: false },
|
||||
{ pattern: 'lib/config/app.config.json', included: false, served: true, watched: false }
|
||||
],
|
||||
frameworks: ['jasmine-ajax', 'jasmine', '@angular-devkit/build-angular'],
|
||||
proxies: {
|
||||
'/base/assets/': '/base/assets/',
|
||||
'/base/assets/': '/base/lib/process-services/assets/',
|
||||
'/assets/adf-core/i18n/en.json': '/base/lib/core/i18n/en.json',
|
||||
'/assets/adf-content-services/i18n/en.json': '/base/lib/content-services/i18n/en.json',
|
||||
'/assets/adf-process-services/i18n/en.json': '/base/lib/process-services/i18n/en.json',
|
||||
|
@ -9,7 +9,7 @@
|
||||
"rules": {
|
||||
"adf-license-banner": [
|
||||
true,
|
||||
"lib/+(core|content-services|process-services|insights)/**/*.ts",
|
||||
"lib/+(core|content-services|process-services-cloud|process-services|insights)/**/*.ts",
|
||||
"./license-community.txt"
|
||||
],
|
||||
"align": [
|
||||
|
14
package-lock.json
generated
14
package-lock.json
generated
@ -4910,7 +4910,7 @@
|
||||
},
|
||||
"css-select": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "http://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
|
||||
"integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -5408,7 +5408,7 @@
|
||||
"dependencies": {
|
||||
"domelementtype": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
|
||||
"integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=",
|
||||
"dev": true
|
||||
}
|
||||
@ -6544,7 +6544,7 @@
|
||||
},
|
||||
"file-loader": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "http://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
|
||||
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
|
||||
"integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -8336,7 +8336,7 @@
|
||||
},
|
||||
"html-webpack-plugin": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "http://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz",
|
||||
"integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -8365,7 +8365,7 @@
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "http://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz",
|
||||
"integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -8392,7 +8392,7 @@
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "1.0.34",
|
||||
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
|
||||
"integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -13622,7 +13622,7 @@
|
||||
},
|
||||
"postcss-import": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "http://registry.npmjs.org/postcss-import/-/postcss-import-11.1.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-11.1.0.tgz",
|
||||
"integrity": "sha512-5l327iI75POonjxkXgdRCUS+AlzAdBx4pOvMEhTKTCjb1p8IEeVR9yx3cPbmN7LIWJLbfnIXxAhoB4jpD0c/Cw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user