From 66850722daa79a70de3aec0625e5cdea5ce86ceb Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Mon, 27 Aug 2018 19:52:02 +0000 Subject: [PATCH] Merged in feature/SHIBUI-744 (pull request #180) SHIBUI-744 Implemented preview buttons Approved-by: Shibui Jenkins Approved-by: Ryan Mathis --- .../metadata/domain/action/entity.action.ts | 5 +++- .../domain/effect/entity.effect.spec.ts | 4 +-- .../metadata/domain/effect/entity.effect.ts | 9 +++--- .../container/edit-filter.component.html | 1 + .../filter/container/edit-filter.component.ts | 21 ++++++++++---- .../dashboard-resolvers-list.component.ts | 2 +- .../provider-select.component.spec.ts | 12 ++++++++ .../container/provider-select.component.ts | 17 +++++------ ui/src/app/schema-form/registry.ts | 3 ++ ui/src/app/schema-form/schema-form.module.ts | 4 ++- .../widget/button/icon-button.component.html | 4 +++ .../widget/button/icon-button.component.ts | 28 +++++++++++++++++++ .../filter-target.component.html | 9 ++++-- .../filter-target/filter-target.component.ts | 11 +++++++- .../filter/entity-attributes.schema.json | 7 +++++ 15 files changed, 111 insertions(+), 26 deletions(-) create mode 100644 ui/src/app/schema-form/widget/button/icon-button.component.html create mode 100644 ui/src/app/schema-form/widget/button/icon-button.component.ts diff --git a/ui/src/app/metadata/domain/action/entity.action.ts b/ui/src/app/metadata/domain/action/entity.action.ts index 4bfe1380c..c3f47e1ab 100644 --- a/ui/src/app/metadata/domain/action/entity.action.ts +++ b/ui/src/app/metadata/domain/action/entity.action.ts @@ -6,7 +6,10 @@ export const PREVIEW_ENTITY = '[Domain] Preview Entity'; export class PreviewEntity implements Action { readonly type = PREVIEW_ENTITY; - constructor(public payload: MetadataEntity) { } + constructor(public payload: { + id: string, + entity: MetadataEntity + }) { } } export type Actions = diff --git a/ui/src/app/metadata/domain/effect/entity.effect.spec.ts b/ui/src/app/metadata/domain/effect/entity.effect.spec.ts index 9039a4cd9..07f7143e5 100644 --- a/ui/src/app/metadata/domain/effect/entity.effect.spec.ts +++ b/ui/src/app/metadata/domain/effect/entity.effect.spec.ts @@ -48,7 +48,7 @@ describe('Entity Effects', () => { it('should open a modal window for a filter', fakeAsync(() => { spyOn(modal, 'open').and.returnValue({componentInstance: {}}); spyOn(idService, 'preview').and.returnValue(of('')); - effects.openModal(new EntityAttributesFilterEntity()); + effects.openModal({ id: 'foo', entity: new EntityAttributesFilterEntity()}); expect(idService.preview).toHaveBeenCalled(); tick(10); expect(modal.open).toHaveBeenCalled(); @@ -57,7 +57,7 @@ describe('Entity Effects', () => { it('should open a modal window for a provider', fakeAsync(() => { spyOn(modal, 'open').and.returnValue({ componentInstance: {} }); spyOn(providerService, 'preview').and.returnValue(of('')); - effects.openModal(new FileBackedHttpMetadataResolver()); + effects.openModal({id: 'foo', entity: new FileBackedHttpMetadataResolver()}); expect(providerService.preview).toHaveBeenCalled(); tick(10); expect(modal.open).toHaveBeenCalled(); diff --git a/ui/src/app/metadata/domain/effect/entity.effect.ts b/ui/src/app/metadata/domain/effect/entity.effect.ts index 4901b3828..2bf1825aa 100644 --- a/ui/src/app/metadata/domain/effect/entity.effect.ts +++ b/ui/src/app/metadata/domain/effect/entity.effect.ts @@ -20,7 +20,7 @@ export class EntityEffects { previewEntityXml$ = this.actions$.pipe( ofType(entityActions.PREVIEW_ENTITY), map(action => action.payload), - tap(entity => this.openModal(entity)) + tap(prev => this.openModal(prev)) ); constructor( @@ -30,9 +30,10 @@ export class EntityEffects { private entityService: EntityIdService ) { } - openModal(entity: MetadataEntity): void { - let request: Observable = entity.kind === MetadataTypes.FILTER ? - this.entityService.preview(entity.getId()) : this.providerService.preview(entity.getId()); + openModal(prev: { id: string, entity: MetadataEntity }): void { + let { id, entity } = prev, + request: Observable = entity.kind === MetadataTypes.FILTER ? + this.entityService.preview(id) : this.providerService.preview(id); request.subscribe(xml => { let modal = this.modalService.open(PreviewDialogComponent, { size: 'lg', diff --git a/ui/src/app/metadata/filter/container/edit-filter.component.html b/ui/src/app/metadata/filter/container/edit-filter.component.html index cbdf2df18..5c9ecb5c8 100644 --- a/ui/src/app/metadata/filter/container/edit-filter.component.html +++ b/ui/src/app/metadata/filter/container/edit-filter.component.html @@ -29,6 +29,7 @@ [schema]="schema$ | async" [model]="model$ | async" [validators]="definition.getValidators()" + [actions]="actions" (onChange)="valueChangeSubject.next($event)" (onErrorChange)="statusChangeSubject.next($event)"> diff --git a/ui/src/app/metadata/filter/container/edit-filter.component.ts b/ui/src/app/metadata/filter/container/edit-filter.component.ts index 50184abf8..6e058a464 100644 --- a/ui/src/app/metadata/filter/container/edit-filter.component.ts +++ b/ui/src/app/metadata/filter/container/edit-filter.component.ts @@ -1,11 +1,11 @@ import { Component } from '@angular/core'; import { Store } from '@ngrx/store'; -import { Subject, Observable, of } from 'rxjs'; +import { Subject, Observable } from 'rxjs'; import * as fromFilter from '../reducer'; -import { MetadataFilterTypes, EntityAttributesFilter } from '../model'; +import { MetadataFilterTypes } from '../model'; import { FormDefinition } from '../../../wizard/model'; -import { MetadataFilter, MetadataEntity } from '../../domain/model'; +import { MetadataFilter } from '../../domain/model'; import { SchemaService } from '../../../schema-form/service/schema.service'; import { UpdateFilterRequest } from '../action/collection.action'; import { CancelCreateFilter, UpdateFilterChanges } from '../action/filter.action'; @@ -32,6 +32,8 @@ export class EditFilterComponent { filter: MetadataFilter; isValid: boolean; + actions: any; + constructor( private store: Store, private schemaService: SchemaService @@ -50,6 +52,12 @@ export class EditFilterComponent { this.store .select(fromFilter.getFilter) .subscribe(filter => this.filter = filter); + + this.actions = { + preview: (property: any, parameters: any) => { + this.preview(parameters.id); + } + }; } save(): void { @@ -60,8 +68,11 @@ export class EditFilterComponent { this.store.dispatch(new CancelCreateFilter()); } - preview(entity: MetadataFilter): void { - this.store.dispatch(new PreviewEntity(new EntityAttributesFilterEntity(entity))); + preview(id: string): void { + this.store.dispatch(new PreviewEntity({ + id, + entity: new EntityAttributesFilterEntity(this.filter) + })); } } diff --git a/ui/src/app/metadata/manager/container/dashboard-resolvers-list.component.ts b/ui/src/app/metadata/manager/container/dashboard-resolvers-list.component.ts index 962efd52e..b4b5af807 100644 --- a/ui/src/app/metadata/manager/container/dashboard-resolvers-list.component.ts +++ b/ui/src/app/metadata/manager/container/dashboard-resolvers-list.component.ts @@ -79,7 +79,7 @@ export class DashboardResolversListComponent implements OnInit { } openPreviewDialog(entity: MetadataEntity): void { - this.store.dispatch(new PreviewEntity(entity)); + this.store.dispatch(new PreviewEntity({ id: entity.getId(), entity })); } deleteResolver(entity: MetadataResolver): void { diff --git a/ui/src/app/metadata/provider/container/provider-select.component.spec.ts b/ui/src/app/metadata/provider/container/provider-select.component.spec.ts index b8e07460b..c52a494b8 100644 --- a/ui/src/app/metadata/provider/container/provider-select.component.spec.ts +++ b/ui/src/app/metadata/provider/container/provider-select.component.spec.ts @@ -6,6 +6,7 @@ import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; import { ProviderSelectComponent } from './provider-select.component'; import * as fromRoot from '../reducer'; import * as fromWizard from '../../../wizard/reducer'; +import { MetadataProvider } from '../../domain/model'; @Component({ template: ` @@ -53,4 +54,15 @@ describe('Provider Select Component', () => { it('should instantiate the component', async(() => { expect(app).toBeTruthy(); })); + + describe('setDefinition method', () => { + it('should not dispatch an action if no provider is defined', () => { + app.setDefinition(null); + expect(store.dispatch).not.toHaveBeenCalled(); + }); + it('should dispatch an action if a provider is defined', () => { + app.setDefinition({} as MetadataProvider); + expect(store.dispatch).toHaveBeenCalled(); + }); + }); }); diff --git a/ui/src/app/metadata/provider/container/provider-select.component.ts b/ui/src/app/metadata/provider/container/provider-select.component.ts index 1e64aaae6..baba7f626 100644 --- a/ui/src/app/metadata/provider/container/provider-select.component.ts +++ b/ui/src/app/metadata/provider/container/provider-select.component.ts @@ -33,14 +33,15 @@ export class ProviderSelectComponent implements OnDestroy { this.provider$ = this.store.select(fromProviders.getSelectedProvider).pipe(skipWhile(p => !p)); - this.provider$ - .subscribe(provider => { - if (provider) { - this.store.dispatch(new SetDefinition({ - ...MetadataProviderEditorTypes.find(def => def.type === provider['@type']) - })); - } - }); + this.provider$.subscribe(provider => this.setDefinition(provider)); + } + + setDefinition(provider: MetadataProvider): void { + if (provider) { + this.store.dispatch(new SetDefinition({ + ...MetadataProviderEditorTypes.find(def => def.type === provider['@type']) + })); + } } ngOnDestroy() { diff --git a/ui/src/app/schema-form/registry.ts b/ui/src/app/schema-form/registry.ts index 050edbf42..81ca2ac63 100644 --- a/ui/src/app/schema-form/registry.ts +++ b/ui/src/app/schema-form/registry.ts @@ -16,6 +16,7 @@ import { CustomArrayComponent } from './widget/array/array.component'; import { CustomIntegerComponent } from './widget/number/number.component'; import { FilterTargetComponent } from './widget/filter-target/filter-target.component'; import { ChecklistComponent } from './widget/check/checklist.component'; +import { IconButtonComponent } from './widget/button/icon-button.component'; export class CustomWidgetRegistry extends WidgetRegistry { @@ -55,6 +56,8 @@ export class CustomWidgetRegistry extends WidgetRegistry { this.register('filter-target', FilterTargetComponent); + this.register('icon-button', IconButtonComponent); + /* NGX-Form */ this.register('range', RangeWidget); diff --git a/ui/src/app/schema-form/schema-form.module.ts b/ui/src/app/schema-form/schema-form.module.ts index a637d629c..d4a157e47 100644 --- a/ui/src/app/schema-form/schema-form.module.ts +++ b/ui/src/app/schema-form/schema-form.module.ts @@ -17,6 +17,7 @@ import { CustomArrayComponent } from './widget/array/array.component'; import { CustomIntegerComponent } from './widget/number/number.component'; import { FilterTargetComponent } from './widget/filter-target/filter-target.component'; import { ChecklistComponent } from './widget/check/checklist.component'; +import { IconButtonComponent } from './widget/button/icon-button.component'; export const COMPONENTS = [ BooleanRadioComponent, @@ -29,7 +30,8 @@ export const COMPONENTS = [ CustomArrayComponent, CustomIntegerComponent, FilterTargetComponent, - ChecklistComponent + ChecklistComponent, + IconButtonComponent ]; @NgModule({ diff --git a/ui/src/app/schema-form/widget/button/icon-button.component.html b/ui/src/app/schema-form/widget/button/icon-button.component.html new file mode 100644 index 000000000..107a8eb7c --- /dev/null +++ b/ui/src/app/schema-form/widget/button/icon-button.component.html @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/ui/src/app/schema-form/widget/button/icon-button.component.ts b/ui/src/app/schema-form/widget/button/icon-button.component.ts new file mode 100644 index 000000000..2dcca890f --- /dev/null +++ b/ui/src/app/schema-form/widget/button/icon-button.component.ts @@ -0,0 +1,28 @@ +import { + Component, AfterViewInit, +} from '@angular/core'; +import { ButtonWidget } from 'ngx-schema-form'; +import { ɵb as ActionRegistry } from 'ngx-schema-form'; + +@Component({ + selector: 'icon-button', + templateUrl: `./icon-button.component.html` +}) +export class IconButtonComponent extends ButtonWidget implements AfterViewInit { + + action = ($event) => {}; + + constructor(private actionRegistry: ActionRegistry) { + super(); + } + + ngAfterViewInit(): void { + this.action = (e) => { + let action = this.actionRegistry.get(this.button.id); + if (this.button.id && action) { + action(this.formProperty, this.button.parameters); + } + e.preventDefault(); + }; + } +} diff --git a/ui/src/app/schema-form/widget/filter-target/filter-target.component.html b/ui/src/app/schema-form/widget/filter-target/filter-target.component.html index 5124e7fac..73c392817 100644 --- a/ui/src/app/schema-form/widget/filter-target/filter-target.component.html +++ b/ui/src/app/schema-form/widget/filter-target/filter-target.component.html @@ -97,9 +97,12 @@
  • {{ id }} - + + + +
diff --git a/ui/src/app/schema-form/widget/filter-target/filter-target.component.ts b/ui/src/app/schema-form/widget/filter-target/filter-target.component.ts index a93963678..2b08949d2 100644 --- a/ui/src/app/schema-form/widget/filter-target/filter-target.component.ts +++ b/ui/src/app/schema-form/widget/filter-target/filter-target.component.ts @@ -61,7 +61,6 @@ export class FilterTargetComponent extends ObjectWidget implements OnDestroy, Af ngAfterViewInit(): void { super.ngAfterViewInit(); this.script.setValue(this.targets[0]); - this.search.setValidators(this.unique()); } @@ -80,6 +79,16 @@ export class FilterTargetComponent extends ObjectWidget implements OnDestroy, Af } } + getButtonConfig(id: string): any { + let buttons = this.formProperty.getProperty('value').schema.buttons; + return (buttons || []).map(btn => ({ + ...btn, + parameters: { + id + } + })); + } + get targets(): string[] { return this.formProperty.getProperty('value').value; } diff --git a/ui/src/assets/schema/filter/entity-attributes.schema.json b/ui/src/assets/schema/filter/entity-attributes.schema.json index e57792b00..3baede17f 100644 --- a/ui/src/assets/schema/filter/entity-attributes.schema.json +++ b/ui/src/assets/schema/filter/entity-attributes.schema.json @@ -74,6 +74,13 @@ }, "value": { "type": "array", + "buttons": [ + { + "id": "preview", + "label": "Preview", + "widget": "icon-button" + } + ], "minItems": 1, "uniqueItems": true, "items": {