Skip to content

Commit

Permalink
Merged in feature/SHIBUI-627 (pull request #124)
Browse files Browse the repository at this point in the history
SHIBUI-627 Added advanced form for provider editor

* SHIBUI-627 Added advanced form for provider editor

* feature/SHIBUI-627 Implemented form lock for advanced settings

* SHIBUI-627 Removed console log

* SHIBUI-627 Implemented unit test

* SHIBUI-627 Implemented provider editor

Approved-by: Shibui Jenkins <shibui.jenkins@gmail.com>
Approved-by: Ryan Mathis <rmathis@unicon.net>
  • Loading branch information
rmathis committed Jul 24, 2018
1 parent 3d47c4b commit 8d5e842
Show file tree
Hide file tree
Showing 29 changed files with 599 additions and 39 deletions.
4 changes: 1 addition & 3 deletions ui/src/app/metadata/domain/service/provider.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export class MetadataProviderService {
}

find(id: string): Observable<MetadataProvider> {
// console.log(id);
return this.http.get<MetadataProvider>(`${this.base}${this.endpoint}/${id}`);
}

Expand All @@ -28,7 +27,6 @@ export class MetadataProviderService {
}

save(provider: MetadataProvider): Observable<MetadataProvider> {
const { metadataFilters, id, ...pruned } = provider as FileBackedHttpMetadataProvider;
return this.http.post<MetadataProvider>(`${this.base}${this.endpoint}`, pruned);
return this.http.post<MetadataProvider>(`${this.base}${this.endpoint}`, provider);
}
}
4 changes: 2 additions & 2 deletions ui/src/app/metadata/manager/container/manager.component.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<div class="container-fluid p-3" role="main">
<ul class="nav nav-tabs">
<li class="nav-item">
<a class="nav-link" [routerLink]="['./', 'resolvers']" routerLinkActive="active">Sources</a>
<a class="nav-link" [routerLink]="['./', 'resolvers']" routerLinkActive="active">Metadata Sources</a>
</li>
<li class="nav-item">
<a class="nav-link" [routerLink]="['./', 'providers']" routerLinkActive="active">Providers</a>
<a class="nav-link" [routerLink]="['./', 'providers']" routerLinkActive="active">Metadata Providers</a>
</li>
</ul>
<router-outlet></router-outlet>
Expand Down
17 changes: 15 additions & 2 deletions ui/src/app/metadata/provider/action/editor.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ export enum EditorActionTypes {

SELECT_PROVIDER_TYPE = '[Provider Editor] Select Provider Type',

CLEAR = '[Provider Editor] Clear'
CLEAR = '[Provider Editor] Clear',

LOCK = '[Provider Editor] Lock',
UNLOCK = '[Provider Editor] Unlock'
}

