TSK-1291: Removing action property in store to make the code cleaner
This commit is contained in:
parent
6e3c9b4560
commit
83a79eab18
|
|
@ -20,7 +20,7 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<h4 class="panel-header">{{classification.name}} [{{classification.type}}]
|
<h4 class="panel-header">{{classification.name}} [{{classification.type}}]
|
||||||
<span *ngIf="action" class="badge warning"> {{badgeMessage}}</span>
|
<span *ngIf="isCreatingNewClassification" class="badge warning"> {{badgeMessage$ | async}}</span>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -33,9 +33,9 @@
|
||||||
<!-- KEY -->
|
<!-- KEY -->
|
||||||
<div class="form-group required">
|
<div class="form-group required">
|
||||||
<label for="classification-key" class="control-label">Key</label>
|
<label for="classification-key" class="control-label">Key</label>
|
||||||
<input type="text" required #key="ngModel" [disabled]="!action" class="form-control"
|
<input type="text" required #key="ngModel" [disabled]="!isCreatingNewClassification" class="form-control"
|
||||||
id="classification-key" placeholder="Key" [(ngModel)]="classification.key" name="classification.key">
|
id="classification-key" placeholder="Key" [(ngModel)]="classification.key" name="classification.key">
|
||||||
<taskana-shared-field-error-display *ngIf="action" [displayError]="!isFieldValid('classification.key')"
|
<taskana-shared-field-error-display *ngIf="isCreatingNewClassification" [displayError]="!isFieldValid('classification.key')"
|
||||||
[validationTrigger]="this.toogleValidationMap.get('classification.key')" errorMessage="* Key is required">
|
[validationTrigger]="this.toogleValidationMap.get('classification.key')" errorMessage="* Key is required">
|
||||||
</taskana-shared-field-error-display>
|
</taskana-shared-field-error-display>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ import { EngineConfigurationSelectors } from 'app/shared/store/engine-configurat
|
||||||
import { ClassificationSelectors } from 'app/shared/store/classification-store/classification.selectors';
|
import { ClassificationSelectors } from 'app/shared/store/classification-store/classification.selectors';
|
||||||
import { ClassificationDetailsComponent } from './classification-details.component';
|
import { ClassificationDetailsComponent } from './classification-details.component';
|
||||||
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
||||||
import { ACTION } from '../../../shared/models/action';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'taskana-dummy-detail',
|
selector: 'taskana-dummy-detail',
|
||||||
|
|
@ -100,20 +99,8 @@ describe('ClassificationDetailsComponent', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should copy the classification without its key', async done => {
|
it('should enable editing of key on create and on copy', async done => {
|
||||||
const startClassification = { ...component.classification };
|
component.isCreatingNewClassification = true;
|
||||||
const copyButton = fixture.debugElement.nativeElement.querySelector('#copyButton');
|
|
||||||
copyButton.click();
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(component.classification.name).toEqual(startClassification.name);
|
|
||||||
expect(component.classification.classificationId).toEqual(startClassification.classificationId);
|
|
||||||
expect(component.classification.key).toBeNull();
|
|
||||||
expect(fixture.debugElement.nativeElement.querySelector('#classification-key').disabled).toEqual(false);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should enable editing of key on create', async done => {
|
|
||||||
component.action = ACTION.CREATE;
|
|
||||||
await fixture.detectChanges();
|
await fixture.detectChanges();
|
||||||
expect(fixture.debugElement.nativeElement.querySelector('#classification-key').disabled).toEqual(false);
|
expect(fixture.debugElement.nativeElement.querySelector('#classification-key').disabled).toEqual(false);
|
||||||
done();
|
done();
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,9 @@
|
||||||
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||||
import { Select, Store } from '@ngxs/store';
|
import { Select, Store } from '@ngxs/store';
|
||||||
import { combineLatest, Observable, Subject } from 'rxjs';
|
import { Observable, Subject } from 'rxjs';
|
||||||
|
|
||||||
import { ACTION } from 'app/shared/models/action';
|
|
||||||
|
|
||||||
import { highlight } from 'theme/animations/validation.animation';
|
import { highlight } from 'theme/animations/validation.animation';
|
||||||
|
|
||||||
import { ClassificationsService } from 'app/shared/services/classifications/classifications.service';
|
|
||||||
import { RequestInProgressService } from 'app/shared/services/request-in-progress/request-in-progress.service';
|
import { RequestInProgressService } from 'app/shared/services/request-in-progress/request-in-progress.service';
|
||||||
|
|
||||||
import { DomainService } from 'app/shared/services/domain/domain.service';
|
import { DomainService } from 'app/shared/services/domain/domain.service';
|
||||||
|
|
@ -27,12 +24,12 @@ import { Classification } from '../../../shared/models/classification';
|
||||||
import { customFieldCount } from '../../../shared/models/classification-summary';
|
import { customFieldCount } from '../../../shared/models/classification-summary';
|
||||||
import { CategoriesResponse } from '../../../shared/services/classification-categories/classification-categories.service';
|
import { CategoriesResponse } from '../../../shared/services/classification-categories/classification-categories.service';
|
||||||
|
|
||||||
import { CreateClassification,
|
import { SaveCreatedClassification,
|
||||||
RemoveSelectedClassification,
|
RemoveSelectedClassification,
|
||||||
RestoreSelectedClassification,
|
RestoreSelectedClassification,
|
||||||
SaveClassification,
|
SaveModifiedClassification,
|
||||||
SelectClassification,
|
SelectClassification,
|
||||||
SetActiveAction } from '../../../shared/store/classification-store/classification.actions';
|
CopyClassification } from '../../../shared/store/classification-store/classification.actions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'taskana-administration-classification-details',
|
selector: 'taskana-administration-classification-details',
|
||||||
|
|
@ -42,25 +39,23 @@ import { CreateClassification,
|
||||||
})
|
})
|
||||||
export class ClassificationDetailsComponent implements OnInit, OnDestroy {
|
export class ClassificationDetailsComponent implements OnInit, OnDestroy {
|
||||||
classification: Classification;
|
classification: Classification;
|
||||||
badgeMessage = '';
|
|
||||||
requestInProgress = false;
|
requestInProgress = false;
|
||||||
@Select(ClassificationSelectors.selectCategories) categories$: Observable<string[]>;
|
@Select(ClassificationSelectors.selectCategories) categories$: Observable<string[]>;
|
||||||
@Select(EngineConfigurationSelectors.selectCategoryIcons) categoryIcons$: Observable<ClassificationCategoryImages>;
|
@Select(EngineConfigurationSelectors.selectCategoryIcons) categoryIcons$: Observable<ClassificationCategoryImages>;
|
||||||
@Select(ClassificationSelectors.selectedClassificationType) selectedClassificationType$: Observable<string>;
|
@Select(ClassificationSelectors.selectedClassificationType) selectedClassificationType$: Observable<string>;
|
||||||
@Select(ClassificationSelectors.selectClassificationTypesObject) classificationTypes$: Observable<CategoriesResponse>;
|
@Select(ClassificationSelectors.selectClassificationTypesObject) classificationTypes$: Observable<CategoriesResponse>;
|
||||||
@Select(ClassificationSelectors.selectedClassification) selectedClassification$: Observable<Classification>;
|
@Select(ClassificationSelectors.selectedClassification) selectedClassification$: Observable<Classification>;
|
||||||
@Select(ClassificationSelectors.activeAction) action$: Observable<ACTION>;
|
@Select(ClassificationSelectors.getBadgeMessage) badgeMessage$: Observable<string>;
|
||||||
|
|
||||||
spinnerIsRunning = false;
|
spinnerIsRunning = false;
|
||||||
customFields$: Observable<CustomField[]>;
|
customFields$: Observable<CustomField[]>;
|
||||||
|
isCreatingNewClassification: boolean = false;
|
||||||
|
|
||||||
@ViewChild('ClassificationForm', { static: false }) classificationForm: NgForm;
|
@ViewChild('ClassificationForm', { static: false }) classificationForm: NgForm;
|
||||||
toogleValidationMap = new Map<string, boolean>();
|
toogleValidationMap = new Map<string, boolean>();
|
||||||
action: ACTION;
|
|
||||||
destroy$ = new Subject<void>();
|
destroy$ = new Subject<void>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private classificationsService: ClassificationsService,
|
|
||||||
private location: Location,
|
private location: Location,
|
||||||
private requestInProgressService: RequestInProgressService,
|
private requestInProgressService: RequestInProgressService,
|
||||||
private domainService: DomainService,
|
private domainService: DomainService,
|
||||||
|
|
@ -77,22 +72,10 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
|
||||||
getCustomFields(customFieldCount)
|
getCustomFields(customFieldCount)
|
||||||
);
|
);
|
||||||
|
|
||||||
combineLatest([this.selectedClassification$, this.action$]).pipe(takeUntil(this.destroy$))
|
this.selectedClassification$.pipe(takeUntil(this.destroy$))
|
||||||
.subscribe(([classification, action]) => {
|
.subscribe(classification => {
|
||||||
this.action = action;
|
this.classification = { ...classification };
|
||||||
if (this.action === ACTION.CREATE) {
|
this.isCreatingNewClassification = typeof this.classification.classificationId === 'undefined';
|
||||||
this.selectedClassification$.pipe(take(1)).subscribe(initialClassification => {
|
|
||||||
this.classification = { ...initialClassification };
|
|
||||||
});
|
|
||||||
this.badgeMessage = 'Creating new classification';
|
|
||||||
} else if (this.action === ACTION.COPY) {
|
|
||||||
this.badgeMessage = `Copying Classification: ${this.classification.name}`;
|
|
||||||
this.classification = { ...classification };
|
|
||||||
this.classification.key = null;
|
|
||||||
} else {
|
|
||||||
this.badgeMessage = '';
|
|
||||||
this.classification = { ...classification };
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.importExportService.getImportingFinished().pipe(takeUntil(this.destroy$)).subscribe(() => {
|
this.importExportService.getImportingFinished().pipe(takeUntil(this.destroy$)).subscribe(() => {
|
||||||
|
|
@ -120,28 +103,18 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
onRestore() {
|
onRestore() {
|
||||||
this.formsValidatorService.formSubmitAttempt = false;
|
this.formsValidatorService.formSubmitAttempt = false;
|
||||||
if (this.action === ACTION.CREATE) {
|
this.store.dispatch(
|
||||||
this.categories$.pipe(take(1)).subscribe(categories => {
|
new RestoreSelectedClassification(this.classification.classificationId)
|
||||||
const category = categories[0];
|
).pipe(take(1)).subscribe(() => {
|
||||||
const { type, created, modified, domain, parentId, parentKey } = this.classification;
|
this.notificationsService.showToast(NOTIFICATION_TYPES.INFO_ALERT);
|
||||||
this.classification = { type, created, category, modified, domain, parentId, parentKey };
|
});
|
||||||
this.notificationsService.showToast(NOTIFICATION_TYPES.INFO_ALERT);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.store.dispatch(
|
|
||||||
new RestoreSelectedClassification(this.classification.classificationId)
|
|
||||||
).pipe(take(1)).subscribe(() => {
|
|
||||||
this.notificationsService.showToast(NOTIFICATION_TYPES.INFO_ALERT);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onCopy() {
|
onCopy() {
|
||||||
if (this.action !== ACTION.CREATE) {
|
if (this.isCreatingNewClassification) {
|
||||||
this.store.dispatch(new SetActiveAction(ACTION.COPY));
|
|
||||||
this.classification.key = null;
|
|
||||||
} else {
|
|
||||||
this.notificationsService.showToast(NOTIFICATION_TYPES.WARNING_CANT_COPY);
|
this.notificationsService.showToast(NOTIFICATION_TYPES.WARNING_CANT_COPY);
|
||||||
|
} else {
|
||||||
|
this.store.dispatch(new CopyClassification());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,10 +157,9 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
private async onSave() {
|
private async onSave() {
|
||||||
this.requestInProgressService.setRequestInProgress(true);
|
this.requestInProgressService.setRequestInProgress(true);
|
||||||
if (this.action) {
|
if (typeof this.classification.classificationId === 'undefined') {
|
||||||
this.classification.classificationId = null; // in case the id has been set, but a new classification should be created
|
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
new CreateClassification(this.classification)
|
new SaveCreatedClassification(this.classification)
|
||||||
).pipe(take(1)).subscribe(store => {
|
).pipe(take(1)).subscribe(store => {
|
||||||
this.notificationsService.showToast(
|
this.notificationsService.showToast(
|
||||||
NOTIFICATION_TYPES.SUCCESS_ALERT_2,
|
NOTIFICATION_TYPES.SUCCESS_ALERT_2,
|
||||||
|
|
@ -204,7 +176,7 @@ export class ClassificationDetailsComponent implements OnInit, OnDestroy {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
this.store.dispatch(new SaveClassification(this.classification))
|
this.store.dispatch(new SaveModifiedClassification(this.classification))
|
||||||
.pipe(take(1)).subscribe(() => {
|
.pipe(take(1)).subscribe(() => {
|
||||||
this.afterRequest();
|
this.afterRequest();
|
||||||
this.notificationsService.showToast(
|
this.notificationsService.showToast(
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,19 @@
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { Observable, Subject } from 'rxjs';
|
import { Observable, Subject } from 'rxjs';
|
||||||
import { map, take, takeUntil } from 'rxjs/operators';
|
import { map, takeUntil } from 'rxjs/operators';
|
||||||
import { Actions, ofActionCompleted, ofActionDispatched, Select, Store } from '@ngxs/store';
|
import { Actions, ofActionCompleted, ofActionDispatched, Select, Store } from '@ngxs/store';
|
||||||
|
|
||||||
import { ImportExportService } from 'app/administration/services/import-export.service';
|
import { ImportExportService } from 'app/administration/services/import-export.service';
|
||||||
|
|
||||||
import { TaskanaType } from 'app/shared/models/taskana-type';
|
import { TaskanaType } from 'app/shared/models/taskana-type';
|
||||||
import { Pair } from 'app/shared/models/pair';
|
import { Pair } from 'app/shared/models/pair';
|
||||||
import { ClassificationsService } from 'app/shared/services/classifications/classifications.service';
|
|
||||||
import { EngineConfigurationSelectors } from 'app/shared/store/engine-configuration-store/engine-configuration.selectors';
|
import { EngineConfigurationSelectors } from 'app/shared/store/engine-configuration-store/engine-configuration.selectors';
|
||||||
import { ClassificationSelectors } from 'app/shared/store/classification-store/classification.selectors';
|
import { ClassificationSelectors } from 'app/shared/store/classification-store/classification.selectors';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { ClassificationCategoryImages } from '../../../shared/models/customisation';
|
import { ClassificationCategoryImages } from '../../../shared/models/customisation';
|
||||||
|
|
||||||
import { GetClassifications,
|
import { GetClassifications,
|
||||||
SetActiveAction } from '../../../shared/store/classification-store/classification.actions';
|
CreateClassification } from '../../../shared/store/classification-store/classification.actions';
|
||||||
import { ACTION } from '../../../shared/models/action';
|
|
||||||
import { DomainService } from '../../../shared/services/domain/domain.service';
|
import { DomainService } from '../../../shared/services/domain/domain.service';
|
||||||
import { ClassificationSummary } from '../../../shared/models/classification-summary';
|
import { ClassificationSummary } from '../../../shared/models/classification-summary';
|
||||||
|
|
||||||
|
|
@ -34,15 +32,12 @@ export class ClassificationListComponent implements OnInit, OnDestroy {
|
||||||
@Select(ClassificationSelectors.selectedClassificationType) classificationTypeSelected$: Observable<string>;
|
@Select(ClassificationSelectors.selectedClassificationType) classificationTypeSelected$: Observable<string>;
|
||||||
@Select(ClassificationSelectors.selectCategories) categories$: Observable<string[]>;
|
@Select(ClassificationSelectors.selectCategories) categories$: Observable<string[]>;
|
||||||
@Select(ClassificationSelectors.classifications) classifications$: Observable<ClassificationSummary[]>;
|
@Select(ClassificationSelectors.classifications) classifications$: Observable<ClassificationSummary[]>;
|
||||||
@Select(ClassificationSelectors.activeAction) activeAction$: Observable<ACTION>;
|
|
||||||
@Select(EngineConfigurationSelectors.selectCategoryIcons) categoryIcons$: Observable<ClassificationCategoryImages>;
|
@Select(EngineConfigurationSelectors.selectCategoryIcons) categoryIcons$: Observable<ClassificationCategoryImages>;
|
||||||
|
|
||||||
action: ACTION;
|
|
||||||
destroy$ = new Subject<void>();
|
destroy$ = new Subject<void>();
|
||||||
classifications: ClassificationSummary[];
|
classifications: ClassificationSummary[];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private classificationService: ClassificationsService,
|
|
||||||
private location: Location,
|
private location: Location,
|
||||||
private importExportService: ImportExportService,
|
private importExportService: ImportExportService,
|
||||||
private store: Store,
|
private store: Store,
|
||||||
|
|
@ -79,12 +74,6 @@ export class ClassificationListComponent implements OnInit, OnDestroy {
|
||||||
this.store.dispatch(new GetClassifications());
|
this.store.dispatch(new GetClassifications());
|
||||||
});
|
});
|
||||||
|
|
||||||
this.activeAction$
|
|
||||||
.pipe(takeUntil(this.destroy$))
|
|
||||||
.subscribe(action => {
|
|
||||||
this.action = action;
|
|
||||||
});
|
|
||||||
|
|
||||||
// needed, so that the list updates, when domain gets changed (could be placed anywhere and should be removed, when domain is in store)
|
// needed, so that the list updates, when domain gets changed (could be placed anywhere and should be removed, when domain is in store)
|
||||||
this.domainService.getSelectedDomain().pipe(takeUntil(this.destroy$)).subscribe(domain => {
|
this.domainService.getSelectedDomain().pipe(takeUntil(this.destroy$)).subscribe(domain => {
|
||||||
this.store.dispatch(GetClassifications);
|
this.store.dispatch(GetClassifications);
|
||||||
|
|
@ -92,9 +81,7 @@ export class ClassificationListComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
addClassification() {
|
addClassification() {
|
||||||
if (this.action !== ACTION.CREATE) {
|
this.store.dispatch(new CreateClassification());
|
||||||
this.store.dispatch(new SetActiveAction(ACTION.CREATE));
|
|
||||||
}
|
|
||||||
this.location.go(this.location.path().replace(/(classifications).*/g, 'classifications/new-classification'));
|
this.location.go(this.location.path().replace(/(classifications).*/g, 'classifications/new-classification'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,7 @@ import { Observable, Subject } from 'rxjs';
|
||||||
import { Select, Store } from '@ngxs/store';
|
import { Select, Store } from '@ngxs/store';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
import { ClassificationSelectors } from '../../../shared/store/classification-store/classification.selectors';
|
import { ClassificationSelectors } from '../../../shared/store/classification-store/classification.selectors';
|
||||||
import { ACTION } from '../../../shared/models/action';
|
import { GetClassifications, SelectClassification, CreateClassification } from '../../../shared/store/classification-store/classification.actions';
|
||||||
import { GetClassifications,
|
|
||||||
SelectClassification,
|
|
||||||
SetActiveAction } from '../../../shared/store/classification-store/classification.actions';
|
|
||||||
import { Classification } from '../../../shared/models/classification';
|
import { Classification } from '../../../shared/models/classification';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|
@ -40,7 +37,7 @@ export class ClassificationOverviewComponent implements OnInit, OnDestroy {
|
||||||
.subscribe(() => this.store.dispatch(new GetClassifications()));
|
.subscribe(() => this.store.dispatch(new GetClassifications()));
|
||||||
}
|
}
|
||||||
if (this.routerParams.id && this.routerParams.id.indexOf('new-classification') !== -1) {
|
if (this.routerParams.id && this.routerParams.id.indexOf('new-classification') !== -1) {
|
||||||
this.store.dispatch(new SetActiveAction(ACTION.CREATE));
|
this.store.dispatch(new CreateClassification());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import { configureTests } from 'app/app.test.configuration';
|
||||||
import { NgxsModule, Store } from '@ngxs/store';
|
import { NgxsModule, Store } from '@ngxs/store';
|
||||||
import { ClassificationSelectors } from 'app/shared/store/classification-store/classification.selectors';
|
import { ClassificationSelectors } from 'app/shared/store/classification-store/classification.selectors';
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { ACTION } from 'app/shared/models/action';
|
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { UpdateClassification } from 'app/shared/store/classification-store/classification.actions';
|
import { UpdateClassification } from 'app/shared/store/classification-store/classification.actions';
|
||||||
import { TaskanaTreeComponent } from './tree.component';
|
import { TaskanaTreeComponent } from './tree.component';
|
||||||
|
|
@ -51,8 +50,6 @@ describe('TaskanaTreeComponent', () => {
|
||||||
switch (selector) {
|
switch (selector) {
|
||||||
case ClassificationSelectors.selectedClassificationId:
|
case ClassificationSelectors.selectedClassificationId:
|
||||||
return of('id4');
|
return of('id4');
|
||||||
case ClassificationSelectors.activeAction:
|
|
||||||
return of(ACTION.CREATE);
|
|
||||||
case ClassificationSelectors.classifications:
|
case ClassificationSelectors.classifications:
|
||||||
return of([{ classificationId: 'id4' }]);
|
return of([{ classificationId: 'id4' }]);
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ import { ClassificationSelectors } from '../../../shared/store/classification-st
|
||||||
import { DeselectClassification,
|
import { DeselectClassification,
|
||||||
SelectClassification,
|
SelectClassification,
|
||||||
UpdateClassification } from '../../../shared/store/classification-store/classification.actions';
|
UpdateClassification } from '../../../shared/store/classification-store/classification.actions';
|
||||||
import { ACTION } from '../../../shared/models/action';
|
|
||||||
import { ClassificationTreeService } from '../../services/classification-tree.service';
|
import { ClassificationTreeService } from '../../services/classification-tree.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|
@ -44,7 +43,6 @@ export class TaskanaTreeComponent implements OnInit, AfterViewChecked, OnDestroy
|
||||||
@Output() switchTaskanaSpinnerEmit = new EventEmitter<boolean>();
|
@Output() switchTaskanaSpinnerEmit = new EventEmitter<boolean>();
|
||||||
@Select(EngineConfigurationSelectors.selectCategoryIcons) categoryIcons$: Observable<ClassificationCategoryImages>;
|
@Select(EngineConfigurationSelectors.selectCategoryIcons) categoryIcons$: Observable<ClassificationCategoryImages>;
|
||||||
@Select(ClassificationSelectors.selectedClassificationId) selectedClassificationId$: Observable<string>;
|
@Select(ClassificationSelectors.selectedClassificationId) selectedClassificationId$: Observable<string>;
|
||||||
@Select(ClassificationSelectors.activeAction) activeAction$: Observable<ACTION>;
|
|
||||||
@Select(ClassificationSelectors.classifications) classifications$: Observable<Classification[]>;
|
@Select(ClassificationSelectors.classifications) classifications$: Observable<Classification[]>;
|
||||||
@Select(ClassificationSelectors.selectedClassificationType) classificationTypeSelected$: Observable<string>;
|
@Select(ClassificationSelectors.selectedClassificationType) classificationTypeSelected$: Observable<string>;
|
||||||
|
|
||||||
|
|
@ -68,7 +66,6 @@ export class TaskanaTreeComponent implements OnInit, AfterViewChecked, OnDestroy
|
||||||
|
|
||||||
private filterTextOld: string;
|
private filterTextOld: string;
|
||||||
private filterIconOld = '';
|
private filterIconOld = '';
|
||||||
private action: ACTION;
|
|
||||||
private destroy$ = new Subject<void>();
|
private destroy$ = new Subject<void>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
@ -89,10 +86,6 @@ export class TaskanaTreeComponent implements OnInit, AfterViewChecked, OnDestroy
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.activeAction$.pipe(takeUntil(this.destroy$)).subscribe(action => {
|
|
||||||
this.action = action;
|
|
||||||
});
|
|
||||||
|
|
||||||
const computedTreeNodes$: Observable<TreeNodeModel[]> = this.classifications$.pipe(
|
const computedTreeNodes$: Observable<TreeNodeModel[]> = this.classifications$.pipe(
|
||||||
filter(classifications => typeof (classifications) !== 'undefined'),
|
filter(classifications => typeof (classifications) !== 'undefined'),
|
||||||
map(classifications => this.classificationTreeService.transformToTreeNode(classifications))
|
map(classifications => this.classificationTreeService.transformToTreeNode(classifications))
|
||||||
|
|
@ -146,7 +139,7 @@ export class TaskanaTreeComponent implements OnInit, AfterViewChecked, OnDestroy
|
||||||
}
|
}
|
||||||
|
|
||||||
onDeactivate(event: any) {
|
onDeactivate(event: any) {
|
||||||
if (!event.treeModel.activeNodes.length && this.action !== ACTION.CREATE) {
|
if (!event.treeModel.activeNodes.length) {
|
||||||
this.store.dispatch(new DeselectClassification());
|
this.store.dispatch(new DeselectClassification());
|
||||||
this.location.go(this.location.path().replace(/(classifications).*/g, 'classifications'));
|
this.location.go(this.location.path().replace(/(classifications).*/g, 'classifications'));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { RequestInProgressService } from 'app/shared/services/request-in-progress/request-in-progress.service';
|
import { RequestInProgressService } from 'app/shared/services/request-in-progress/request-in-progress.service';
|
||||||
import { environment } from 'environments/environment';
|
import { environment } from 'environments/environment';
|
||||||
import { map, tap } from 'rxjs/operators';
|
import { tap } from 'rxjs/operators';
|
||||||
import { NotificationService } from '../notifications/notification.service';
|
import { NotificationService } from '../notifications/notification.service';
|
||||||
import { NOTIFICATION_TYPES } from '../../models/notifications';
|
import { NOTIFICATION_TYPES } from '../../models/notifications';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { ACTION } from '../../models/action';
|
|
||||||
import { Classification } from '../../models/classification';
|
import { Classification } from '../../models/classification';
|
||||||
|
|
||||||
export class SetSelectedClassificationType {
|
export class SetSelectedClassificationType {
|
||||||
|
|
@ -19,12 +18,20 @@ export class DeselectClassification {
|
||||||
|
|
||||||
export class CreateClassification {
|
export class CreateClassification {
|
||||||
static readonly type = '[Classification] Create a new classification';
|
static readonly type = '[Classification] Create a new classification';
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CopyClassification {
|
||||||
|
static readonly type = '[Classification] Copy a classification';
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SaveCreatedClassification {
|
||||||
|
static readonly type = '[Classification] Save a classification that has been newly created or copied';
|
||||||
constructor(public classification: Classification) {
|
constructor(public classification: Classification) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SaveClassification {
|
export class SaveModifiedClassification {
|
||||||
static readonly type = '[Classification] Save a classification and select it';
|
static readonly type = '[Classification] Save an existing classification that has been modified';
|
||||||
constructor(public classification: Classification) {
|
constructor(public classification: Classification) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -35,12 +42,6 @@ export class RestoreSelectedClassification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SetActiveAction {
|
|
||||||
static readonly type = '[Classification] Set the currently active Action';
|
|
||||||
constructor(public action?: ACTION) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class RemoveSelectedClassification {
|
export class RemoveSelectedClassification {
|
||||||
static readonly type = '[Classification] Remove the selected Classification';
|
static readonly type = '[Classification] Remove the selected Classification';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { Selector } from '@ngxs/store';
|
import { Selector } from '@ngxs/store';
|
||||||
import { ClassificationStateModel, ClassificationState } from './classification.state';
|
import { ClassificationStateModel, ClassificationState } from './classification.state';
|
||||||
import { ACTION } from '../../models/action';
|
|
||||||
import { Classification } from '../../models/classification';
|
import { Classification } from '../../models/classification';
|
||||||
import { CategoriesResponse } from '../../services/classification-categories/classification-categories.service';
|
import { CategoriesResponse } from '../../services/classification-categories/classification-categories.service';
|
||||||
|
|
||||||
|
|
@ -35,13 +34,13 @@ export class ClassificationSelectors {
|
||||||
return state.selectedClassification;
|
return state.selectedClassification;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Selector([ClassificationState])
|
|
||||||
static activeAction(state: ClassificationStateModel): ACTION {
|
|
||||||
return state.action;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Selector([ClassificationState])
|
@Selector([ClassificationState])
|
||||||
static selectedClassificationId(state: ClassificationStateModel): string {
|
static selectedClassificationId(state: ClassificationStateModel): string {
|
||||||
return state.selectedClassification.classificationId;
|
return state.selectedClassification.classificationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Selector([ClassificationState])
|
||||||
|
static getBadgeMessage(state: ClassificationStateModel): string {
|
||||||
|
return state.badgeMessage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,16 @@ import { take, tap } from 'rxjs/operators';
|
||||||
import { TaskanaDate } from 'app/shared/util/taskana.date';
|
import { TaskanaDate } from 'app/shared/util/taskana.date';
|
||||||
import { CategoriesResponse,
|
import { CategoriesResponse,
|
||||||
ClassificationCategoriesService } from '../../services/classification-categories/classification-categories.service';
|
ClassificationCategoriesService } from '../../services/classification-categories/classification-categories.service';
|
||||||
import { CreateClassification,
|
import { SaveCreatedClassification,
|
||||||
DeselectClassification,
|
DeselectClassification,
|
||||||
GetClassifications,
|
GetClassifications, CopyClassification, CreateClassification,
|
||||||
RemoveSelectedClassification,
|
RemoveSelectedClassification,
|
||||||
RestoreSelectedClassification,
|
RestoreSelectedClassification,
|
||||||
SaveClassification,
|
SaveModifiedClassification,
|
||||||
SelectClassification,
|
SelectClassification,
|
||||||
SetActiveAction,
|
|
||||||
SetSelectedClassificationType,
|
SetSelectedClassificationType,
|
||||||
UpdateClassification } from './classification.actions';
|
UpdateClassification } from './classification.actions';
|
||||||
import { ClassificationsService } from '../../services/classifications/classifications.service';
|
import { ClassificationsService } from '../../services/classifications/classifications.service';
|
||||||
import { ACTION } from '../../models/action';
|
|
||||||
import { DomainService } from '../../services/domain/domain.service';
|
import { DomainService } from '../../services/domain/domain.service';
|
||||||
import { Classification } from '../../models/classification';
|
import { Classification } from '../../models/classification';
|
||||||
import { ClassificationSummary } from '../../models/classification-summary';
|
import { ClassificationSummary } from '../../models/classification-summary';
|
||||||
|
|
@ -52,8 +50,7 @@ export class ClassificationState implements NgxsAfterBootstrap {
|
||||||
if (ctx.getState().classificationTypes[action.selectedType]) {
|
if (ctx.getState().classificationTypes[action.selectedType]) {
|
||||||
ctx.patchState({
|
ctx.patchState({
|
||||||
selectedClassificationType: action.selectedType,
|
selectedClassificationType: action.selectedType,
|
||||||
selectedClassification: undefined,
|
selectedClassification: undefined
|
||||||
action: ACTION.DEFAULT
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return of(null);
|
return of(null);
|
||||||
|
|
@ -66,8 +63,7 @@ export class ClassificationState implements NgxsAfterBootstrap {
|
||||||
take(1),
|
take(1),
|
||||||
tap(selectedClassification => ctx.patchState({
|
tap(selectedClassification => ctx.patchState({
|
||||||
selectedClassification,
|
selectedClassification,
|
||||||
selectedClassificationType: selectedClassification.type,
|
selectedClassificationType: selectedClassification.type
|
||||||
action: ACTION.DEFAULT
|
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -77,8 +73,7 @@ export class ClassificationState implements NgxsAfterBootstrap {
|
||||||
@Action(DeselectClassification)
|
@Action(DeselectClassification)
|
||||||
deselectClassification(ctx: StateContext<ClassificationStateModel>): Observable<null> {
|
deselectClassification(ctx: StateContext<ClassificationStateModel>): Observable<null> {
|
||||||
ctx.patchState({
|
ctx.patchState({
|
||||||
selectedClassification: undefined,
|
selectedClassification: undefined
|
||||||
action: ACTION.DEFAULT
|
|
||||||
});
|
});
|
||||||
return of(null);
|
return of(null);
|
||||||
}
|
}
|
||||||
|
|
@ -94,19 +89,19 @@ export class ClassificationState implements NgxsAfterBootstrap {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Action(CreateClassification)
|
@Action(SaveCreatedClassification)
|
||||||
createClassification(ctx: StateContext<ClassificationStateModel>, action: CreateClassification): Observable<any> {
|
// this action is called when a copied or a new classification is saved
|
||||||
|
createClassification(ctx: StateContext<ClassificationStateModel>, action: SaveCreatedClassification): Observable<any> {
|
||||||
return this.classificationsService.postClassification(action.classification).pipe(
|
return this.classificationsService.postClassification(action.classification).pipe(
|
||||||
take(1), tap(classification => ctx.patchState({
|
take(1), tap(classification => ctx.patchState({
|
||||||
classifications: [...ctx.getState().classifications, classification],
|
classifications: [...ctx.getState().classifications, classification],
|
||||||
selectedClassification: classification,
|
selectedClassification: classification
|
||||||
action: ACTION.DEFAULT
|
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Action(SaveClassification)
|
@Action(SaveModifiedClassification)
|
||||||
saveClassification(ctx: StateContext<ClassificationStateModel>, action: SaveClassification): Observable<any> {
|
saveClassification(ctx: StateContext<ClassificationStateModel>, action: SaveModifiedClassification): Observable<any> {
|
||||||
return this.classificationsService.putClassification(action.classification).pipe(
|
return this.classificationsService.putClassification(action.classification).pipe(
|
||||||
take(1),
|
take(1),
|
||||||
tap(savedClassification => ctx.patchState({
|
tap(savedClassification => ctx.patchState({
|
||||||
|
|
@ -118,33 +113,59 @@ export class ClassificationState implements NgxsAfterBootstrap {
|
||||||
|
|
||||||
@Action(RestoreSelectedClassification)
|
@Action(RestoreSelectedClassification)
|
||||||
restoreSelectedClassification(ctx: StateContext<ClassificationStateModel>, action: RestoreSelectedClassification): Observable<any> {
|
restoreSelectedClassification(ctx: StateContext<ClassificationStateModel>, action: RestoreSelectedClassification): Observable<any> {
|
||||||
return this.classificationsService.getClassification(action.classificationId).pipe(
|
const state = ctx.getState();
|
||||||
take(1),
|
|
||||||
tap(selectedClassification => ctx.patchState({ selectedClassification }))
|
// check whether the classification already exists
|
||||||
);
|
// returns true in case the classification was edited or copied
|
||||||
|
if (state.classifications.some(classification => classification.classificationId === action.classificationId)) {
|
||||||
|
return this.classificationsService.getClassification(action.classificationId).pipe(
|
||||||
|
take(1),
|
||||||
|
tap(selectedClassification => {
|
||||||
|
ctx.patchState({ selectedClassification });
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the classification is restored to a new classification
|
||||||
|
const category = state.classificationTypes[state.selectedClassificationType][0];
|
||||||
|
const { type, created, modified, domain, parentId, parentKey } = state.selectedClassification;
|
||||||
|
ctx.patchState({ selectedClassification: { type, created, category, modified, domain, parentId, parentKey } });
|
||||||
|
|
||||||
|
return of(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Action(SetActiveAction)
|
@Action(CreateClassification)
|
||||||
setActiveAction(ctx: StateContext<ClassificationStateModel>, action: SetActiveAction): Observable<null> {
|
newCreateClassification(ctx: StateContext<ClassificationStateModel>): Observable<null> {
|
||||||
if (action.action === ACTION.CREATE) {
|
// Initialization of a new classification
|
||||||
// Initialization of a new classification
|
const state: ClassificationStateModel = ctx.getState();
|
||||||
const state: ClassificationStateModel = ctx.getState();
|
const date = TaskanaDate.getDate();
|
||||||
const date = TaskanaDate.getDate();
|
const initialClassification: Classification = {
|
||||||
const initialClassification: Classification = {
|
type: state.selectedClassificationType,
|
||||||
type: state.selectedClassificationType,
|
category: state.classificationTypes[state.selectedClassificationType][0],
|
||||||
category: state.classificationTypes[state.selectedClassificationType][0],
|
created: date,
|
||||||
created: date,
|
modified: date,
|
||||||
modified: date,
|
domain: this.domainService.getSelectedDomainValue(),
|
||||||
domain: this.domainService.getSelectedDomainValue(),
|
};
|
||||||
};
|
if (state.selectedClassification) {
|
||||||
if (state.selectedClassification) {
|
initialClassification.parentId = state.selectedClassification.classificationId;
|
||||||
initialClassification.parentId = state.selectedClassification.classificationId;
|
initialClassification.parentKey = state.selectedClassification.key;
|
||||||
initialClassification.parentKey = state.selectedClassification.key;
|
|
||||||
}
|
|
||||||
ctx.patchState({ selectedClassification: initialClassification, action: action.action });
|
|
||||||
} else {
|
|
||||||
ctx.patchState({ action: action.action });
|
|
||||||
}
|
}
|
||||||
|
ctx.patchState({
|
||||||
|
selectedClassification: initialClassification,
|
||||||
|
badgeMessage: 'Creating new classification'
|
||||||
|
});
|
||||||
|
return of(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Action(CopyClassification)
|
||||||
|
newCopyClassification(ctx: StateContext<ClassificationStateModel>): Observable<null> {
|
||||||
|
const copy = { ...ctx.getState().selectedClassification };
|
||||||
|
copy.key = null;
|
||||||
|
copy.classificationId = undefined;
|
||||||
|
ctx.patchState({
|
||||||
|
selectedClassification: copy,
|
||||||
|
badgeMessage: `Copying Classification: ${copy.name}`
|
||||||
|
});
|
||||||
return of(null);
|
return of(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -161,7 +182,7 @@ export class ClassificationState implements NgxsAfterBootstrap {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Action(UpdateClassification)
|
@Action(UpdateClassification)
|
||||||
updateClassification(ctx: StateContext<ClassificationStateModel>, action: SaveClassification): Observable<any> {
|
updateClassification(ctx: StateContext<ClassificationStateModel>, action: SaveModifiedClassification): Observable<any> {
|
||||||
return this.classificationsService.putClassification(action.classification).pipe(
|
return this.classificationsService.putClassification(action.classification).pipe(
|
||||||
take(1),
|
take(1),
|
||||||
tap(
|
tap(
|
||||||
|
|
@ -201,5 +222,5 @@ export interface ClassificationStateModel {
|
||||||
selectedClassification: Classification,
|
selectedClassification: Classification,
|
||||||
selectedClassificationType: string;
|
selectedClassificationType: string;
|
||||||
classificationTypes: CategoriesResponse,
|
classificationTypes: CategoriesResponse,
|
||||||
action: ACTION,
|
badgeMessage: string
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue