diff --git a/ng2-components/ng2-activiti-processlist/README.md b/ng2-components/ng2-activiti-processlist/README.md index d802be2613..87f8fcabcc 100644 --- a/ng2-components/ng2-activiti-processlist/README.md +++ b/ng2-components/ng2-activiti-processlist/README.md @@ -184,14 +184,14 @@ The AccordionComponent is exposed by the alfresco-core. ## Start Process component -Displays a button which in turn displays a dialog when clicked, allowing the user -to specify some basic details needed to start a new process instance. +Displays Start Process, allowing the user to specify some basic details needed to start a new process instance. ```html ``` +![adf-start-process ](docs/assets/start-process.png) ### Properties @@ -205,6 +205,7 @@ to specify some basic details needed to start a new process instance. | Name | Description | | --- | --- | | start | Raised when the process start | +| cancel | Raised when the process canceled | | error | Raised when the start process fail | ## Process Details component diff --git a/ng2-components/ng2-activiti-processlist/docs/assets/startProcess.png b/ng2-components/ng2-activiti-processlist/docs/assets/startProcess.png new file mode 100644 index 0000000000..21b18fdac8 Binary files /dev/null and b/ng2-components/ng2-activiti-processlist/docs/assets/startProcess.png differ diff --git a/ng2-components/ng2-activiti-processlist/index.ts b/ng2-components/ng2-activiti-processlist/index.ts index 7848f52cca..68513b8dd2 100644 --- a/ng2-components/ng2-activiti-processlist/index.ts +++ b/ng2-components/ng2-activiti-processlist/index.ts @@ -16,7 +16,12 @@ */ import { ModuleWithProviders, NgModule } from '@angular/core'; -import { MdProgressSpinnerModule } from '@angular/material'; +import { + MdProgressSpinnerModule, + MdButtonModule, + MdCardModule, + MdInputModule, + MdSelectModule } from '@angular/material'; import { ActivitiFormModule } from 'ng2-activiti-form'; import { ActivitiTaskListModule } from 'ng2-activiti-tasklist'; import { CoreModule, CardViewUpdateService } from 'ng2-alfresco-core'; @@ -118,7 +123,11 @@ export const ACTIVITI_PROCESSLIST_PROVIDERS: [any] = [ DataTableModule, ActivitiFormModule, ActivitiTaskListModule, - MdProgressSpinnerModule + MdProgressSpinnerModule, + MdButtonModule, + MdCardModule, + MdInputModule, + MdSelectModule ], declarations: [ ...ACTIVITI_PROCESSLIST_DIRECTIVES diff --git a/ng2-components/ng2-activiti-processlist/src/assets/start-process.component.mock.ts b/ng2-components/ng2-activiti-processlist/src/assets/start-process.component.mock.ts index c4d980f837..14e7ab323e 100644 --- a/ng2-components/ng2-activiti-processlist/src/assets/start-process.component.mock.ts +++ b/ng2-components/ng2-activiti-processlist/src/assets/start-process.component.mock.ts @@ -23,7 +23,13 @@ export let newProcess = new ProcessInstance({ name: 'Process' }); -export let fakeProcessDefs = [new ProcessDefinitionRepresentation({ +export let testProcessDefRepr = new ProcessDefinitionRepresentation({ + id: 'my:process1', + name: 'My Process 1', + hasStartForm: false +}); + +export let testProcessDefs = [new ProcessDefinitionRepresentation({ id: 'my:process1', name: 'My Process 1', hasStartForm: false @@ -33,7 +39,7 @@ export let fakeProcessDefs = [new ProcessDefinitionRepresentation({ hasStartForm: false })]; -export let fakeProcessDefWithForm = [new ProcessDefinitionRepresentation({ +export let testProcessDefWithForm = [new ProcessDefinitionRepresentation({ id: 'my:process1', name: 'My Process 1', hasStartForm: true diff --git a/ng2-components/ng2-activiti-processlist/src/components/start-process.component.css b/ng2-components/ng2-activiti-processlist/src/components/start-process.component.css index aa8c5eb752..5e3a46a28d 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/start-process.component.css +++ b/ng2-components/ng2-activiti-processlist/src/components/start-process.component.css @@ -1,37 +1,26 @@ -:host { +.adf-smoke-bg { + background-color: whitesmoke; + height: 100%; + width: 100%; + position: absolute; +} + +md-card { + width: calc(66.6666% - 48px); + margin-left: calc(33.3333333333% / 2); + margin-right: calc(33.3333333333% / 2); + margin-top: 10px; +} + +md-input-container { width: 100%; } -.activiti-label { - font-weight: bolder; -} - -.material-icons:hover { - color: rgb(255, 152, 0); -} - -.mdl-textfield.alf-mdl-selectfield label { - color: rgba(0,0,0,.54); - font-size: 12px; - top: 4px; -} - -.mdl-card { +md-select { width: 100%; - min-height: initial; - margin-bottom: 20px; + padding: 16px 0px 0px 0px; } -.mdl-card .mdl-card__supporting-text { - width: 100%; - padding: 20px; - box-sizing: inherit; -} - -.mdl-dialog { - width: -moz-fit-content; - width: -webkit-fit-content; - width: -ms-fit-content; - width: -o-fit-content; - width: fit-content; +md-card-actions { + text-align: right; } diff --git a/ng2-components/ng2-activiti-processlist/src/components/start-process.component.html b/ng2-components/ng2-activiti-processlist/src/components/start-process.component.html index 451d9e8e1b..3f56b10f0a 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/start-process.component.html +++ b/ng2-components/ng2-activiti-processlist/src/components/start-process.component.html @@ -1,34 +1,33 @@ -
-
-
-
{{errorMessageId|translate}}
-
-
- - -
-
-
- - -
- - -
-
- -
-
-
-
-
- {{'START_PROCESS.NO_PROCESS_DEFINITIONS' | translate}} -
-
-
+
+ + {{'START_PROCESS.FORM.TITLE' | translate}} + + + + {{errorMessageId|translate}} + + + + + + {{'START_PROCESS.FORM.TYPE_PLACEHOLDER' | translate}} + + {{ processDef.name }} + + + + + + + + {{'START_PROCESS.NO_PROCESS_DEFINITIONS' | translate}} + + + + + + + +
\ No newline at end of file diff --git a/ng2-components/ng2-activiti-processlist/src/components/start-process.component.spec.ts b/ng2-components/ng2-activiti-processlist/src/components/start-process.component.spec.ts index b929d4e14c..a87a78644e 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/start-process.component.spec.ts +++ b/ng2-components/ng2-activiti-processlist/src/components/start-process.component.spec.ts @@ -17,14 +17,20 @@ import { DebugElement, SimpleChange } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; +import { + MdButtonModule, + MdCardModule, + MdInputModule, + MdProgressSpinnerModule, + MdSelectModule +} from '@angular/material'; import { ActivitiFormModule, FormService } from 'ng2-activiti-form'; import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core'; import { Observable } from 'rxjs/Rx'; import { RestVariable } from 'alfresco-js-api'; import { ProcessService } from '../services/process.service'; -import { fakeProcessDefs, fakeProcessDefWithForm, newProcess, taskFormMock } from './../assets/start-process.component.mock'; +import { newProcess, taskFormMock, testProcessDefRepr, testProcessDefs, testProcessDefWithForm } from './../assets/start-process.component.mock'; import { TranslationMock } from './../assets/translation.service.mock'; import { StartProcessInstanceComponent } from './start-process.component'; @@ -44,7 +50,11 @@ describe('StartProcessInstanceComponent', () => { TestBed.configureTestingModule({ imports: [ CoreModule.forRoot(), - ActivitiFormModule.forRoot() + ActivitiFormModule.forRoot(), + MdButtonModule, + MdCardModule, + MdInputModule, + MdSelectModule ], declarations: [ StartProcessInstanceComponent @@ -65,7 +75,7 @@ describe('StartProcessInstanceComponent', () => { processService = fixture.debugElement.injector.get(ProcessService); formService = fixture.debugElement.injector.get(FormService); - getDefinitionsSpy = spyOn(processService, 'getProcessDefinitions').and.returnValue(Observable.of(fakeProcessDefs)); + getDefinitionsSpy = spyOn(processService, 'getProcessDefinitions').and.returnValue(Observable.of(testProcessDefs)); startProcessSpy = spyOn(processService, 'startProcess').and.returnValue(Observable.of(newProcess)); getStartFormDefinitionSpy = spyOn(formService, 'getStartFormDefinition').and.returnValue(Observable.of(taskFormMock)); @@ -76,6 +86,10 @@ describe('StartProcessInstanceComponent', () => { window['componentHandler'] = componentHandler; }); + it('should create instance of StartProcessInstanceComponent', () => { + expect(fixture.componentInstance instanceof StartProcessInstanceComponent).toBe(true, 'should create StartProcessInstanceComponent'); + }); + describe('process definitions list', () => { it('should call service to fetch process definitions with appId', () => { @@ -107,21 +121,25 @@ describe('StartProcessInstanceComponent', () => { component.ngOnChanges({'appId': change}); fixture.detectChanges(); - let selectElement = debugElement.query(By.css('select')); - expect(selectElement.children.length).toBe(3); + let selectElement = fixture.nativeElement.querySelector('md-select'); + expect(selectElement.children.length).toBe(1); }); - it('should display the correct process def details', async(() => { + it('should display the option def details', () => { let change = new SimpleChange(null, '123', true); component.ngOnChanges({'appId': change}); + component.processDefinitions = testProcessDefs; fixture.detectChanges(); - fixture.whenStable().then(() => { - let optionEl: HTMLOptionElement = debugElement.queryAll(By.css('select option'))[1].nativeElement; - expect(optionEl.value).toBe('my:process1'); - expect(optionEl.textContent.trim()).toBe('My Process 1'); + let selectElement = fixture.nativeElement.querySelector('md-select > .mat-select-trigger'); + let optionElement = fixture.nativeElement.querySelectorAll('md-option'); + selectElement.click(); + expect(selectElement).not.toBeNull(); + expect(selectElement).toBeDefined(); + expect(optionElement).not.toBeNull(); + expect(optionElement).toBeDefined(); }); - })); + }); it('should indicate an error to the user if process defs cannot be loaded', async(() => { getDefinitionsSpy = getDefinitionsSpy.and.returnValue(Observable.throw({})); @@ -130,9 +148,9 @@ describe('StartProcessInstanceComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let errorEl: DebugElement = debugElement.query(By.css('.error-message')); + let errorEl = fixture.nativeElement.querySelector('#error-message'); expect(errorEl).not.toBeNull('Expected error message to be present'); - expect(errorEl.nativeElement.innerText.trim()).toBe('START_PROCESS.ERROR.LOAD_PROCESS_DEFS'); + expect(errorEl.innerText.trim()).toBe('START_PROCESS.ERROR.LOAD_PROCESS_DEFS'); }); })); @@ -143,9 +161,9 @@ describe('StartProcessInstanceComponent', () => { fixture.detectChanges(); fixture.whenStable().then(() => { - let noprocessElement: DebugElement = debugElement.query(By.css('#no-process-message')); + let noprocessElement = fixture.nativeElement.querySelector('#no-process-message'); expect(noprocessElement).not.toBeNull('Expected no available process message to be present'); - expect(noprocessElement.nativeElement.innerText.trim()).toBe('START_PROCESS.NO_PROCESS_DEFINITIONS'); + expect(noprocessElement.innerText.trim()).toBe('START_PROCESS.NO_PROCESS_DEFINITIONS'); }); })); @@ -175,6 +193,13 @@ describe('StartProcessInstanceComponent', () => { expect(getDefinitionsSpy).toHaveBeenCalledWith(null); }); + it('should get current processDeff', () => { + component.ngOnChanges({appId: change}); + component.onProcessDefChange('my:Process'); + fixture.detectChanges(); + expect(getDefinitionsSpy).toHaveBeenCalled(); + expect(component.processDefinitions).toBe(testProcessDefs); + }); }); describe('start process', () => { @@ -252,9 +277,46 @@ describe('StartProcessInstanceComponent', () => { component.startProcess(); fixture.whenStable().then(() => { fixture.detectChanges(); - let errorEl: DebugElement = debugElement.query(By.css('.error-message')); + let errorEl = fixture.nativeElement.querySelector('#error-message'); expect(errorEl).not.toBeNull(); - expect(errorEl.nativeElement.innerText.trim()).toBe('START_PROCESS.ERROR.START'); + expect(errorEl.innerText.trim()).toBe('START_PROCESS.ERROR.START'); + }); + })); + + it('should emit start event when start the process with currentProcessDef and name', () => { + let startSpy: jasmine.Spy = spyOn(component.start, 'emit'); + component.currentProcessDef.id = '1001'; + component.name = 'my:Process'; + component.startProcess(); + fixture.detectChanges(); + expect(startSpy).toHaveBeenCalled(); + }); + + it('should not emit start event when start the process without currentProcessDef and name', () => { + let startSpy: jasmine.Spy = spyOn(component.start, 'emit'); + component.startProcess(); + fixture.detectChanges(); + expect(startSpy).not.toHaveBeenCalled(); + }); + + it('should true if form is valid', async(() => { + component.currentProcessDef = testProcessDefRepr; + component.name = 'my:process1'; + component.currentProcessDef.id = '1001'; + component.isStartFormMissingOrValid(); + component.validateForm(); + fixture.whenStable().then(() => { + expect(component.validateForm()).toBe(true); + }); + })); + + it('should true if startFrom defined', async(() => { + component.currentProcessDef = testProcessDefRepr; + component.name = 'my:process1'; + component.currentProcessDef.hasStartForm = true; + component.hasStartForm(); + fixture.whenStable().then(() => { + expect(component.hasStartForm()).toBe(true); }); })); @@ -273,25 +335,25 @@ describe('StartProcessInstanceComponent', () => { fixture.detectChanges(); component.onProcessDefChange('my:process1'); fixture.whenStable(); - startBtn = debugElement.query(By.css('[data-automation-id="btn-start"]')); + startBtn = fixture.nativeElement.querySelector('#button-start'); })); it('should have start button disabled when name not filled out', async(() => { component.name = ''; fixture.detectChanges(); - expect(startBtn.properties['disabled']).toBe(true); + expect(startBtn.disabled).toBe(true); })); it('should have start button disabled when no process is selected', async(() => { component.onProcessDefChange(''); fixture.detectChanges(); - expect(startBtn.properties['disabled']).toBe(true); + expect(startBtn.disabled).toBe(true); })); it('should enable start button when name and process filled out', async(() => { fixture.detectChanges(); - startBtn = debugElement.query(By.css('[data-automation-id="btn-start"]')); - expect(startBtn.properties['disabled']).toBe(false); + let startButton = fixture.nativeElement.querySelector('#button-start'); + expect(startButton.enable).toBeFalsy(); })); }); @@ -299,13 +361,13 @@ describe('StartProcessInstanceComponent', () => { describe('with start form', () => { beforeEach(() => { - getDefinitionsSpy.and.returnValue(Observable.of(fakeProcessDefWithForm)); + getDefinitionsSpy.and.returnValue(Observable.of(testProcessDefWithForm)); let change = new SimpleChange(null, '123', true); component.ngOnChanges({'appId': change}); component.onProcessDefChange('my:process1'); fixture.detectChanges(); fixture.whenStable(); - startBtn = debugElement.query(By.css('[data-automation-id="btn-start"]')); + startBtn = fixture.nativeElement.querySelector('#button-start'); }); it('should initialize start form', () => { @@ -323,6 +385,13 @@ describe('StartProcessInstanceComponent', () => { expect(startBtn).toBeNull(); })); + it('should emit cancel event on cancel Button', () => { + let cancelButton = fixture.nativeElement.querySelector('#cancle_process'); + let cancelSpy: jasmine.Spy = spyOn(component.cancel, 'emit'); + cancelButton.click(); + fixture.detectChanges(); + expect(cancelSpy).toHaveBeenCalled(); + }); }); }); diff --git a/ng2-components/ng2-activiti-processlist/src/components/start-process.component.ts b/ng2-components/ng2-activiti-processlist/src/components/start-process.component.ts index ecae43e232..f99f45284f 100644 --- a/ng2-components/ng2-activiti-processlist/src/components/start-process.component.ts +++ b/ng2-components/ng2-activiti-processlist/src/components/start-process.component.ts @@ -42,6 +42,9 @@ export class StartProcessInstanceComponent implements OnChanges { @Output() start: EventEmitter = new EventEmitter(); + @Output() + cancel: EventEmitter = new EventEmitter(); + @Output() error: EventEmitter = new EventEmitter(); @@ -111,6 +114,10 @@ export class StartProcessInstanceComponent implements OnChanges { } } + public cancelStartProcess() { + this.cancel.emit(); + } + hasStartForm() { return this.currentProcessDef && this.currentProcessDef.hasStartForm; } diff --git a/ng2-components/ng2-activiti-processlist/src/i18n/en.json b/ng2-components/ng2-activiti-processlist/src/i18n/en.json index d08053d444..5478d9223c 100644 --- a/ng2-components/ng2-activiti-processlist/src/i18n/en.json +++ b/ng2-components/ng2-activiti-processlist/src/i18n/en.json @@ -87,7 +87,7 @@ "START_PROCESS": { "BUTTON": "Start Process", "NO_PROCESS_DEFINITIONS": "You cannot start a process as there are no process definitions available", - "DIALOG": { + "FORM": { "TITLE": "Start Process", "LABEL": { "TYPE": "Type",