export class UpdateStatus implements Action {
Expand Down Expand Up @@ -45,10 +48,20 @@ export class ClearEditor implements Action {
readonly type = EditorActionTypes.CLEAR;
}

export class LockEditor implements Action {
readonly type = EditorActionTypes.LOCK;
}

export class UnlockEditor implements Action {
readonly type = EditorActionTypes.UNLOCK;
}

export type EditorActionUnion =
| UpdateStatus
| LoadSchemaRequest
| LoadSchemaSuccess
| LoadSchemaFail
| SelectProviderType
| ClearEditor;
| ClearEditor
| LockEditor
| UnlockEditor;
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<ng-container *ngSwitchDefault>
<ng-container *ngIf="property.name">
<strong class="text-primary d-block" role="term">{{ property.name }}</strong>
<span class="d-block" role="definition">{{ property.value || '-' }}</span>
<span class="d-block" role="definition">{{ property.value || property.value === false ? property.value : '-' }}</span>
</ng-container>
</ng-container>
<ng-container *ngSwitchCase="'object'">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
<ng-container *ngIf="definition$ | async">
<div class="alert alert-danger d-flex justify-content-between font-weight-bold mb-3" *ngIf="(step$ | async).locked">
<span class="d-flex justify-content-between">
<toggle-switch id="toggle" [formControl]="lock"></toggle-switch>
<span class="p-1">{{ lock.value ? 'Locked' : 'Unlocked' }}</span>
</span>
<span class="p-1">For Advanced Knowledge Only</span>
</div>
<sf-form
[schema]="schema$ | async"
[model]="model$ | async"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe('Provider Edit Step Component', () => {
app.currentPage = 'common';
app.updateStatus({value: 'common'});
app.updateStatus({value: 'foo'});
expect(store.dispatch).toHaveBeenCalledTimes(2);
expect(store.dispatch).toHaveBeenCalledTimes(3);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ import { Observable, Subject } from 'rxjs';
import { Store } from '@ngrx/store';

import * as fromProvider from '../reducer';
import { UpdateStatus } from '../action/editor.action';
import { Wizard } from '../../../wizard/model';
import { UpdateStatus, LockEditor, UnlockEditor } from '../action/editor.action';
import { Wizard, WizardStep } from '../../../wizard/model';
import { MetadataProvider } from '../../domain/model';

import * as fromWizard from '../../../wizard/reducer';
import { withLatestFrom, map, skipWhile, distinctUntilChanged } from 'rxjs/operators';
import { withLatestFrom, map, skipWhile, distinctUntilChanged, startWith, combineLatest } from 'rxjs/operators';
import { UpdateProvider } from '../action/entity.action';
import { FormControl } from '@angular/forms';

@Component({
selector: 'provider-edit-step',
templateUrl: './provider-edit-step.component.html',
styleUrls: []
})

export class ProviderEditStepComponent implements OnDestroy {
valueChangeSubject = new Subject<Partial<any>>();
private valueChangeEmitted$ = this.valueChangeSubject.asObservable();
Expand All @@ -33,16 +33,30 @@ export class ProviderEditStepComponent implements OnDestroy {
model$: Observable<any>;
definition$: Observable<Wizard<MetadataProvider>>;
changes$: Observable<MetadataProvider>;
step$: Observable<WizardStep>;

validators$: Observable<{ [key: string]: any }>;

lock: FormControl = new FormControl(true);

constructor(
private store: Store<fromProvider.ProviderState>
) {
this.schema$ = this.store.select(fromProvider.getSchema);
this.definition$ = this.store.select(fromWizard.getWizardDefinition);
this.changes$ = this.store.select(fromProvider.getEntityChanges);
this.provider$ = this.store.select(fromProvider.getSelectedProvider);
this.step$ = this.store.select(fromWizard.getCurrent);
this.schema$ = this.store.select(fromProvider.getSchema);

this.step$.subscribe(s => {
if (s && s.locked) {
this.store.dispatch(new LockEditor());
} else {
this.store.dispatch(new UnlockEditor());
}
});

this.lock.valueChanges.subscribe(locked => this.store.dispatch(locked ? new LockEditor() : new UnlockEditor()));

this.validators$ = this.store.select(fromProvider.getProviderNames).pipe(
withLatestFrom(this.definition$, this.provider$),
Expand Down Expand Up @@ -76,7 +90,11 @@ export class ProviderEditStepComponent implements OnDestroy {
)
.subscribe(changes => this.store.dispatch(new UpdateProvider(changes)));

this.statusChangeEmitted$.pipe(distinctUntilChanged()).subscribe(errors => this.updateStatus(errors));
this.statusChangeEmitted$
.pipe(distinctUntilChanged())
.subscribe(errors => {
this.updateStatus(errors);
});

this.store.select(fromWizard.getWizardIndex).subscribe(i => this.currentPage = i);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { startWith } from 'rxjs/operators';
import { Wizard, WizardStep } from '../../../wizard/model';
import { MetadataProvider } from '../../domain/model';
import { ClearProvider } from '../action/entity.action';
import { Router, ActivatedRoute } from '@angular/router';
import { map } from 'rxjs/operators';
import { AddProviderRequest } from '../action/collection.action';
import { MetadataProviderWizard } from '../model';
Expand All @@ -36,9 +35,7 @@ export class ProviderWizardComponent implements OnDestroy {
provider: MetadataProvider;

constructor(
private store: Store<fromProvider.ProviderState>,
private router: Router,
private route: ActivatedRoute
private store: Store<fromProvider.ProviderState>
) {
this.store
.select(fromWizard.getCurrentWizardSchema)
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/metadata/provider/effect/collection.effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export class CollectionEffects {
);

@Effect()
addResolverSuccessReload$ = this.actions$.pipe(
addProviderSuccessReload$ = this.actions$.pipe(
ofType<AddProviderSuccess>(ProviderCollectionActionTypes.ADD_PROVIDER_SUCCESS),
map(action => action.payload),
map(provider => new LoadProviderRequest())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export const FileBackedHttpMetadataProviderEditor: Wizard<FileBackedHttpMetadata
label: 'Advanced Settings',
index: 4,
initialValues: [],
locked: true,
schema: 'assets/schema/provider/filebacked-http-advanced.schema.json'
}
]
Expand Down
47 changes: 46 additions & 1 deletion ui/src/app/metadata/provider/reducer/editor.reducer.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import { reducer, initialState as snapshot } from './editor.reducer';
import { EditorActionTypes, ClearEditor } from '../action/editor.action';
import {
EditorActionTypes,
ClearEditor,
LockEditor,
LoadSchemaRequest,
LoadSchemaFail,
LoadSchemaSuccess,
UnlockEditor,
SelectProviderType
} from '../action/editor.action';

describe('Provider Editor Reducer', () => {
describe('undefined action', () => {
Expand All @@ -15,4 +24,40 @@ describe('Provider Editor Reducer', () => {
expect(reducer(snapshot, new ClearEditor())).toEqual(snapshot);
});
});

describe(`${EditorActionTypes.LOCK}`, () => {
it('should reset to initial state', () => {
expect(reducer(snapshot, new LockEditor())).toEqual({ ...snapshot, locked: true });
});
});

describe(`${EditorActionTypes.UNLOCK}`, () => {
it('should reset to initial state', () => {
expect(reducer(snapshot, new UnlockEditor())).toEqual({ ...snapshot, locked: false });
});
});

describe(`${EditorActionTypes.LOAD_SCHEMA_REQUEST}`, () => {
it('should reset to initial state', () => {
expect(reducer(snapshot, new LoadSchemaRequest('foo'))).toEqual({ ...snapshot, schemaPath: 'foo', loading: true });
});
});

describe(`${EditorActionTypes.LOAD_SCHEMA_FAIL}`, () => {
it('should reset to initial state', () => {
expect(reducer(snapshot, new LoadSchemaFail(new Error('fail')))).toEqual({ ...snapshot });
});
});

describe(`${EditorActionTypes.LOAD_SCHEMA_REQUEST}`, () => {
it('should reset to initial state', () => {
expect(reducer(snapshot, new LoadSchemaSuccess({}))).toEqual({ ...snapshot, schema: {} });
});
});

describe(`${EditorActionTypes.SELECT_PROVIDER_TYPE}`, () => {
it('should reset to initial state', () => {
expect(reducer(snapshot, new SelectProviderType('foo'))).toEqual({ ...snapshot, type: 'foo' });
});
});
});
19 changes: 18 additions & 1 deletion ui/src/app/metadata/provider/reducer/editor.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ export interface EditorState {
loading: boolean;
schema: any;
type: string;
locked: boolean;
}

export const initialState: EditorState = {
status: {},
schemaPath: null,
loading: false,
schema: null,
type: null
type: null,
locked: false
};

export function reducer(state = initialState, action: EditorActionUnion): EditorState {
Expand Down Expand Up @@ -59,13 +61,28 @@ export function reducer(state = initialState, action: EditorActionUnion): Editor
schema: initialState.schema
};
}

case EditorActionTypes.LOCK: {
return {
...state,
locked: true
};
}

case EditorActionTypes.UNLOCK: {
return {
...state,
locked: false
};
}
default: {
return state;
}
}
}

export const getSchema = (state: EditorState) => state.schema;
export const getLocked = (state: EditorState) => state.locked;

export const isEditorValid = (state: EditorState) =>
!Object.keys(state.status).some(key => state.status[key] === ('INVALID'));
Expand Down
34 changes: 33 additions & 1 deletion ui/src/app/metadata/provider/reducer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import * as fromEditor from './editor.reducer';
import * as fromEntity from './entity.reducer';
import * as fromCollection from './collection.reducer';
import * as utils from '../../domain/domain.util';

import * as fromWizard from '../../../wizard/reducer';

import { MetadataProvider } from '../../domain/model';
import { WizardStep } from '../../../wizard/model';

export interface ProviderState {
editor: fromEditor.EditorState;
Expand Down Expand Up @@ -36,13 +40,41 @@ export const getCollectionState = createSelector(getProviderState, getCollection
Editor State
*/

export const getSchema = createSelector(getEditorState, fromEditor.getSchema);
export function getSchemaParseFn(schema, locked): any {
if (!schema) {
return null;
}
return {
...schema,
properties: Object.keys(schema.properties).reduce((prev, current) => {
return {
...prev,
[current]: {
...schema.properties[current],
readOnly: locked,
...(schema.properties[current].hasOwnProperty('properties') ?
getSchemaParseFn(schema.properties[current], locked) :
{}
)
}
};
}, {})
};
}

export const getSchemaLockedFn = (step, locked) => step ? step.locked ? locked : false : false;
export const getLockedStatus = createSelector(getEditorState, fromEditor.getLocked);
export const getLocked = createSelector(fromWizard.getCurrent, getLockedStatus, getSchemaLockedFn);

export const getSchemaObject = createSelector(getEditorState, fromEditor.getSchema);
export const getSchema = createSelector(getSchemaObject, getLocked, getSchemaParseFn);

export const getEditorIsValid = createSelector(getEditorState, fromEditor.isEditorValid);

export const getFormStatus = createSelector(getEditorState, fromEditor.getFormStatus);
export const getInvalidEditorForms = createSelector(getEditorState, fromEditor.getInvalidForms);


/*
Entity State
*/
Expand Down
3 changes: 2 additions & 1 deletion ui/src/app/schema-form/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export class CustomWidgetRegistry extends WidgetRegistry {
this.register('boolean-radio', BooleanRadioComponent);

this.register('fieldset', FieldsetComponent);
this.register('object', FieldsetComponent);

this.register('array', CustomArrayComponent);

this.register('select', CustomSelectComponent);
Expand All @@ -50,7 +52,6 @@ export class CustomWidgetRegistry extends WidgetRegistry {
this.register('datalist', DatalistComponent);

/* NGX-Form */
this.register('object', ObjectWidget);
this.register('range', RangeWidget);

this.register('file', FileWidget);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { Component } from '@angular/core';
import { Component, AfterViewInit } from '@angular/core';
import { ControlWidget } from 'ngx-schema-form';

@Component({
selector: 'boolean-radio',
templateUrl: './boolean-radio.component.html',
styleUrls: ['./boolean-radio.component.scss']
})
export class BooleanRadioComponent extends ControlWidget {

export class BooleanRadioComponent extends ControlWidget implements AfterViewInit {
ngAfterViewInit(): void {
super.ngAfterViewInit();
if (this.schema.readOnly) {
this.control.disable();
} else {
this.control.enable();
}
}
}
Loading

0 comments on commit 8d5e842

Please sign in to comment.