diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts new file mode 100644 index 0000000000000000000000000000000000000000..8cc4ca2918cd54829a1a86990b4c6ef51ace4f90 --- /dev/null +++ b/src/app/app-routing.module.ts @@ -0,0 +1,33 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule, PreloadAllModules } from '@angular/router'; + +import { NotFoundPageComponent } from './core/containers/not-found-page.component'; + +const routes: Routes = [ + { path: '', redirectTo: 'home', pathMatch: 'full' }, + { + path: 'search', + loadChildren: () => import('./search/search.module').then(m => m.SearchModule) + }, + { + path: 'detail/:dname/:objectSelected', + loadChildren: () => import('./detail/detail.module').then(m => m.DetailModule) + }, + { + path: 'documentation', + loadChildren: () => import('./documentation/documentation.module').then(m => m.DocumentationModule) + }, + { path: '**', component: NotFoundPageComponent } +]; + +@NgModule({ + imports: [ + RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules }) + ], + exports: [RouterModule] +}) +export class AppRoutingModule { } + +export const routedComponents = [ + NotFoundPageComponent +]; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index c59f2ab0474fc9c6dbfb5c9bcd5d01763e0d64e7..b8f555893e7142e31809b9ae137d1b18d30f1e40 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -13,10 +13,8 @@ import { reducers, metaReducers } from './app.reducer'; import { CoreModule } from './core/core.module'; import { StaticModule } from './static/static.module'; import { LoginModule } from './login/login.module'; -import { SearchModule } from './search/search.module'; -import { DetailModule } from './detail/detail.module'; -import { DocumentationModule } from './documentation/documentation.module'; -import { AppRoutingModule } from './app.routing'; +import { MetamodelModule } from "./metamodel/metamodel.module"; +import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './core/containers/app.component'; import { environment } from '../environments/environment'; @@ -28,9 +26,7 @@ import { environment } from '../environments/environment'; CoreModule, StaticModule, LoginModule, - SearchModule, - DetailModule, - DocumentationModule, + MetamodelModule, StoreModule.forRoot(reducers, { metaReducers, runtimeChecks: { diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts deleted file mode 100644 index 9f63e9a59103943d5ea6e2781c6de4c3760ed7b0..0000000000000000000000000000000000000000 --- a/src/app/app.routing.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { NgModule } from '@angular/core'; -import { Routes, RouterModule } from '@angular/router'; - -import { NotFoundPageComponent } from './core/containers/not-found-page.component'; - -const routes: Routes = [ - { path: '', redirectTo: 'home', pathMatch: 'full' }, - { path: '**', component: NotFoundPageComponent } -]; - -@NgModule({ - imports: [RouterModule.forRoot(routes)], - exports: [RouterModule] -}) -export class AppRoutingModule { } - -export const routedComponents = [ - NotFoundPageComponent -]; diff --git a/src/app/detail/containers/detail.component.ts b/src/app/detail/containers/detail.component.ts index 0d5421f0ba2ce90de5f76007c43ec616f57c681d..bf17d249b5a9850fbdf3d03e8da2235936052e6e 100644 --- a/src/app/detail/containers/detail.component.ts +++ b/src/app/detail/containers/detail.component.ts @@ -7,7 +7,6 @@ import { Store } from '@ngrx/store'; import * as detailActions from '../store/detail.action'; import * as fromDetail from '../store/detail.reducer'; import * as detailSelector from '../store/detail.selector'; -import * as searchSelector from '../../search/store/search.selector'; import { Attribute, Category, Family } from '../../metamodel/model'; import * as metamodelSelector from "../../metamodel/selectors"; @@ -33,7 +32,7 @@ export class DetailComponent implements OnInit, OnDestroy { public spectraCSV: Observable<string>; constructor(private location: Location, private store: Store<StoreState>) { - this.pristine = this.store.select(searchSelector.getPristine); + this.pristine = this.store.select(detailSelector.getSearchIsPristine); this.datasetName = this.store.select(detailSelector.getDatasetName); this.attributeList = this.store.select(detailSelector.getAttributeList); this.outputFamilyList = this.store.select(metamodelSelector.getOutputFamilyList); diff --git a/src/app/detail/detail.routing.ts b/src/app/detail/detail-routing.module.ts similarity index 83% rename from src/app/detail/detail.routing.ts rename to src/app/detail/detail-routing.module.ts index f50de91bbd77031a39271b386b9cfaf931163461..38147e76bc83f137854071d27d5d71de2c7caab9 100644 --- a/src/app/detail/detail.routing.ts +++ b/src/app/detail/detail-routing.module.ts @@ -4,7 +4,7 @@ import { Routes, RouterModule } from '@angular/router'; import { DetailComponent } from './containers/detail.component'; const routes: Routes = [ - { path: 'detail/:dname/:objectSelected', component: DetailComponent } + { path: '', component: DetailComponent } ]; @NgModule({ diff --git a/src/app/detail/detail.module.ts b/src/app/detail/detail.module.ts index 5526a3811c67a0eac1fd4dafc82d6588a3b38e1b..f095bb7429eaf3457654ddf3ce0077ad1c04fae6 100644 --- a/src/app/detail/detail.module.ts +++ b/src/app/detail/detail.module.ts @@ -7,7 +7,7 @@ import { SharedModule } from '../shared/shared.module'; import { MetamodelModule } from '../metamodel/metamodel.module'; import { DetailEffects } from './store/detail.effects'; import { DetailService } from './store/detail.service'; -import { DetailRoutingModule, routedComponents } from './detail.routing'; +import { DetailRoutingModule, routedComponents } from './detail-routing.module'; import { dummiesComponents } from './components'; import { reducer } from './store/detail.reducer'; diff --git a/src/app/detail/store/detail.action.spec.ts b/src/app/detail/store/detail.action.spec.ts index dc4d9cb3d497e5c61c108e7fdd98524caf460ea1..dc859ad49f3df443748e08bce88180c87e8a4724 100644 --- a/src/app/detail/store/detail.action.spec.ts +++ b/src/app/detail/store/detail.action.spec.ts @@ -8,6 +8,12 @@ describe('[Detail] Action', () => { expect(action.type).toEqual(detailActions.INIT_DETAIL); }); + it('should SetSearchIsPristineAction', () => { + const action = new detailActions.SetSearchIsPristineAction(true); + expect(action.type).toEqual(detailActions.SET_SEARCH_IS_PRISTINE); + expect(action.payload).toBeTruthy(); + }); + it('should SetDatsetNameAction', () => { const action = new detailActions.SetDatasetNameAction('toto'); expect(action.type).toEqual(detailActions.SET_DATASET_NAME); diff --git a/src/app/detail/store/detail.action.ts b/src/app/detail/store/detail.action.ts index b58470033ce0868bd4cd790a672550f9eac9417b..2b716e8641372ee69fbfbd573800de5b055a13dd 100644 --- a/src/app/detail/store/detail.action.ts +++ b/src/app/detail/store/detail.action.ts @@ -2,6 +2,7 @@ import { Action } from '@ngrx/store'; import { Attribute } from '../../metamodel/model' export const INIT_DETAIL = '[Detail] Init Detail'; +export const SET_SEARCH_IS_PRISTINE = '[Detail] Set Search Is Pristine'; export const SET_DATASET_NAME = '[Detail] Set Dataset Name'; export const LOAD_ATTRIBUTE_LIST = '[Detail] Load Attribute List'; export const LOAD_ATTRIBUTE_LIST_SUCCESS = '[Detail] Load Attribute List Success'; @@ -27,6 +28,12 @@ export class SetDatasetNameAction implements Action { constructor(public payload: string) { } } +export class SetSearchIsPristineAction implements Action { + readonly type = SET_SEARCH_IS_PRISTINE; + + constructor(public payload: boolean) { } +} + export class LoadAttributeListAction implements Action { readonly type = LOAD_ATTRIBUTE_LIST; @@ -95,6 +102,7 @@ export class DestroyDetailAction implements Action { export type Actions = InitDetailAction + | SetSearchIsPristineAction | SetDatasetNameAction | LoadAttributeListAction | LoadAttributeListSuccessAction diff --git a/src/app/detail/store/detail.effects.ts b/src/app/detail/store/detail.effects.ts index 7d7caa66c6fd972546282f3d359d0cb4564c808b..41f3a9654335a85ff962ebba339299baaeeff2d5 100644 --- a/src/app/detail/store/detail.effects.ts +++ b/src/app/detail/store/detail.effects.ts @@ -42,11 +42,13 @@ export class DetailEffects { const datasetName = state.router.state.params.dname; let actions: Action[] = [new detailActions.SetDatasetNameAction(datasetName)]; - if (state.search.pristine) { + if (!state.search || state.search.pristine) { actions.push(new detailActions.LoadAttributeListAction()); actions.push(new outputActions.LoadOutputSearchMetaAction(datasetName)); + actions.push(new detailActions.SetSearchIsPristineAction(true)); } else { - actions.push(new detailActions.CopyAttributeListAction()) + actions.push(new detailActions.CopyAttributeListAction()); + actions.push(new detailActions.SetSearchIsPristineAction(false)); } return actions; diff --git a/src/app/detail/store/detail.reducer.spec.ts b/src/app/detail/store/detail.reducer.spec.ts index 1fc2cc0be3122f2192e5e7b74ad715ba3ae2e8d9..21464ff0fdc50a775a32171f8a4becb74afb49db 100644 --- a/src/app/detail/store/detail.reducer.spec.ts +++ b/src/app/detail/store/detail.reducer.spec.ts @@ -17,6 +17,7 @@ describe('[Detail] Reducer', () => { const action = new detailActions.InitDetailAction(); const state = fromDetail.reducer(initialState, action); + expect(state.searchIsPristine).toBeNull(); expect(state.datasetName).toBeNull(); expect(state.attributeList).toBeNull(); expect(state.objectIsLoading).toBeTruthy(); @@ -28,11 +29,29 @@ describe('[Detail] Reducer', () => { expect(state).not.toEqual(initialState); }); + it('should set searchIsPristine', () => { + const { initialState } = fromDetail; + const action = new detailActions.SetSearchIsPristineAction(true); + const state = fromDetail.reducer(initialState, action); + + expect(state.searchIsPristine).toBeTruthy(); + expect(state.datasetName).toBeNull(); + expect(state.attributeList).toBeNull(); + expect(state.objectIsLoading).toBeFalsy(); + expect(state.objectIsLoaded).toBeFalsy(); + expect(state.object).toBeNull(); + expect(state.spectraIsLoading).toBeFalsy(); + expect(state.spectraIsLoaded).toBeFalsy(); + expect(state.spectraCSV).toBeNull(); + expect(state).not.toEqual(initialState); + }); + it('should set datasetName', () => { const { initialState } = fromDetail; const action = new detailActions.SetDatasetNameAction('toto'); const state = fromDetail.reducer(initialState, action); + expect(state.searchIsPristine).toBeNull(); expect(state.datasetName).toEqual('toto'); expect(state.attributeList).toBeNull(); expect(state.objectIsLoading).toBeFalsy(); @@ -50,6 +69,7 @@ describe('[Detail] Reducer', () => { const action = new detailActions.LoadAttributeListSuccessAction(attributeList); const state = fromDetail.reducer(initialState, action); + expect(state.searchIsPristine).toBeNull(); expect(state.datasetName).toBeNull(); expect(state.attributeList.length).toEqual(2); expect(state.objectIsLoading).toBeFalsy(); @@ -66,6 +86,7 @@ describe('[Detail] Reducer', () => { const action = new detailActions.RetrieveObjectSuccessAction(['object']); const state = fromDetail.reducer(initialState, action); + expect(state.searchIsPristine).toBeNull(); expect(state.datasetName).toBeNull(); expect(state.attributeList).toBeNull(); expect(state.objectIsLoading).toBeFalsy(); @@ -79,13 +100,14 @@ describe('[Detail] Reducer', () => { it('should set objectIsLoading and objectIsLoaded to false by attributeList fail', () => { const initialState = { - ...fromDetail.initialState, + ...fromDetail.initialState, objectIsLoading: true, objectIsLoaded: true }; const action = new detailActions.LoadAttributeListFailAction(); const state = fromDetail.reducer(initialState, action); + expect(state.searchIsPristine).toBeNull(); expect(state.datasetName).toBeNull(); expect(state.attributeList).toBeNull(); expect(state.objectIsLoading).toBeFalsy(); @@ -96,16 +118,17 @@ describe('[Detail] Reducer', () => { expect(state.spectraCSV).toBeNull(); expect(state).not.toEqual(initialState); }); - + it('should set objectIsLoading and objectIsLoaded to false by object fail', () => { const initialState = { - ...fromDetail.initialState, + ...fromDetail.initialState, objectIsLoading: true, objectIsLoaded: true }; const action = new detailActions.RetrieveObjectFailAction(); const state = fromDetail.reducer(initialState, action); + expect(state.searchIsPristine).toBeNull(); expect(state.datasetName).toBeNull(); expect(state.attributeList).toBeNull(); expect(state.objectIsLoading).toBeFalsy(); @@ -123,6 +146,7 @@ describe('[Detail] Reducer', () => { const action = new detailActions.RetrieveSpectraAction(spectraFile); const state = fromDetail.reducer(initialState, action); + expect(state.searchIsPristine).toBeNull(); expect(state.datasetName).toBeNull(); expect(state.attributeList).toBeNull(); expect(state.objectIsLoading).toBeFalsy(); @@ -140,6 +164,7 @@ describe('[Detail] Reducer', () => { const action = new detailActions.RetrieveSpectraSuccessAction(spectraCSV); const state = fromDetail.reducer(initialState, action); + expect(state.searchIsPristine).toBeNull(); expect(state.datasetName).toBeNull(); expect(state.attributeList).toBeNull(); expect(state.objectIsLoading).toBeFalsy(); @@ -156,6 +181,7 @@ describe('[Detail] Reducer', () => { const action = new detailActions.RetrieveSpectraFailAction(); const state = fromDetail.reducer(initialState, action); + expect(state.searchIsPristine).toBeNull(); expect(state.datasetName).toBeNull(); expect(state.attributeList).toBeNull(); expect(state.objectIsLoading).toBeFalsy(); @@ -169,6 +195,7 @@ describe('[Detail] Reducer', () => { it('should reset state', () => { const initialState = { + searchIsPristine: true, datasetName: 'dname', attributeList: ATTRIBUTE_LIST, objectIsLoading: true, @@ -181,6 +208,7 @@ describe('[Detail] Reducer', () => { const action = new detailActions.DestroyDetailAction(); const state = fromDetail.reducer(initialState, action); + expect(state.searchIsPristine).toBeNull(); expect(state.datasetName).toBeNull(); expect(state.attributeList).toBeNull(); expect(state.objectIsLoading).toBeFalsy(); @@ -192,6 +220,13 @@ describe('[Detail] Reducer', () => { expect(state).not.toEqual(initialState); }); + it('should get searchIsPristine', () => { + const action = {} as detailActions.Actions; + const state = fromDetail.reducer(undefined, action); + + expect(fromDetail.getSearchIsPristine(state)).toBeNull(); + }); + it('should get datasetName', () => { const action = {} as detailActions.Actions; const state = fromDetail.reducer(undefined, action); @@ -205,42 +240,42 @@ describe('[Detail] Reducer', () => { expect(fromDetail.getAttributeList(state)).toBeNull(); }); - + it('should get objectIsLoading', () => { const action = {} as detailActions.Actions; const state = fromDetail.reducer(undefined, action); expect(fromDetail.getObjectIsLoading(state)).toBeFalsy(); }); - + it('should get objectIsLoaded', () => { const action = {} as detailActions.Actions; const state = fromDetail.reducer(undefined, action); expect(fromDetail.getObjectIsLoaded(state)).toBeFalsy(); }); - + it('should get object', () => { const action = {} as detailActions.Actions; const state = fromDetail.reducer(undefined, action); expect(fromDetail.getObject(state)).toBeNull(); }); - + it('should get spectraIsLoading', () => { const action = {} as detailActions.Actions; const state = fromDetail.reducer(undefined, action); expect(fromDetail.getSpectraIsLoading(state)).toBeFalsy(); }); - + it('should get spectraIsLoaded', () => { const action = {} as detailActions.Actions; const state = fromDetail.reducer(undefined, action); expect(fromDetail.getSpectraIsLoaded(state)).toBeFalsy(); }); - + it('should get spectraCSV', () => { const action = {} as detailActions.Actions; const state = fromDetail.reducer(undefined, action); diff --git a/src/app/detail/store/detail.reducer.ts b/src/app/detail/store/detail.reducer.ts index ced7a4c56e9da5c28336f6b650c68a128f82c7e9..88894ea847e019bc53c2ec83bb5533603a9ece77 100644 --- a/src/app/detail/store/detail.reducer.ts +++ b/src/app/detail/store/detail.reducer.ts @@ -3,6 +3,7 @@ import * as actions from './detail.action'; import { Attribute } from '../../metamodel/model'; export interface State { + searchIsPristine: boolean datasetName: string; attributeList: Attribute[]; objectIsLoading: boolean; @@ -14,6 +15,7 @@ export interface State { } export const initialState: State = { + searchIsPristine: null, datasetName: null, attributeList: null, objectIsLoading: false, @@ -32,6 +34,14 @@ export function reducer(state: State = initialState, action: actions.Actions): S objectIsLoading: true }; + case actions.SET_SEARCH_IS_PRISTINE: + const searchIsPristine: boolean = action.payload; + + return { + ...state, + searchIsPristine + }; + case actions.SET_DATASET_NAME: const datasetName: string = action.payload; @@ -94,6 +104,7 @@ export function reducer(state: State = initialState, action: actions.Actions): S } } +export const getSearchIsPristine = (state: State) => state.searchIsPristine; export const getDatasetName = (state: State) => state.datasetName; export const getAttributeList = (state: State) => state.attributeList; export const getObjectIsLoading = (state: State) => state.objectIsLoading; diff --git a/src/app/detail/store/detail.selector.spec.ts b/src/app/detail/store/detail.selector.spec.ts index d46e617999a0056ae6ead15acc808f29e397a870..42ba4713b74f097a6c1ff97acefd7e9ae4e982ab 100644 --- a/src/app/detail/store/detail.selector.spec.ts +++ b/src/app/detail/store/detail.selector.spec.ts @@ -2,6 +2,11 @@ import * as detailSelector from './detail.selector'; import * as fromDetail from './detail.reducer'; describe('[Detail] Selector', () => { + it('should get searchIsPristine', () => { + const state = { detail: { ...fromDetail.initialState }}; + expect(detailSelector.getSearchIsPristine(state)).toBeNull(); + }); + it('should get datasetName', () => { const state = { detail: { ...fromDetail.initialState }}; expect(detailSelector.getDatasetName(state)).toBeNull(); diff --git a/src/app/detail/store/detail.selector.ts b/src/app/detail/store/detail.selector.ts index 6089b9cb36bbb317b3b2fd5a7f27abb2f8012f0e..88ad9ce96520e8ddb269dcdfd9e2a0037899b4ef 100644 --- a/src/app/detail/store/detail.selector.ts +++ b/src/app/detail/store/detail.selector.ts @@ -4,6 +4,11 @@ import * as detail from './detail.reducer'; export const getDetailState = createFeatureSelector<detail.State>('detail'); +export const getSearchIsPristine = createSelector( + getDetailState, + detail.getSearchIsPristine +); + export const getDatasetName = createSelector( getDetailState, detail.getDatasetName diff --git a/src/app/documentation/documentation.routing.ts b/src/app/documentation/documentation-routing.module.ts similarity index 80% rename from src/app/documentation/documentation.routing.ts rename to src/app/documentation/documentation-routing.module.ts index 1c157868b1e31836c836b1cd58e50ac23e8ecbfc..97bf8a647ec8129ef53a2e03b24928881052a033 100644 --- a/src/app/documentation/documentation.routing.ts +++ b/src/app/documentation/documentation-routing.module.ts @@ -3,9 +3,7 @@ import { Routes, RouterModule } from '@angular/router'; import { DocumentationComponent } from './containers/documentation.component'; -const routes: Routes = [ - { path: 'documentation', component: DocumentationComponent } -]; +const routes: Routes = [{ path: '', component: DocumentationComponent }]; @NgModule({ imports: [ RouterModule.forChild(routes) ], diff --git a/src/app/documentation/documentation.module.ts b/src/app/documentation/documentation.module.ts index 113382034ea9b6009368ca03b42f9a3ce4d4f56e..1f49def50e55b364c7ab8f6059e0e702301f1d4c 100644 --- a/src/app/documentation/documentation.module.ts +++ b/src/app/documentation/documentation.module.ts @@ -4,7 +4,7 @@ import { StoreModule } from '@ngrx/store'; import { EffectsModule } from '@ngrx/effects'; import { SharedModule } from '../shared/shared.module'; -import { DocumentationRoutingModule, routedComponents } from './documentation.routing'; +import { DocumentationRoutingModule, routedComponents } from './documentation-routing.module'; import { reducer } from './store/documentation.reducer'; import { DocumentationEffects } from './store/documentation.effects'; import { DocumentationService } from './store/documentation.service'; diff --git a/src/app/login/login.routing.ts b/src/app/login/login-routing.module.ts similarity index 100% rename from src/app/login/login.routing.ts rename to src/app/login/login-routing.module.ts diff --git a/src/app/login/login.module.ts b/src/app/login/login.module.ts index 247c79ae1e7fb41db4955f456db5bcb320ebd2f6..e2f85fed24706bec38ba330950caff4da1caa978 100644 --- a/src/app/login/login.module.ts +++ b/src/app/login/login.module.ts @@ -4,7 +4,7 @@ import { StoreModule } from '@ngrx/store'; import { EffectsModule } from '@ngrx/effects'; import { SharedModule } from '../shared/shared.module'; -import { LoginRoutingModule, routedComponents } from './login.routing'; +import { LoginRoutingModule, routedComponents } from './login-routing.module'; import { dummiesComponents } from './components'; import { reducer } from './store/login.reducer'; import { LoginEffects } from './store/login.effects'; diff --git a/src/app/search/search.routing.ts b/src/app/search/search-routing.module.ts similarity index 94% rename from src/app/search/search.routing.ts rename to src/app/search/search-routing.module.ts index f8c12fc28441d6c0c15ca4a63afaaee5f1d7c44c..30677ba44e510f763475891bfdfa996c654dbc73 100644 --- a/src/app/search/search.routing.ts +++ b/src/app/search/search-routing.module.ts @@ -9,7 +9,7 @@ import { ResultComponent } from './containers/result.component'; const routes: Routes = [ { - path: 'search', component: SearchComponent, children: [ + path: '', component: SearchComponent, children: [ { path: '', redirectTo: 'dataset', pathMatch: 'full' }, { path: 'dataset', component: DatasetComponent }, { path: 'criteria/:dname', component: CriteriaComponent }, diff --git a/src/app/search/search.module.ts b/src/app/search/search.module.ts index 593687b2f9a97c2f05d074c11cb8c48f6e95c321..eb93b0b7ae1094a123150e73018e323f4e7496ef 100644 --- a/src/app/search/search.module.ts +++ b/src/app/search/search.module.ts @@ -7,7 +7,7 @@ import { SharedModule } from '../shared/shared.module'; import { MetamodelModule } from '../metamodel/metamodel.module'; import { SearchEffects } from './store/search.effects'; import { SearchService } from './store/search.service'; -import { SearchRoutingModule, routedComponents } from './search.routing'; +import { SearchRoutingModule, routedComponents } from './search-routing.module'; import { dummiesComponents } from './components'; import { reducer } from './store/search.reducer'; diff --git a/src/app/static/static.routing.ts b/src/app/static/static-routing.module.ts similarity index 100% rename from src/app/static/static.routing.ts rename to src/app/static/static-routing.module.ts diff --git a/src/app/static/static.module.ts b/src/app/static/static.module.ts index faf30b56fb5506f77b40bc7b0acf03d849d1f21e..56af675827cdfc6bd846ddbbd279bed6053e4161 100644 --- a/src/app/static/static.module.ts +++ b/src/app/static/static.module.ts @@ -1,6 +1,6 @@ import { NgModule } from '@angular/core'; -import { StaticRoutingModule, routedComponents } from './static.routing'; +import { StaticRoutingModule, routedComponents } from './static-routing.module'; @NgModule({ imports: [StaticRoutingModule],