diff --git a/web/package-lock.json b/web/package-lock.json index a75eef70f..8f31ce49c 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -504,8 +504,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -526,14 +525,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -548,20 +545,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -678,8 +672,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -691,7 +684,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -706,7 +698,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -714,14 +705,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -740,7 +729,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -821,8 +809,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -834,7 +821,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -920,8 +906,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -957,7 +942,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -977,7 +961,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -1021,14 +1004,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -4808,8 +4789,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -4830,14 +4810,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4852,20 +4830,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -4982,8 +4957,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -4995,7 +4969,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5010,7 +4983,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5018,14 +4990,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -5044,7 +5014,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -5125,8 +5094,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -5138,7 +5106,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -5224,8 +5191,7 @@ "safe-buffer": { "version": "5.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -5261,7 +5227,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5281,7 +5246,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -5325,14 +5289,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, diff --git a/web/src/app/models/classification-resource.ts b/web/src/app/models/classification-resource.ts index f1012605f..5499e64fb 100644 --- a/web/src/app/models/classification-resource.ts +++ b/web/src/app/models/classification-resource.ts @@ -1,7 +1,6 @@ import { Classification } from './classification'; import { Links } from './links'; - export class ClassificationResource { constructor( public _embedded: { diff --git a/web/src/app/services/classifications/classifications.service.ts b/web/src/app/services/classifications/classifications.service.ts index 9d75ec03b..7ec213aa2 100644 --- a/web/src/app/services/classifications/classifications.service.ts +++ b/web/src/app/services/classifications/classifications.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { environment } from 'environments/environment'; -import { Observable, Subject, combineLatest } from 'rxjs'; +import { combineLatest, Observable, Subject} from 'rxjs'; import { mergeMap, tap } from 'rxjs/operators'; import { Classification } from 'app/models/classification'; @@ -20,6 +20,8 @@ export class ClassificationsService { private url = `${environment.taskanaRestUrl}/v1/classifications/`; private classificationSelected = new Subject(); private classificationSaved = new Subject(); + private classificationResourcePromise: Promise; + private lastDomain: string; constructor( private httpClient: HttpClient, @@ -39,6 +41,16 @@ export class ClassificationsService { ) } + // GET + getClassificationsByDomain(domain: string, forceRefresh = false): Promise { + if (this.lastDomain !== domain || !this.classificationResourcePromise || forceRefresh) { + this.lastDomain = domain; + this.classificationResourcePromise = this.httpClient.get( + `${this.url}${TaskanaQueryParameters.getQueryParameters(this.classificationParameters(domain))}`).toPromise(); + } + return this.classificationResourcePromise; + } + // GET getClassification(id: string): Observable { return this.httpClient.get(`${this.url}${id}`) @@ -49,7 +61,6 @@ export class ClassificationsService { })); } - // POST postClassification(classification: Classification): Observable { return this.httpClient.post(`${this.url}`, classification); @@ -72,7 +83,6 @@ export class ClassificationsService { getSelectedClassification(): Observable { return this.classificationSelected.asObservable(); - } triggerClassificationSaved() { @@ -97,7 +107,7 @@ export class ClassificationsService { return parameters; } - private getClassificationObservable(classificationRef: Observable): Observable { + private getClassificationObservable(classificationRef: Observable): Observable> { const classificationTypes = this.classificationCategoriesService.getSelectedClassificationType(); return combineLatest( classificationRef, @@ -111,7 +121,7 @@ export class ClassificationsService { ) } - private buildHierarchy(classifications: Array, type: string) { + private buildHierarchy(classifications: Array, type: string): Array { const roots = []; const children = []; @@ -139,4 +149,3 @@ export class ClassificationsService { } } } - diff --git a/web/src/app/shared/dropdown/dropdown.component.html b/web/src/app/shared/dropdown/dropdown.component.html new file mode 100644 index 000000000..ac0212433 --- /dev/null +++ b/web/src/app/shared/dropdown/dropdown.component.html @@ -0,0 +1,18 @@ + diff --git a/web/src/app/shared/dropdown/dropdown.component.scss b/web/src/app/shared/dropdown/dropdown.component.scss new file mode 100644 index 000000000..583d02615 --- /dev/null +++ b/web/src/app/shared/dropdown/dropdown.component.scss @@ -0,0 +1,4 @@ +.height-and-scroll { + max-height: 300px; + overflow-y: auto; +} diff --git a/web/src/app/shared/dropdown/dropdown.component.spec.ts b/web/src/app/shared/dropdown/dropdown.component.spec.ts new file mode 100644 index 000000000..b386f364f --- /dev/null +++ b/web/src/app/shared/dropdown/dropdown.component.spec.ts @@ -0,0 +1,44 @@ +import {async, ComponentFixture, TestBed} from '@angular/core/testing'; + +import {DropdownComponent} from './dropdown.component'; + +describe('DropdownComponent', () => { + let component: DropdownComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [DropdownComponent] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DropdownComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should have values', () => { + component.list = new Array('first', 'second'); + component.itemSelected = 'second'; + expect(component.list).not.toBeNull(); + expect(component.list).not.toBeNaN(); + expect(component.itemSelected).not.toBeNull(); + expect(component.itemSelected).not.toBeNaN(); + }); + + it('should have the correct item selected', () => { + component.list = new Array('first', 'second'); + + component.selectItem('first'); + expect(component.itemSelected).toBe('first'); + + component.selectItem('second'); + expect(component.itemSelected).toBe('second'); + }); +}); diff --git a/web/src/app/shared/dropdown/dropdown.component.ts b/web/src/app/shared/dropdown/dropdown.component.ts new file mode 100644 index 000000000..7f8b63b26 --- /dev/null +++ b/web/src/app/shared/dropdown/dropdown.component.ts @@ -0,0 +1,26 @@ +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {SortingModel} from '../../models/sorting'; +import {Classification} from '../../models/classification'; + +@Component({ + selector: 'taskana-dropdown', + templateUrl: './dropdown.component.html', + styleUrls: ['./dropdown.component.scss'] +}) +export class DropdownComponent implements OnInit { + + @Input() itemSelected: any; + @Input() list: Array; + @Output() performClassification = new EventEmitter(); + + constructor() { + } + + ngOnInit(): void { + } + + selectItem(item: any) { + this.itemSelected = item; + this.performClassification.emit(item); + } +} diff --git a/web/src/app/shared/shared.module.ts b/web/src/app/shared/shared.module.ts index e2a2ff696..62f84daaa 100644 --- a/web/src/app/shared/shared.module.ts +++ b/web/src/app/shared/shared.module.ts @@ -26,6 +26,7 @@ import {PaginationComponent} from './pagination/pagination.component'; import {NumberPickerComponent} from './number-picker/number-picker.component'; import {ProgressBarComponent} from './progress-bar/progress-bar.component'; import {DatePickerComponent} from './date-picker/date-picker.component'; +import {DropdownComponent} from './dropdown/dropdown.component'; /** * Pipes @@ -82,7 +83,8 @@ const DECLARATIONS = [ PaginationComponent, NumberPickerComponent, ProgressBarComponent, - DatePickerComponent + DatePickerComponent, + DropdownComponent ]; @NgModule({ diff --git a/web/src/app/workplace/taskdetails/general/general-fields.component.html b/web/src/app/workplace/taskdetails/general/general-fields.component.html index e16ad7d3f..d09010d44 100644 --- a/web/src/app/workplace/taskdetails/general/general-fields.component.html +++ b/web/src/app/workplace/taskdetails/general/general-fields.component.html @@ -57,25 +57,8 @@
- - + +
diff --git a/web/src/app/workplace/taskdetails/general/general-fields.component.spec.ts b/web/src/app/workplace/taskdetails/general/general-fields.component.spec.ts index 6ffbd0375..4d4de3f0a 100644 --- a/web/src/app/workplace/taskdetails/general/general-fields.component.spec.ts +++ b/web/src/app/workplace/taskdetails/general/general-fields.component.spec.ts @@ -1,21 +1,25 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; -import { TaskdetailsGeneralFieldsComponent } from './general-fields.component'; -import { FormsModule } from '@angular/forms'; -import { ClassificationsService } from 'app/services/classifications/classifications.service'; -import { HttpClient, HttpClientModule } from '@angular/common/http'; -import { ClassificationCategoriesService } from 'app/services/classifications/classification-categories.service'; -import { CustomFieldsService } from 'app/services/custom-fields/custom-fields.service'; -import { DomainService } from 'app/services/domain/domain.service'; -import { RouterTestingModule } from '@angular/router/testing'; -import { Routes } from '@angular/router'; -import { Component } from '@angular/core'; -import { RequestInProgressService } from 'app/services/requestInProgress/request-in-progress.service'; -import { SelectedRouteService } from 'app/services/selected-route/selected-route'; +import {TaskdetailsGeneralFieldsComponent} from './general-fields.component'; +import {FormsModule} from '@angular/forms'; +import {HttpClient, HttpClientModule} from '@angular/common/http'; +import {ClassificationCategoriesService} from 'app/services/classifications/classification-categories.service'; +import {CustomFieldsService} from 'app/services/custom-fields/custom-fields.service'; +import {DomainService} from 'app/services/domain/domain.service'; +import {RouterTestingModule} from '@angular/router/testing'; +import {Routes} from '@angular/router'; +import {Component} from '@angular/core'; +import {RequestInProgressService} from 'app/services/requestInProgress/request-in-progress.service'; +import {SelectedRouteService} from 'app/services/selected-route/selected-route'; +import {ClassificationsService} from '../../../services/classifications/classifications.service'; +import {configureTests} from '../../../app.test.configuration'; +import {Classification} from '../../../models/classification'; +import {Links} from '../../../models/links'; +import {ClassificationResource} from '../../../models/classification-resource'; @Component({ - selector: 'taskana-dummy-detail', - template: 'dummydetail' + selector: 'taskana-dummy-detail', + template: 'dummydetail' }) export class DummyDetailComponent { } @@ -24,20 +28,35 @@ export class DummyDetailComponent { xdescribe('GeneralComponent', () => { let component: TaskdetailsGeneralFieldsComponent; let fixture: ComponentFixture; + let classificationsService; const routes: Routes = [ - { path: '*', component: DummyDetailComponent } - ]; + {path: '*', component: DummyDetailComponent} + ]; - beforeEach(async(() => { - TestBed.configureTestingModule({ - imports: [FormsModule, HttpClientModule, RouterTestingModule.withRoutes(routes)], - declarations: [TaskdetailsGeneralFieldsComponent, DummyDetailComponent], - providers: [ClassificationsService, HttpClient, ClassificationCategoriesService, CustomFieldsService, - DomainService, RequestInProgressService, SelectedRouteService] - }) - .compileComponents(); - })); + beforeEach(done => { + const configure = (testBed: TestBed) => { + TestBed.configureTestingModule({ + imports: [FormsModule, HttpClientModule, RouterTestingModule.withRoutes(routes)], + declarations: [TaskdetailsGeneralFieldsComponent, DummyDetailComponent], + providers: [HttpClient, ClassificationCategoriesService, CustomFieldsService, + DomainService, RequestInProgressService, SelectedRouteService, ClassificationsService] + }) + }; + configureTests(configure).then(testBed => { + classificationsService = TestBed.get(ClassificationsService); + spyOn(classificationsService, 'getClassificationsByDomain').and.returnValue(new ClassificationResource( + { + 'classificationSummaryResourceList': new Array( + new Classification('id1', '1', 'category', 'type', 'domain_a', 'classification1', 'parentId', + 1, 'service', new Links({ 'href': 'someurl' })), + new Classification('id2', '2', 'category', 'type', 'domain_a', 'classification2', 'parentId2', + 1, 'service', new Links({ 'href': 'someurl' }))) + }, new Links({ 'href': 'someurl' }) + )); + done(); + }); + }); beforeEach(() => { fixture = TestBed.createComponent(TaskdetailsGeneralFieldsComponent); @@ -48,4 +67,10 @@ xdescribe('GeneralComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should call to getClassificationsByDomain', done => { + component.ngOnInit(); + expect(classificationsService.getClassificationsByDomain).toHaveBeenCalled(); + done(); + }); }); diff --git a/web/src/app/workplace/taskdetails/general/general-fields.component.ts b/web/src/app/workplace/taskdetails/general/general-fields.component.ts index ec4cd5a30..9b8847119 100644 --- a/web/src/app/workplace/taskdetails/general/general-fields.component.ts +++ b/web/src/app/workplace/taskdetails/general/general-fields.component.ts @@ -1,10 +1,11 @@ -import { Component, EventEmitter, Input, OnInit, Output, ViewChild, SimpleChanges, OnChanges, HostListener } from '@angular/core'; -import { Task } from 'app/workplace/models/task'; -import { Classification } from '../../../models/classification'; -import { ClassificationsService } from '../../../services/classifications/classifications.service'; -import { CustomFieldsService } from 'app/services/custom-fields/custom-fields.service'; -import { FormsValidatorService } from 'app/shared/services/forms/forms-validator.service'; -import { NgForm } from '@angular/forms'; +import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild} from '@angular/core'; +import {Task} from 'app/workplace/models/task'; +import {Classification} from '../../../models/classification'; +import {ClassificationsService} from '../../../services/classifications/classifications.service'; +import {CustomFieldsService} from 'app/services/custom-fields/custom-fields.service'; +import {FormsValidatorService} from 'app/shared/services/forms/forms-validator.service'; +import {NgForm} from '@angular/forms'; +import {DomainService} from '../../../services/domain/domain.service'; @Component({ selector: 'taskana-task-details-general-fields', @@ -21,8 +22,6 @@ export class TaskdetailsGeneralFieldsComponent implements OnInit, OnChanges { saveToggleTriggered: boolean; @Output() formValid: EventEmitter = new EventEmitter(); - @Output() classificationsReceived: EventEmitter = new EventEmitter(); - @ViewChild('TaskForm') taskForm: NgForm; @@ -38,7 +37,12 @@ export class TaskdetailsGeneralFieldsComponent implements OnInit, OnChanges { constructor( private classificationService: ClassificationsService, private customFieldsService: CustomFieldsService, - private formsValidatorService: FormsValidatorService) { + private formsValidatorService: FormsValidatorService, + private domainService: DomainService) { + } + + ngOnInit() { + this.getClassificationByDomain(); } ngOnChanges(changes: SimpleChanges): void { @@ -47,20 +51,10 @@ export class TaskdetailsGeneralFieldsComponent implements OnInit, OnChanges { } } - ngOnInit() { - this.requestInProgress = true; - this.classificationService.getClassifications().subscribe(classificationList => { - this.requestInProgress = false; - this.classifications = classificationList; - this.classificationsReceived.emit(this.classifications); - }); - } - selectClassification(classification: Classification) { this.task.classificationSummaryResource = classification; } - isFieldValid(field: string): boolean { return this.formsValidatorService.isFieldValid(this.taskForm, field); } @@ -81,4 +75,15 @@ export class TaskdetailsGeneralFieldsComponent implements OnInit, OnChanges { } }); } + + private changedClassification(itemSelected: any) { + this.task.classificationSummaryResource = itemSelected; + } + + private async getClassificationByDomain() { + this.requestInProgress = true; + this.classifications = (await this.classificationService.getClassificationsByDomain(this.domainService.getSelectedDomainValue())) + ._embedded.classificationSummaryResourceList; + this.requestInProgress = false; + } } diff --git a/web/src/app/workplace/taskdetails/taskdetails.component.ts b/web/src/app/workplace/taskdetails/taskdetails.component.ts index 213ff64c4..096737505 100644 --- a/web/src/app/workplace/taskdetails/taskdetails.component.ts +++ b/web/src/app/workplace/taskdetails/taskdetails.component.ts @@ -95,7 +95,6 @@ export class TaskdetailsComponent implements OnInit, OnDestroy { this.onSave(); } - openTask() { this.router.navigate([{outlets: {detail: `task/${this.currentId}`}}], {relativeTo: this.route.parent}); } @@ -124,7 +123,6 @@ export class TaskdetailsComponent implements OnInit, OnDestroy { this.tabSelected = tab; } - backClicked(): void { this.task = undefined; this.taskService.selectTask(this.task); diff --git a/web/src/app/workplace/taskmaster/task-list-toolbar/task-list-toolbar.component.ts b/web/src/app/workplace/taskmaster/task-list-toolbar/task-list-toolbar.component.ts index e757d401b..abe4d28b4 100644 --- a/web/src/app/workplace/taskmaster/task-list-toolbar/task-list-toolbar.component.ts +++ b/web/src/app/workplace/taskmaster/task-list-toolbar/task-list-toolbar.component.ts @@ -41,7 +41,6 @@ export class TaskListToolbarComponent implements OnInit { toolbarState = false; filterType = TaskanaType.TASKS; searched = false; - searchParam = 'search'; search = Search; searchSelected: Search = Search.byWorkbasket; diff --git a/web/src/assets/_buttons.scss b/web/src/assets/_buttons.scss index 361398bf7..fa861e251 100644 --- a/web/src/assets/_buttons.scss +++ b/web/src/assets/_buttons.scss @@ -2,7 +2,7 @@ border-bottom-right-radius: 0; border-top-right-radius: 0; } -.btn-group ul + .btn, { +.btn-group ul + .btn { margin-left: -1px; }