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
|
||||
*/
|
||||
import { SavingWorkbasketService } from './services/saving-workbaskets.service';
|
||||
import { ClassificationDefinitionService } from './services/classification-definition.service';
|
||||
import { WorkbasketDefinitionService } from './services/workbasket-definition.service';
|
||||
import { ImportExportService } from './services/import-export.service';
|
||||
|
@ -113,7 +112,6 @@ const DECLARATIONS = [
|
|||
providers: [
|
||||
ClassificationDefinitionService,
|
||||
WorkbasketDefinitionService,
|
||||
SavingWorkbasketService,
|
||||
ClassificationCategoriesService,
|
||||
ImportExportService
|
||||
],
|
||||
|
|
|
@ -6,7 +6,6 @@ import { Observable, of } from 'rxjs';
|
|||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { TypeAheadComponent } from '../../../shared/components/type-ahead/type-ahead.component';
|
||||
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 { FormsValidatorService } from '../../../shared/services/forms-validator/forms-validator.service';
|
||||
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
||||
|
@ -31,8 +30,6 @@ import {
|
|||
UpdateWorkbasketAccessItems
|
||||
} from '../../../shared/store/workbasket-store/workbasket.actions';
|
||||
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 { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
|
@ -47,12 +44,6 @@ class SpinnerStub {
|
|||
@Input() positionClass: string;
|
||||
}
|
||||
|
||||
const savingWorkbasketServiceSpy = jest.fn().mockImplementation(
|
||||
(): Partial<SavingWorkbasketService> => ({
|
||||
triggeredAccessItemsSaving: jest.fn().mockReturnValue(of(true))
|
||||
})
|
||||
);
|
||||
|
||||
const requestInProgressServiceSpy = jest.fn().mockImplementation(
|
||||
(): Partial<RequestInProgressService> => ({
|
||||
setRequestInProgress: jest.fn()
|
||||
|
@ -106,7 +97,6 @@ describe('WorkbasketAccessItemsComponent', () => {
|
|||
],
|
||||
declarations: [WorkbasketAccessItemsComponent, TypeAheadComponent, SpinnerStub],
|
||||
providers: [
|
||||
{ provide: SavingWorkbasketService, useClass: savingWorkbasketServiceSpy },
|
||||
{ provide: RequestInProgressService, useClass: requestInProgressServiceSpy },
|
||||
{ provide: FormsValidatorService, useClass: formValidatorServiceSpy },
|
||||
{ provide: NotificationService, useClass: notificationServiceSpy },
|
||||
|
@ -145,14 +135,11 @@ describe('WorkbasketAccessItemsComponent', () => {
|
|||
});
|
||||
|
||||
it('should initialize when accessItems exist', async(() => {
|
||||
component.action = ACTION.COPY;
|
||||
let actionDispatched = false;
|
||||
component.onSave = jest.fn().mockImplementation();
|
||||
actions$.pipe(ofActionDispatched(GetWorkbasketAccessItems)).subscribe(() => (actionDispatched = true));
|
||||
component.init();
|
||||
expect(component.initialized).toBe(true);
|
||||
expect(actionDispatched).toBe(true);
|
||||
expect(component.onSave).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it("should discard initializing when accessItems don't exist", () => {
|
||||
|
@ -197,14 +184,4 @@ describe('WorkbasketAccessItemsComponent', () => {
|
|||
expect(onSaveSpy).toHaveBeenCalled();
|
||||
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 { customFieldCount, WorkbasketAccessItems } from 'app/shared/models/workbasket-access-items';
|
||||
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 { highlight } from 'app/shared/animations/validation.animation';
|
||||
import { FormsValidatorService } from 'app/shared/services/forms-validator/forms-validator.service';
|
||||
import { AccessIdDefinition } from 'app/shared/models/access-id';
|
||||
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 { NotificationService } from '../../../shared/services/notifications/notification.service';
|
||||
import { AccessItemsCustomisation, CustomField, getCustomFields } from '../../../shared/models/customisation';
|
||||
import {
|
||||
GetWorkbasketAccessItems,
|
||||
OnButtonPressed,
|
||||
UpdateWorkbasketAccessItems,
|
||||
UpdateWorkbasket
|
||||
SaveNewWorkbasket,
|
||||
UpdateWorkbasket,
|
||||
UpdateWorkbasketAccessItems
|
||||
} from '../../../shared/store/workbasket-store/workbasket.actions';
|
||||
import { WorkbasketSelectors } from '../../../shared/store/workbasket-store/workbasket.selectors';
|
||||
import { WorkbasketComponent } from '../../models/workbasket-component';
|
||||
|
@ -48,16 +46,12 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
|||
@Input()
|
||||
workbasket: Workbasket;
|
||||
|
||||
@Input()
|
||||
action: ACTION;
|
||||
|
||||
@Input()
|
||||
expanded: boolean;
|
||||
|
||||
@ViewChildren('htmlInputElement')
|
||||
inputs: QueryList<ElementRef>;
|
||||
|
||||
badgeMessage = '';
|
||||
selectedRows: number[] = [];
|
||||
workbasketClone: Workbasket;
|
||||
|
||||
|
@ -65,8 +59,8 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
|||
customFields: CustomField[];
|
||||
|
||||
accessItemsRepresentation: WorkbasketAccessItemsRepresentation;
|
||||
accessItemsClone: Array<WorkbasketAccessItems>;
|
||||
accessItemsResetClone: Array<WorkbasketAccessItems>;
|
||||
accessItemsClone: WorkbasketAccessItems[];
|
||||
accessItemsResetClone: WorkbasketAccessItems[];
|
||||
AccessItemsForm = this.formBuilder.group({
|
||||
accessItemsGroups: this.formBuilder.array([])
|
||||
});
|
||||
|
@ -76,6 +70,9 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
|||
added = false;
|
||||
destroy$ = new Subject<void>();
|
||||
|
||||
@Select(WorkbasketSelectors.selectedWorkbasket)
|
||||
selectedWorkbasket$: Observable<Workbasket>;
|
||||
|
||||
@Select(EngineConfigurationSelectors.accessItemsCustomisation)
|
||||
accessItemsCustomization$: Observable<AccessItemsCustomisation>;
|
||||
|
||||
|
@ -89,7 +86,6 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
|||
selectedComponent$: Observable<WorkbasketComponent>;
|
||||
|
||||
constructor(
|
||||
private savingWorkbaskets: SavingWorkbasketService,
|
||||
private requestInProgressService: RequestInProgressService,
|
||||
private formBuilder: FormBuilder,
|
||||
public formsValidatorService: FormsValidatorService,
|
||||
|
@ -110,17 +106,27 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
|||
});
|
||||
this.accessItemsRepresentation$.subscribe((accessItemsRepresentation) => {
|
||||
if (typeof accessItemsRepresentation !== 'undefined') {
|
||||
this.accessItemsRepresentation = accessItemsRepresentation;
|
||||
this.accessItemsRepresentation = { ...accessItemsRepresentation };
|
||||
this.setAccessItemsGroups(accessItemsRepresentation.accessItems);
|
||||
this.accessItemsClone = 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.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$
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.pipe(filter((buttonAction) => typeof buttonAction !== 'undefined'))
|
||||
|
@ -168,9 +174,6 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
|||
}
|
||||
|
||||
ngOnChanges(changes?: SimpleChanges) {
|
||||
if (changes.action) {
|
||||
this.setBadge();
|
||||
}
|
||||
if (this.workbasketClone) {
|
||||
if (this.workbasketClone.workbasketId != this.workbasket.workbasketId) {
|
||||
this.init();
|
||||
|
@ -189,16 +192,6 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -291,7 +284,7 @@ export class WorkbasketAccessItemsComponent implements OnInit, OnChanges, OnDest
|
|||
|
||||
accessItemSelected(accessItem: AccessIdDefinition, row: number) {
|
||||
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() {
|
||||
|
@ -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> {
|
||||
return this.AccessItemsForm.value.accessItemsGroups.map((accessItems: WorkbasketAccessItems) => ({
|
||||
...accessItems
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<mat-toolbar class="workbasket-details__toolbar">
|
||||
<h4 class="workbasket-details__title">
|
||||
<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>
|
||||
<span class="workbasket-details__spacer"></span>
|
||||
<button mat-button class="workbasket-details__button workbasket-details__save-button"
|
||||
|
@ -52,11 +52,11 @@
|
|||
</taskana-administration-workbasket-information>
|
||||
</mat-tab>
|
||||
<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>
|
||||
</mat-tab>
|
||||
<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>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
|
|
|
@ -2,7 +2,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|||
import { WorkbasketDetailsComponent } from './workbasket-details.component';
|
||||
import { Component, DebugElement, Input } from '@angular/core';
|
||||
import { Actions, NgxsModule, Store } from '@ngxs/store';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { Workbasket } from '../../../shared/models/workbasket';
|
||||
import { ACTION } from '../../../shared/models/action';
|
||||
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 { MatToolbarModule } from '@angular/material/toolbar';
|
||||
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';
|
||||
|
||||
@Component({ selector: 'taskana-administration-workbasket-information', template: '<div>i</div>' })
|
||||
|
@ -49,6 +49,14 @@ class WorkbasketDistributionTargetsStub {
|
|||
@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 = {
|
||||
selectedWorkbasket: selectedWorkbasketMock,
|
||||
action: ACTION.COPY
|
||||
|
@ -92,7 +100,7 @@ describe('WorkbasketDetailsComponent', () => {
|
|||
WorkbasketInformationStub
|
||||
],
|
||||
providers: [
|
||||
DomainService,
|
||||
{ provide: DomainService, useClass: domainServiceSpy },
|
||||
ImportExportService,
|
||||
WorkbasketService,
|
||||
RequestInProgressService,
|
||||
|
@ -126,23 +134,32 @@ describe('WorkbasketDetailsComponent', () => {
|
|||
expect(information).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render new workbasket when action is CREATE', () => {
|
||||
store.reset({
|
||||
...store.snapshot(),
|
||||
workbasket: workbasketCreateState
|
||||
});
|
||||
fixture.detectChanges();
|
||||
expect(component.selectedId).toBeUndefined();
|
||||
it('should render new workbasket when action is CREATE', async (done) => {
|
||||
store
|
||||
.dispatch(new CreateWorkbasket())
|
||||
.pipe(take(1))
|
||||
.subscribe(() => {
|
||||
component.selectedWorkbasketAndComponentAndAction$.pipe(take(1)).subscribe((state) => {
|
||||
expect(state.selectedWorkbasket.workbasketId).toBeUndefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should render copied workbasket when action is COPY', () => {
|
||||
store.reset({
|
||||
...store.snapshot(),
|
||||
workbasket: workbasketCopyState
|
||||
});
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
expect(component.workbasketCopy).toEqual(component.workbasket);
|
||||
it('should render copied workbasket when action is COPY', (done) => {
|
||||
const workbasket = component.workbasket;
|
||||
store
|
||||
.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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should render workbasket when action is READ', () => {
|
||||
|
@ -158,11 +175,14 @@ describe('WorkbasketDetailsComponent', () => {
|
|||
|
||||
it('should select information tab when action is CREATE', (done) => {
|
||||
component.selectComponent(1);
|
||||
store.dispatch(new CreateWorkbasket());
|
||||
fixture.detectChanges();
|
||||
component.selectedTab$.pipe(take(1)).subscribe((tab) => {
|
||||
expect(tab).toEqual(0);
|
||||
done();
|
||||
});
|
||||
store
|
||||
.dispatch(new CreateWorkbasket())
|
||||
.pipe(take(1))
|
||||
.subscribe(() => {
|
||||
component.selectedTab$.pipe(take(1)).subscribe((tab) => {
|
||||
expect(tab).toEqual(0);
|
||||
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 { Observable, Subject } from 'rxjs';
|
||||
import { Workbasket } from 'app/shared/models/workbasket';
|
||||
import { ACTION } from 'app/shared/models/action';
|
||||
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 { 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 {
|
||||
WorkbasketAndComponentAndAction,
|
||||
WorkbasketSelectors
|
||||
} from '../../../shared/store/workbasket-store/workbasket.selectors';
|
||||
import { Location } from '@angular/common';
|
||||
import {
|
||||
CopyWorkbasket,
|
||||
DeselectWorkbasket,
|
||||
OnButtonPressed,
|
||||
SelectComponent
|
||||
} from '../../../shared/store/workbasket-store/workbasket.actions';
|
||||
import { ButtonAction } from '../../models/button-action';
|
||||
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
|
||||
import { WorkbasketComponent } from '../../models/workbasket-component';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-administration-workbasket-details',
|
||||
templateUrl: './workbasket-details.component.html',
|
||||
styleUrls: ['./workbasket-details.component.scss']
|
||||
})
|
||||
export class WorkbasketDetailsComponent implements OnInit, OnDestroy, OnChanges {
|
||||
export class WorkbasketDetailsComponent implements OnInit, OnDestroy {
|
||||
workbasket: Workbasket;
|
||||
workbasketCopy: Workbasket;
|
||||
selectedId: string;
|
||||
action: ACTION;
|
||||
badgeMessage = '';
|
||||
|
||||
@Select(WorkbasketSelectors.selectedWorkbasket)
|
||||
selectedWorkbasket$: Observable<Workbasket>;
|
||||
selectedComponent: WorkbasketComponent;
|
||||
|
||||
@Select(WorkbasketSelectors.selectedComponent)
|
||||
selectedTab$: Observable<number>;
|
||||
|
||||
@Select(WorkbasketSelectors.workbasketActiveAction)
|
||||
activeAction$: Observable<ACTION>;
|
||||
@Select(WorkbasketSelectors.badgeMessage)
|
||||
badgeMessage$: Observable<string>;
|
||||
|
||||
@Select(WorkbasketSelectors.selectedWorkbasketAndAction)
|
||||
selectedWorkbasketAndAction$: Observable<WorkbasketAndAction>;
|
||||
@Select(WorkbasketSelectors.selectedWorkbasketAndComponentAndAction)
|
||||
selectedWorkbasketAndComponentAndAction$: Observable<WorkbasketAndComponentAndAction>;
|
||||
|
||||
destroy$ = new Subject<void>();
|
||||
|
||||
|
@ -52,97 +49,38 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy, OnChanges
|
|||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private domainService: DomainService,
|
||||
private importExportService: ImportExportService,
|
||||
private requestInProgressService: RequestInProgressService,
|
||||
private store: Store
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.selectedWorkbasketAndAction$.pipe(takeUntil(this.destroy$)).subscribe((selectedWorkbasketAndAction) => {
|
||||
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.getWorkbasketFromStore();
|
||||
}
|
||||
|
||||
getWorkbasketFromStore() {
|
||||
// this is necessary since we receive workbaskets from store even when there is no update
|
||||
// this would unintentionally discard changes
|
||||
|
||||
this.selectedWorkbasketAndComponentAndAction$.pipe(takeUntil(this.destroy$)).subscribe((object) => {
|
||||
const workbasket = object.selectedWorkbasket;
|
||||
const action = object.action;
|
||||
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 };
|
||||
}
|
||||
|
||||
this.action = action;
|
||||
this.selectedComponent = component;
|
||||
});
|
||||
|
||||
this.importExportService
|
||||
.getImportingFinished()
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe(() => {
|
||||
if (this.workbasket) {
|
||||
this.getWorkbasketInformation(this.workbasket);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnChanges(changes?: SimpleChanges) {}
|
||||
|
||||
addDateToWorkbasket(workbasket: Workbasket) {
|
||||
const date = TaskanaDate.getDate();
|
||||
workbasket.created = date;
|
||||
workbasket.modified = date;
|
||||
}
|
||||
|
||||
initWorkbasket() {
|
||||
const emptyWorkbasket: Workbasket = {};
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
selectComponent(index) {
|
||||
|
@ -159,6 +97,7 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy, OnChanges
|
|||
|
||||
onCopy() {
|
||||
this.store.dispatch(new OnButtonPressed(ButtonAction.COPY));
|
||||
this.store.dispatch(new CopyWorkbasket(this.workbasket));
|
||||
}
|
||||
|
||||
onRemoveAsDistributionTarget() {
|
||||
|
|
|
@ -7,7 +7,6 @@ import { MatToolbarModule } from '@angular/material/toolbar';
|
|||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { WorkbasketService } from '../../../shared/services/workbasket/workbasket.service';
|
||||
import { SavingWorkbasketService } from '../../services/saving-workbaskets.service';
|
||||
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
||||
import { Actions, NgxsModule, Store } from '@ngxs/store';
|
||||
import { WorkbasketState } from '../../../shared/store/workbasket-store/workbasket.state';
|
||||
|
@ -21,6 +20,7 @@ import {
|
|||
} from '../../../shared/store/mock-data/mock-store';
|
||||
import { WorkbasketQueryFilterParameter } from '../../../shared/models/workbasket-query-filter-parameter';
|
||||
import { Pair } from '../../../shared/models/pair';
|
||||
import { DomainService } from '../../../shared/services/domain/domain.service';
|
||||
|
||||
const routeParamsMock = { id: 'workbasket' };
|
||||
const activatedRouteMock = {
|
||||
|
@ -42,6 +42,14 @@ class WorkbasketDistributionTargetsListStub {
|
|||
@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(
|
||||
(): Partial<WorkbasketService> => ({
|
||||
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(
|
||||
(): Partial<NotificationService> => ({
|
||||
showToast: jest.fn().mockReturnValue(true)
|
||||
|
@ -84,10 +87,10 @@ describe('WorkbasketDistributionTargetsComponent', () => {
|
|||
declarations: [WorkbasketDistributionTargetsComponent, WorkbasketDistributionTargetsListStub],
|
||||
providers: [
|
||||
{ provide: WorkbasketService, useClass: workbasketServiceSpy },
|
||||
{ provide: SavingWorkbasketService, useClass: savingWorkbasketServiceSpy },
|
||||
{ provide: NotificationService, useClass: notificationsServiceSpy },
|
||||
{ provide: ActivatedRoute, useValue: activatedRouteMock },
|
||||
{ provide: RequestInProgressService, useClass: requestInProgressServiceSpy }
|
||||
{ provide: RequestInProgressService, useClass: requestInProgressServiceSpy },
|
||||
{ provide: DomainService, useClass: domainServiceSpy }
|
||||
]
|
||||
}).compileComponents();
|
||||
|
||||
|
|
|
@ -5,19 +5,18 @@ import { Workbasket } from 'app/shared/models/workbasket';
|
|||
import { WorkbasketSummary } from 'app/shared/models/workbasket-summary';
|
||||
import { WorkbasketSummaryRepresentation } from 'app/shared/models/workbasket-summary-representation';
|
||||
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 { SavingWorkbasketService, SavingInformation } from 'app/administration/services/saving-workbaskets.service';
|
||||
import { Page } from 'app/shared/models/page';
|
||||
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 { NotificationService } from '../../../shared/services/notifications/notification.service';
|
||||
import {
|
||||
GetAvailableDistributionTargets,
|
||||
GetWorkbasketDistributionTargets,
|
||||
UpdateWorkbasketDistributionTargets,
|
||||
UpdateWorkbasketAccessItems
|
||||
SaveNewWorkbasket,
|
||||
UpdateWorkbasket,
|
||||
UpdateWorkbasketDistributionTargets
|
||||
} from '../../../shared/store/workbasket-store/workbasket.actions';
|
||||
import { WorkbasketSelectors } from '../../../shared/store/workbasket-store/workbasket.selectors';
|
||||
import { ButtonAction } from '../../models/button-action';
|
||||
|
@ -38,20 +37,17 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
@Input()
|
||||
workbasket: Workbasket;
|
||||
|
||||
@Input()
|
||||
action: ACTION;
|
||||
|
||||
toolbarState = false;
|
||||
sideBySide = true;
|
||||
displayingDistributionTargetsPicker = true;
|
||||
|
||||
distributionTargetsSelectedResource: WorkbasketDistributionTargets;
|
||||
availableDistributionTargets: Array<WorkbasketSummary> = [];
|
||||
distributionTargetsClone: Array<WorkbasketSummary>;
|
||||
availableDistributionTargets: WorkbasketSummary[] = [];
|
||||
distributionTargetsClone: WorkbasketSummary[];
|
||||
|
||||
distributionTargetsLeft: Array<WorkbasketSummary> = [];
|
||||
distributionTargetsSelected: Array<WorkbasketSummary>;
|
||||
distributionTargetsSelectedClone: Array<WorkbasketSummary>;
|
||||
distributionTargetsLeft: WorkbasketSummary[] = [];
|
||||
distributionTargetsSelected: WorkbasketSummary[];
|
||||
distributionTargetsSelectedClone: WorkbasketSummary[];
|
||||
|
||||
loadingItems = false;
|
||||
side = Side;
|
||||
|
@ -81,7 +77,6 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
|
||||
constructor(
|
||||
private workbasketService: WorkbasketService,
|
||||
private savingWorkbaskets: SavingWorkbasketService,
|
||||
private notificationsService: NotificationService,
|
||||
private store: Store,
|
||||
private ngxsActions$: Actions
|
||||
|
@ -97,7 +92,8 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
.subscribe((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 GetAvailableDistributionTargets());
|
||||
}
|
||||
|
@ -109,16 +105,6 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
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) => {
|
||||
if (typeof workbasketDistributionTargets !== 'undefined') {
|
||||
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();
|
||||
});
|
||||
|
||||
// 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$
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.pipe(filter((buttonAction) => typeof buttonAction !== 'undefined'))
|
||||
|
@ -261,11 +258,11 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
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);
|
||||
}
|
||||
|
||||
unselectItems(originList: Array<any>): Array<any> {
|
||||
unselectItems(originList: any[]): any[] {
|
||||
return originList
|
||||
.filter((item) => item.selected)
|
||||
.map((item) => {
|
||||
|
@ -283,7 +280,7 @@ export class WorkbasketDistributionTargetsComponent implements OnInit, OnDestroy
|
|||
return copyList;
|
||||
}
|
||||
|
||||
getSelectedIds(): Array<string> {
|
||||
getSelectedIds(): string[] {
|
||||
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 { WorkbasketService } from '../../../shared/services/workbasket/workbasket.service';
|
||||
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 { FormsValidatorService } from '../../../shared/services/forms-validator/forms-validator.service';
|
||||
import { NotificationService } from '../../../shared/services/notifications/notification.service';
|
||||
|
@ -127,7 +126,6 @@ describe('WorkbasketInformationComponent', () => {
|
|||
{ provide: WorkbasketService, useClass: workbasketServiceMock },
|
||||
{ provide: FormsValidatorService, useClass: formValidatorServiceSpy },
|
||||
{ provide: NotificationService, useClass: notificationServiceSpy },
|
||||
SavingWorkbasketService,
|
||||
RequestInProgressService,
|
||||
DomainService,
|
||||
SelectedRouteService,
|
||||
|
@ -168,18 +166,6 @@ describe('WorkbasketInformationComponent', () => {
|
|||
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', () => {
|
||||
const formsValidatorService = TestBed.inject(FormsValidatorService);
|
||||
component.onSubmit();
|
||||
|
|
|
@ -5,7 +5,6 @@ import { Select, Store } from '@ngxs/store';
|
|||
import { ACTION } from 'app/shared/models/action';
|
||||
import { customFieldCount, Workbasket } from 'app/shared/models/workbasket';
|
||||
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 { RequestInProgressService } from 'app/shared/services/request-in-progress/request-in-progress.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 { CustomField, getCustomFields, WorkbasketsCustomisation } from '../../../shared/models/customisation';
|
||||
import {
|
||||
CopyWorkbasket,
|
||||
MarkWorkbasketForDeletion,
|
||||
RemoveDistributionTarget,
|
||||
SaveNewWorkbasket,
|
||||
|
@ -43,7 +41,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
|
|||
|
||||
workbasketClone: Workbasket;
|
||||
allTypes: Map<string, string>;
|
||||
badgeMessage = '';
|
||||
toggleValidationMap = new Map<string, boolean>();
|
||||
lookupField = false;
|
||||
|
||||
|
@ -65,7 +62,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
|
|||
|
||||
constructor(
|
||||
private workbasketService: WorkbasketService,
|
||||
private savingWorkbasket: SavingWorkbasketService,
|
||||
private requestInProgressService: RequestInProgressService,
|
||||
private formsValidatorService: FormsValidatorService,
|
||||
private notificationService: NotificationService,
|
||||
|
@ -109,9 +105,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
|
|||
case ButtonAction.UNDO:
|
||||
this.onUndo();
|
||||
break;
|
||||
case ButtonAction.COPY:
|
||||
this.copyWorkbasket();
|
||||
break;
|
||||
case ButtonAction.REMOVE_AS_DISTRIBUTION_TARGETS:
|
||||
this.removeDistributionTargets();
|
||||
break;
|
||||
|
@ -126,11 +119,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
|
|||
|
||||
ngOnChanges(changes?: SimpleChanges) {
|
||||
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() {
|
||||
|
@ -159,10 +147,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
|
|||
);
|
||||
}
|
||||
|
||||
copyWorkbasket() {
|
||||
this.store.dispatch(new CopyWorkbasket(this.workbasket));
|
||||
}
|
||||
|
||||
removeDistributionTargets() {
|
||||
this.store.dispatch(new RemoveDistributionTarget(this.workbasket._links.removeDistributionTargets.href));
|
||||
}
|
||||
|
@ -171,12 +155,12 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
|
|||
this.beforeRequest();
|
||||
if (!this.workbasket.workbasketId) {
|
||||
this.postNewWorkbasket();
|
||||
return;
|
||||
} else {
|
||||
this.store.dispatch(new UpdateWorkbasket(this.workbasket._links.self.href, this.workbasket)).subscribe(() => {
|
||||
this.requestInProgressService.setRequestInProgress(false);
|
||||
this.workbasketClone = { ...this.workbasket };
|
||||
});
|
||||
}
|
||||
this.store.dispatch(new UpdateWorkbasket(this.workbasket._links.self.href, this.workbasket)).subscribe(() => {
|
||||
this.requestInProgressService.setRequestInProgress(false);
|
||||
this.workbasketClone = { ...this.workbasket };
|
||||
});
|
||||
}
|
||||
|
||||
beforeRequest() {
|
||||
|
@ -192,14 +176,6 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
|
|||
this.addDateToWorkbasket();
|
||||
this.store.dispatch(new SaveNewWorkbasket(this.workbasket)).subscribe(() => {
|
||||
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) {
|
||||
this.requestInProgressService.setRequestInProgress(true);
|
||||
if (this.selectedId === id) {
|
||||
this.store.dispatch(new DeselectWorkbasket());
|
||||
this.store
|
||||
.dispatch(new DeselectWorkbasket())
|
||||
.subscribe(() => this.requestInProgressService.setRequestInProgress(false));
|
||||
} 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 { WorkbasketOverviewComponent } from './workbasket-overview.component';
|
||||
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 { WorkbasketState } from '../../../shared/store/workbasket-store/workbasket.state';
|
||||
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 { workbasketReadStateMock } from '../../../shared/store/mock-data/mock-store';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
const showDialogFn = jest.fn().mockReturnValue(true);
|
||||
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 = {
|
||||
firstChild: {
|
||||
params: of({
|
||||
|
@ -79,6 +88,7 @@ describe('WorkbasketOverviewComponent', () => {
|
|||
WorkbasketService,
|
||||
{ provide: NotificationService, useClass: NotificationServiceSpy },
|
||||
{ provide: ActivatedRoute, useValue: mockActivatedRoute },
|
||||
{ provide: DomainService, useValue: domainServiceSpy },
|
||||
DomainService,
|
||||
RequestInProgressService,
|
||||
SelectedRouteService,
|
||||
|
@ -114,14 +124,14 @@ describe('WorkbasketOverviewComponent', () => {
|
|||
expect(debugElement.nativeElement.querySelector('taskana-administration-workbasket-details')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should display details when params id exists', async(() => {
|
||||
let actionDispatched = false;
|
||||
actions$.pipe(ofActionDispatched(CreateWorkbasket)).subscribe(() => (actionDispatched = true));
|
||||
it('should display details when params id exists', async((done) => {
|
||||
actions$.pipe(ofActionCompleted(CreateWorkbasket), take(1)).subscribe(() => {
|
||||
expect(component.routerParams.id).toMatch('new-workbasket');
|
||||
expect(component.showDetail).toBeTruthy();
|
||||
expect(debugElement.nativeElement.querySelector('taskana-administration-workbasket-details')).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
component.ngOnInit();
|
||||
expect(actionDispatched).toBe(true);
|
||||
expect(component.routerParams.id).toMatch('new-workbasket');
|
||||
expect(component.showDetail).toBeTruthy();
|
||||
expect(debugElement.nativeElement.querySelector('taskana-administration-workbasket-details')).toBeTruthy();
|
||||
}));
|
||||
});
|
||||
|
||||
|
|
|
@ -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])
|
||||
static selectedComponent(state: WorkbasketStateModel): WorkbasketComponent {
|
||||
return state.selectedComponent;
|
||||
|
@ -65,9 +74,20 @@ export class WorkbasketSelectors {
|
|||
static availableDistributionTargets(state: WorkbasketStateModel): WorkbasketSummary[] {
|
||||
return state.workbasketAvailableDistributionTargets;
|
||||
}
|
||||
|
||||
@Selector([WorkbasketState])
|
||||
static badgeMessage(state: WorkbasketStateModel): string {
|
||||
return state.badgeMessage;
|
||||
}
|
||||
}
|
||||
|
||||
export interface WorkbasketAndAction {
|
||||
selectedWorkbasket: Workbasket;
|
||||
action: ACTION;
|
||||
}
|
||||
|
||||
export interface WorkbasketAndComponentAndAction {
|
||||
selectedWorkbasket: Workbasket;
|
||||
action: ACTION;
|
||||
selectedComponent: WorkbasketComponent;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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 { Location } from '@angular/common';
|
||||
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 { ActivatedRoute } from '@angular/router';
|
||||
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 {
|
||||
static readonly type = '[Workbasket] Initializing state';
|
||||
|
@ -45,6 +48,7 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
|||
private workbasketService: WorkbasketService,
|
||||
private location: Location,
|
||||
private notificationService: NotificationService,
|
||||
private domainService: DomainService,
|
||||
private route: ActivatedRoute,
|
||||
private requestInProgressService: RequestInProgressService
|
||||
) {}
|
||||
|
@ -70,6 +74,10 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
|||
tab = WorkbasketComponent.INFORMATION;
|
||||
}
|
||||
|
||||
ctx.patchState({
|
||||
badgeMessage: ''
|
||||
});
|
||||
|
||||
ctx.dispatch(new SelectComponent(tab));
|
||||
});
|
||||
return of();
|
||||
|
@ -105,12 +113,6 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
|||
break;
|
||||
}
|
||||
|
||||
this.location.go(
|
||||
this.location
|
||||
.path()
|
||||
.replace(/(workbaskets).*/g, `workbaskets/(detail:${action.workbasketId})?tab=${selectedComponent}`)
|
||||
);
|
||||
|
||||
const id = action.workbasketId;
|
||||
if (typeof id !== 'undefined') {
|
||||
return this.workbasketService.getWorkBasket(id).pipe(
|
||||
|
@ -118,12 +120,20 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
|||
tap((selectedWorkbasket) => {
|
||||
ctx.patchState({
|
||||
selectedWorkbasket,
|
||||
action: ACTION.READ
|
||||
action: ACTION.READ,
|
||||
badgeMessage: ``
|
||||
});
|
||||
|
||||
ctx.dispatch(new GetWorkbasketAccessItems(ctx.getState().selectedWorkbasket._links.accessItems.href));
|
||||
ctx.dispatch(
|
||||
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);
|
||||
}
|
||||
|
||||
@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)
|
||||
setActiveAction(ctx: StateContext<WorkbasketStateModel>, action: SetActiveAction): Observable<any> {
|
||||
ctx.patchState({ action: action.action });
|
||||
|
@ -197,13 +196,13 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
|||
new Map<string, string>([['workbasketKey', workbasketUpdated.key]])
|
||||
);
|
||||
|
||||
ctx.dispatch(new SelectWorkbasket(workbasketUpdated.workbasketId));
|
||||
this.location.go(this.location.path().replace(/(workbaskets).*/g, 'workbaskets'));
|
||||
},
|
||||
(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> {
|
||||
this.location.go(this.location.path().replace(/(workbaskets).*/g, 'workbaskets/(detail:new-workbasket)'));
|
||||
ctx.dispatch(new OnButtonPressed(undefined));
|
||||
|
||||
const workbasket = { ...ctx.getState().selectedWorkbasket };
|
||||
delete workbasket.workbasketId;
|
||||
|
||||
ctx.patchState({
|
||||
action: ACTION.COPY
|
||||
action: ACTION.COPY,
|
||||
selectedWorkbasket: workbasket,
|
||||
badgeMessage: `Copying workbasket: ${workbasket.key}`
|
||||
});
|
||||
|
||||
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)
|
||||
updateWorkbasket(ctx: StateContext<WorkbasketStateModel>, action: UpdateWorkbasket): Observable<any> {
|
||||
ctx.dispatch(new OnButtonPressed(undefined));
|
||||
|
@ -286,6 +328,8 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
|||
NOTIFICATION_TYPES.SUCCESS_ALERT_12,
|
||||
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,
|
||||
new Map<string, string>([['workbasketKey', ctx.getState().selectedWorkbasket.key]])
|
||||
);
|
||||
return of(null);
|
||||
},
|
||||
(error) => {
|
||||
this.notificationService.triggerError(NOTIFICATION_TYPES.SAVE_ERR_2, error);
|
||||
|
@ -385,6 +430,8 @@ export class WorkbasketState implements NgxsAfterBootstrap {
|
|||
NOTIFICATION_TYPES.SUCCESS_ALERT_8,
|
||||
new Map<string, string>([['workbasketName', ctx.getState().selectedWorkbasket.name]])
|
||||
);
|
||||
|
||||
return of(null);
|
||||
},
|
||||
(error) => {
|
||||
this.notificationService.triggerError(NOTIFICATION_TYPES.SAVE_ERR_3, error);
|
||||
|
@ -420,5 +467,6 @@ export interface WorkbasketStateModel {
|
|||
workbasketDistributionTargets: WorkbasketDistributionTargets;
|
||||
workbasketAvailableDistributionTargets: WorkbasketSummary[];
|
||||
selectedComponent: WorkbasketComponent;
|
||||
badgeMessage: string;
|
||||
button: ButtonAction | undefined;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue