TSK-1279: Enable the creation of subclassifications

This commit is contained in:
Sofie Hofmann 2020-06-22 12:13:42 +02:00
parent e352016584
commit 2760b9ee59
5 changed files with 58 additions and 52 deletions

View File

@ -23,7 +23,7 @@ taskana.schemaName=TASKANA
########spring.jpa.generate-ddl=true
########spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
####### property that control rest api security deploy use true for no security.
devMode=true
devMode=false
####### property that control if the database is cleaned and sample data is generated
generateSampleData=true

View File

@ -2,12 +2,10 @@ import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { Select, Store } from '@ngxs/store';
import { Observable, Subject, zip } from 'rxjs';
import { ClassificationDefinition,
customFieldCount } from 'app/shared/models/classification-definition';
import { ClassificationDefinition, customFieldCount } from 'app/shared/models/classification-definition';
import { ACTION } from 'app/shared/models/action';
import { highlight } from 'theme/animations/validation.animation';
import { TaskanaDate } from 'app/shared/util/taskana.date';
import { ClassificationsService } from 'app/shared/services/classifications/classifications.service';
import { RequestInProgressService } from 'app/shared/services/request-in-progress/request-in-progress.service';
@ -80,7 +78,9 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
this.action$.pipe(takeUntil(this.destroy$)).subscribe(data => {
this.action = data;
if (this.action === ACTION.CREATE) {
this.initClassificationOnCreation();
this.selectedClassification$.pipe(take(1)).subscribe(initialClassification => {
this.classification = { ...initialClassification };
});
this.badgeMessage = 'Creating new classification';
} else {
this.badgeMessage = '';
@ -207,23 +207,6 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
this.classification = { ...classificationSelected };
}
private addDateToClassification(classification: ClassificationDefinition) {
const date = TaskanaDate.getDate();
classification.created = date;
classification.modified = date;
}
private initClassificationOnCreation() {
zip(this.categories$, this.selectedClassificationType$).pipe(take(1)).subscribe(([categories, selectedType]: [string[], string]) => {
const tempClassification: ClassificationDefinition = new ClassificationDefinition();
[tempClassification.category] = categories;
tempClassification.domain = this.domainService.getSelectedDomainValue();
tempClassification.type = selectedType;
this.addDateToClassification(tempClassification);
this.classification = tempClassification;
});
}
private removeClassificationConfirmation() {
if (!this.classification || !this.classification.classificationId) {
this.notificationsService.triggerError(NOTIFICATION_TYPES.SELECT_ERR);
@ -236,6 +219,7 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
new Map<string, string>([['classificationKey', this.classification.key]]));
this.afterRequest();
});
this.location.go(this.location.path().replace(/(classifications).*/g, 'classifications'));
}
getClassificationCustom(customNumber: number): string {

View File

@ -1,7 +1,6 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import { ActivatedRoute } from '@angular/router';
import { Actions, ofActionCompleted, ofActionDispatched, Select, Store } from '@ngxs/store';
import { ImportExportService } from 'app/administration/services/import-export.service';
@ -14,8 +13,6 @@ import { ClassificationSelectors } from 'app/shared/store/classification-store/c
import { Location } from '@angular/common';
import { ClassificationCategoryImages } from '../../../shared/models/customisation';
import { NotificationService } from '../../../shared/services/notifications/notification.service';
import { GetClassifications, SetActiveAction } from '../../../shared/store/classification-store/classification.actions';
import { ACTION } from '../../../shared/models/action';
import { TreeNodeModel } from '../../../shared/models/tree-node';
@ -46,9 +43,7 @@ export class ClassificationListComponent implements OnInit, OnDestroy {
constructor(
private classificationService: ClassificationsService,
private location: Location,
private route: ActivatedRoute,
private importExportService: ImportExportService,
private notificationsService: NotificationService,
private store: Store,
private ngxsActions$: Actions
) {

View File

@ -1,10 +1,4 @@
import { AfterViewChecked,
Component,
ElementRef,
EventEmitter,
HostListener,
Input,
OnDestroy,
import { AfterViewChecked, Component, ElementRef, EventEmitter, HostListener, Input, OnDestroy,
OnInit,
Output,
ViewChild } from '@angular/core';
@ -12,8 +6,8 @@ import { TreeNodeModel } from 'app/shared/models/tree-node';
import { ITreeOptions, KEYS, TREE_ACTIONS, TreeComponent } from 'angular-tree-component';
import { Pair } from 'app/shared/models/pair';
import { Observable, Subject } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import { Observable, Subject, combineLatest } from 'rxjs';
import { map, takeUntil, filter, tap } from 'rxjs/operators';
import { Select, Store } from '@ngxs/store';
import { EngineConfigurationSelectors } from 'app/shared/store/engine-configuration-store/engine-configuration.selectors';
@ -45,6 +39,7 @@ export class TaskanaTreeComponent implements OnInit, AfterViewChecked, OnDestroy
@Select(ClassificationSelectors.selectedClassificationId) selectedClassificationId$: Observable<string>;
@Select(ClassificationSelectors.activeAction) activeAction$: Observable<ACTION>;
@Select(ClassificationSelectors.classifications) classifications$: Observable<TreeNodeModel[]>;
@Select(ClassificationSelectors.selectedClassificationType) classificationTypeSelected$: Observable<string>;
options: ITreeOptions = {
displayField: 'name',
@ -92,19 +87,24 @@ export class TaskanaTreeComponent implements OnInit, AfterViewChecked, OnDestroy
this.action = action;
});
this.selectedClassificationId$.pipe(takeUntil(this.destroy$)).subscribe(selectedClassificationId => {
this.selectNodeId = typeof selectedClassificationId !== 'undefined' ? selectedClassificationId : undefined;
if (typeof this.tree.treeModel.getActiveNode() !== 'undefined') {
if (this.tree.treeModel.getActiveNode().data.classificationId !== this.selectNodeId) {
this.selectNode(this.selectNodeId);
}
}
});
const classificationCopy$: Observable<TreeNodeModel[]> = this.classifications$.pipe(
filter(classifications => typeof (classifications) !== 'undefined'),
map(classifications => classifications.map(this.classificationsDeepCopy.bind(this)))
);
this.classifications$.pipe(takeUntil(this.destroy$)).subscribe(classifications => {
if (typeof (classifications) !== 'undefined') {
this.classifications = classifications.map(this.classificationsDeepCopy.bind(this));
}
combineLatest(this.selectedClassificationId$, classificationCopy$).pipe(takeUntil(this.destroy$))
.subscribe(([selectedClassificationId, classifications]) => {
this.classifications = classifications;
this.selectNodeId = typeof selectedClassificationId !== 'undefined' ? selectedClassificationId : undefined;
if (typeof this.tree.treeModel.getActiveNode() !== 'undefined') {
if (this.tree.treeModel.getActiveNode().data.classificationId !== this.selectNodeId) {
this.selectNode(this.selectNodeId);
}
}
});
this.classificationTypeSelected$.pipe(takeUntil(this.destroy$)).subscribe(() => {
if (this.tree.treeModel.getActiveNode()) { this.deselectActiveNode(); }
});
}
@ -120,6 +120,12 @@ export class TaskanaTreeComponent implements OnInit, AfterViewChecked, OnDestroy
this.selectNode(this.selectNodeId);
}
if (typeof this.selectNodeId !== 'undefined') {
if (typeof this.getNode(this.selectNodeId) !== 'undefined') {
this.getNode(this.selectNodeId).ensureVisible();
}
}
if (this.filterTextOld !== this.filterText
|| this.filterIconOld !== this.filterIcon) {
this.filterIconOld = this.filterIcon;

View File

@ -1,6 +1,7 @@
import { Action, NgxsAfterBootstrap, State, StateContext } from '@ngxs/store';
import { Observable, of } from 'rxjs';
import { take, tap } from 'rxjs/operators';
import { TaskanaDate } from 'app/shared/util/taskana.date';
import { CategoriesResponse,
ClassificationCategoriesService } from '../../services/classification-categories/classification-categories.service';
import { CreateClassification,
@ -16,6 +17,7 @@ import { CreateClassification,
import { ClassificationsService } from '../../services/classifications/classifications.service';
import { ClassificationDefinition } from '../../models/classification-definition';
import { ACTION } from '../../models/action';
import { DomainService } from '../../services/domain/domain.service';
class InitializeStore {
static readonly type = '[ClassificationState] Initializing state';
@ -23,15 +25,21 @@ class InitializeStore {
@State<ClassificationStateModel>({ name: 'classification' })
export class ClassificationState implements NgxsAfterBootstrap {
constructor(private categoryService: ClassificationCategoriesService,
private classificationsService: ClassificationsService) {
constructor(
private categoryService: ClassificationCategoriesService,
private classificationsService: ClassificationsService,
private domainService: DomainService
) {
}
@Action(SetSelectedClassificationType)
setSelectedClassificationType(ctx: StateContext<ClassificationStateModel>, action: SetSelectedClassificationType): Observable<null> {
const state: ClassificationStateModel = ctx.getState();
if (state.classificationTypes[action.selectedType]) {
ctx.patchState({ selectedClassificationType: action.selectedType });
ctx.patchState({
selectedClassificationType: action.selectedType,
selectedClassification: undefined
});
}
return of(null);
}
@ -141,7 +149,20 @@ export class ClassificationState implements NgxsAfterBootstrap {
@Action(SetActiveAction)
setActiveAction(ctx: StateContext<ClassificationStateModel>, action: SetActiveAction): Observable<null> {
if (action.action === ACTION.CREATE) {
ctx.patchState({ selectedClassification: new ClassificationDefinition(), action: action.action });
// Initialization of a new classification
const initialClassification: ClassificationDefinition = new ClassificationDefinition();
const state: ClassificationStateModel = ctx.getState();
initialClassification.type = state.selectedClassificationType;
[initialClassification.category] = state.classificationTypes[initialClassification.type];
const date = TaskanaDate.getDate();
initialClassification.created = date;
initialClassification.modified = date;
initialClassification.domain = this.domainService.getSelectedDomainValue();
if (state.selectedClassification) {
initialClassification.parentId = state.selectedClassification.classificationId;
initialClassification.parentKey = state.selectedClassification.key;
}
ctx.patchState({ selectedClassification: initialClassification, action: action.action });
} else {
ctx.patchState({ action: action.action });
}