task/827 Modify classification's parent
Create a drag and drop test
This commit is contained in:
parent
aea64975db
commit
b09e0b789a
File diff suppressed because it is too large
Load Diff
|
@ -24,7 +24,7 @@
|
|||
"@angular/router": "7.1.3",
|
||||
"ajv": "6.5.2",
|
||||
"angular-svg-icon": "6.0.0",
|
||||
"angular-tree-component": "7.1.0",
|
||||
"angular-tree-component": "8.2.0",
|
||||
"bootstrap": "4.3.1",
|
||||
"bootstrap-sass": "3.4.1",
|
||||
"chart.js": "2.7.2",
|
||||
|
@ -42,8 +42,8 @@
|
|||
"zone.js": "0.8.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "0.13.2",
|
||||
"@angular/cli": "7.1.3",
|
||||
"@angular-devkit/build-angular": "^0.13.8",
|
||||
"@angular/cli": "^7.3.8",
|
||||
"@angular/compiler-cli": "7.2.7",
|
||||
"@types/jasmine": "2.8.4",
|
||||
"@types/node": "9.3.0",
|
||||
|
|
|
@ -165,7 +165,7 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
|
|||
this.action = undefined
|
||||
}
|
||||
|
||||
private onSave() {
|
||||
private async onSave() {
|
||||
this.requestInProgressService.setRequestInProgress(true);
|
||||
if (this.action === ACTION.CREATE) {
|
||||
this.classificationSavingSubscription = this.classificationsService.postClassification(this.classification)
|
||||
|
@ -180,17 +180,17 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
|
|||
this.afterRequest();
|
||||
});
|
||||
} else {
|
||||
this.classificationSavingSubscription = this.classificationsService
|
||||
.putClassification(this.classification._links.self.href, this.classification)
|
||||
.subscribe((classification: ClassificationDefinition) => {
|
||||
this.classification = classification;
|
||||
this.afterRequest();
|
||||
this.alertService.triggerAlert(new AlertModel(AlertType.SUCCESS, `Classification ${classification.key} was saved successfully`));
|
||||
this.cloneClassification(classification);
|
||||
}, error => {
|
||||
this.generalModalService.triggerMessage(new MessageModal('There was error while saving your classification', error))
|
||||
this.afterRequest();
|
||||
})
|
||||
try {
|
||||
this.classification = (<ClassificationDefinition> await this.classificationsService.putClassification(
|
||||
this.classification._links.self.href, this.classification));
|
||||
this.afterRequest();
|
||||
this.alertService.triggerAlert(
|
||||
new AlertModel(AlertType.SUCCESS, `Classification ${this.classification.key} was saved successfully`));
|
||||
this.cloneClassification(this.classification);
|
||||
} catch (error) {
|
||||
this.generalModalService.triggerMessage(new MessageModal('There was error while saving your classification', error))
|
||||
this.afterRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,16 +216,15 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
|
|||
this.classificationsService.triggerClassificationSaved();
|
||||
}
|
||||
|
||||
private selectClassification(id: string) {
|
||||
private async selectClassification(id: string) {
|
||||
if (this.classificationIsAlreadySelected()) {
|
||||
return true;
|
||||
}
|
||||
this.requestInProgress = true;
|
||||
this.selectedClassificationSubscription = this.classificationsService.getClassification(id).subscribe(classification => {
|
||||
this.fillClassificationInformation(classification)
|
||||
this.classificationsService.selectClassification(classification);
|
||||
this.requestInProgress = false;
|
||||
});
|
||||
const classification = await this.classificationsService.getClassification(id);
|
||||
this.fillClassificationInformation(classification)
|
||||
this.classificationsService.selectClassification(classification);
|
||||
this.requestInProgress = false;
|
||||
}
|
||||
|
||||
private classificationIsAlreadySelected(): boolean {
|
||||
|
@ -285,7 +284,7 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
|
|||
this.classification = undefined;
|
||||
this.afterRequest();
|
||||
this.classificationsService.selectClassification(undefined);
|
||||
this.router.navigate(['administration/classifications']);
|
||||
this.router.navigate(['taskana/administration/classifications']);
|
||||
this.alertService.triggerAlert(new AlertModel(AlertType.SUCCESS, `Classification ${key} was removed successfully`))
|
||||
}, error => {
|
||||
this.generalModalService.triggerMessage(new MessageModal('There was error while removing your classification', error))
|
||||
|
|
|
@ -45,11 +45,12 @@
|
|||
<taskana-spinner class="col-xs-12" [isRunning]="requestInProgress" positionClass="centered-spinner-whole-screen"></taskana-spinner>
|
||||
<taskana-tree class="col-xs-12" *ngIf="(classifications && classifications.length) else empty_classifications"
|
||||
[treeNodes]="classifications" [selectNodeId]="selectedId" [filterText]="inputValue" [filterIcon]="selectedCategory"
|
||||
(selectNodeIdChanged)="selectClassification($event)"></taskana-tree>
|
||||
(selectNodeIdChanged)="selectClassification($event)" (refreshClassification)="getClassifications($event)"
|
||||
(switchTaskanaSpinnerEmit)="switchTaskanaSpinner($event)"></taskana-tree>
|
||||
<ng-template #empty_classifications>
|
||||
<div *ngIf="!requestInProgress" class="col-xs-12 container-no-items center-block">
|
||||
<h3 class="grey">There are no classifications</h3>
|
||||
<svg-icon class="img-responsive empty-icon" src="./assets/icons/classification-empty.svg"></svg-icon>
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -13,6 +13,8 @@ import {
|
|||
import { Pair } from 'app/models/pair';
|
||||
import { ClassificationDefinition } from '../../../../models/classification-definition';
|
||||
import { ImportExportService } from 'app/administration/services/import-export/import-export.service';
|
||||
import {AlertModel, AlertType} from '../../../../models/alert';
|
||||
import {AlertService} from '../../../../services/alert/alert.service';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-classification-list',
|
||||
|
@ -45,7 +47,8 @@ export class ClassificationListComponent implements OnInit, OnDestroy {
|
|||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private categoryService: ClassificationCategoriesService,
|
||||
private importExportService: ImportExportService) {
|
||||
private importExportService: ImportExportService,
|
||||
private alertService: AlertService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@ -70,20 +73,15 @@ export class ClassificationListComponent implements OnInit, OnDestroy {
|
|||
|
||||
selectClassificationType(classificationTypeSelected: string) {
|
||||
this.classifications = [];
|
||||
this.requestInProgress = true;
|
||||
this.categoryService.selectClassificationType(classificationTypeSelected);
|
||||
this.classificationService.getClassifications()
|
||||
.subscribe((classifications: Array<TreeNodeModel>) => {
|
||||
this.classifications = classifications;
|
||||
this.requestInProgress = false;
|
||||
});
|
||||
this.getClassifications();
|
||||
this.selectClassification(undefined);
|
||||
}
|
||||
|
||||
selectClassification(id: string) {
|
||||
this.selectedId = id;
|
||||
if (!id) {
|
||||
this.router.navigate(['administration/classifications']);
|
||||
this.router.navigate(['taskana/administration/classifications']);
|
||||
return;
|
||||
}
|
||||
this.router.navigate([{ outlets: { detail: [this.selectedId] } }], { relativeTo: this.route });
|
||||
|
@ -129,6 +127,24 @@ export class ClassificationListComponent implements OnInit, OnDestroy {
|
|||
this.initialized = true;
|
||||
|
||||
}
|
||||
|
||||
private getClassifications(key: string = undefined) {
|
||||
this.requestInProgress = true;
|
||||
this.classificationService.getClassifications()
|
||||
.subscribe((classifications: Array<TreeNodeModel>) => {
|
||||
this.classifications = classifications;
|
||||
this.requestInProgress = false;
|
||||
});
|
||||
|
||||
if (key) {
|
||||
this.alertService.triggerAlert(new AlertModel(AlertType.SUCCESS, `Classification ${key} was saved successfully`));
|
||||
}
|
||||
}
|
||||
|
||||
private switchTaskanaSpinner($event) {
|
||||
this.requestInProgress = $event;
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this.classificationServiceSubscription) { this.classificationServiceSubscription.unsubscribe(); }
|
||||
if (this.classificationTypeServiceSubscription) { this.classificationTypeServiceSubscription.unsubscribe(); }
|
||||
|
|
|
@ -288,7 +288,7 @@ export class WorkbasketInformationComponent
|
|||
new AlertModel(AlertType.SUCCESS, 'The Workbasket ' + this.workbasket.workbasketId + ' has been marked for deletion')
|
||||
);
|
||||
}
|
||||
this.router.navigate(['administration/workbaskets']);
|
||||
this.router.navigate(['taskana/administration/workbaskets']);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,14 +8,14 @@ import {WindowRefService} from '../window/window.service';
|
|||
import {environment} from '../../../environments/environment';
|
||||
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
|
||||
|
||||
fdescribe('StartupService', () => {
|
||||
describe('StartupService', () => {
|
||||
const environmentFile = '/environments/data-sources/environment-information.json';
|
||||
const someRestUrl = 'someRestUrl';
|
||||
const someLogoutUrl = 'someLogoutUrl';
|
||||
const dummyEnvironmentInformation = {
|
||||
'taskanaRestUrl': someRestUrl,
|
||||
'taskanaLogoutUrl': someLogoutUrl
|
||||
}
|
||||
};
|
||||
|
||||
let httpMock, service;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Observable , Subject } from 'rxjs';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
@Injectable()
|
||||
export class TreeService {
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { environment } from 'environments/environment';
|
||||
import { combineLatest, Observable, Subject} from 'rxjs';
|
||||
import { mergeMap, tap } from 'rxjs/operators';
|
||||
import {Injectable} from '@angular/core';
|
||||
import {HttpClient} from '@angular/common/http';
|
||||
import {environment} from 'environments/environment';
|
||||
import {combineLatest, Observable, Subject} from 'rxjs';
|
||||
import {mergeMap, tap} from 'rxjs/operators';
|
||||
|
||||
import { Classification } from 'app/models/classification';
|
||||
import { ClassificationDefinition } from 'app/models/classification-definition';
|
||||
import {Classification} from 'app/models/classification';
|
||||
import {ClassificationDefinition} from 'app/models/classification-definition';
|
||||
|
||||
import { ClassificationResource } from 'app/models/classification-resource';
|
||||
import { ClassificationCategoriesService } from './classification-categories.service';
|
||||
import { DomainService } from 'app/services/domain/domain.service';
|
||||
import { TaskanaQueryParameters } from 'app/shared/util/query-parameters';
|
||||
import { Direction } from 'app/models/sorting';
|
||||
import { QueryParametersModel } from 'app/models/query-parameters';
|
||||
import {ClassificationResource} from 'app/models/classification-resource';
|
||||
import {ClassificationCategoriesService} from './classification-categories.service';
|
||||
import {DomainService} from 'app/services/domain/domain.service';
|
||||
import {TaskanaQueryParameters} from 'app/shared/util/query-parameters';
|
||||
import {Direction} from 'app/models/sorting';
|
||||
import {QueryParametersModel} from 'app/models/query-parameters';
|
||||
|
||||
@Injectable()
|
||||
export class ClassificationsService {
|
||||
|
@ -37,7 +37,9 @@ export class ClassificationsService {
|
|||
`${this.url}${TaskanaQueryParameters.getQueryParameters(this.classificationParameters(domain))}`));
|
||||
|
||||
}),
|
||||
tap(() => { this.domainService.domainChangedComplete(); })
|
||||
tap(() => {
|
||||
this.domainService.domainChangedComplete();
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -52,13 +54,13 @@ export class ClassificationsService {
|
|||
}
|
||||
|
||||
// GET
|
||||
getClassification(id: string): Observable<ClassificationDefinition> {
|
||||
getClassification(id: string): Promise<ClassificationDefinition> {
|
||||
return this.httpClient.get<ClassificationDefinition>(`${this.url}${id}`)
|
||||
.pipe(tap((classification: ClassificationDefinition) => {
|
||||
if (classification) {
|
||||
this.classificationCategoriesService.selectClassificationType(classification.type);
|
||||
}
|
||||
}));
|
||||
})).toPromise();
|
||||
}
|
||||
|
||||
// POST
|
||||
|
@ -67,8 +69,8 @@ export class ClassificationsService {
|
|||
}
|
||||
|
||||
// PUT
|
||||
putClassification(url: string, classification: Classification): Observable<Classification> {
|
||||
return this.httpClient.put<Classification>(url, classification);
|
||||
putClassification(url: string, classification: Classification): Promise<Classification> {
|
||||
return this.httpClient.put<Classification>(url, classification).toPromise();
|
||||
}
|
||||
|
||||
// DELETE
|
||||
|
|
|
@ -60,7 +60,7 @@ const MODULES = [
|
|||
AngularSvgIconModule,
|
||||
HttpClientModule,
|
||||
RouterModule,
|
||||
TreeModule
|
||||
TreeModule.forRoot()
|
||||
];
|
||||
|
||||
const DECLARATIONS = [
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<tree-root #tree [nodes]="treeNodes" [options]="options" (activate)="onActivate($event)" (deactivate)="onDeactivate($event)">
|
||||
<tree-root #tree [nodes]="treeNodes" [options]="options" (activate)="onActivate($event)" (deactivate)="onDeactivate($event)"
|
||||
(moveNode)="onMoveNode($event)" (treeDrop)="onDrop($event)">
|
||||
<ng-template #treeNodeTemplate let-node let-index="index">
|
||||
<span class="text-top">
|
||||
<svg-icon *ngIf="node.data.category" class="blue fa-fw" [src]="getCategoryIcon(node.data.category).name" data-toggle="tooltip"
|
||||
|
@ -9,4 +10,4 @@
|
|||
</span>
|
||||
<span> - {{ node.data.name }}</span>
|
||||
</ng-template>
|
||||
</tree-root>
|
||||
</tree-root>
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
import { Input, Component } from '@angular/core';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {AngularSvgIconModule} from 'angular-svg-icon';
|
||||
import {HttpClientModule} from '@angular/common/http';
|
||||
|
||||
import { TaskanaTreeComponent } from './tree.component';
|
||||
import {TaskanaTreeComponent} from './tree.component';
|
||||
|
||||
import { TreeService } from 'app/services/tree/tree.service';
|
||||
import {
|
||||
ClassificationCategoriesService
|
||||
} from 'app/shared/services/classifications/classification-categories.service';
|
||||
import { configureTests } from 'app/app.test.configuration';
|
||||
import { Pair } from 'app/models/pair';
|
||||
import {TreeService} from 'app/services/tree/tree.service';
|
||||
import {configureTests} from 'app/app.test.configuration';
|
||||
import {Pair} from 'app/models/pair';
|
||||
import {ClassificationDefinition} from '../../models/classification-definition';
|
||||
import {LinksClassification} from '../../models/links-classfication';
|
||||
import {ClassificationCategoriesService} from '../services/classifications/classification-categories.service';
|
||||
import {ClassificationsService} from '../services/classifications/classifications.service';
|
||||
|
||||
// tslint:disable:component-selector
|
||||
@Component({
|
||||
|
@ -22,23 +23,27 @@ class TreeVendorComponent {
|
|||
@Input() state;
|
||||
@Input() nodes;
|
||||
treeModel = {
|
||||
getActiveNode() { }
|
||||
getActiveNode() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tslint:enable:component-selector
|
||||
|
||||
describe('TaskanaTreeComponent', () => {
|
||||
let component: TaskanaTreeComponent;
|
||||
let fixture: ComponentFixture<TaskanaTreeComponent>;
|
||||
let classificationCategoriesService;
|
||||
|
||||
let classificationsService;
|
||||
let moveNodeEvent;
|
||||
let dropEvent;
|
||||
|
||||
beforeEach(done => {
|
||||
const configure = (testBed: TestBed) => {
|
||||
testBed.configureTestingModule({
|
||||
imports: [AngularSvgIconModule, HttpClientModule],
|
||||
declarations: [TreeVendorComponent],
|
||||
providers: [TreeService, ClassificationCategoriesService]
|
||||
providers: [TreeService, ClassificationCategoriesService, ClassificationsService]
|
||||
|
||||
})
|
||||
};
|
||||
|
@ -46,6 +51,45 @@ describe('TaskanaTreeComponent', () => {
|
|||
fixture = testBed.createComponent(TaskanaTreeComponent);
|
||||
classificationCategoriesService = testBed.get(ClassificationCategoriesService);
|
||||
spyOn(classificationCategoriesService, 'getCategoryIcon').and.returnValue(new Pair('assets/icons/categories/external.svg'));
|
||||
classificationsService = TestBed.get(ClassificationsService);
|
||||
spyOn(classificationsService, 'putClassification').and.callFake(function (url, classification) {
|
||||
return classification;
|
||||
});
|
||||
moveNodeEvent = {
|
||||
eventName: 'moveNode',
|
||||
node: {
|
||||
classificationId: 'id4',
|
||||
parentId: '',
|
||||
parentKey: '',
|
||||
_links: {
|
||||
self: {
|
||||
href: 'url'
|
||||
}
|
||||
}
|
||||
},
|
||||
to: {
|
||||
parent: {
|
||||
classificationId: 'id3',
|
||||
key: 'key3'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
dropEvent = {
|
||||
event: {
|
||||
target: {
|
||||
tagName: 'TREE-VIEWPORT'
|
||||
}
|
||||
},
|
||||
element: {
|
||||
data: {
|
||||
classificationId: 'id3',
|
||||
parentId: 'id1',
|
||||
parentKey: 'key1'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
done();
|
||||
|
@ -55,4 +99,41 @@ describe('TaskanaTreeComponent', () => {
|
|||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should be change the classification parent (onMoveNode)', async () => {
|
||||
spyOn(classificationsService, 'getClassification').and.returnValue(new ClassificationDefinition('id4',
|
||||
'key4', '', '', 'MANUAL', 'DOMAIN_A', 'TASK', true, '019-04-10T10:23:34.985Z', '2019-04-10T10:23:34.985Z',
|
||||
'classification4', 'description', 1, 'level', '', '', '', '', '', ''
|
||||
, '', '', '', new LinksClassification({href: ''}, '', '', {href: ''}, {href: ''}, {href: ''})));
|
||||
spyOn(component, 'switchTaskanaSpinner');
|
||||
const classification = classificationsService.getClassification();
|
||||
expect(classification.parentId).toEqual('');
|
||||
expect(classification.parentKey).toEqual('');
|
||||
|
||||
await component.onMoveNode(moveNodeEvent);
|
||||
|
||||
expect(classification.parentId).toEqual('id3');
|
||||
expect(classification.parentKey).toEqual('key3');
|
||||
expect(classificationsService.putClassification).toHaveBeenCalledWith(classification._links.self.href, classification);
|
||||
expect(component.switchTaskanaSpinner).toHaveBeenCalledWith(true);
|
||||
expect(component.switchTaskanaSpinner).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
it('should be changed the parent classification to root node (onDrop)', async () => {
|
||||
spyOn(classificationsService, 'getClassification').and.returnValue(new ClassificationDefinition('id3',
|
||||
'key3', 'id1', 'key1', 'MANUAL', 'DOMAIN_A', 'TASK', true, '019-04-10T10:23:34.985Z', '2019-04-10T10:23:34.985Z',
|
||||
'classification3', 'description', 1, 'level', '', '', '', '', '', ''
|
||||
, '', '', '', new LinksClassification({href: ''}, '', '', {href: ''}, {href: ''}, {href: ''})));
|
||||
spyOn(component, 'switchTaskanaSpinner');
|
||||
const classification = classificationsService.getClassification();
|
||||
expect(classification.parentId).toEqual('id1');
|
||||
expect(classification.parentKey).toEqual('key1');
|
||||
|
||||
await component.onDrop(dropEvent);
|
||||
|
||||
expect(classification.parentId).toEqual('');
|
||||
expect(classification.parentKey).toEqual('');
|
||||
expect(component.switchTaskanaSpinner).toHaveBeenCalledWith(true);
|
||||
expect(component.switchTaskanaSpinner).toHaveBeenCalledWith(false);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,16 +1,25 @@
|
|||
import {
|
||||
Component, OnInit, Input, Output, EventEmitter, ViewChild, AfterViewChecked,
|
||||
OnDestroy, ElementRef, HostListener
|
||||
AfterViewChecked,
|
||||
Component,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
HostListener,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import { TreeNodeModel } from 'app/models/tree-node';
|
||||
import {TreeNodeModel} from 'app/models/tree-node';
|
||||
|
||||
import { KEYS, ITreeOptions, TreeComponent, TreeNode } from 'angular-tree-component';
|
||||
import { TreeService } from '../../services/tree/tree.service';
|
||||
import {
|
||||
ClassificationCategoriesService
|
||||
} from 'app/shared/services/classifications/classification-categories.service';
|
||||
import { Pair } from 'app/models/pair';
|
||||
import { Subscription } from 'rxjs';
|
||||
import {ITreeOptions, KEYS, TreeComponent, TreeNode} from 'angular-tree-component';
|
||||
import {TreeService} from '../../services/tree/tree.service';
|
||||
import {ClassificationCategoriesService} from 'app/shared/services/classifications/classification-categories.service';
|
||||
import {Pair} from 'app/models/pair';
|
||||
import {Subscription} from 'rxjs';
|
||||
import {Classification} from '../../models/classification';
|
||||
import {ClassificationDefinition} from '../../models/classification-definition';
|
||||
import {ClassificationsService} from '../services/classifications/classifications.service';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-tree',
|
||||
|
@ -19,19 +28,19 @@ import { Subscription } from 'rxjs';
|
|||
})
|
||||
export class TaskanaTreeComponent implements OnInit, AfterViewChecked, OnDestroy {
|
||||
|
||||
|
||||
@ViewChild('tree')
|
||||
private tree: TreeComponent;
|
||||
|
||||
@Input() treeNodes: TreeNodeModel;
|
||||
@Input() treeNodes: Array<TreeNodeModel>;
|
||||
@Output() treeNodesChange = new EventEmitter<Array<TreeNodeModel>>();
|
||||
@Input() selectNodeId: string;
|
||||
@Output() selectNodeIdChanged = new EventEmitter<string>();
|
||||
@Input() filterText: string;
|
||||
@Input() filterIcon = '';
|
||||
@Output() refreshClassification = new EventEmitter<string>();
|
||||
@Output() switchTaskanaSpinnerEmit = new EventEmitter<boolean>();
|
||||
|
||||
|
||||
private filterTextOld: string
|
||||
private filterTextOld: string;
|
||||
private filterIconOld = '';
|
||||
private removedNodeIdSubscription: Subscription;
|
||||
|
||||
|
@ -47,8 +56,10 @@ export class TaskanaTreeComponent implements OnInit, AfterViewChecked, OnDestroy
|
|||
},
|
||||
animateExpand: true,
|
||||
animateSpeed: 20,
|
||||
levelPadding: 20
|
||||
}
|
||||
levelPadding: 20,
|
||||
allowDrag: true,
|
||||
allowDrop: true
|
||||
};
|
||||
|
||||
@HostListener('document:click', ['$event'])
|
||||
onDocumentClick(event) {
|
||||
|
@ -60,7 +71,9 @@ export class TaskanaTreeComponent implements OnInit, AfterViewChecked, OnDestroy
|
|||
constructor(
|
||||
private treeService: TreeService,
|
||||
private categoryService: ClassificationCategoriesService,
|
||||
private elementRef: ElementRef) { }
|
||||
private elementRef: ElementRef,
|
||||
private classificationsService: ClassificationsService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.removedNodeIdSubscription = this.treeService.getRemovedNodeId().subscribe(value => {
|
||||
|
@ -71,7 +84,6 @@ export class TaskanaTreeComponent implements OnInit, AfterViewChecked, OnDestroy
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
ngAfterViewChecked(): void {
|
||||
if (this.selectNodeId && !this.tree.treeModel.getActiveNode()) {
|
||||
this.selectNode(this.selectNodeId);
|
||||
|
@ -96,6 +108,25 @@ export class TaskanaTreeComponent implements OnInit, AfterViewChecked, OnDestroy
|
|||
this.selectNodeIdChanged.emit(undefined);
|
||||
}
|
||||
|
||||
async onMoveNode($event) {
|
||||
this.switchTaskanaSpinner(true);
|
||||
const classification = await this.getClassification($event.node.classificationId);
|
||||
classification.parentId = $event.to.parent.classificationId;
|
||||
classification.parentKey = $event.to.parent.key;
|
||||
this.collapseParentNodeIfItIsTheLastChild($event.node);
|
||||
await this.updateClassification(classification);
|
||||
}
|
||||
|
||||
async onDrop($event) {
|
||||
if ($event.event.target.tagName === 'TREE-VIEWPORT') {
|
||||
this.switchTaskanaSpinner(true);
|
||||
const classification = await this.getClassification($event.element.data.classificationId);
|
||||
this.collapseParentNodeIfItIsTheLastChild($event.element.data);
|
||||
classification.parentId = '';
|
||||
classification.parentKey = '';
|
||||
await this.updateClassification(classification);
|
||||
}
|
||||
}
|
||||
|
||||
getCategoryIcon(category: string): Pair {
|
||||
return this.categoryService.getCategoryIcon(category);
|
||||
|
@ -103,9 +134,9 @@ export class TaskanaTreeComponent implements OnInit, AfterViewChecked, OnDestroy
|
|||
|
||||
private selectNode(nodeId: string) {
|
||||
if (nodeId) {
|
||||
const selectedNode = this.getNode(nodeId)
|
||||
const selectedNode = this.getNode(nodeId);
|
||||
if (selectedNode) {
|
||||
selectedNode.setIsActive(true)
|
||||
selectedNode.setIsActive(true);
|
||||
this.expandParent(selectedNode);
|
||||
}
|
||||
}
|
||||
|
@ -141,6 +172,7 @@ export class TaskanaTreeComponent implements OnInit, AfterViewChecked, OnDestroy
|
|||
return (node.data.name.toUpperCase().includes(text.toUpperCase())
|
||||
|| node.data.key.toUpperCase().includes(text.toUpperCase()))
|
||||
}
|
||||
|
||||
private checkIcon(node: any, iconText: string): boolean {
|
||||
return (node.data.category.toUpperCase() === iconText.toUpperCase()
|
||||
|| iconText === '')
|
||||
|
@ -160,9 +192,31 @@ export class TaskanaTreeComponent implements OnInit, AfterViewChecked, OnDestroy
|
|||
event.target.localName === 'taskana-tree')
|
||||
}
|
||||
|
||||
private getClassification(classificationId: string): Promise<ClassificationDefinition> {
|
||||
return this.classificationsService.getClassification(classificationId);
|
||||
}
|
||||
|
||||
private async updateClassification(classification: Classification) {
|
||||
await this.classificationsService.putClassification(classification._links.self.href, classification);
|
||||
this.refreshClassification.emit(classification.key);
|
||||
this.switchTaskanaSpinner(false);
|
||||
}
|
||||
|
||||
private collapseParentNodeIfItIsTheLastChild(node: any) {
|
||||
if (node.parentId.length > 0 && this.getNode(node.parentId) && this.getNode(node.parentId).children.length < 2) {
|
||||
this.tree.treeModel.update();
|
||||
this.getNode(node.parentId).collapse();
|
||||
}
|
||||
}
|
||||
|
||||
switchTaskanaSpinner(active: boolean) {
|
||||
this.switchTaskanaSpinnerEmit.emit(active);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this.removedNodeIdSubscription) { this.removedNodeIdSubscription.unsubscribe() }
|
||||
if (this.removedNodeIdSubscription) {
|
||||
this.removedNodeIdSubscription.unsubscribe()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ export class TaskComponent implements OnInit, OnDestroy {
|
|||
this.requestInProgress = true;
|
||||
this.task = await this.taskService.getTask(id).toPromise();
|
||||
const classification = await this.classificationService.getClassification
|
||||
(this.task.classificationSummaryResource.classificationId).toPromise();
|
||||
(this.task.classificationSummaryResource.classificationId);
|
||||
this.address = this.extractUrl(classification.applicationEntryPoint) || `${this.address}/?q=${this.task.name}`;
|
||||
this.link = this.sanitizer.bypassSecurityTrustResourceUrl(this.address);
|
||||
this.getWorkbaskets();
|
||||
|
|
Loading…
Reference in New Issue