From f778a743ac4c5c17f73737ff0fc18bd06082c80b Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 29 Aug 2019 15:28:26 -0700 Subject: [PATCH] SHIBUI-1385 Implemented version restore editing --- .../configuration/action/restore.action.ts | 17 +++++ .../component/editor.component.html | 2 +- .../component/editor.component.ts | 5 +- .../metadata-header.component.spec.ts | 2 - .../container/configuration.component.spec.ts | 8 --- .../restore-edit-step.component.html | 3 + .../container/restore-edit-step.component.ts | 70 +++++++++++-------- .../container/restore-edit.component.html | 17 +---- .../container/restore-edit.component.ts | 18 +++-- .../container/restore.component.spec.ts | 11 +-- .../configuration/effect/restore.effect.ts | 22 +++++- .../reducer/configuration.reducer.spec.ts | 4 +- .../metadata/configuration/reducer/index.ts | 29 ++++++-- .../reducer/restore.reducer.spec.ts | 34 +++++++++ .../configuration/reducer/restore.reducer.ts | 14 ++++ .../service/history.service.spec.ts | 17 ----- .../configuration/service/history.service.ts | 2 +- .../wizard-summary.component.spec.ts | 5 +- .../component/wizard-summary.component.ts | 19 ++--- .../container/provider-edit-step.component.ts | 4 +- .../provider/model/base.provider.form.ts | 4 +- ui/src/app/metadata/provider/reducer/index.ts | 10 +++ .../container/resolver-wizard.component.ts | 6 +- ui/src/app/metadata/resolver/reducer/index.ts | 15 ++++ ui/src/app/wizard/model/form-definition.ts | 2 +- ui/src/app/wizard/reducer/wizard.reducer.ts | 1 - 26 files changed, 230 insertions(+), 111 deletions(-) create mode 100644 ui/src/app/metadata/configuration/reducer/restore.reducer.spec.ts diff --git a/ui/src/app/metadata/configuration/action/restore.action.ts b/ui/src/app/metadata/configuration/action/restore.action.ts index 04a15fca7..0407e830b 100644 --- a/ui/src/app/metadata/configuration/action/restore.action.ts +++ b/ui/src/app/metadata/configuration/action/restore.action.ts @@ -10,6 +10,9 @@ export enum RestoreActionTypes { UPDATE_RESTORATION_REQUEST = '[Restore Version] Update Changes Request', UPDATE_RESTORATION_SUCCESS = '[Restore Version] Update Changes Success', + UPDATE_STATUS = '[Restore Version] Update Restore Form Status', + SET_SAVING_STATUS = '[Restore Version] Set Saving Status', + CLEAR_VERSION = '[Restore Version] Clear Versions', CANCEL_RESTORE = '[Restore Version] Cancel Restore' } @@ -39,6 +42,18 @@ export class UpdateRestorationChangesSuccess implements Action { constructor(public payload: any) { } } +export class UpdateRestoreFormStatus implements Action { + readonly type = RestoreActionTypes.UPDATE_STATUS; + + constructor(public payload: { [key: string]: string }) { } +} + +export class SetSavingStatus implements Action { + readonly type = RestoreActionTypes.SET_SAVING_STATUS; + + constructor(public payload: boolean) { } +} + export class CancelRestore implements Action { readonly type = RestoreActionTypes.CANCEL_RESTORE; constructor() { } @@ -50,4 +65,6 @@ export type RestoreActionsUnion = | RestoreVersionError | UpdateRestorationChangesRequest | UpdateRestorationChangesSuccess + | UpdateRestoreFormStatus + | SetSavingStatus | CancelRestore; diff --git a/ui/src/app/metadata/configuration/component/editor.component.html b/ui/src/app/metadata/configuration/component/editor.component.html index 53414fcf6..fd71771aa 100644 --- a/ui/src/app/metadata/configuration/component/editor.component.html +++ b/ui/src/app/metadata/configuration/component/editor.component.html @@ -11,4 +11,4 @@ [validators]="validators" [bindings]="bindings" (onChange)="change.emit($event.value)" - (onError)="status.emit($event)"> \ No newline at end of file + (onErrorChange)="status.emit($event)"> \ No newline at end of file diff --git a/ui/src/app/metadata/configuration/component/editor.component.ts b/ui/src/app/metadata/configuration/component/editor.component.ts index 8e0ab78dd..59f3ef375 100644 --- a/ui/src/app/metadata/configuration/component/editor.component.ts +++ b/ui/src/app/metadata/configuration/component/editor.component.ts @@ -18,9 +18,12 @@ export class MetadataEditorComponent { @Output() change: EventEmitter = new EventEmitter(); @Output() status: EventEmitter = new EventEmitter(); + @Output() onLockChange: EventEmitter = new EventEmitter(); lock: FormControl = new FormControl(true); - constructor() {} + constructor() { + this.lock.valueChanges.subscribe(locked => this.onLockChange.emit(locked)); + } } diff --git a/ui/src/app/metadata/configuration/component/metadata-header.component.spec.ts b/ui/src/app/metadata/configuration/component/metadata-header.component.spec.ts index e8db42c36..f3cfd0d45 100644 --- a/ui/src/app/metadata/configuration/component/metadata-header.component.spec.ts +++ b/ui/src/app/metadata/configuration/component/metadata-header.component.spec.ts @@ -9,7 +9,6 @@ import { MetadataHeaderComponent } from './metadata-header.component'; ` @@ -25,7 +24,6 @@ class TestHostComponent { creator: 'foobar', date: new Date().toDateString() }; - versionNumber = 1; isCurrent = false; } diff --git a/ui/src/app/metadata/configuration/container/configuration.component.spec.ts b/ui/src/app/metadata/configuration/container/configuration.component.spec.ts index 0d2fca0d3..71bb05ab0 100644 --- a/ui/src/app/metadata/configuration/container/configuration.component.spec.ts +++ b/ui/src/app/metadata/configuration/container/configuration.component.spec.ts @@ -59,12 +59,4 @@ describe('Metadata Configuration Page Component', () => { it('should load metadata objects', async(() => { expect(app).toBeTruthy(); })); - - describe('hasVersion function', () => { - it('should determine if a version is defined', () => { - expect(app.hasVersion([[{id: 'foo'}], { version: 'foo' }])).toBe('foo'); - expect(app.hasVersion([[{ id: 'foo' }], {}])).toBe('foo'); - expect(app.hasVersion([[], {}])).toBeNull(); - }); - }); }); diff --git a/ui/src/app/metadata/configuration/container/restore-edit-step.component.html b/ui/src/app/metadata/configuration/container/restore-edit-step.component.html index 496aa29f0..be953b86b 100644 --- a/ui/src/app/metadata/configuration/container/restore-edit-step.component.html +++ b/ui/src/app/metadata/configuration/container/restore-edit-step.component.html @@ -2,5 +2,8 @@ [schema]="schema$ | async" [model]="model$ | async" [validators]="validators$ | async" + [lockable]="lockable$ | async" (change)="onChange($event)" + (status)="statusChange$.next($event)" + (onLockChange)="lockChange$.next($event)" > \ No newline at end of file diff --git a/ui/src/app/metadata/configuration/container/restore-edit-step.component.ts b/ui/src/app/metadata/configuration/container/restore-edit-step.component.ts index 2e066a3d2..3d93f5ebd 100644 --- a/ui/src/app/metadata/configuration/container/restore-edit-step.component.ts +++ b/ui/src/app/metadata/configuration/container/restore-edit-step.component.ts @@ -1,18 +1,18 @@ -import { Component } from '@angular/core'; -import { Observable, combineLatest, of } from 'rxjs'; +import { Component, OnDestroy } from '@angular/core'; +import { Observable, combineLatest, of, Subject } from 'rxjs'; import { ActivatedRoute } from '@angular/router'; import { Store } from '@ngrx/store'; import { - ConfigurationState, - getFormattedModel, - getRestorationChanges + ConfigurationState, getFormattedModel } from '../reducer'; -import { getWizardDefinition, getSchema, getValidators } from '../../../wizard/reducer'; -import { Wizard } from '../../../wizard/model'; +import { getWizardDefinition, getSchema, getValidators, getCurrent, getWizardIndex } from '../../../wizard/reducer'; +import { Wizard, WizardStep } from '../../../wizard/model'; import { Metadata } from '../../domain/domain.type'; -import { map, switchMap } from 'rxjs/operators'; +import { map, switchMap, withLatestFrom } from 'rxjs/operators'; import { NAV_FORMATS } from '../../domain/component/editor-nav.component'; -import { UpdateRestorationChangesRequest } from '../action/restore.action'; +import { UpdateRestorationChangesRequest, UpdateRestoreFormStatus } from '../action/restore.action'; +import { LockEditor, UnlockEditor } from '../../../wizard/action/wizard.action'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'restore-edit-step', @@ -20,11 +20,19 @@ import { UpdateRestorationChangesRequest } from '../action/restore.action'; styleUrls: [] }) -export class RestoreEditStepComponent { +export class RestoreEditStepComponent implements OnDestroy { + + private ngUnsubscribe: Subject = new Subject(); + + readonly lockChange$: Subject = new Subject(); + readonly statusChange$: Subject = new Subject(); definition$: Observable> = this.store.select(getWizardDefinition); schema$: Observable = this.store.select(getSchema); model$: Observable = this.store.select(getFormattedModel); + step$: Observable = this.store.select(getCurrent); + + lockable$: Observable = this.step$.pipe(map(step => step.locked)); validators$: Observable; @@ -40,29 +48,31 @@ export class RestoreEditStepComponent { switchMap(selections => this.store.select(getValidators(selections))) ); - this.store.select(getRestorationChanges).subscribe(console.log); + this.step$ + .pipe(takeUntil(this.ngUnsubscribe)) + .subscribe(s => this.lockChange$.next(s && s.locked ? true : false)); + + this.lockChange$ + .pipe(takeUntil(this.ngUnsubscribe)) + .subscribe(locked => this.store.dispatch(locked ? new LockEditor() : new UnlockEditor())); + + this.statusChange$ + .pipe( + takeUntil(this.ngUnsubscribe), + withLatestFrom(this.store.select(getWizardIndex)) + ) + .subscribe(([errors, currentPage]) => { + const status = { [currentPage]: !(errors.value) ? 'VALID' : 'INVALID' }; + this.store.dispatch(new UpdateRestoreFormStatus(status)); + }); } onChange(changes: any): void { this.store.dispatch(new UpdateRestorationChangesRequest(changes)); } -} -/* -this.valueChangeEmitted$.pipe( - map(changes => changes.value), - withLatestFrom(this.definition$, this.store.select(fromProvider.getSelectedProvider)), - filter(([changes, definition, provider]) => definition && changes && provider), - map(([changes, definition, provider]) => { - const parsed = definition.parser(changes); - return ({ - ...parsed, - metadataFilters: [ - ...provider.metadataFilters, - ...(parsed.metadataFilters || []) - ] - }); - }) - ) - .subscribe(changes => this.store.dispatch(new UpdateProvider(changes))); -*/ + ngOnDestroy() { + this.ngUnsubscribe.next(); + this.ngUnsubscribe.complete(); + } +} diff --git a/ui/src/app/metadata/configuration/container/restore-edit.component.html b/ui/src/app/metadata/configuration/container/restore-edit.component.html index 6199dc016..7b1569f9a 100644 --- a/ui/src/app/metadata/configuration/container/restore-edit.component.html +++ b/ui/src/app/metadata/configuration/container/restore-edit.component.html @@ -4,14 +4,6 @@ - - -
@@ -46,15 +38,8 @@
diff --git a/ui/src/app/metadata/configuration/container/restore-edit.component.ts b/ui/src/app/metadata/configuration/container/restore-edit.component.ts index a50c0a52b..7bd939ee4 100644 --- a/ui/src/app/metadata/configuration/container/restore-edit.component.ts +++ b/ui/src/app/metadata/configuration/container/restore-edit.component.ts @@ -2,12 +2,17 @@ import { Component } from '@angular/core'; import { Observable, of } from 'rxjs'; import { Store } from '@ngrx/store'; import { - ConfigurationState, getConfigurationModelKind + ConfigurationState, + getConfigurationModelKind, + getRestorationIsSaving, + getRestorationIsValid, + getInvalidRestorationForms } from '../../configuration/reducer'; import { RestoreVersionRequest, CancelRestore } from '../action/restore.action'; import { NAV_FORMATS } from '../../domain/component/editor-nav.component'; import { Metadata } from '../../domain/domain.type'; import { getVersionModel } from '../reducer'; +import { map } from 'rxjs/operators'; @Component({ @@ -21,10 +26,9 @@ export class RestoreEditComponent { model$: Observable = this.store.select(getVersionModel); kind$: Observable = this.store.select(getConfigurationModelKind); - isInvalid$: Observable = of(false); - canFilter$: Observable = of(false); - status$: Observable = of('VALID'); - isSaving$: Observable = of(false); + isInvalid$: Observable = this.store.select(getRestorationIsValid).pipe(map(v => !v)); + status$: Observable = this.store.select(getInvalidRestorationForms); + isSaving$: Observable = this.store.select(getRestorationIsSaving); validators$: Observable; @@ -32,7 +36,9 @@ export class RestoreEditComponent { constructor( private store: Store - ) {} + ) { + // this.status$.subscribe(console.log); + } save() { this.store.dispatch(new RestoreVersionRequest()); diff --git a/ui/src/app/metadata/configuration/container/restore.component.spec.ts b/ui/src/app/metadata/configuration/container/restore.component.spec.ts index e79cbcac9..ef3b0f3fa 100644 --- a/ui/src/app/metadata/configuration/container/restore.component.spec.ts +++ b/ui/src/app/metadata/configuration/container/restore.component.spec.ts @@ -11,6 +11,7 @@ import { MockI18nModule } from '../../../../testing/i18n.stub'; import { RestoreComponent } from './restore.component'; import { of } from 'rxjs'; import { DatePipe } from '@angular/common'; +import { Router } from '@angular/router'; @Component({ template: ` @@ -28,6 +29,7 @@ describe('Metadata Restore Page Component', () => { let instance: TestHostComponent; let app: RestoreComponent; let store: Store; + let router: Router; beforeEach(async(() => { TestBed.configureTestingModule({ @@ -51,6 +53,7 @@ describe('Metadata Restore Page Component', () => { }).compileComponents(); store = TestBed.get(Store); + router = TestBed.get(Router); spyOn(store, 'dispatch'); spyOn(store, 'select').and.callFake(() => of(new Date().toDateString())); @@ -62,15 +65,15 @@ describe('Metadata Restore Page Component', () => { it('should load metadata objects', async(() => { expect(app).toBeTruthy(); - expect(store.select).toHaveBeenCalledTimes(4); + expect(store.select).toHaveBeenCalledTimes(1); expect(store.dispatch).not.toHaveBeenCalled(); })); describe('restore method', () => { - it('should emit a value from the restore subject', () => { - spyOn(app.subj, 'next').and.callThrough(); + it('should navigate to the restore edit page', () => { + spyOn(router, 'navigate').and.callThrough(); app.restore(); - expect(app.subj.next).toHaveBeenCalled(); + expect(router.navigate).toHaveBeenCalled(); }); }); }); diff --git a/ui/src/app/metadata/configuration/effect/restore.effect.ts b/ui/src/app/metadata/configuration/effect/restore.effect.ts index b34cfe997..7be47103e 100644 --- a/ui/src/app/metadata/configuration/effect/restore.effect.ts +++ b/ui/src/app/metadata/configuration/effect/restore.effect.ts @@ -9,7 +9,8 @@ import { RestoreVersionError, CancelRestore, UpdateRestorationChangesRequest, - UpdateRestorationChangesSuccess + UpdateRestorationChangesSuccess, + SetSavingStatus } from '../action/restore.action'; import { MetadataHistoryService } from '../service/history.service'; import { of } from 'rxjs'; @@ -28,6 +29,7 @@ import { } from '../reducer'; import { SetMetadata } from '../action/configuration.action'; import { removeNulls } from '../../../shared/util'; +import { getModel } from '../../../wizard/reducer'; @Injectable() @@ -53,6 +55,24 @@ export class RestoreEffects { ) ); + @Effect() + restoreVersionSaving$ = this.actions$.pipe( + ofType(RestoreActionTypes.RESTORE_VERSION_REQUEST), + map(() => new SetSavingStatus(true)) + ); + + @Effect() + restoreVersionSaved$ = this.actions$.pipe( + ofType(RestoreActionTypes.RESTORE_VERSION_SUCCESS), + map(() => new SetSavingStatus(false)) + ); + + @Effect() + restoreVersionError$ = this.actions$.pipe( + ofType(RestoreActionTypes.RESTORE_VERSION_ERROR), + map(() => new SetSavingStatus(false)) + ); + @Effect({ dispatch: false }) restoreVersionCancel$ = this.actions$.pipe( ofType(RestoreActionTypes.CANCEL_RESTORE), diff --git a/ui/src/app/metadata/configuration/reducer/configuration.reducer.spec.ts b/ui/src/app/metadata/configuration/reducer/configuration.reducer.spec.ts index a0dd05d58..714da74b4 100644 --- a/ui/src/app/metadata/configuration/reducer/configuration.reducer.spec.ts +++ b/ui/src/app/metadata/configuration/reducer/configuration.reducer.spec.ts @@ -27,7 +27,7 @@ describe('Configuration Reducer', () => { describe('SET_DEFINITION action', () => { it('should set the state definition', () => { - const action = new actions.SetDefinition(definition); + const action = new actions.SetConfigurationDefinition(definition); const result = reducer(initialState, action); expect(result).toEqual({ ...initialState, definition }); @@ -36,7 +36,7 @@ describe('Configuration Reducer', () => { describe('SET_SCHEMA action', () => { it('should set the state schema', () => { - const action = new actions.SetSchema(schema); + const action = new actions.SetConfigurationSchema(schema); const result = reducer(initialState, action); expect(result).toEqual({ ...initialState, schema }); diff --git a/ui/src/app/metadata/configuration/reducer/index.ts b/ui/src/app/metadata/configuration/reducer/index.ts index fe961cfc3..b64b6e070 100644 --- a/ui/src/app/metadata/configuration/reducer/index.ts +++ b/ui/src/app/metadata/configuration/reducer/index.ts @@ -9,7 +9,7 @@ import * as fromRestore from './restore.reducer'; import { WizardStep } from '../../../wizard/model'; import * as utils from '../../domain/utility/configuration'; -import { getSplitSchema } from '../../../wizard/reducer'; +import { getSplitSchema, getModel } from '../../../wizard/reducer'; import { getInCollectionFn } from '../../domain/domain.util'; import { MetadataConfiguration } from '../model/metadata-configuration'; import { Metadata } from '../../domain/domain.type'; @@ -192,13 +192,34 @@ export const getInvalidRestorationForms = createSelector(getRestoreState, fromRe export const getFormattedModel = createSelector( getVersionModel, getConfigurationDefinition, - (model, definition) => definition.formatter(model) + (model, definition) => definition ? definition.formatter(model) : null +); + +export const getFormattedChanges = createSelector( + getRestorationChanges, + getConfigurationDefinition, + (model, definition) => definition ? definition.formatter(model) : null +); + +export const getFormattedModelWithChanges = createSelector( + getVersionModel, + getRestorationChanges, + getConfigurationDefinition, + (model, changes, definition) => definition ? definition.formatter({ + ...model, + ...changes + }) : null ); export const getRestorationModel = createSelector( getVersionModel, getRestorationChanges, - (model, changes) => model + getModel, + (model, changes, empty) => ({ + ...model, + ...empty, + ...changes + }) ); // Mixed states @@ -229,4 +250,4 @@ export const getConfigurationModelType = createSelector(getConfigurationModel, g export const getConfigurationHasXml = createSelector(getConfigurationXml, xml => !!xml); export const getConfigurationFilters = createSelector(getConfigurationModel, model => model.metadataFilters); -export const getConfigurationVersionDate = createSelector(getRestoreModel, version => version && version.modifiedDate); +export const getConfigurationVersionDate = createSelector(getVersionModel, version => version && version.modifiedDate); diff --git a/ui/src/app/metadata/configuration/reducer/restore.reducer.spec.ts b/ui/src/app/metadata/configuration/reducer/restore.reducer.spec.ts new file mode 100644 index 000000000..9aa588b98 --- /dev/null +++ b/ui/src/app/metadata/configuration/reducer/restore.reducer.spec.ts @@ -0,0 +1,34 @@ +import { reducer } from './restore.reducer'; +import * as fromRestore from './restore.reducer'; +import * as actions from '../action/restore.action'; + +describe('Restore Reducer', () => { + + const baseState = fromRestore.initialState; + + describe('undefined action', () => { + it('should return the default state', () => { + const result = reducer(undefined, {} as any); + + expect(result).toEqual(fromRestore.initialState); + }); + }); + + describe('SET_HISTORY action', () => { + it('should set the state metadata model', () => { + const serviceEnabled = true; + const action = new actions.UpdateRestorationChangesSuccess({ serviceEnabled }); + const result = reducer(fromRestore.initialState, action); + + expect(Object.keys(result.changes)).toEqual({serviceEnabled: true}); + }); + }); + + describe('selector function', () => { + describe('getChanges', () => { + it('should return the selected version id', () => { + expect(fromRestore.getChanges({ ...baseState, serviceEnabled: false })).toEqual({ serviceEnabled: false }); + }); + }); + }); +}); diff --git a/ui/src/app/metadata/configuration/reducer/restore.reducer.ts b/ui/src/app/metadata/configuration/reducer/restore.reducer.ts index 4ca626459..f2e000728 100644 --- a/ui/src/app/metadata/configuration/reducer/restore.reducer.ts +++ b/ui/src/app/metadata/configuration/reducer/restore.reducer.ts @@ -23,6 +23,20 @@ export function reducer(state = initialState, action: RestoreActionsUnion): Rest ...action.payload } }; + case RestoreActionTypes.SET_SAVING_STATUS: + return { + ...state, + saving: action.payload + }; + case RestoreActionTypes.UPDATE_STATUS: { + return { + ...state, + status: { + ...state.status, + ...action.payload + } + }; + } default: { return state; } diff --git a/ui/src/app/metadata/configuration/service/history.service.spec.ts b/ui/src/app/metadata/configuration/service/history.service.spec.ts index 0927f8e70..e4fa72dac 100644 --- a/ui/src/app/metadata/configuration/service/history.service.spec.ts +++ b/ui/src/app/metadata/configuration/service/history.service.spec.ts @@ -80,21 +80,4 @@ describe(`Attributes Service`, () => { } ))); }); - - describe('restoreVersion method', () => { - it(`should send a put request`, async(inject([MetadataHistoryService, HttpTestingController], - (service: MetadataHistoryService, backend: HttpTestingController) => { - const resourceId = 'foo'; - const type = 'resource'; - const versionId = '1'; - const response = {version: 'bar'} as Metadata; - spyOn(service, 'getVersions').and.returnValue(of([response, { ...response, version: 'foo' }])); - spyOn(service, 'updateVersion').and.returnValue(of(response)); - service.restoreVersion(resourceId, type, versionId).subscribe(updated => { - expect(service.getVersions).toHaveBeenCalled(); - expect(service.updateVersion).toHaveBeenCalled(); - }); - } - ))); - }); }); diff --git a/ui/src/app/metadata/configuration/service/history.service.ts b/ui/src/app/metadata/configuration/service/history.service.ts index 4f480f916..9d3edc212 100644 --- a/ui/src/app/metadata/configuration/service/history.service.ts +++ b/ui/src/app/metadata/configuration/service/history.service.ts @@ -32,7 +32,7 @@ export class MetadataHistoryService { )); } - getVersion(resourceId: string, type: string, versionId: string): Observable { + getVersion(resourceId: string, type: string, versionId: string = null): Observable { const api = versionId ? `/${this.base}/${PATHS[type]}/${resourceId}/${this.path}/${versionId}` : diff --git a/ui/src/app/metadata/domain/component/wizard-summary.component.spec.ts b/ui/src/app/metadata/domain/component/wizard-summary.component.spec.ts index 107ef7241..ecd51b1b9 100644 --- a/ui/src/app/metadata/domain/component/wizard-summary.component.spec.ts +++ b/ui/src/app/metadata/domain/component/wizard-summary.component.spec.ts @@ -12,6 +12,8 @@ import { SummaryPropertyComponent } from './summary-property.component'; import { SCHEMA } from '../../../../testing/form-schema.stub'; import { MockI18nModule } from '../../../../testing/i18n.stub'; import { MetadataProviderWizard } from '../../provider/model'; +import { AttributesService } from '../service/attributes.service'; +import { MockAttributeService } from '../../../../testing/attributes.stub'; @Component({ template: ` @@ -54,7 +56,8 @@ describe('Provider Wizard Summary Component', () => { TestHostComponent ], providers: [ - { provide: WidgetRegistry, useClass: DefaultWidgetRegistry } + { provide: WidgetRegistry, useClass: DefaultWidgetRegistry }, + { provide: AttributesService, useClass: MockAttributeService } ] }).compileComponents(); diff --git a/ui/src/app/metadata/domain/component/wizard-summary.component.ts b/ui/src/app/metadata/domain/component/wizard-summary.component.ts index 82cd86c8d..80f246c83 100644 --- a/ui/src/app/metadata/domain/component/wizard-summary.component.ts +++ b/ui/src/app/metadata/domain/component/wizard-summary.component.ts @@ -43,16 +43,19 @@ export class WizardSummaryComponent implements OnChanges { .filter(step => step.id !== 'summary') .map( (step: WizardStep, num: number) => { + const { id, index, label } = step; + const split = getSplitSchema(schema, step); + const properties = getStepProperties( + split, + def.formatter(model), + schema.definitions || {} + ); return ({ - id: step.id, + id, pageNumber: num + 1, - index: step.index, - label: step.label, - properties: getStepProperties( - getSplitSchema(schema, step), - def.formatter(model), - schema.definitions || {} - ) + index, + label, + properties }); } ); diff --git a/ui/src/app/metadata/provider/container/provider-edit-step.component.ts b/ui/src/app/metadata/provider/container/provider-edit-step.component.ts index be79bb1fa..c869c8e9c 100644 --- a/ui/src/app/metadata/provider/container/provider-edit-step.component.ts +++ b/ui/src/app/metadata/provider/container/provider-edit-step.component.ts @@ -1,6 +1,7 @@ import { Component, OnDestroy } from '@angular/core'; import { Observable, Subject } from 'rxjs'; import { Store } from '@ngrx/store'; +import { FormControl } from '@angular/forms'; import * as fromProvider from '../reducer'; import { UpdateStatus } from '../action/editor.action'; @@ -9,9 +10,8 @@ import { MetadataProvider } from '../../domain/model'; import { LockEditor, UnlockEditor } from '../../../wizard/action/wizard.action'; import * as fromWizard from '../../../wizard/reducer'; -import { withLatestFrom, map, skipWhile, distinctUntilChanged, takeUntil, filter } from 'rxjs/operators'; +import { withLatestFrom, map, distinctUntilChanged, filter } from 'rxjs/operators'; import { UpdateProvider } from '../action/entity.action'; -import { FormControl } from '@angular/forms'; @Component({ selector: 'provider-edit-step', diff --git a/ui/src/app/metadata/provider/model/base.provider.form.ts b/ui/src/app/metadata/provider/model/base.provider.form.ts index 645e21f23..1fce5263d 100644 --- a/ui/src/app/metadata/provider/model/base.provider.form.ts +++ b/ui/src/app/metadata/provider/model/base.provider.form.ts @@ -1,12 +1,12 @@ import { Wizard } from '../../../wizard/model'; import { BaseMetadataProvider } from '../../domain/model/providers'; -import { getProviderNames, getProviderXmlIds } from '../reducer'; +import { getFilteredProviderNames, getFilteredProviderXmlIds } from '../reducer'; export const BaseMetadataProviderEditor: Wizard = { label: 'BaseMetadataProvider', type: 'BaseMetadataResolver', schema: '', - validatorParams: [getProviderNames, getProviderXmlIds], + validatorParams: [getFilteredProviderNames, getFilteredProviderXmlIds], getValidators(namesList: string[], xmlIdList: string[]): any { const validators = { '/': (value, property, form_current) => { diff --git a/ui/src/app/metadata/provider/reducer/index.ts b/ui/src/app/metadata/provider/reducer/index.ts index d40313299..562a4ab44 100644 --- a/ui/src/app/metadata/provider/reducer/index.ts +++ b/ui/src/app/metadata/provider/reducer/index.ts @@ -66,9 +66,19 @@ export const getProviderIds = createSelector(getCollectionState, fromCollection. export const getProviderCollectionIsLoaded = createSelector(getCollectionState, fromCollection.getIsLoaded); export const getProviderNames = createSelector(getAllProviders, (providers: MetadataProvider[]) => providers.map(p => p.name)); +export const getFilteredProviderNames = createSelector( + getProviderNames, + getSelectedProvider, (names, provider) => names.filter(name => name !== provider.name) +); + export const getProviderFilters = createSelector(getSelectedProvider, provider => provider.metadataFilters); export const getProviderXmlIds = createSelector(getAllProviders, (providers: MetadataProvider[]) => providers.map(p => p.xmlId)); export const getOrderedProviders = createSelector(getAllProviders, getProviderOrder, utils.mergeOrderFn); export const getOrderedProvidersInSearch = createSelector(getAllProviders, getProviderOrder, utils.mergeOrderFn); + +export const getFilteredProviderXmlIds = createSelector( + getProviderXmlIds, + getSelectedProvider, (ids, provider) => ids.filter(id => id !== provider.xmlId) +); diff --git a/ui/src/app/metadata/resolver/container/resolver-wizard.component.ts b/ui/src/app/metadata/resolver/container/resolver-wizard.component.ts index ffabac236..56848ad5e 100644 --- a/ui/src/app/metadata/resolver/container/resolver-wizard.component.ts +++ b/ui/src/app/metadata/resolver/container/resolver-wizard.component.ts @@ -117,13 +117,13 @@ export class ResolverWizardComponent implements OnDestroy, CanComponentDeactivat this.summary$ = combine( this.store.select(fromWizard.getWizardDefinition), - this.store.select(fromWizard.getSchema), - this.store.select(fromResolver.getEntityChanges) + this.store.select(fromWizard.getSchemaObject), + this.store.select(fromResolver.getDraftModelWithChanges) ).pipe( map(([definition, schema, model]) => ( { definition, - schema, + schema: schema || {}, model } )) diff --git a/ui/src/app/metadata/resolver/reducer/index.ts b/ui/src/app/metadata/resolver/reducer/index.ts index 43bc2fbc7..a1cc5256d 100644 --- a/ui/src/app/metadata/resolver/reducer/index.ts +++ b/ui/src/app/metadata/resolver/reducer/index.ts @@ -5,6 +5,7 @@ import * as fromSearch from './search.reducer'; import * as fromCopy from './copy.reducer'; import * as fromDraft from './draft.reducer'; import * as fromCollection from './collection.reducer'; +import * as fromWizard from '../../../wizard/reducer'; import { combineAllFn, getEntityIdsFn, getInCollectionFn, doesExistFn } from '../../domain/domain.util'; @@ -109,3 +110,17 @@ export const getAllOtherIds = createSelector( getSelectedResolverId, (ids, selected) => ids.filter(id => id !== selected) ); + +export const getDraftModelWithChanges = createSelector( + fromWizard.getSchema, + fromWizard.getModel, + getSelectedDraft, + getEntityChanges, + fromWizard.getWizardDefinition, + (schema, wizardModel, selectedDraft, changes, definition) => definition.formatter({ + ...wizardModel, + ...selectedDraft, + ...changes + }) +); + diff --git a/ui/src/app/wizard/model/form-definition.ts b/ui/src/app/wizard/model/form-definition.ts index 4402aa354..bde8e10ad 100644 --- a/ui/src/app/wizard/model/form-definition.ts +++ b/ui/src/app/wizard/model/form-definition.ts @@ -5,7 +5,7 @@ export interface FormDefinition { type: string; schema: string; bindings?: any; - validatorParams: any[]; + validatorParams: any; getEntity?(entity: any): any; parser(changes: Partial, schema?: any); formatter(changes: Partial, schema?: any); diff --git a/ui/src/app/wizard/reducer/wizard.reducer.ts b/ui/src/app/wizard/reducer/wizard.reducer.ts index 11205afb3..819a82533 100644 --- a/ui/src/app/wizard/reducer/wizard.reducer.ts +++ b/ui/src/app/wizard/reducer/wizard.reducer.ts @@ -5,7 +5,6 @@ export interface State { index: string; disabled: boolean; definition: Wizard; - schemaPath: string; loading: boolean; schema: any;