TSK-1503: Refactored copy function and saving mechanism
This commit is contained in:
parent
abfa07ce6a
commit
7e965a2709
|
|
@ -31,7 +31,6 @@ import { WorkbasketOverviewComponent } from './components/workbasket-overview/wo
|
||||||
/**
|
/**
|
||||||
* Services
|
* Services
|
||||||
*/
|
*/
|
||||||
import { SavingWorkbasketService } from './services/saving-workbaskets.service';
|
|
||||||
import { ClassificationDefinitionService } from './services/classification-definition.service';
|
import { ClassificationDefinitionService } from './services/classification-definition.service';
|
||||||
import { WorkbasketDefinitionService } from './services/workbasket-definition.service';
|
import { WorkbasketDefinitionService } from './services/workbasket-definition.service';
|
||||||
import { ImportExportService } from './services/import-export.service';
|
import { ImportExportService } from './services/import-export.service';
|
||||||
|
|
@ -113,7 +112,6 @@ const DECLARATIONS = [
|
||||||
providers: [
|
providers: [
|
||||||
ClassificationDefinitionService,
|
ClassificationDefinitionService,
|
||||||
WorkbasketDefinitionService,
|
WorkbasketDefinitionService,
|
||||||
SavingWorkbasketService,
|
|
||||||
ClassificationCategoriesService,
|
ClassificationCategoriesService,
|
||||||
ImportExportService
|
ImportExportService
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import { Observable, of } from 'rxjs';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { TypeAheadComponent } from '../../../shared/components/type-ahead/type-ahead.component';
|
import { TypeAheadComponent } from '../../../shared/components/type-ahead/type-ahead.component';
|
||||||
import { TypeaheadModule } from 'ngx-bootstrap';
|
import { TypeaheadModule } from 'ngx-bootstrap';
|
||||||
import { SavingWorkbasketService } from '../../services/saving-workbaskets.service';
|
|
||||||
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
|
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
|
||||||
import { FormsValidatorService } from '../../../shared/services/forms-validator/forms-validator.service';
|
import { FormsValidatorService } from '../../../shared/services/forms-validator/forms-validator.service';
|
||||||
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
||||||
|
|
@ -31,8 +30,6 @@ import {
|
||||||
UpdateWorkbasketAccessItems
|
UpdateWorkbasketAccessItems
|
||||||
} from '../../../shared/store/workbasket-store/workbasket.actions';
|
} from '../../../shared/store/workbasket-store/workbasket.actions';
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { ACTION } from '../../../shared/models/action';
|
|
||||||
import { WorkbasketAccessItems } from '../../../shared/models/workbasket-access-items';
|
|
||||||
import { MatSelectModule } from '@angular/material/select';
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
|
@ -47,12 +44,6 @@ class SpinnerStub {
|
||||||
@Input() positionClass: string;
|
@Input() positionClass: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const savingWorkbasketServiceSpy = jest.fn().mockImplementation(
|
|
||||||
(): Partial<SavingWorkbasketService> => ({
|
|
||||||
triggeredAccessItemsSaving: jest.fn().mockReturnValue(of(true))
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const requestInProgressServiceSpy = jest.fn().mockImplementation(
|
const requestInProgressServiceSpy = jest.fn().mockImplementation(
|
||||||
(): Partial<RequestInProgressService> => ({
|
(): Partial<RequestInProgressService> => ({
|
||||||
setRequestInProgress: jest.fn()
|
setRequestInProgress: jest.fn()
|
||||||
|
|
@ -106,7 +97,6 @@ describe('WorkbasketAccessItemsComponent', () => {
|
||||||
],
|
],
|
||||||
declarations: [WorkbasketAccessItemsComponent, TypeAheadComponent, SpinnerStub],
|
declarations: [WorkbasketAccessItemsComponent, TypeAheadComponent, SpinnerStub],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: SavingWorkbasketService, useClass: savingWorkbasketServiceSpy },
|
|
||||||
{ provide: RequestInProgressService, useClass: requestInProgressServiceSpy },
|
{ provide: RequestInProgressService, useClass: requestInProgressServiceSpy },
|
||||||
{ provide: FormsValidatorService, useClass: formValidatorServiceSpy },
|
{ provide: FormsValidatorService, useClass: formValidatorServiceSpy },
|
||||||
{ provide: NotificationService, useClass: notificationServiceSpy },
|
{ provide: NotificationService, useClass: notificationServiceSpy },
|
||||||
|
|
@ -145,14 +135,11 @@ describe('WorkbasketAccessItemsComponent', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should initialize when accessItems exist', async(() => {
|
it('should initialize when accessItems exist', async(() => {
|
||||||
component.action = ACTION.COPY;
|
|
||||||
let actionDispatched = false;
|
let actionDispatched = false;
|
||||||
component.onSave = jest.fn().mockImplementation();
|
|
||||||
actions$.pipe(ofActionDispatched(GetWorkbasketAccessItems)).subscribe(() => (actionDispatched = true));
|
actions$.pipe(ofActionDispatched(GetWorkbasketAccessItems)).subscribe(() => (actionDispatched = true));
|
||||||
component.init();
|
component.init();
|
||||||
expect(component.initialized).toBe(true);
|
expect(component.initialized).toBe(true);
|
||||||
expect(actionDispatched).toBe(true);
|
expect(actionDispatched).toBe(true);
|
||||||
expect(component.onSave).toHaveBeenCalled();
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it("should discard initializing when accessItems don't exist", () => {
|
it("should discard initializing when accessItems don't exist", () => {
|
||||||
|
|
@ -197,14 +184,4 @@ describe('WorkbasketAccessItemsComponent', () => {
|
||||||
expect(onSaveSpy).toHaveBeenCalled();
|
expect(onSaveSpy).toHaveBeenCalled();
|
||||||
expect(actionDispatched).toBe(true);
|
expect(actionDispatched).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set badge correctly', () => {
|
|
||||||
component.action = ACTION.READ;
|
|
||||||
component.setBadge();
|
|
||||||
expect(component.badgeMessage).toMatch('');
|
|
||||||
|
|
||||||
component.action = ACTION.COPY;
|
|
||||||
component.setBadge();
|
|
||||||
expect(component.badgeMessage).toMatch(`Copying workbasket: ${component.workbasket.key}`);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,23 +16,21 @@ import { FormArray, FormBuilder, Validators } from '@angular/forms';
|
||||||
import { Workbasket } from 'app/shared/models/workbasket';
|
import { Workbasket } from 'app/shared/models/workbasket';
|
||||||
import { customFieldCount, WorkbasketAccessItems } from 'app/shared/models/workbasket-access-items';
|
import { customFieldCount, WorkbasketAccessItems } from 'app/shared/models/workbasket-access-items';
|
||||||
import { WorkbasketAccessItemsRepresentation } from 'app/shared/models/workbasket-access-items-representation';
|
import { WorkbasketAccessItemsRepresentation } from 'app/shared/models/workbasket-access-items-representation';
|
||||||
import { ACTION } from 'app/shared/models/action';
|
|
||||||
|
|
||||||
import { SavingInformation, SavingWorkbasketService } from 'app/administration/services/saving-workbaskets.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 { highlight } from 'app/shared/animations/validation.animation';
|
import { highlight } from 'app/shared/animations/validation.animation';
|
||||||
import { FormsValidatorService } from 'app/shared/services/forms-validator/forms-validator.service';
|
import { FormsValidatorService } from 'app/shared/services/forms-validator/forms-validator.service';
|
||||||
import { AccessIdDefinition } from 'app/shared/models/access-id';
|
import { AccessIdDefinition } from 'app/shared/models/access-id';
|
||||||
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 { filter, takeUntil } from 'rxjs/operators';
|
import { filter, take, takeUntil } from 'rxjs/operators';
|
||||||
import { NOTIFICATION_TYPES } from '../../../shared/models/notifications';
|
import { NOTIFICATION_TYPES } from '../../../shared/models/notifications';
|
||||||
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
||||||
import { AccessItemsCustomisation, CustomField, getCustomFields } from '../../../shared/models/customisation';
|
import { AccessItemsCustomisation, CustomField, getCustomFields } from '../../../shared/models/customisation';
|
||||||
import {
|
import {
|
||||||
GetWorkbasketAccessItems,
|
GetWorkbasketAccessItems,
|
||||||
OnButtonPressed,
|
OnButtonPressed,
|
||||||
UpdateWorkbasketAccessItems,
|
SaveNewWorkbasket,
|
||||||
UpdateWorkbasket
|
UpdateWorkbasket,
|
||||||
|
UpdateWorkbasketAccessItems
|
||||||
} from '../../../shared/store/workbasket-store/workbasket.actions';
|
} from '../../../shared/store/workbasket-store/workbasket.actions';
|
||||||
import { WorkbasketSelectors } from '../../../shared/store/workbasket-store/workbasket.selectors';
|
import { WorkbasketSelectors } from '../../../shared/store/workbasket-store/workbasket.selectors';
|
||||||
import { WorkbasketComponent } from '../../models/workbasket-component';
|
import { WorkbasketComponent } from '../../models/workbasket-component';
|
||||||
|
|
@ -48,16 +46,12 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
||||||
@Input()
|
@Input()
|
||||||
workbasket: Workbasket;
|
workbasket: Workbasket;
|
||||||
|
|
||||||
@Input()
|
|
||||||
action: ACTION;
|
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
expanded: boolean;
|
expanded: boolean;
|
||||||
|
|
||||||
@ViewChildren('htmlInputElement')
|
@ViewChildren('htmlInputElement')
|
||||||
inputs: QueryList<ElementRef>;
|
inputs: QueryList<ElementRef>;
|
||||||
|
|
||||||
badgeMessage = '';
|
|
||||||
selectedRows: number[] = [];
|
selectedRows: number[] = [];
|
||||||
workbasketClone: Workbasket;
|
workbasketClone: Workbasket;
|
||||||
|
|
||||||
|
|
@ -65,8 +59,8 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
||||||
customFields: CustomField[];
|
customFields: CustomField[];
|
||||||
|
|
||||||
accessItemsRepresentation: WorkbasketAccessItemsRepresentation;
|
accessItemsRepresentation: WorkbasketAccessItemsRepresentation;
|
||||||
accessItemsClone: Array<WorkbasketAccessItems>;
|
accessItemsClone: WorkbasketAccessItems[];
|
||||||
accessItemsResetClone: Array<WorkbasketAccessItems>;
|
accessItemsResetClone: WorkbasketAccessItems[];
|
||||||
AccessItemsForm = this.formBuilder.group({
|
AccessItemsForm = this.formBuilder.group({
|
||||||
accessItemsGroups: this.formBuilder.array([])
|
accessItemsGroups: this.formBuilder.array([])
|
||||||
});
|
});
|
||||||
|
|
@ -76,6 +70,9 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
||||||
added = false;
|
added = false;
|
||||||
destroy$ = new Subject<void>();
|
destroy$ = new Subject<void>();
|
||||||
|
|
||||||
|
@Select(WorkbasketSelectors.selectedWorkbasket)
|
||||||
|
selectedWorkbasket$: Observable<Workbasket>;
|
||||||
|
|
||||||
@Select(EngineConfigurationSelectors.accessItemsCustomisation)
|
@Select(EngineConfigurationSelectors.accessItemsCustomisation)
|
||||||
accessItemsCustomization$: Observable<AccessItemsCustomisation>;
|
accessItemsCustomization$: Observable<AccessItemsCustomisation>;
|
||||||
|
|
||||||
|
|
@ -89,7 +86,6 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
||||||
selectedComponent$: Observable<WorkbasketComponent>;
|
selectedComponent$: Observable<WorkbasketComponent>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private savingWorkbaskets: SavingWorkbasketService,
|
|
||||||
private requestInProgressService: RequestInProgressService,
|
private requestInProgressService: RequestInProgressService,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
public formsValidatorService: FormsValidatorService,
|
public formsValidatorService: FormsValidatorService,
|
||||||
|
|
@ -110,17 +106,27 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
||||||
});
|
});
|
||||||
this.accessItemsRepresentation$.subscribe((accessItemsRepresentation) => {
|
this.accessItemsRepresentation$.subscribe((accessItemsRepresentation) => {
|
||||||
if (typeof accessItemsRepresentation !== 'undefined') {
|
if (typeof accessItemsRepresentation !== 'undefined') {
|
||||||
this.accessItemsRepresentation = accessItemsRepresentation;
|
this.accessItemsRepresentation = { ...accessItemsRepresentation };
|
||||||
this.setAccessItemsGroups(accessItemsRepresentation.accessItems);
|
this.setAccessItemsGroups(accessItemsRepresentation.accessItems);
|
||||||
this.accessItemsClone = this.cloneAccessItems(accessItemsRepresentation.accessItems);
|
this.accessItemsClone = this.cloneAccessItems(accessItemsRepresentation.accessItems);
|
||||||
this.accessItemsResetClone = this.cloneAccessItems(accessItemsRepresentation.accessItems);
|
this.accessItemsResetClone = this.cloneAccessItems(accessItemsRepresentation.accessItems);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// saving workbasket access items when workbasket already exists
|
||||||
this.ngxsActions$.pipe(ofActionCompleted(UpdateWorkbasket), takeUntil(this.destroy$)).subscribe(() => {
|
this.ngxsActions$.pipe(ofActionCompleted(UpdateWorkbasket), takeUntil(this.destroy$)).subscribe(() => {
|
||||||
this.onSubmit();
|
this.onSubmit();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// saving workbasket access items when workbasket was copied or created
|
||||||
|
this.ngxsActions$.pipe(ofActionCompleted(SaveNewWorkbasket), takeUntil(this.destroy$)).subscribe(() => {
|
||||||
|
this.selectedWorkbasket$.pipe(take(1)).subscribe((workbasket) => {
|
||||||
|
this.accessItemsRepresentation._links = { self: { href: workbasket._links.accessItems.href } };
|
||||||
|
this.setWorkbasketIdForCopy(workbasket.workbasketId);
|
||||||
|
this.onSave();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
this.buttonAction$
|
this.buttonAction$
|
||||||
.pipe(takeUntil(this.destroy$))
|
.pipe(takeUntil(this.destroy$))
|
||||||
.pipe(filter((buttonAction) => typeof buttonAction !== 'undefined'))
|
.pipe(filter((buttonAction) => typeof buttonAction !== 'undefined'))
|
||||||
|
|
@ -168,9 +174,6 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(changes?: SimpleChanges) {
|
ngOnChanges(changes?: SimpleChanges) {
|
||||||
if (changes.action) {
|
|
||||||
this.setBadge();
|
|
||||||
}
|
|
||||||
if (this.workbasketClone) {
|
if (this.workbasketClone) {
|
||||||
if (this.workbasketClone.workbasketId != this.workbasket.workbasketId) {
|
if (this.workbasketClone.workbasketId != this.workbasket.workbasketId) {
|
||||||
this.init();
|
this.init();
|
||||||
|
|
@ -189,16 +192,6 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
||||||
this.requestInProgressService.setRequestInProgress(false);
|
this.requestInProgressService.setRequestInProgress(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.savingWorkbaskets
|
|
||||||
.triggeredAccessItemsSaving()
|
|
||||||
.pipe(takeUntil(this.destroy$))
|
|
||||||
.subscribe((savingInformation: SavingInformation) => {
|
|
||||||
if (this.action === ACTION.COPY) {
|
|
||||||
this.accessItemsRepresentation._links.self.href = savingInformation.url;
|
|
||||||
this.setWorkbasketIdForCopy(savingInformation.workbasketId);
|
|
||||||
this.onSave();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -291,7 +284,7 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
||||||
|
|
||||||
accessItemSelected(accessItem: AccessIdDefinition, row: number) {
|
accessItemSelected(accessItem: AccessIdDefinition, row: number) {
|
||||||
this.accessItemsGroups.controls[row].get('accessId').setValue(accessItem?.accessId);
|
this.accessItemsGroups.controls[row].get('accessId').setValue(accessItem?.accessId);
|
||||||
this.accessItemsGroups.controls[row].get('accessName').setValue(accessItem.name);
|
this.accessItemsGroups.controls[row].get('accessName').setValue(accessItem?.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSave() {
|
onSave() {
|
||||||
|
|
@ -335,12 +328,6 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setBadge() {
|
|
||||||
if (this.action === ACTION.COPY) {
|
|
||||||
this.badgeMessage = `Copying workbasket: ${this.workbasket.key}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cloneAccessItems(inputaccessItem): Array<WorkbasketAccessItems> {
|
cloneAccessItems(inputaccessItem): Array<WorkbasketAccessItems> {
|
||||||
return this.AccessItemsForm.value.accessItemsGroups.map((accessItems: WorkbasketAccessItems) => ({
|
return this.AccessItemsForm.value.accessItemsGroups.map((accessItems: WorkbasketAccessItems) => ({
|
||||||
...accessItems
|
...accessItems
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<mat-toolbar class="workbasket-details__toolbar">
|
<mat-toolbar class="workbasket-details__toolbar">
|
||||||
<h4 class="workbasket-details__title">
|
<h4 class="workbasket-details__title">
|
||||||
<span class="workbasket-details__title-name">{{workbasket.name}}</span>
|
<span class="workbasket-details__title-name">{{workbasket.name}}</span>
|
||||||
<span class="workbasket-details__title-badge" *ngIf="!workbasket.workbasketId"> {{ badgeMessage }}</span>
|
<span class="workbasket-details__title-badge"> {{ badgeMessage$ | async }}</span>
|
||||||
</h4>
|
</h4>
|
||||||
<span class="workbasket-details__spacer"></span>
|
<span class="workbasket-details__spacer"></span>
|
||||||
<button mat-button class="workbasket-details__button workbasket-details__save-button"
|
<button mat-button class="workbasket-details__button workbasket-details__save-button"
|
||||||
|
|
@ -52,11 +52,11 @@
|
||||||
</taskana-administration-workbasket-information>
|
</taskana-administration-workbasket-information>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
<mat-tab label="Access">
|
<mat-tab label="Access">
|
||||||
<taskana-administration-workbasket-access-items [workbasket]="workbasket" [action]="action" [expanded]="expanded">
|
<taskana-administration-workbasket-access-items [workbasket]="workbasket" [expanded]="expanded">
|
||||||
</taskana-administration-workbasket-access-items>
|
</taskana-administration-workbasket-access-items>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
<mat-tab label="Distribution Targets">
|
<mat-tab label="Distribution Targets">
|
||||||
<taskana-administration-workbasket-distribution-targets [workbasket]="workbasket" [action]="action">
|
<taskana-administration-workbasket-distribution-targets [workbasket]="workbasket">
|
||||||
</taskana-administration-workbasket-distribution-targets>
|
</taskana-administration-workbasket-distribution-targets>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
</mat-tab-group>
|
</mat-tab-group>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { WorkbasketDetailsComponent } from './workbasket-details.component';
|
import { WorkbasketDetailsComponent } from './workbasket-details.component';
|
||||||
import { Component, DebugElement, Input } from '@angular/core';
|
import { Component, DebugElement, Input } from '@angular/core';
|
||||||
import { Actions, NgxsModule, Store } from '@ngxs/store';
|
import { Actions, NgxsModule, Store } from '@ngxs/store';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { Workbasket } from '../../../shared/models/workbasket';
|
import { Workbasket } from '../../../shared/models/workbasket';
|
||||||
import { ACTION } from '../../../shared/models/action';
|
import { ACTION } from '../../../shared/models/action';
|
||||||
import { WorkbasketState } from '../../../shared/store/workbasket-store/workbasket.state';
|
import { WorkbasketState } from '../../../shared/store/workbasket-store/workbasket.state';
|
||||||
|
|
@ -25,7 +25,7 @@ import { MatTabsModule } from '@angular/material/tabs';
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { CreateWorkbasket } from '../../../shared/store/workbasket-store/workbasket.actions';
|
import { CopyWorkbasket, CreateWorkbasket } from '../../../shared/store/workbasket-store/workbasket.actions';
|
||||||
import { take } from 'rxjs/operators';
|
import { take } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({ selector: 'taskana-administration-workbasket-information', template: '<div>i</div>' })
|
@Component({ selector: 'taskana-administration-workbasket-information', template: '<div>i</div>' })
|
||||||
|
|
@ -49,6 +49,14 @@ class WorkbasketDistributionTargetsStub {
|
||||||
@Input() active: string;
|
@Input() active: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const domainServiceSpy = jest.fn().mockImplementation(
|
||||||
|
(): Partial<DomainService> => ({
|
||||||
|
getSelectedDomainValue: jest.fn().mockReturnValue(of()),
|
||||||
|
getSelectedDomain: jest.fn().mockReturnValue(of('A')),
|
||||||
|
getDomains: jest.fn().mockReturnValue(of())
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
export const workbasketCopyState = {
|
export const workbasketCopyState = {
|
||||||
selectedWorkbasket: selectedWorkbasketMock,
|
selectedWorkbasket: selectedWorkbasketMock,
|
||||||
action: ACTION.COPY
|
action: ACTION.COPY
|
||||||
|
|
@ -92,7 +100,7 @@ describe('WorkbasketDetailsComponent', () => {
|
||||||
WorkbasketInformationStub
|
WorkbasketInformationStub
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
DomainService,
|
{ provide: DomainService, useClass: domainServiceSpy },
|
||||||
ImportExportService,
|
ImportExportService,
|
||||||
WorkbasketService,
|
WorkbasketService,
|
||||||
RequestInProgressService,
|
RequestInProgressService,
|
||||||
|
|
@ -126,23 +134,32 @@ describe('WorkbasketDetailsComponent', () => {
|
||||||
expect(information).toBeTruthy();
|
expect(information).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render new workbasket when action is CREATE', () => {
|
it('should render new workbasket when action is CREATE', async (done) => {
|
||||||
store.reset({
|
store
|
||||||
...store.snapshot(),
|
.dispatch(new CreateWorkbasket())
|
||||||
workbasket: workbasketCreateState
|
.pipe(take(1))
|
||||||
|
.subscribe(() => {
|
||||||
|
component.selectedWorkbasketAndComponentAndAction$.pipe(take(1)).subscribe((state) => {
|
||||||
|
expect(state.selectedWorkbasket.workbasketId).toBeUndefined();
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
fixture.detectChanges();
|
|
||||||
expect(component.selectedId).toBeUndefined();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render copied workbasket when action is COPY', () => {
|
it('should render copied workbasket when action is COPY', (done) => {
|
||||||
store.reset({
|
const workbasket = component.workbasket;
|
||||||
...store.snapshot(),
|
store
|
||||||
workbasket: workbasketCopyState
|
.dispatch(new CopyWorkbasket(component.workbasket))
|
||||||
|
.pipe(take(1))
|
||||||
|
.subscribe(() => {
|
||||||
|
component.selectedWorkbasketAndComponentAndAction$.pipe(take(1)).subscribe((state) => {
|
||||||
|
const workbasketCopy = state.selectedWorkbasket;
|
||||||
|
expect(workbasketCopy.workbasketId).toBeUndefined();
|
||||||
|
expect(workbasketCopy.key).toEqual(workbasket.key);
|
||||||
|
expect(workbasketCopy.owner).toEqual(workbasket.owner);
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
component.ngOnInit();
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(component.workbasketCopy).toEqual(component.workbasket);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render workbasket when action is READ', () => {
|
it('should render workbasket when action is READ', () => {
|
||||||
|
|
@ -158,11 +175,14 @@ describe('WorkbasketDetailsComponent', () => {
|
||||||
|
|
||||||
it('should select information tab when action is CREATE', (done) => {
|
it('should select information tab when action is CREATE', (done) => {
|
||||||
component.selectComponent(1);
|
component.selectComponent(1);
|
||||||
store.dispatch(new CreateWorkbasket());
|
store
|
||||||
fixture.detectChanges();
|
.dispatch(new CreateWorkbasket())
|
||||||
|
.pipe(take(1))
|
||||||
|
.subscribe(() => {
|
||||||
component.selectedTab$.pipe(take(1)).subscribe((tab) => {
|
component.selectedTab$.pipe(take(1)).subscribe((tab) => {
|
||||||
expect(tab).toEqual(0);
|
expect(tab).toEqual(0);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,44 @@
|
||||||
import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
|
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { Observable, Subject } from 'rxjs';
|
import { Observable, Subject } from 'rxjs';
|
||||||
import { Workbasket } from 'app/shared/models/workbasket';
|
import { Workbasket } from 'app/shared/models/workbasket';
|
||||||
import { ACTION } from 'app/shared/models/action';
|
import { ACTION } from 'app/shared/models/action';
|
||||||
import { DomainService } from 'app/shared/services/domain/domain.service';
|
import { DomainService } from 'app/shared/services/domain/domain.service';
|
||||||
import { ImportExportService } from 'app/administration/services/import-export.service';
|
|
||||||
import { Select, Store } from '@ngxs/store';
|
import { Select, Store } from '@ngxs/store';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
import { WorkbasketAndAction, WorkbasketSelectors } from '../../../shared/store/workbasket-store/workbasket.selectors';
|
|
||||||
import { TaskanaDate } from '../../../shared/util/taskana.date';
|
|
||||||
import { Location } from '@angular/common';
|
|
||||||
import { WorkbasketType } from '../../../shared/models/workbasket-type';
|
|
||||||
import {
|
import {
|
||||||
|
WorkbasketAndComponentAndAction,
|
||||||
|
WorkbasketSelectors
|
||||||
|
} from '../../../shared/store/workbasket-store/workbasket.selectors';
|
||||||
|
import { Location } from '@angular/common';
|
||||||
|
import {
|
||||||
|
CopyWorkbasket,
|
||||||
DeselectWorkbasket,
|
DeselectWorkbasket,
|
||||||
OnButtonPressed,
|
OnButtonPressed,
|
||||||
SelectComponent
|
SelectComponent
|
||||||
} from '../../../shared/store/workbasket-store/workbasket.actions';
|
} from '../../../shared/store/workbasket-store/workbasket.actions';
|
||||||
import { ButtonAction } from '../../models/button-action';
|
import { ButtonAction } from '../../models/button-action';
|
||||||
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
|
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
|
||||||
|
import { WorkbasketComponent } from '../../models/workbasket-component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'taskana-administration-workbasket-details',
|
selector: 'taskana-administration-workbasket-details',
|
||||||
templateUrl: './workbasket-details.component.html',
|
templateUrl: './workbasket-details.component.html',
|
||||||
styleUrls: ['./workbasket-details.component.scss']
|
styleUrls: ['./workbasket-details.component.scss']
|
||||||
})
|
})
|
||||||
export class WorkbasketDetailsComponent implements OnInit, OnDestroy, OnChanges {
|
export class WorkbasketDetailsComponent implements OnInit, OnDestroy {
|
||||||
workbasket: Workbasket;
|
workbasket: Workbasket;
|
||||||
workbasketCopy: Workbasket;
|
|
||||||
selectedId: string;
|
|
||||||
action: ACTION;
|
action: ACTION;
|
||||||
badgeMessage = '';
|
selectedComponent: WorkbasketComponent;
|
||||||
|
|
||||||
@Select(WorkbasketSelectors.selectedWorkbasket)
|
|
||||||
selectedWorkbasket$: Observable<Workbasket>;
|
|
||||||
|
|
||||||
@Select(WorkbasketSelectors.selectedComponent)
|
@Select(WorkbasketSelectors.selectedComponent)
|
||||||
selectedTab$: Observable<number>;
|
selectedTab$: Observable<number>;
|
||||||
|
|
||||||
@Select(WorkbasketSelectors.workbasketActiveAction)
|
@Select(WorkbasketSelectors.badgeMessage)
|
||||||
activeAction$: Observable<ACTION>;
|
badgeMessage$: Observable<string>;
|
||||||
|
|
||||||
@Select(WorkbasketSelectors.selectedWorkbasketAndAction)
|
@Select(WorkbasketSelectors.selectedWorkbasketAndComponentAndAction)
|
||||||
selectedWorkbasketAndAction$: Observable<WorkbasketAndAction>;
|
selectedWorkbasketAndComponentAndAction$: Observable<WorkbasketAndComponentAndAction>;
|
||||||
|
|
||||||
destroy$ = new Subject<void>();
|
destroy$ = new Subject<void>();
|
||||||
|
|
||||||
|
|
@ -52,96 +49,37 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy, OnChanges
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private domainService: DomainService,
|
private domainService: DomainService,
|
||||||
private importExportService: ImportExportService,
|
|
||||||
private requestInProgressService: RequestInProgressService,
|
private requestInProgressService: RequestInProgressService,
|
||||||
private store: Store
|
private store: Store
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.selectedWorkbasketAndAction$.pipe(takeUntil(this.destroy$)).subscribe((selectedWorkbasketAndAction) => {
|
this.getWorkbasketFromStore();
|
||||||
this.action = selectedWorkbasketAndAction.action;
|
|
||||||
if (this.action === ACTION.CREATE) {
|
|
||||||
this.selectedId = undefined;
|
|
||||||
this.badgeMessage = 'Creating new workbasket';
|
|
||||||
this.initWorkbasket();
|
|
||||||
} else if (this.action === ACTION.COPY) {
|
|
||||||
// delete this.workbasket.key;
|
|
||||||
this.workbasketCopy = this.workbasket;
|
|
||||||
this.getWorkbasketInformation();
|
|
||||||
this.badgeMessage = `Copying workbasket: ${this.workbasket.key}`;
|
|
||||||
} else if (typeof selectedWorkbasketAndAction.selectedWorkbasket !== 'undefined') {
|
|
||||||
this.workbasket = { ...selectedWorkbasketAndAction.selectedWorkbasket };
|
|
||||||
this.getWorkbasketInformation(this.workbasket);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.importExportService
|
|
||||||
.getImportingFinished()
|
|
||||||
.pipe(takeUntil(this.destroy$))
|
|
||||||
.subscribe(() => {
|
|
||||||
if (this.workbasket) {
|
|
||||||
this.getWorkbasketInformation(this.workbasket);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(changes?: SimpleChanges) {}
|
getWorkbasketFromStore() {
|
||||||
|
// this is necessary since we receive workbaskets from store even when there is no update
|
||||||
|
// this would unintentionally discard changes
|
||||||
|
|
||||||
addDateToWorkbasket(workbasket: Workbasket) {
|
this.selectedWorkbasketAndComponentAndAction$.pipe(takeUntil(this.destroy$)).subscribe((object) => {
|
||||||
const date = TaskanaDate.getDate();
|
const workbasket = object.selectedWorkbasket;
|
||||||
workbasket.created = date;
|
const action = object.action;
|
||||||
workbasket.modified = date;
|
const component = object.selectedComponent;
|
||||||
|
|
||||||
|
// get workbasket from store when:
|
||||||
|
// a) workbasket with another ID is selected (includes copying)
|
||||||
|
// b) empty workbasket is created
|
||||||
|
// c) saving the workbasket
|
||||||
|
|
||||||
|
const isAnotherId = this.workbasket?.workbasketId !== workbasket?.workbasketId;
|
||||||
|
const isCreation = action !== this.action && action === ACTION.CREATE;
|
||||||
|
const isSameComponent = component === this.selectedComponent;
|
||||||
|
if (isAnotherId || isCreation || isSameComponent) {
|
||||||
|
this.workbasket = { ...workbasket };
|
||||||
}
|
}
|
||||||
|
|
||||||
initWorkbasket() {
|
this.action = action;
|
||||||
const emptyWorkbasket: Workbasket = {};
|
this.selectedComponent = component;
|
||||||
emptyWorkbasket.domain = this.domainService.getSelectedDomainValue();
|
|
||||||
emptyWorkbasket.type = WorkbasketType.PERSONAL;
|
|
||||||
this.addDateToWorkbasket(emptyWorkbasket);
|
|
||||||
this.workbasket = emptyWorkbasket;
|
|
||||||
}
|
|
||||||
|
|
||||||
backClicked(): void {
|
|
||||||
this.router.navigate(['./'], { relativeTo: this.route.parent });
|
|
||||||
}
|
|
||||||
|
|
||||||
getWorkbasketInformation(selectedWorkbasket?: Workbasket) {
|
|
||||||
let workbasketIdSelected: string;
|
|
||||||
if (selectedWorkbasket) {
|
|
||||||
workbasketIdSelected = selectedWorkbasket.workbasketId;
|
|
||||||
}
|
|
||||||
this.requestInProgressService.setRequestInProgress(true);
|
|
||||||
if (!workbasketIdSelected && this.action === ACTION.CREATE) {
|
|
||||||
// CREATE
|
|
||||||
this.workbasket = {};
|
|
||||||
this.domainService
|
|
||||||
.getSelectedDomain()
|
|
||||||
.pipe(takeUntil(this.destroy$))
|
|
||||||
.subscribe((domain) => {
|
|
||||||
this.workbasket.domain = domain;
|
|
||||||
});
|
|
||||||
this.requestInProgressService.setRequestInProgress(false);
|
|
||||||
} else if (!workbasketIdSelected && this.action === ACTION.COPY) {
|
|
||||||
// COPY
|
|
||||||
this.workbasket = { ...this.workbasketCopy };
|
|
||||||
delete this.workbasket.workbasketId;
|
|
||||||
this.requestInProgressService.setRequestInProgress(false);
|
|
||||||
}
|
|
||||||
if (workbasketIdSelected) {
|
|
||||||
this.workbasket = selectedWorkbasket;
|
|
||||||
this.requestInProgressService.setRequestInProgress(false);
|
|
||||||
this.checkDomainAndRedirect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkDomainAndRedirect() {
|
|
||||||
this.domainService
|
|
||||||
.getSelectedDomain()
|
|
||||||
.pipe(takeUntil(this.destroy$))
|
|
||||||
.subscribe((domain) => {
|
|
||||||
if (domain !== '' && this.workbasket && this.workbasket.domain !== domain) {
|
|
||||||
this.backClicked();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,6 +97,7 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy, OnChanges
|
||||||
|
|
||||||
onCopy() {
|
onCopy() {
|
||||||
this.store.dispatch(new OnButtonPressed(ButtonAction.COPY));
|
this.store.dispatch(new OnButtonPressed(ButtonAction.COPY));
|
||||||
|
this.store.dispatch(new CopyWorkbasket(this.workbasket));
|
||||||
}
|
}
|
||||||
|
|
||||||
onRemoveAsDistributionTarget() {
|
onRemoveAsDistributionTarget() {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { WorkbasketService } from '../../../shared/services/workbasket/workbasket.service';
|
import { WorkbasketService } from '../../../shared/services/workbasket/workbasket.service';
|
||||||
import { SavingWorkbasketService } from '../../services/saving-workbaskets.service';
|
|
||||||
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
||||||
import { Actions, NgxsModule, Store } from '@ngxs/store';
|
import { Actions, NgxsModule, Store } from '@ngxs/store';
|
||||||
import { WorkbasketState } from '../../../shared/store/workbasket-store/workbasket.state';
|
import { WorkbasketState } from '../../../shared/store/workbasket-store/workbasket.state';
|
||||||
|
|
@ -21,6 +20,7 @@ import {
|
||||||
} from '../../../shared/store/mock-data/mock-store';
|
} from '../../../shared/store/mock-data/mock-store';
|
||||||
import { WorkbasketQueryFilterParameter } from '../../../shared/models/workbasket-query-filter-parameter';
|
import { WorkbasketQueryFilterParameter } from '../../../shared/models/workbasket-query-filter-parameter';
|
||||||
import { Pair } from '../../../shared/models/pair';
|
import { Pair } from '../../../shared/models/pair';
|
||||||
|
import { DomainService } from '../../../shared/services/domain/domain.service';
|
||||||
|
|
||||||
const routeParamsMock = { id: 'workbasket' };
|
const routeParamsMock = { id: 'workbasket' };
|
||||||
const activatedRouteMock = {
|
const activatedRouteMock = {
|
||||||
|
|
@ -42,6 +42,14 @@ class WorkbasketDistributionTargetsListStub {
|
||||||
@Output() allSelectedChange = new EventEmitter<boolean>();
|
@Output() allSelectedChange = new EventEmitter<boolean>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const domainServiceSpy = jest.fn().mockImplementation(
|
||||||
|
(): Partial<DomainService> => ({
|
||||||
|
getSelectedDomainValue: jest.fn().mockReturnValue(of()),
|
||||||
|
getSelectedDomain: jest.fn().mockReturnValue(of('A')),
|
||||||
|
getDomains: jest.fn().mockReturnValue(of())
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const workbasketServiceSpy = jest.fn().mockImplementation(
|
const workbasketServiceSpy = jest.fn().mockImplementation(
|
||||||
(): Partial<WorkbasketService> => ({
|
(): Partial<WorkbasketService> => ({
|
||||||
getWorkBasketsSummary: jest.fn().mockReturnValue(of()),
|
getWorkBasketsSummary: jest.fn().mockReturnValue(of()),
|
||||||
|
|
@ -49,11 +57,6 @@ const workbasketServiceSpy = jest.fn().mockImplementation(
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const savingWorkbasketServiceSpy = jest.fn().mockImplementation(
|
|
||||||
(): Partial<SavingWorkbasketService> => ({
|
|
||||||
triggeredDistributionTargetsSaving: jest.fn().mockReturnValue(of())
|
|
||||||
})
|
|
||||||
);
|
|
||||||
const notificationsServiceSpy = jest.fn().mockImplementation(
|
const notificationsServiceSpy = jest.fn().mockImplementation(
|
||||||
(): Partial<NotificationService> => ({
|
(): Partial<NotificationService> => ({
|
||||||
showToast: jest.fn().mockReturnValue(true)
|
showToast: jest.fn().mockReturnValue(true)
|
||||||
|
|
@ -84,10 +87,10 @@ describe('WorkbasketDistributionTargetsComponent', () => {
|
||||||
declarations: [WorkbasketDistributionTargetsComponent, WorkbasketDistributionTargetsListStub],
|
declarations: [WorkbasketDistributionTargetsComponent, WorkbasketDistributionTargetsListStub],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: WorkbasketService, useClass: workbasketServiceSpy },
|
{ provide: WorkbasketService, useClass: workbasketServiceSpy },
|
||||||
{ provide: SavingWorkbasketService, useClass: savingWorkbasketServiceSpy },
|
|
||||||
{ provide: NotificationService, useClass: notificationsServiceSpy },
|
{ provide: NotificationService, useClass: notificationsServiceSpy },
|
||||||
{ provide: ActivatedRoute, useValue: activatedRouteMock },
|
{ provide: ActivatedRoute, useValue: activatedRouteMock },
|
||||||
{ provide: RequestInProgressService, useClass: requestInProgressServiceSpy }
|
{ provide: RequestInProgressService, useClass: requestInProgressServiceSpy },
|
||||||
|
{ provide: DomainService, useClass: domainServiceSpy }
|
||||||
]
|
]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,18 @@ import { Workbasket } from 'app/shared/models/workbasket';
|
||||||
import { WorkbasketSummary } from 'app/shared/models/workbasket-summary';
|
import { WorkbasketSummary } from 'app/shared/models/workbasket-summary';
|
||||||
import { WorkbasketSummaryRepresentation } from 'app/shared/models/workbasket-summary-representation';
|
import { WorkbasketSummaryRepresentation } from 'app/shared/models/workbasket-summary-representation';
|
||||||
import { WorkbasketDistributionTargets } from 'app/shared/models/workbasket-distribution-targets';
|
import { WorkbasketDistributionTargets } from 'app/shared/models/workbasket-distribution-targets';
|
||||||
import { ACTION } from 'app/shared/models/action';
|
|
||||||
import { WorkbasketService } from 'app/shared/services/workbasket/workbasket.service';
|
import { WorkbasketService } from 'app/shared/services/workbasket/workbasket.service';
|
||||||
import { SavingWorkbasketService, SavingInformation } from 'app/administration/services/saving-workbaskets.service';
|
|
||||||
import { Page } from 'app/shared/models/page';
|
import { Page } from 'app/shared/models/page';
|
||||||
import { Actions, ofActionCompleted, Select, Store } from '@ngxs/store';
|
import { Actions, ofActionCompleted, Select, Store } from '@ngxs/store';
|
||||||
import { filter, takeUntil } from 'rxjs/operators';
|
import { filter, take, takeUntil } from 'rxjs/operators';
|
||||||
import { NOTIFICATION_TYPES } from '../../../shared/models/notifications';
|
import { NOTIFICATION_TYPES } from '../../../shared/models/notifications';
|
||||||
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
||||||
import {
|
import {
|
||||||
GetAvailableDistributionTargets,
|
GetAvailableDistributionTargets,
|
||||||
GetWorkbasketDistributionTargets,
|
GetWorkbasketDistributionTargets,
|
||||||
UpdateWorkbasketDistributionTargets,
|
SaveNewWorkbasket,
|
||||||
UpdateWorkbasketAccessItems
|
UpdateWorkbasket,
|
||||||
|
UpdateWorkbasketDistributionTargets
|
||||||
} from '../../../shared/store/workbasket-store/workbasket.actions';
|
} from '../../../shared/store/workbasket-store/workbasket.actions';
|
||||||
import { WorkbasketSelectors } from '../../../shared/store/workbasket-store/workbasket.selectors';
|
import { WorkbasketSelectors } from '../../../shared/store/workbasket-store/workbasket.selectors';
|
||||||
import { ButtonAction } from '../../models/button-action';
|
import { ButtonAction } from '../../models/button-action';
|
||||||
|
|
@ -38,20 +37,17 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
||||||
@Input()
|
@Input()
|
||||||
workbasket: Workbasket;
|
workbasket: Workbasket;
|
||||||
|
|
||||||
@Input()
|
|
||||||
action: ACTION;
|
|
||||||
|
|
||||||
toolbarState = false;
|
toolbarState = false;
|
||||||
sideBySide = true;
|
sideBySide = true;
|
||||||
displayingDistributionTargetsPicker = true;
|
displayingDistributionTargetsPicker = true;
|
||||||
|
|
||||||
distributionTargetsSelectedResource: WorkbasketDistributionTargets;
|
distributionTargetsSelectedResource: WorkbasketDistributionTargets;
|
||||||
availableDistributionTargets: Array<WorkbasketSummary> = [];
|
availableDistributionTargets: WorkbasketSummary[] = [];
|
||||||
distributionTargetsClone: Array<WorkbasketSummary>;
|
distributionTargetsClone: WorkbasketSummary[];
|
||||||
|
|
||||||
distributionTargetsLeft: Array<WorkbasketSummary> = [];
|
distributionTargetsLeft: WorkbasketSummary[] = [];
|
||||||
distributionTargetsSelected: Array<WorkbasketSummary>;
|
distributionTargetsSelected: WorkbasketSummary[];
|
||||||
distributionTargetsSelectedClone: Array<WorkbasketSummary>;
|
distributionTargetsSelectedClone: WorkbasketSummary[];
|
||||||
|
|
||||||
loadingItems = false;
|
loadingItems = false;
|
||||||
side = Side;
|
side = Side;
|
||||||
|
|
@ -81,7 +77,6 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private workbasketService: WorkbasketService,
|
private workbasketService: WorkbasketService,
|
||||||
private savingWorkbaskets: SavingWorkbasketService,
|
|
||||||
private notificationsService: NotificationService,
|
private notificationsService: NotificationService,
|
||||||
private store: Store,
|
private store: Store,
|
||||||
private ngxsActions$: Actions
|
private ngxsActions$: Actions
|
||||||
|
|
@ -97,7 +92,8 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
||||||
.subscribe((selectedWorkbasket) => {
|
.subscribe((selectedWorkbasket) => {
|
||||||
this.workbasket = selectedWorkbasket;
|
this.workbasket = selectedWorkbasket;
|
||||||
});
|
});
|
||||||
if (Object.keys(this.workbasket).length !== 0) {
|
|
||||||
|
if (this.workbasket?.workbasketId) {
|
||||||
this.store.dispatch(new GetWorkbasketDistributionTargets(this.workbasket._links.distributionTargets.href));
|
this.store.dispatch(new GetWorkbasketDistributionTargets(this.workbasket._links.distributionTargets.href));
|
||||||
this.store.dispatch(new GetAvailableDistributionTargets());
|
this.store.dispatch(new GetAvailableDistributionTargets());
|
||||||
}
|
}
|
||||||
|
|
@ -109,16 +105,6 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
||||||
this.availableDistributionTargets = availableDistributionTargets.map((wb) => ({ ...wb }));
|
this.availableDistributionTargets = availableDistributionTargets.map((wb) => ({ ...wb }));
|
||||||
});
|
});
|
||||||
|
|
||||||
this.savingWorkbaskets
|
|
||||||
.triggeredDistributionTargetsSaving()
|
|
||||||
.pipe(takeUntil(this.destroy$))
|
|
||||||
.subscribe((savingInformation: SavingInformation) => {
|
|
||||||
if (this.action === ACTION.COPY) {
|
|
||||||
this.distributionTargetsSelectedResource._links.self.href = savingInformation.url;
|
|
||||||
this.onSave();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.workbasketDistributionTargets$.subscribe((workbasketDistributionTargets) => {
|
this.workbasketDistributionTargets$.subscribe((workbasketDistributionTargets) => {
|
||||||
if (typeof workbasketDistributionTargets !== 'undefined') {
|
if (typeof workbasketDistributionTargets !== 'undefined') {
|
||||||
this.distributionTargetsSelectedResource = { ...workbasketDistributionTargets };
|
this.distributionTargetsSelectedResource = { ...workbasketDistributionTargets };
|
||||||
|
|
@ -129,10 +115,21 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.ngxsActions$.pipe(ofActionCompleted(UpdateWorkbasketAccessItems), takeUntil(this.destroy$)).subscribe(() => {
|
// saving workbasket distributions targets when existing workbasket was modified
|
||||||
|
this.ngxsActions$.pipe(ofActionCompleted(UpdateWorkbasket), takeUntil(this.destroy$)).subscribe(() => {
|
||||||
this.onSave();
|
this.onSave();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// saving workbasket distributions targets when workbasket was copied or created
|
||||||
|
this.ngxsActions$.pipe(ofActionCompleted(SaveNewWorkbasket), takeUntil(this.destroy$)).subscribe(() => {
|
||||||
|
this.selectedWorkbasket$.pipe(take(1)).subscribe((workbasket) => {
|
||||||
|
this.distributionTargetsSelectedResource._links = {
|
||||||
|
self: { href: workbasket._links.distributionTargets.href }
|
||||||
|
};
|
||||||
|
this.onSave();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
this.buttonAction$
|
this.buttonAction$
|
||||||
.pipe(takeUntil(this.destroy$))
|
.pipe(takeUntil(this.destroy$))
|
||||||
.pipe(filter((buttonAction) => typeof buttonAction !== 'undefined'))
|
.pipe(filter((buttonAction) => typeof buttonAction !== 'undefined'))
|
||||||
|
|
@ -261,11 +258,11 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
||||||
this.distributionTargetsLeft = side === Side.SELECTED ? workbaskets : this.distributionTargetsLeft;
|
this.distributionTargetsLeft = side === Side.SELECTED ? workbaskets : this.distributionTargetsLeft;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSelectedItems(originList: any): Array<any> {
|
getSelectedItems(originList: any): any[] {
|
||||||
return originList.filter((item: any) => item.selected === true);
|
return originList.filter((item: any) => item.selected === true);
|
||||||
}
|
}
|
||||||
|
|
||||||
unselectItems(originList: Array<any>): Array<any> {
|
unselectItems(originList: any[]): any[] {
|
||||||
return originList
|
return originList
|
||||||
.filter((item) => item.selected)
|
.filter((item) => item.selected)
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
|
|
@ -283,7 +280,7 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
||||||
return copyList;
|
return copyList;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSelectedIds(): Array<string> {
|
getSelectedIds(): string[] {
|
||||||
return this.distributionTargetsSelected.map((distributionTarget) => distributionTarget.workbasketId);
|
return this.distributionTargetsSelected.map((distributionTarget) => distributionTarget.workbasketId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import { MapValuesPipe } from '../../../shared/pipes/map-values.pipe';
|
||||||
import { RemoveNoneTypePipe } from '../../../shared/pipes/remove-empty-type.pipe';
|
import { RemoveNoneTypePipe } from '../../../shared/pipes/remove-empty-type.pipe';
|
||||||
import { WorkbasketService } from '../../../shared/services/workbasket/workbasket.service';
|
import { WorkbasketService } from '../../../shared/services/workbasket/workbasket.service';
|
||||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||||
import { SavingWorkbasketService } from '../../services/saving-workbaskets.service';
|
|
||||||
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
|
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
|
||||||
import { FormsValidatorService } from '../../../shared/services/forms-validator/forms-validator.service';
|
import { FormsValidatorService } from '../../../shared/services/forms-validator/forms-validator.service';
|
||||||
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
||||||
|
|
@ -127,7 +126,6 @@ describe('WorkbasketInformationComponent', () => {
|
||||||
{ provide: WorkbasketService, useClass: workbasketServiceMock },
|
{ provide: WorkbasketService, useClass: workbasketServiceMock },
|
||||||
{ provide: FormsValidatorService, useClass: formValidatorServiceSpy },
|
{ provide: FormsValidatorService, useClass: formValidatorServiceSpy },
|
||||||
{ provide: NotificationService, useClass: notificationServiceSpy },
|
{ provide: NotificationService, useClass: notificationServiceSpy },
|
||||||
SavingWorkbasketService,
|
|
||||||
RequestInProgressService,
|
RequestInProgressService,
|
||||||
DomainService,
|
DomainService,
|
||||||
SelectedRouteService,
|
SelectedRouteService,
|
||||||
|
|
@ -168,18 +166,6 @@ describe('WorkbasketInformationComponent', () => {
|
||||||
expect(component.workbasketClone).toMatchObject(component.workbasket);
|
expect(component.workbasketClone).toMatchObject(component.workbasket);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display create badge message when action is CREATE', () => {
|
|
||||||
component.action = ACTION.CREATE;
|
|
||||||
component.ngOnChanges();
|
|
||||||
expect(component.badgeMessage).toMatch('Creating new workbasket');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display copy badge message when action is COPY', () => {
|
|
||||||
component.action = ACTION.COPY;
|
|
||||||
component.ngOnChanges();
|
|
||||||
expect(component.badgeMessage).toContain(`Copying workbasket: ${component.workbasket.key}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should submit when validatorService is true', () => {
|
it('should submit when validatorService is true', () => {
|
||||||
const formsValidatorService = TestBed.inject(FormsValidatorService);
|
const formsValidatorService = TestBed.inject(FormsValidatorService);
|
||||||
component.onSubmit();
|
component.onSubmit();
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import { Select, Store } from '@ngxs/store';
|
||||||
import { ACTION } from 'app/shared/models/action';
|
import { ACTION } from 'app/shared/models/action';
|
||||||
import { customFieldCount, Workbasket } from 'app/shared/models/workbasket';
|
import { customFieldCount, Workbasket } from 'app/shared/models/workbasket';
|
||||||
import { TaskanaDate } from 'app/shared/util/taskana.date';
|
import { TaskanaDate } from 'app/shared/util/taskana.date';
|
||||||
import { SavingInformation, SavingWorkbasketService } from 'app/administration/services/saving-workbaskets.service';
|
|
||||||
import { WorkbasketService } from 'app/shared/services/workbasket/workbasket.service';
|
import { WorkbasketService } from 'app/shared/services/workbasket/workbasket.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 { FormsValidatorService } from 'app/shared/services/forms-validator/forms-validator.service';
|
import { FormsValidatorService } from 'app/shared/services/forms-validator/forms-validator.service';
|
||||||
|
|
@ -15,7 +14,6 @@ import { NOTIFICATION_TYPES } from '../../../shared/models/notifications';
|
||||||
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
||||||
import { CustomField, getCustomFields, WorkbasketsCustomisation } from '../../../shared/models/customisation';
|
import { CustomField, getCustomFields, WorkbasketsCustomisation } from '../../../shared/models/customisation';
|
||||||
import {
|
import {
|
||||||
CopyWorkbasket,
|
|
||||||
MarkWorkbasketForDeletion,
|
MarkWorkbasketForDeletion,
|
||||||
RemoveDistributionTarget,
|
RemoveDistributionTarget,
|
||||||
SaveNewWorkbasket,
|
SaveNewWorkbasket,
|
||||||
|
|
@ -43,7 +41,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
|
||||||
|
|
||||||
workbasketClone: Workbasket;
|
workbasketClone: Workbasket;
|
||||||
allTypes: Map<string, string>;
|
allTypes: Map<string, string>;
|
||||||
badgeMessage = '';
|
|
||||||
toggleValidationMap = new Map<string, boolean>();
|
toggleValidationMap = new Map<string, boolean>();
|
||||||
lookupField = false;
|
lookupField = false;
|
||||||
|
|
||||||
|
|
@ -65,7 +62,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private workbasketService: WorkbasketService,
|
private workbasketService: WorkbasketService,
|
||||||
private savingWorkbasket: SavingWorkbasketService,
|
|
||||||
private requestInProgressService: RequestInProgressService,
|
private requestInProgressService: RequestInProgressService,
|
||||||
private formsValidatorService: FormsValidatorService,
|
private formsValidatorService: FormsValidatorService,
|
||||||
private notificationService: NotificationService,
|
private notificationService: NotificationService,
|
||||||
|
|
@ -109,9 +105,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
|
||||||
case ButtonAction.UNDO:
|
case ButtonAction.UNDO:
|
||||||
this.onUndo();
|
this.onUndo();
|
||||||
break;
|
break;
|
||||||
case ButtonAction.COPY:
|
|
||||||
this.copyWorkbasket();
|
|
||||||
break;
|
|
||||||
case ButtonAction.REMOVE_AS_DISTRIBUTION_TARGETS:
|
case ButtonAction.REMOVE_AS_DISTRIBUTION_TARGETS:
|
||||||
this.removeDistributionTargets();
|
this.removeDistributionTargets();
|
||||||
break;
|
break;
|
||||||
|
|
@ -126,11 +119,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
|
||||||
|
|
||||||
ngOnChanges(changes?: SimpleChanges) {
|
ngOnChanges(changes?: SimpleChanges) {
|
||||||
this.workbasketClone = { ...this.workbasket };
|
this.workbasketClone = { ...this.workbasket };
|
||||||
if (this.action === ACTION.CREATE) {
|
|
||||||
this.badgeMessage = 'Creating new workbasket';
|
|
||||||
} else if (this.action === ACTION.COPY) {
|
|
||||||
this.badgeMessage = `Copying workbasket: ${this.workbasket.key}`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
|
|
@ -159,10 +147,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
copyWorkbasket() {
|
|
||||||
this.store.dispatch(new CopyWorkbasket(this.workbasket));
|
|
||||||
}
|
|
||||||
|
|
||||||
removeDistributionTargets() {
|
removeDistributionTargets() {
|
||||||
this.store.dispatch(new RemoveDistributionTarget(this.workbasket._links.removeDistributionTargets.href));
|
this.store.dispatch(new RemoveDistributionTarget(this.workbasket._links.removeDistributionTargets.href));
|
||||||
}
|
}
|
||||||
|
|
@ -171,13 +155,13 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
|
||||||
this.beforeRequest();
|
this.beforeRequest();
|
||||||
if (!this.workbasket.workbasketId) {
|
if (!this.workbasket.workbasketId) {
|
||||||
this.postNewWorkbasket();
|
this.postNewWorkbasket();
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
this.store.dispatch(new UpdateWorkbasket(this.workbasket._links.self.href, this.workbasket)).subscribe(() => {
|
this.store.dispatch(new UpdateWorkbasket(this.workbasket._links.self.href, this.workbasket)).subscribe(() => {
|
||||||
this.requestInProgressService.setRequestInProgress(false);
|
this.requestInProgressService.setRequestInProgress(false);
|
||||||
this.workbasketClone = { ...this.workbasket };
|
this.workbasketClone = { ...this.workbasket };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
beforeRequest() {
|
beforeRequest() {
|
||||||
this.requestInProgressService.setRequestInProgress(true);
|
this.requestInProgressService.setRequestInProgress(true);
|
||||||
|
|
@ -192,14 +176,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
|
||||||
this.addDateToWorkbasket();
|
this.addDateToWorkbasket();
|
||||||
this.store.dispatch(new SaveNewWorkbasket(this.workbasket)).subscribe(() => {
|
this.store.dispatch(new SaveNewWorkbasket(this.workbasket)).subscribe(() => {
|
||||||
this.afterRequest();
|
this.afterRequest();
|
||||||
if (this.action === ACTION.COPY) {
|
|
||||||
this.savingWorkbasket.triggerDistributionTargetSaving(
|
|
||||||
new SavingInformation(this.workbasket._links.distributionTargets.href, this.workbasket.workbasketId)
|
|
||||||
);
|
|
||||||
this.savingWorkbasket.triggerAccessItemsSaving(
|
|
||||||
new SavingInformation(this.workbasket._links.accessItems.href, this.workbasket.workbasketId)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -139,10 +139,15 @@ export class WorkbasketListComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
selectWorkbasket(id: string) {
|
selectWorkbasket(id: string) {
|
||||||
|
this.requestInProgressService.setRequestInProgress(true);
|
||||||
if (this.selectedId === id) {
|
if (this.selectedId === id) {
|
||||||
this.store.dispatch(new DeselectWorkbasket());
|
this.store
|
||||||
|
.dispatch(new DeselectWorkbasket())
|
||||||
|
.subscribe(() => this.requestInProgressService.setRequestInProgress(false));
|
||||||
} else {
|
} else {
|
||||||
this.store.dispatch(new SelectWorkbasket(id));
|
this.store
|
||||||
|
.dispatch(new SelectWorkbasket(id))
|
||||||
|
.subscribe(() => this.requestInProgressService.setRequestInProgress(false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { WorkbasketOverviewComponent } from './workbasket-overview.component';
|
import { WorkbasketOverviewComponent } from './workbasket-overview.component';
|
||||||
import { Component, DebugElement, Input } from '@angular/core';
|
import { Component, DebugElement, Input } from '@angular/core';
|
||||||
import { Actions, NgxsModule, ofActionDispatched, Store } from '@ngxs/store';
|
import { Actions, NgxsModule, ofActionCompleted, ofActionDispatched, Store } from '@ngxs/store';
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { WorkbasketState } from '../../../shared/store/workbasket-store/workbasket.state';
|
import { WorkbasketState } from '../../../shared/store/workbasket-store/workbasket.state';
|
||||||
import { WorkbasketService } from '../../../shared/services/workbasket/workbasket.service';
|
import { WorkbasketService } from '../../../shared/services/workbasket/workbasket.service';
|
||||||
|
|
@ -18,6 +18,7 @@ import { TaskanaEngineService } from '../../../shared/services/taskana-engine/ta
|
||||||
import { WindowRefService } from '../../../shared/services/window/window.service';
|
import { WindowRefService } from '../../../shared/services/window/window.service';
|
||||||
import { workbasketReadStateMock } from '../../../shared/store/mock-data/mock-store';
|
import { workbasketReadStateMock } from '../../../shared/store/mock-data/mock-store';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { take } from 'rxjs/operators';
|
||||||
|
|
||||||
const showDialogFn = jest.fn().mockReturnValue(true);
|
const showDialogFn = jest.fn().mockReturnValue(true);
|
||||||
const NotificationServiceSpy = jest.fn().mockImplementation(
|
const NotificationServiceSpy = jest.fn().mockImplementation(
|
||||||
|
|
@ -27,6 +28,14 @@ const NotificationServiceSpy = jest.fn().mockImplementation(
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const domainServiceSpy = jest.fn().mockImplementation(
|
||||||
|
(): Partial<DomainService> => ({
|
||||||
|
getSelectedDomainValue: jest.fn().mockReturnValue(of()),
|
||||||
|
getSelectedDomain: jest.fn().mockReturnValue(of('A')),
|
||||||
|
getDomains: jest.fn().mockReturnValue(of())
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const mockActivatedRoute = {
|
const mockActivatedRoute = {
|
||||||
firstChild: {
|
firstChild: {
|
||||||
params: of({
|
params: of({
|
||||||
|
|
@ -79,6 +88,7 @@ describe('WorkbasketOverviewComponent', () => {
|
||||||
WorkbasketService,
|
WorkbasketService,
|
||||||
{ provide: NotificationService, useClass: NotificationServiceSpy },
|
{ provide: NotificationService, useClass: NotificationServiceSpy },
|
||||||
{ provide: ActivatedRoute, useValue: mockActivatedRoute },
|
{ provide: ActivatedRoute, useValue: mockActivatedRoute },
|
||||||
|
{ provide: DomainService, useValue: domainServiceSpy },
|
||||||
DomainService,
|
DomainService,
|
||||||
RequestInProgressService,
|
RequestInProgressService,
|
||||||
SelectedRouteService,
|
SelectedRouteService,
|
||||||
|
|
@ -114,14 +124,14 @@ describe('WorkbasketOverviewComponent', () => {
|
||||||
expect(debugElement.nativeElement.querySelector('taskana-administration-workbasket-details')).toBeTruthy();
|
expect(debugElement.nativeElement.querySelector('taskana-administration-workbasket-details')).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display details when params id exists', async(() => {
|
it('should display details when params id exists', async((done) => {
|
||||||
let actionDispatched = false;
|
actions$.pipe(ofActionCompleted(CreateWorkbasket), take(1)).subscribe(() => {
|
||||||
actions$.pipe(ofActionDispatched(CreateWorkbasket)).subscribe(() => (actionDispatched = true));
|
|
||||||
component.ngOnInit();
|
|
||||||
expect(actionDispatched).toBe(true);
|
|
||||||
expect(component.routerParams.id).toMatch('new-workbasket');
|
expect(component.routerParams.id).toMatch('new-workbasket');
|
||||||
expect(component.showDetail).toBeTruthy();
|
expect(component.showDetail).toBeTruthy();
|
||||||
expect(debugElement.nativeElement.querySelector('taskana-administration-workbasket-details')).toBeTruthy();
|
expect(debugElement.nativeElement.querySelector('taskana-administration-workbasket-details')).toBeTruthy();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
component.ngOnInit();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { Subject, Observable } from 'rxjs';
|
|
||||||
|
|
||||||
export class SavingInformation {
|
|
||||||
constructor(public url: string, public workbasketId: string) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class SavingWorkbasketService {
|
|
||||||
public distributionTargetsSavingInformation = new Subject<SavingInformation>();
|
|
||||||
public accessItemsSavingInformation = new Subject<SavingInformation>();
|
|
||||||
|
|
||||||
triggerDistributionTargetSaving(distributionTargetInformation: SavingInformation) {
|
|
||||||
this.distributionTargetsSavingInformation.next(distributionTargetInformation);
|
|
||||||
}
|
|
||||||
|
|
||||||
triggerAccessItemsSaving(accessItemsInformation: SavingInformation) {
|
|
||||||
this.accessItemsSavingInformation.next(accessItemsInformation);
|
|
||||||
}
|
|
||||||
|
|
||||||
triggeredDistributionTargetsSaving(): Observable<SavingInformation> {
|
|
||||||
return this.distributionTargetsSavingInformation.asObservable();
|
|
||||||
}
|
|
||||||
|
|
||||||
triggeredAccessItemsSaving(): Observable<SavingInformation> {
|
|
||||||
return this.accessItemsSavingInformation.asObservable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -39,6 +39,15 @@ export class WorkbasketSelectors {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Selector([WorkbasketState])
|
||||||
|
static selectedWorkbasketAndComponentAndAction(state: WorkbasketStateModel): WorkbasketAndComponentAndAction {
|
||||||
|
return {
|
||||||
|
selectedWorkbasket: state.selectedWorkbasket,
|
||||||
|
action: state.action,
|
||||||
|
selectedComponent: state.selectedComponent
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Selector([WorkbasketState])
|
@Selector([WorkbasketState])
|
||||||
static selectedComponent(state: WorkbasketStateModel): WorkbasketComponent {
|
static selectedComponent(state: WorkbasketStateModel): WorkbasketComponent {
|
||||||
return state.selectedComponent;
|
return state.selectedComponent;
|
||||||
|
|
@ -65,9 +74,20 @@ export class WorkbasketSelectors {
|
||||||
static availableDistributionTargets(state: WorkbasketStateModel): WorkbasketSummary[] {
|
static availableDistributionTargets(state: WorkbasketStateModel): WorkbasketSummary[] {
|
||||||
return state.workbasketAvailableDistributionTargets;
|
return state.workbasketAvailableDistributionTargets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Selector([WorkbasketState])
|
||||||
|
static badgeMessage(state: WorkbasketStateModel): string {
|
||||||
|
return state.badgeMessage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WorkbasketAndAction {
|
export interface WorkbasketAndAction {
|
||||||
selectedWorkbasket: Workbasket;
|
selectedWorkbasket: Workbasket;
|
||||||
action: ACTION;
|
action: ACTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface WorkbasketAndComponentAndAction {
|
||||||
|
selectedWorkbasket: Workbasket;
|
||||||
|
action: ACTION;
|
||||||
|
selectedComponent: WorkbasketComponent;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Action, NgxsAfterBootstrap, State, StateContext } from '@ngxs/store';
|
import { Action, NgxsAfterBootstrap, State, StateContext } from '@ngxs/store';
|
||||||
import { take, tap } from 'rxjs/operators';
|
import { concatMap, take, tap } from 'rxjs/operators';
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { WorkbasketService } from '../../services/workbasket/workbasket.service';
|
import { WorkbasketService } from '../../services/workbasket/workbasket.service';
|
||||||
|
|
@ -34,6 +34,9 @@ import { WorkbasketComponent } from '../../../administration/models/workbasket-c
|
||||||
import { ButtonAction } from '../../../administration/models/button-action';
|
import { ButtonAction } from '../../../administration/models/button-action';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { RequestInProgressService } from '../../services/request-in-progress/request-in-progress.service';
|
import { RequestInProgressService } from '../../services/request-in-progress/request-in-progress.service';
|
||||||
|
import { WorkbasketType } from '../../models/workbasket-type';
|
||||||
|
import { TaskanaDate } from '../../util/taskana.date';
|
||||||
|
import { DomainService } from '../../services/domain/domain.service';
|
||||||
|
|
||||||
class InitializeStore {
|
class InitializeStore {
|
||||||
static readonly type = '[Workbasket] Initializing state';
|
static readonly type = '[Workbasket] Initializing state';
|
||||||
|
|
@ -45,6 +48,7 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
||||||
private workbasketService: WorkbasketService,
|
private workbasketService: WorkbasketService,
|
||||||
private location: Location,
|
private location: Location,
|
||||||
private notificationService: NotificationService,
|
private notificationService: NotificationService,
|
||||||
|
private domainService: DomainService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private requestInProgressService: RequestInProgressService
|
private requestInProgressService: RequestInProgressService
|
||||||
) {}
|
) {}
|
||||||
|
|
@ -70,6 +74,10 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
||||||
tab = WorkbasketComponent.INFORMATION;
|
tab = WorkbasketComponent.INFORMATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.patchState({
|
||||||
|
badgeMessage: ''
|
||||||
|
});
|
||||||
|
|
||||||
ctx.dispatch(new SelectComponent(tab));
|
ctx.dispatch(new SelectComponent(tab));
|
||||||
});
|
});
|
||||||
return of();
|
return of();
|
||||||
|
|
@ -105,12 +113,6 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.location.go(
|
|
||||||
this.location
|
|
||||||
.path()
|
|
||||||
.replace(/(workbaskets).*/g, `workbaskets/(detail:${action.workbasketId})?tab=${selectedComponent}`)
|
|
||||||
);
|
|
||||||
|
|
||||||
const id = action.workbasketId;
|
const id = action.workbasketId;
|
||||||
if (typeof id !== 'undefined') {
|
if (typeof id !== 'undefined') {
|
||||||
return this.workbasketService.getWorkBasket(id).pipe(
|
return this.workbasketService.getWorkBasket(id).pipe(
|
||||||
|
|
@ -118,12 +120,20 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
||||||
tap((selectedWorkbasket) => {
|
tap((selectedWorkbasket) => {
|
||||||
ctx.patchState({
|
ctx.patchState({
|
||||||
selectedWorkbasket,
|
selectedWorkbasket,
|
||||||
action: ACTION.READ
|
action: ACTION.READ,
|
||||||
|
badgeMessage: ``
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.dispatch(new GetWorkbasketAccessItems(ctx.getState().selectedWorkbasket._links.accessItems.href));
|
ctx.dispatch(new GetWorkbasketAccessItems(ctx.getState().selectedWorkbasket._links.accessItems.href));
|
||||||
ctx.dispatch(
|
ctx.dispatch(
|
||||||
new GetWorkbasketDistributionTargets(ctx.getState().selectedWorkbasket._links.distributionTargets.href)
|
new GetWorkbasketDistributionTargets(ctx.getState().selectedWorkbasket._links.distributionTargets.href)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.location.go(
|
||||||
|
this.location
|
||||||
|
.path()
|
||||||
|
.replace(/(workbaskets).*/g, `workbaskets/(detail:${action.workbasketId})?tab=${selectedComponent}`)
|
||||||
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -140,17 +150,6 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
||||||
return of(null);
|
return of(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Action(CreateWorkbasket)
|
|
||||||
createWorkbasket(ctx: StateContext<WorkbasketStateModel>): Observable<any> {
|
|
||||||
this.location.go(this.location.path().replace(/(workbaskets).*/g, 'workbaskets/(detail:new-workbasket)'));
|
|
||||||
ctx.patchState({
|
|
||||||
selectedWorkbasket: undefined,
|
|
||||||
selectedComponent: WorkbasketComponent.INFORMATION,
|
|
||||||
action: ACTION.CREATE
|
|
||||||
});
|
|
||||||
return of(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Action(SetActiveAction)
|
@Action(SetActiveAction)
|
||||||
setActiveAction(ctx: StateContext<WorkbasketStateModel>, action: SetActiveAction): Observable<any> {
|
setActiveAction(ctx: StateContext<WorkbasketStateModel>, action: SetActiveAction): Observable<any> {
|
||||||
ctx.patchState({ action: action.action });
|
ctx.patchState({ action: action.action });
|
||||||
|
|
@ -197,13 +196,13 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
||||||
new Map<string, string>([['workbasketKey', workbasketUpdated.key]])
|
new Map<string, string>([['workbasketKey', workbasketUpdated.key]])
|
||||||
);
|
);
|
||||||
|
|
||||||
ctx.dispatch(new SelectWorkbasket(workbasketUpdated.workbasketId));
|
|
||||||
this.location.go(this.location.path().replace(/(workbaskets).*/g, 'workbaskets'));
|
this.location.go(this.location.path().replace(/(workbaskets).*/g, 'workbaskets'));
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
this.notificationService.triggerError(NOTIFICATION_TYPES.CREATE_ERR_2, error);
|
this.notificationService.triggerError(NOTIFICATION_TYPES.CREATE_ERR_2, error);
|
||||||
}
|
}
|
||||||
)
|
),
|
||||||
|
concatMap((workbasketUpdated) => ctx.dispatch(new SelectWorkbasket(workbasketUpdated.workbasketId)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -211,12 +210,55 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
||||||
copyWorkbasket(ctx: StateContext<WorkbasketStateModel>, action: CopyWorkbasket): Observable<any> {
|
copyWorkbasket(ctx: StateContext<WorkbasketStateModel>, action: CopyWorkbasket): Observable<any> {
|
||||||
this.location.go(this.location.path().replace(/(workbaskets).*/g, 'workbaskets/(detail:new-workbasket)'));
|
this.location.go(this.location.path().replace(/(workbaskets).*/g, 'workbaskets/(detail:new-workbasket)'));
|
||||||
ctx.dispatch(new OnButtonPressed(undefined));
|
ctx.dispatch(new OnButtonPressed(undefined));
|
||||||
|
|
||||||
|
const workbasket = { ...ctx.getState().selectedWorkbasket };
|
||||||
|
delete workbasket.workbasketId;
|
||||||
|
|
||||||
ctx.patchState({
|
ctx.patchState({
|
||||||
action: ACTION.COPY
|
action: ACTION.COPY,
|
||||||
|
selectedWorkbasket: workbasket,
|
||||||
|
badgeMessage: `Copying workbasket: ${workbasket.key}`
|
||||||
});
|
});
|
||||||
|
|
||||||
return of(null);
|
return of(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Action(CreateWorkbasket)
|
||||||
|
createWorkbasket(ctx: StateContext<WorkbasketStateModel>): Observable<any> {
|
||||||
|
return this.domainService.getSelectedDomain().pipe(
|
||||||
|
take(1),
|
||||||
|
tap((domain) => {
|
||||||
|
this.location.go(this.location.path().replace(/(workbaskets).*/g, 'workbaskets/(detail:new-workbasket)'));
|
||||||
|
|
||||||
|
if (!ctx.getState().workbasketAvailableDistributionTargets) {
|
||||||
|
ctx.dispatch(new GetAvailableDistributionTargets());
|
||||||
|
}
|
||||||
|
|
||||||
|
const emptyWorkbasket: Workbasket = {};
|
||||||
|
emptyWorkbasket.domain = domain;
|
||||||
|
emptyWorkbasket.type = WorkbasketType.PERSONAL;
|
||||||
|
|
||||||
|
const date = TaskanaDate.getDate();
|
||||||
|
emptyWorkbasket.created = date;
|
||||||
|
emptyWorkbasket.modified = date;
|
||||||
|
|
||||||
|
const accessItems = { accessItems: [], _links: {} };
|
||||||
|
const distributionTargets = { distributionTargets: [], _links: {} };
|
||||||
|
|
||||||
|
ctx.patchState({
|
||||||
|
action: ACTION.CREATE,
|
||||||
|
selectedWorkbasket: emptyWorkbasket,
|
||||||
|
selectedComponent: WorkbasketComponent.INFORMATION,
|
||||||
|
badgeMessage: `Creating new workbasket`,
|
||||||
|
workbasketAccessItems: accessItems,
|
||||||
|
workbasketDistributionTargets: distributionTargets
|
||||||
|
});
|
||||||
|
|
||||||
|
return of(null);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Action(UpdateWorkbasket)
|
@Action(UpdateWorkbasket)
|
||||||
updateWorkbasket(ctx: StateContext<WorkbasketStateModel>, action: UpdateWorkbasket): Observable<any> {
|
updateWorkbasket(ctx: StateContext<WorkbasketStateModel>, action: UpdateWorkbasket): Observable<any> {
|
||||||
ctx.dispatch(new OnButtonPressed(undefined));
|
ctx.dispatch(new OnButtonPressed(undefined));
|
||||||
|
|
@ -286,6 +328,8 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
||||||
NOTIFICATION_TYPES.SUCCESS_ALERT_12,
|
NOTIFICATION_TYPES.SUCCESS_ALERT_12,
|
||||||
new Map<string, string>([['workbasketId', ctx.getState().selectedWorkbasket.workbasketId]])
|
new Map<string, string>([['workbasketId', ctx.getState().selectedWorkbasket.workbasketId]])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ctx.dispatch(new DeselectWorkbasket());
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
@ -322,6 +366,7 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
||||||
NOTIFICATION_TYPES.SUCCESS_ALERT_7,
|
NOTIFICATION_TYPES.SUCCESS_ALERT_7,
|
||||||
new Map<string, string>([['workbasketKey', ctx.getState().selectedWorkbasket.key]])
|
new Map<string, string>([['workbasketKey', ctx.getState().selectedWorkbasket.key]])
|
||||||
);
|
);
|
||||||
|
return of(null);
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
this.notificationService.triggerError(NOTIFICATION_TYPES.SAVE_ERR_2, error);
|
this.notificationService.triggerError(NOTIFICATION_TYPES.SAVE_ERR_2, error);
|
||||||
|
|
@ -385,6 +430,8 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
||||||
NOTIFICATION_TYPES.SUCCESS_ALERT_8,
|
NOTIFICATION_TYPES.SUCCESS_ALERT_8,
|
||||||
new Map<string, string>([['workbasketName', ctx.getState().selectedWorkbasket.name]])
|
new Map<string, string>([['workbasketName', ctx.getState().selectedWorkbasket.name]])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return of(null);
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
this.notificationService.triggerError(NOTIFICATION_TYPES.SAVE_ERR_3, error);
|
this.notificationService.triggerError(NOTIFICATION_TYPES.SAVE_ERR_3, error);
|
||||||
|
|
@ -420,5 +467,6 @@ export interface WorkbasketStateModel {
|
||||||
workbasketDistributionTargets: WorkbasketDistributionTargets;
|
workbasketDistributionTargets: WorkbasketDistributionTargets;
|
||||||
workbasketAvailableDistributionTargets: WorkbasketSummary[];
|
workbasketAvailableDistributionTargets: WorkbasketSummary[];
|
||||||
selectedComponent: WorkbasketComponent;
|
selectedComponent: WorkbasketComponent;
|
||||||
|
badgeMessage: string;
|
||||||
button: ButtonAction | undefined;
|
button: ButtonAction | undefined;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue