Skip to content

Commit

Permalink
Merge branch 'master' into bugfix/SHIBUI-996
Browse files Browse the repository at this point in the history
  • Loading branch information
Bill Smith committed Dec 4, 2018
2 parents 5024bc0 + 50b5b29 commit cbeb3c6
Show file tree
Hide file tree
Showing 18 changed files with 119 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
Expand Down Expand Up @@ -33,8 +34,8 @@ public MetadataResolver findResolverOrThrowHttp404(String resolverResourceId) {
return resolver;
}


@ExceptionHandler
//TODO: Review this handler and update accordingly. Do we still need it?
@ExceptionHandler(HttpClientErrorException.class)
public ResponseEntity<?> notFoundHandler(HttpClientErrorException ex) {
if(ex.getStatusCode() == NOT_FOUND) {
return ResponseEntity.status(NOT_FOUND).body(ex.getStatusText());
Expand All @@ -46,4 +47,10 @@ public ResponseEntity<?> notFoundHandler(HttpClientErrorException ex) {
public ResponseEntity<ErrorResponse> handleDatabaseConstraintViolation(ConstraintViolationException ex) {
return ResponseEntity.status(BAD_REQUEST).body(new ErrorResponse("400", "message.database-constraint"));
}

@ExceptionHandler(Exception.class)
public final ResponseEntity<ErrorResponse> handleAllOtherExceptions(Exception ex) {
ErrorResponse errorResponse = new ErrorResponse("400", ex.getLocalizedMessage());
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ export class MetadataSourceBase implements Wizard<MetadataResolver> {
errors.push(error);
}
});
console.log(errors, form_current);
return errors;
},
'/entityId': (value, property, form) => {
Expand Down
4 changes: 4 additions & 0 deletions ui/src/app/metadata/domain/service/draft.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ export class EntityDraftService {
);
}

exists(id: string, attr: string = 'id'): boolean {
return this.storage.query().some(entity => entity[attr] === id);
}

save(provider: MetadataResolver): Observable<MetadataResolver> {
this.storage.add(provider);
return of(provider);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ describe('Dashboard Resolvers List Page', () => {
it('should route to the wizard page', () => {
spyOn(router, 'navigate');
instance.edit(draft);
expect(router.navigate).toHaveBeenCalledWith(['metadata', 'resolver', 'new', 'blank', 'org-info'], {
expect(router.navigate).toHaveBeenCalledWith(['metadata', 'resolver', 'new', 'blank', 'common'], {
queryParams: { id: '1' }
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export class DashboardResolversListComponent implements OnInit {

edit(entity: MetadataEntity): void {
if (entity.isDraft()) {
this.router.navigate(['metadata', 'resolver', 'new', 'blank', 'org-info'], {
this.router.navigate(['metadata', 'resolver', 'new', 'blank', 'common'], {
queryParams: {
id: entity.getId()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ <h3 translate="label.how-are-you-adding-the-metadata-information">How are you ad
class="btn btn-lg btn-block btn-secondary"
aria-label="Upload local metadata file or use a metadata URL"
role="button"
routerLink="upload"
[routerLink]="['./', 'upload']"
queryParamsHandling="merge"
routerLinkActive="btn-success">
<translate-i18n key="label.upload-url">Upload/URL</translate-i18n>
<i class="fa fa-link fa-2x d-block"></i>
Expand All @@ -33,7 +34,8 @@ <h3 translate="label.how-are-you-adding-the-metadata-information">How are you ad
class="btn btn-lg btn-block btn-secondary"
aria-label="Create metadata source using the wizard"
role="button"
[routerLink]="['./']"
[routerLink]="['./', 'blank', 'common']"
queryParamsHandling="merge"
routerLinkActive="btn-info">
<translate-i18n key="action.create">Create</translate-i18n>
<i class="fa fa-plus-square fa-2x d-block"></i>
Expand All @@ -47,7 +49,8 @@ <h3 translate="label.how-are-you-adding-the-metadata-information">How are you ad
class="btn btn-lg btn-block btn-secondary"
aria-label="Copy a metadata source"
role="button"
routerLink="copy"
[routerLink]="['./', 'copy']"
queryParamsHandling="merge"
routerLinkActive="btn-warning">
<translate-i18n key="action.copy">Copy</translate-i18n>
<i class="fa fa-copy fa-2x d-block"></i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ describe('New Resolver Page', () => {
let instance: NewResolverComponent;
let activatedRoute: ActivatedRouteStub = new ActivatedRouteStub();
activatedRoute.testParamMap = { id: 'foo', events: of({}) };
activatedRoute.data = of('foo');

beforeEach(() => {
TestBed.configureTestingModule({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ export class NewResolverComponent {
debounceTime(10),
map(url => {
let child = this.route.snapshot.firstChild;
return child.routeConfig.path.match('blank').length === 0 || child.params.index === 'common';
return !child.routeConfig.path.match('blank') || child.params.index === 'common';
})
);

this.actionsSubscription = this.route.queryParams.pipe(
this.actionsSubscription = this.route.data.pipe(
distinctUntilChanged(),
map(params => new SelectDraftRequest(params.id))
map(data => new SelectDraftRequest(data.draft))
).subscribe(this.store);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,10 @@ export class ResolverWizardStepComponent implements OnDestroy {
this.valueChangeEmitted$.pipe(
withLatestFrom(this.definition$),
filter(([ changes, definition ]) => (!!definition && !!changes)),
map(([ changes, definition ]) => definition.parser(changes.value)),
withLatestFrom(this.store.select(fromResolver.getSelectedDraft)),
map(([changes, original]) => ({ ...original, ...changes }))
map(([ changes, definition ]) => definition.parser(changes.value))
)
.subscribe(changes => {
if (changes.id) {
this.store.dispatch(new UpdateChanges(changes));
}
this.store.dispatch(new UpdateChanges(changes));
});

this.statusChangeEmitted$.pipe(distinctUntilChanged()).subscribe(errors => this.updateStatus(errors));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,22 @@ import { Component, ViewChild } from '@angular/core';
import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { StoreModule, Store, combineReducers } from '@ngrx/store';

import { NgbDropdownModule, NgbPopoverModule, NgbModal, NgbModalModule } from '@ng-bootstrap/ng-bootstrap';
import { RouterStateSnapshot } from '@angular/router';
import { NgbDropdownModule, NgbPopoverModule, NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { of } from 'rxjs';

import { ResolverWizardComponent } from './resolver-wizard.component';
import * as fromRoot from '../reducer';
import { WizardModule } from '../../../wizard/wizard.module';
import { WizardSummaryComponent } from '../../domain/component/wizard-summary.component';
import { SummaryPropertyComponent } from '../../domain/component/summary-property.component';
import * as fromWizard from '../../../wizard/reducer';
import { MockI18nModule } from '../../../../testing/i18n.stub';
import { METADATA_SOURCE_WIZARD } from '../wizard-definition';
import { MetadataSourceWizard } from '../../domain/model/wizards/metadata-source-wizard';
import { initialState } from '../reducer/entity.reducer';
import { MockWizardModule } from '../../../../testing/wizard.stub';
import { RouterStateSnapshot, ActivatedRouteSnapshot } from '@angular/router';

import { NgbModalStub } from '../../../../testing/modal.stub';
import { of } from 'rxjs';
import { MetadataResolver } from '../../domain/model';
import { DifferentialService } from '../../../core/service/differential.service';

@Component({
template: `
Expand Down Expand Up @@ -94,6 +92,7 @@ describe('Resolver Wizard Component', () => {
TestHostComponent
],
providers: [
DifferentialService,
{ provide: NgbModal, useClass: NgbModalStub },
{ provide: METADATA_SOURCE_WIZARD, useValue: MetadataSourceWizard }
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { Observable, Subject, of, combineLatest as combine } from 'rxjs';
import { skipWhile, startWith, distinctUntilChanged, map, takeUntil, combineLatest } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';

import { MetadataResolver } from '../../domain/model/metadata-resolver';
import * as fromCollections from '../reducer';
Expand All @@ -26,8 +27,8 @@ import { SetDefinition, SetIndex, SetDisabled, ClearWizard } from '../../../wiza
import * as fromWizard from '../../../wizard/reducer';
import { LoadSchemaRequest } from '../../../wizard/action/wizard.action';
import { UnsavedEntityComponent } from '../../domain/component/unsaved-entity.dialog';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { Clear } from '../action/entity.action';
import { DifferentialService } from '../../../core/service/differential.service';

@Component({
selector: 'resolver-wizard-page',
Expand Down Expand Up @@ -66,6 +67,7 @@ export class ResolverWizardComponent implements OnDestroy, CanComponentDeactivat
private route: ActivatedRoute,
private router: Router,
private modalService: NgbModal,
private diffService: DifferentialService,
@Inject(METADATA_SOURCE_WIZARD) private sourceWizard: Wizard<MetadataResolver>
) {
this.store
Expand Down Expand Up @@ -113,6 +115,8 @@ export class ResolverWizardComponent implements OnDestroy, CanComponentDeactivat
combineLatest(this.resolver$, (changes, base) => ({ ...base, ...changes }))
).subscribe(latest => this.latest = latest);

// this.changes$.subscribe(c => console.log(c));

this.summary$ = combine(
this.store.select(fromWizard.getWizardDefinition),
this.store.select(fromWizard.getSchemaCollection),
Expand All @@ -128,6 +132,7 @@ export class ResolverWizardComponent implements OnDestroy, CanComponentDeactivat
);

this.changes$.pipe(takeUntil(this.ngUnsubscribe)).subscribe(c => this.changes = c);
this.resolver$.pipe(takeUntil(this.ngUnsubscribe)).subscribe(r => this.resolver = r);
}

next(): void {
Expand Down Expand Up @@ -160,6 +165,18 @@ export class ResolverWizardComponent implements OnDestroy, CanComponentDeactivat
this.store.dispatch(new SetIndex(page));
}

hasChanges(changes: MetadataResolver): boolean {
// const updated = this.diffService.updatedDiff(this.resolver, changes);
// const deleted = this.diffService.deletedDiff(this.resolver, changes);
let blacklist = ['id', 'resourceId'];
return Object.keys(changes).filter(key => !(blacklist.indexOf(key) > -1)).length > 0;
}

isNew(changes: MetadataResolver): boolean {
let blacklist = ['id', 'resourceId'];
return Object.keys(changes).filter(key => !(blacklist.indexOf(key) > -1)).length === 0;
}

ngOnDestroy(): void {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
Expand All @@ -171,18 +188,23 @@ export class ResolverWizardComponent implements OnDestroy, CanComponentDeactivat
currentState: RouterStateSnapshot,
nextState: RouterStateSnapshot
): Observable<boolean> {
if (nextState.url.match('blank') && !!nextState.root.queryParams.id) { return of(true); }
if (Object.keys(this.changes).length > 0) {
if (nextState.url.match('blank') && !!nextState.root.queryParams.id) {
return of(true);
}
if (this.hasChanges(this.changes)) {
let modal = this.modalService.open(UnsavedEntityComponent);
modal.componentInstance.message = 'resolver';
modal.result.then(
() => {
this.store.dispatch(new Clear());
this.router.navigate([nextState.url]);
this.router.navigateByUrl(nextState.url);
},
() => console.warn('denied')
);
}
if (this.isNew(this.latest)) {
return of(true);
}
return this.store.select(fromResolver.getEntityIsSaved);
}
}
5 changes: 4 additions & 1 deletion ui/src/app/metadata/resolver/effect/collection.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@ export class ResolverCollectionEffects {
addResolverSuccessRemoveDraft$ = this.actions$.pipe(
ofType<providerActions.AddResolverSuccess>(ResolverCollectionActionTypes.ADD_RESOLVER_SUCCESS),
map(action => action.payload),
map(provider => new draftActions.RemoveDraftRequest(provider))
map(provider => {
console.log(provider);
return new draftActions.RemoveDraftRequest(provider);
})
);

@Effect()
Expand Down
25 changes: 0 additions & 25 deletions ui/src/app/metadata/resolver/effect/draft-collection.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,6 @@ export class DraftCollectionEffects {
)
);

@Effect({ dispatch: false })
addDraftSuccessRedirect$ = this.actions$.pipe(
ofType<actions.AddDraftSuccess>(DraftActionTypes.ADD_DRAFT_SUCCESS),
map(getPayload),
tap(provider => this.router.navigate(['metadata', 'resolver', provider.entityId, 'wizard']))
);

@Effect()
updateDraft$ = this.actions$.pipe(
ofType<actions.UpdateDraftRequest>(DraftActionTypes.UPDATE_DRAFT_REQUEST),
Expand Down Expand Up @@ -107,24 +100,6 @@ export class DraftCollectionEffects {
map(id => new actions.LoadDraftRequest())
);

@Effect()
selectDraftError$ = this.actions$.pipe(
ofType<SelectDraftError>(DraftActionTypes.SELECT_ERROR),
map(getPayload),
switchMap(id =>
this.draftService
.save({ id: `r-${ Date.now() }`, serviceProviderName: '' })
.pipe(
map(p => new SelectDraftRequest(p.id)),
catchError(e => of(new SelectDraftError()))
)
),
tap(() => {
// this.store.dispatch(new ClearWizard());
this.store.dispatch(new Clear());
})
);

@Effect()
removeDraft$ = this.actions$.pipe(
ofType<actions.RemoveDraftRequest>(DraftActionTypes.REMOVE_DRAFT),
Expand Down
5 changes: 3 additions & 2 deletions ui/src/app/metadata/resolver/effect/wizard.effect.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { Effect, Actions, ofType } from '@ngrx/effects';
import { ActivatedRoute, Router } from '@angular/router';
import { map, filter, tap } from 'rxjs/operators';
import { map, filter, tap, withLatestFrom } from 'rxjs/operators';
import { Store } from '@ngrx/store';

import {
Expand Down Expand Up @@ -29,7 +29,8 @@ export class WizardEffects {
ofType<UpdateChanges>(ResolverEntityActionTypes.UPDATE_CHANGES),
map(action => action.payload),
filter(provider => !provider.createdDate),
map(provider => new UpdateDraftRequest(provider))
withLatestFrom(this.store.select(fromResolver.getSelectedDraft)),
map(([provider, draft]) => new UpdateDraftRequest({ ...draft, ...provider }))
);

@Effect()
Expand Down
4 changes: 3 additions & 1 deletion ui/src/app/metadata/resolver/resolver.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { ResolverSelectComponent } from './container/resolver-select.component';
import { MetadataSourceEditor } from '../domain/model/wizards/metadata-source-editor';
import { FinishFormComponent } from './component/finish-form.component';
import { ProviderFormFragmentComponent } from './component/provider-form-fragment.component';
import { CreateDraftResolverService } from './service/create-draft.resolver';

@NgModule({
declarations: [
Expand Down Expand Up @@ -75,7 +76,8 @@ export class ResolverModule {
return {
ngModule: RootResolverModule,
providers: [
CopyIsSetGuard
CopyIsSetGuard,
CreateDraftResolverService
]
};
}
Expand Down
4 changes: 4 additions & 0 deletions ui/src/app/metadata/resolver/resolver.routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { ResolverWizardStepComponent } from './container/resolver-wizard-step.co
import { ResolverEditComponent } from './container/resolver-edit.component';
import { ResolverEditStepComponent } from './container/resolver-edit-step.component';
import { ResolverSelectComponent } from './container/resolver-select.component';
import { CreateDraftResolverService } from './service/create-draft.resolver';

export const ResolverRoutes: Routes = [
{
Expand All @@ -21,6 +22,9 @@ export const ResolverRoutes: Routes = [
{
path: 'new',
component: NewResolverComponent,
resolve: {
draft: CreateDraftResolverService
},
children: [
{ path: '', redirectTo: 'blank/common', pathMatch: 'prefix' },
{
Expand Down
Loading

0 comments on commit cbeb3c6

Please sign in to comment.