From b19d151e838d744f7653949ed82954cce8cbff85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Agneray?= <francois.agneray@lam.fr>
Date: Thu, 17 Jun 2021 22:54:50 +0200
Subject: [PATCH] Metamodel module work in progress

---
 client/src/app/app.module.ts                  | 24 +++++++-
 client/src/app/app.reducer.ts                 | 27 +++++++++
 client/src/app/custom-route-serializer.ts     | 28 ++++++++++
 client/src/app/metamodel/metamodel.module.ts  |  4 +-
 .../store/actions/attribute.actions.ts        |  7 +++
 .../store/actions/criteria-family.actions.ts  |  7 +++
 .../store/actions/database.actions.ts         |  2 +-
 .../store/actions/dataset-family.actions.ts   |  7 +++
 .../store/actions/dataset.actions.ts          |  7 +++
 .../metamodel/store/actions/group.actions.ts  |  7 +++
 .../store/actions/instance.actions.ts         |  7 +++
 .../store/actions/output-category.actions.ts  |  7 +++
 .../store/actions/output-family.actions.ts    |  7 +++
 .../metamodel/store/actions/survey.actions.ts |  7 +++
 .../metamodel/store/models/attribute.model.ts | 37 ++++++++++++
 .../store/models/criteria-family.model.ts     |  5 ++
 .../store/models/dataset-family.model.ts      |  5 ++
 .../metamodel/store/models/dataset.model.ts   | 51 +++++++++++++++++
 ...lumn.model.ts => db-table-column.model.ts} |  2 +-
 .../app/metamodel/store/models/group.model.ts |  6 ++
 .../src/app/metamodel/store/models/index.ts   | 11 +++-
 .../metamodel/store/models/instance.model.ts  | 20 +++++++
 .../metamodel/store/models/option.model.ts    |  5 ++
 .../store/models/output-category.model.ts     |  6 ++
 .../store/models/output-family.model.ts       |  5 ++
 .../models/renderers/renderer-config.model.ts |  3 +
 .../metamodel/store/models/survey.model.ts    |  9 +++
 .../store/reducers/attribute.reducer.ts       | 55 ++++++++++++++++++
 .../store/reducers/criteria-family.reducer.ts | 55 ++++++++++++++++++
 .../store/reducers/database.reducer.ts        | 12 ++--
 .../store/reducers/dataset-family.reducer.ts  | 55 ++++++++++++++++++
 .../store/reducers/dataset.reducer.ts         | 56 +++++++++++++++++++
 .../metamodel/store/reducers/group.reducer.ts | 56 +++++++++++++++++++
 .../src/app/metamodel/store/reducers/index.ts | 36 +++++++++---
 .../store/reducers/instance.reducer.ts        | 55 ++++++++++++++++++
 .../store/reducers/output-category.reducer.ts | 55 ++++++++++++++++++
 .../store/reducers/output-family.reducer.ts   | 55 ++++++++++++++++++
 .../store/reducers/survey.reducer.ts          | 55 ++++++++++++++++++
 .../store/selectors/database.selectors.ts     | 12 ++--
 .../store/services/attribute.service.ts       | 34 +++++++++++
 .../store/services/criteria-family.service.ts | 30 ++++++++++
 .../store/services/database.service.ts        |  6 +-
 .../store/services/dataset-family.service.ts  | 30 ++++++++++
 .../store/services/dataset.service.ts         | 30 ++++++++++
 .../metamodel/store/services/group.service.ts | 30 ++++++++++
 .../src/app/metamodel/store/services/index.ts | 18 ++++++
 .../store/services/instance.service.ts        | 30 ++++++++++
 .../store/services/output-category.service.ts | 30 ++++++++++
 .../store/services/output-family.service.ts   | 30 ++++++++++
 .../store/services/survey.service.ts          | 30 ++++++++++
 50 files changed, 1135 insertions(+), 33 deletions(-)
 create mode 100644 client/src/app/app.reducer.ts
 create mode 100644 client/src/app/custom-route-serializer.ts
 create mode 100644 client/src/app/metamodel/store/actions/attribute.actions.ts
 create mode 100644 client/src/app/metamodel/store/actions/criteria-family.actions.ts
 create mode 100644 client/src/app/metamodel/store/actions/dataset-family.actions.ts
 create mode 100644 client/src/app/metamodel/store/actions/dataset.actions.ts
 create mode 100644 client/src/app/metamodel/store/actions/group.actions.ts
 create mode 100644 client/src/app/metamodel/store/actions/instance.actions.ts
 create mode 100644 client/src/app/metamodel/store/actions/output-category.actions.ts
 create mode 100644 client/src/app/metamodel/store/actions/output-family.actions.ts
 create mode 100644 client/src/app/metamodel/store/actions/survey.actions.ts
 create mode 100644 client/src/app/metamodel/store/models/attribute.model.ts
 create mode 100644 client/src/app/metamodel/store/models/criteria-family.model.ts
 create mode 100644 client/src/app/metamodel/store/models/dataset-family.model.ts
 create mode 100644 client/src/app/metamodel/store/models/dataset.model.ts
 rename client/src/app/metamodel/store/models/{column.model.ts => db-table-column.model.ts} (54%)
 create mode 100644 client/src/app/metamodel/store/models/group.model.ts
 create mode 100644 client/src/app/metamodel/store/models/instance.model.ts
 create mode 100644 client/src/app/metamodel/store/models/option.model.ts
 create mode 100644 client/src/app/metamodel/store/models/output-category.model.ts
 create mode 100644 client/src/app/metamodel/store/models/output-family.model.ts
 create mode 100644 client/src/app/metamodel/store/models/renderers/renderer-config.model.ts
 create mode 100644 client/src/app/metamodel/store/models/survey.model.ts
 create mode 100644 client/src/app/metamodel/store/reducers/attribute.reducer.ts
 create mode 100644 client/src/app/metamodel/store/reducers/criteria-family.reducer.ts
 create mode 100644 client/src/app/metamodel/store/reducers/dataset-family.reducer.ts
 create mode 100644 client/src/app/metamodel/store/reducers/dataset.reducer.ts
 create mode 100644 client/src/app/metamodel/store/reducers/group.reducer.ts
 create mode 100644 client/src/app/metamodel/store/reducers/instance.reducer.ts
 create mode 100644 client/src/app/metamodel/store/reducers/output-category.reducer.ts
 create mode 100644 client/src/app/metamodel/store/reducers/output-family.reducer.ts
 create mode 100644 client/src/app/metamodel/store/reducers/survey.reducer.ts
 create mode 100644 client/src/app/metamodel/store/services/attribute.service.ts
 create mode 100644 client/src/app/metamodel/store/services/criteria-family.service.ts
 create mode 100644 client/src/app/metamodel/store/services/dataset-family.service.ts
 create mode 100644 client/src/app/metamodel/store/services/dataset.service.ts
 create mode 100644 client/src/app/metamodel/store/services/group.service.ts
 create mode 100644 client/src/app/metamodel/store/services/instance.service.ts
 create mode 100644 client/src/app/metamodel/store/services/output-category.service.ts
 create mode 100644 client/src/app/metamodel/store/services/output-family.service.ts
 create mode 100644 client/src/app/metamodel/store/services/survey.service.ts

diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts
index f7f17ab1..2b682964 100644
--- a/client/src/app/app.module.ts
+++ b/client/src/app/app.module.ts
@@ -11,6 +11,8 @@ import { StoreRouterConnectingModule } from '@ngrx/router-store';
 import { StoreDevtoolsModule } from '@ngrx/store-devtools';
 
 import { environment } from '../environments/environment';
+import { reducers, metaReducers } from './app.reducer';
+import { CustomSerializer } from './custom-route-serializer';
 import { MetamodelModule } from './metamodel/metamodel.module';
 
 @NgModule({
@@ -22,10 +24,26 @@ import { MetamodelModule } from './metamodel/metamodel.module';
         BrowserAnimationsModule,
         HttpClientModule,
         AppRoutingModule,
+        StoreModule.forRoot(reducers, {
+            metaReducers,
+            runtimeChecks: {
+                strictStateImmutability: true,
+                strictActionImmutability: true,
+                strictStateSerializability: true,
+                strictActionSerializability: true,
+                strictActionWithinNgZone: true,
+                strictActionTypeUniqueness: true,
+            }
+        }),
         EffectsModule.forRoot([]),
-        StoreModule.forRoot({}, {}),
-        StoreRouterConnectingModule.forRoot(),
-        StoreDevtoolsModule.instrument({ maxAge: 25, logOnly: environment.production }),
+        StoreRouterConnectingModule.forRoot({
+            serializer: CustomSerializer
+        }),
+        StoreDevtoolsModule.instrument({
+            name: 'ANIS',
+            maxAge: 25,
+            logOnly: environment.production
+        }),
         MetamodelModule
     ],
     providers: [],
diff --git a/client/src/app/app.reducer.ts b/client/src/app/app.reducer.ts
new file mode 100644
index 00000000..a0ea090f
--- /dev/null
+++ b/client/src/app/app.reducer.ts
@@ -0,0 +1,27 @@
+import { ActionReducerMap, ActionReducer, MetaReducer } from '@ngrx/store';
+ 
+import { RouterReducerState, routerReducer } from '@ngrx/router-store';
+
+export interface State {
+    router: RouterReducerState<any>;
+}
+  
+export const reducers: ActionReducerMap<State> = {
+    router: routerReducer
+};
+
+// console.log all actions
+export function debug(reducer: ActionReducer<any>): ActionReducer<any> {
+    return function(state, action) {
+        console.group(action.type);
+        const nextState = reducer(state, action);
+        console.log(`%c prev state`, `color: #9E9E9E; font-weight: bold`, state);
+        console.log(`%c action`, `color: #03A9F4; font-weight: bold`, action);
+        console.log(`%c next state`, `color: #4CAF50; font-weight: bold`, nextState);
+        console.groupEnd();
+
+        return nextState;
+    };
+}
+ 
+export const metaReducers: MetaReducer<any>[] = [debug];
diff --git a/client/src/app/custom-route-serializer.ts b/client/src/app/custom-route-serializer.ts
new file mode 100644
index 00000000..1a6b1c4b
--- /dev/null
+++ b/client/src/app/custom-route-serializer.ts
@@ -0,0 +1,28 @@
+import { Params, RouterStateSnapshot } from '@angular/router';
+import { RouterStateSerializer } from '@ngrx/router-store';
+
+export interface RouterStateUrl {
+    url: string;
+    params: Params;
+    queryParams: Params;
+}
+
+export class CustomSerializer implements RouterStateSerializer<RouterStateUrl> {
+    serialize(routerState: RouterStateSnapshot): RouterStateUrl {
+        let route = routerState.root;
+
+        while (route.firstChild) {
+            route = route.firstChild;
+        }
+
+        const {
+            url,
+            root: { queryParams },
+        } = routerState;
+        const { params } = route;
+
+        // Only return an object including the URL, params and query params
+        // instead of the entire snapshot
+        return { url, params, queryParams };
+    }
+}
\ No newline at end of file
diff --git a/client/src/app/metamodel/metamodel.module.ts b/client/src/app/metamodel/metamodel.module.ts
index 7835a16a..9a4d1474 100644
--- a/client/src/app/metamodel/metamodel.module.ts
+++ b/client/src/app/metamodel/metamodel.module.ts
@@ -4,7 +4,7 @@ import { CommonModule } from '@angular/common';
 import { StoreModule } from '@ngrx/store';
 import { EffectsModule } from '@ngrx/effects';
 
-import { reducer } from './store/reducers';
+import { metamodelReducer } from './store/reducers';
 import { metamodelEffects } from './store/effects';
 import { metamodelServices} from './store/services';
 
@@ -12,7 +12,7 @@ import { metamodelServices} from './store/services';
     declarations: [],
     imports: [
         CommonModule,
-        StoreModule.forFeature('metamodel', reducer),
+        StoreModule.forFeature('metamodel', metamodelReducer),
         EffectsModule.forFeature(metamodelEffects)
     ],
     providers: [
diff --git a/client/src/app/metamodel/store/actions/attribute.actions.ts b/client/src/app/metamodel/store/actions/attribute.actions.ts
new file mode 100644
index 00000000..e26b4b23
--- /dev/null
+++ b/client/src/app/metamodel/store/actions/attribute.actions.ts
@@ -0,0 +1,7 @@
+import { createAction, props } from '@ngrx/store';
+ 
+import { Attribute } from '../models';
+
+export const loadAttributeList = createAction('[Metamodel] Load Attribute List');
+export const loadAttributeListSuccess = createAction('[Metamodel] Load Attribute List Success', props<{ attributes: Attribute[] }>());
+export const loadAttributeListFail = createAction('[Metamodel] Load Attribute List Fail');
diff --git a/client/src/app/metamodel/store/actions/criteria-family.actions.ts b/client/src/app/metamodel/store/actions/criteria-family.actions.ts
new file mode 100644
index 00000000..aede6be0
--- /dev/null
+++ b/client/src/app/metamodel/store/actions/criteria-family.actions.ts
@@ -0,0 +1,7 @@
+import { createAction, props } from '@ngrx/store';
+ 
+import { CriteriaFamily } from '../models';
+
+export const loadCriteriaFamilyList = createAction('[Metamodel] Load Criteria Family List');
+export const loadCriteriaFamilyListSuccess = createAction('[Metamodel] Load Criteria Family List Success', props<{ criteriaFamilies: CriteriaFamily[] }>());
+export const loadCriteriaFamilyListFail = createAction('[Metamodel] Load Criteria Family List Fail');
diff --git a/client/src/app/metamodel/store/actions/database.actions.ts b/client/src/app/metamodel/store/actions/database.actions.ts
index 3d923413..c5ea9829 100644
--- a/client/src/app/metamodel/store/actions/database.actions.ts
+++ b/client/src/app/metamodel/store/actions/database.actions.ts
@@ -1,6 +1,6 @@
 import { createAction, props } from '@ngrx/store';
  
-import { Database } from '../models/database.model';
+import { Database } from '../models';
 
 export const selectDatabase = createAction('[Metamodel] Select Database', props<{ databaseId: number }>());
 export const loadDatabaseList = createAction('[Metamodel] Load Database List');
diff --git a/client/src/app/metamodel/store/actions/dataset-family.actions.ts b/client/src/app/metamodel/store/actions/dataset-family.actions.ts
new file mode 100644
index 00000000..c5d5632e
--- /dev/null
+++ b/client/src/app/metamodel/store/actions/dataset-family.actions.ts
@@ -0,0 +1,7 @@
+import { createAction, props } from '@ngrx/store';
+ 
+import { DatasetFamily } from '../models';
+
+export const loadDatasetFamilyList = createAction('[Metamodel] Load Dataset Family List');
+export const loadDatasetFamilyListSuccess = createAction('[Metamodel] Load Dataset Family List Success', props<{ datasetFamilies: DatasetFamily[] }>());
+export const loadDatasetFamilyListFail = createAction('[Metamodel] Load Dataset Family List Fail');
diff --git a/client/src/app/metamodel/store/actions/dataset.actions.ts b/client/src/app/metamodel/store/actions/dataset.actions.ts
new file mode 100644
index 00000000..a848340b
--- /dev/null
+++ b/client/src/app/metamodel/store/actions/dataset.actions.ts
@@ -0,0 +1,7 @@
+import { createAction, props } from '@ngrx/store';
+ 
+import { Dataset } from '../models';
+
+export const loadDatasetList = createAction('[Metamodel] Load Dataset List');
+export const loadDatasetListSuccess = createAction('[Metamodel] Load Dataset List Success', props<{ datasets: Dataset[] }>());
+export const loadDatasetListFail = createAction('[Metamodel] Load Dataset List Fail');
diff --git a/client/src/app/metamodel/store/actions/group.actions.ts b/client/src/app/metamodel/store/actions/group.actions.ts
new file mode 100644
index 00000000..3929418a
--- /dev/null
+++ b/client/src/app/metamodel/store/actions/group.actions.ts
@@ -0,0 +1,7 @@
+import { createAction, props } from '@ngrx/store';
+ 
+import { Group } from '../models';
+
+export const loadGroupList = createAction('[Metamodel] Load Group List');
+export const loadGroupListSuccess = createAction('[Metamodel] Load Group List Success', props<{ groups: Group[] }>());
+export const loadGroupListFail = createAction('[Metamodel] Load Group List Fail');
diff --git a/client/src/app/metamodel/store/actions/instance.actions.ts b/client/src/app/metamodel/store/actions/instance.actions.ts
new file mode 100644
index 00000000..7c7c611e
--- /dev/null
+++ b/client/src/app/metamodel/store/actions/instance.actions.ts
@@ -0,0 +1,7 @@
+import { createAction, props } from '@ngrx/store';
+ 
+import { Instance } from '../models';
+
+export const loadInstanceList = createAction('[Metamodel] Load Instance List');
+export const loadInstanceListSuccess = createAction('[Metamodel] Load Instance List Success', props<{ instances: Instance[] }>());
+export const loadInstanceListFail = createAction('[Metamodel] Load Instance List Fail');
diff --git a/client/src/app/metamodel/store/actions/output-category.actions.ts b/client/src/app/metamodel/store/actions/output-category.actions.ts
new file mode 100644
index 00000000..7b604d24
--- /dev/null
+++ b/client/src/app/metamodel/store/actions/output-category.actions.ts
@@ -0,0 +1,7 @@
+import { createAction, props } from '@ngrx/store';
+ 
+import { OutputCategory } from '../models';
+
+export const loadOutputCategoryList = createAction('[Metamodel] Load Output Category List');
+export const loadOutputCategoryListSuccess = createAction('[Metamodel] Load Output Category List Success', props<{ outputCategories: OutputCategory[] }>());
+export const loadOutputCategoryListFail = createAction('[Metamodel] Load Output Category List Fail');
diff --git a/client/src/app/metamodel/store/actions/output-family.actions.ts b/client/src/app/metamodel/store/actions/output-family.actions.ts
new file mode 100644
index 00000000..063593cc
--- /dev/null
+++ b/client/src/app/metamodel/store/actions/output-family.actions.ts
@@ -0,0 +1,7 @@
+import { createAction, props } from '@ngrx/store';
+ 
+import { OutputFamily } from '../models';
+
+export const loadOutputFamilyList = createAction('[Metamodel] Load Output Family List');
+export const loadOutputFamilyListSuccess = createAction('[Metamodel] Load Output Family List Success', props<{ outputFamilies: OutputFamily[] }>());
+export const loadOutputFamilyListFail = createAction('[Metamodel] Load Output Family List Fail');
diff --git a/client/src/app/metamodel/store/actions/survey.actions.ts b/client/src/app/metamodel/store/actions/survey.actions.ts
new file mode 100644
index 00000000..f722eec9
--- /dev/null
+++ b/client/src/app/metamodel/store/actions/survey.actions.ts
@@ -0,0 +1,7 @@
+import { createAction, props } from '@ngrx/store';
+ 
+import { Survey } from '../models';
+
+export const loadSurveyList = createAction('[Metamodel] Load Survey List');
+export const loadSurveyListSuccess = createAction('[Metamodel] Load Survey List Success', props<{ surveys: Survey[] }>());
+export const loadSurveyListFail = createAction('[Metamodel] Load Survey List Fail');
diff --git a/client/src/app/metamodel/store/models/attribute.model.ts b/client/src/app/metamodel/store/models/attribute.model.ts
new file mode 100644
index 00000000..37c6623a
--- /dev/null
+++ b/client/src/app/metamodel/store/models/attribute.model.ts
@@ -0,0 +1,37 @@
+import { Option } from './option.model';
+import { RendererConfig } from './renderers/renderer-config.model';
+
+export interface Attribute {
+    id: number;
+    name: string;
+    label: string;
+    form_label: string;
+    description?: string;
+    output_display: number;
+    criteria_display: number;
+    search_flag?: string;
+    search_type?: string;
+    operator?: string;
+    type: string;
+    min?: string;
+    max?: string;
+    placeholder_min?: string;
+    placeholder_max?: string;
+    renderer?: string;
+    renderer_config?: RendererConfig;
+    display_detail: number;
+    selected?: boolean;
+    order_by?: boolean;
+    order_display?: number;
+    detail?: boolean;
+    renderer_detail?: string;
+    options?: Option[];
+    vo_utype?: string;
+    vo_ucd?: string;
+    vo_unit?: string;
+    vo_description?: string;
+    vo_datatype?: string;
+    vo_size?: number;
+    id_criteria_family?: number;
+    id_output_category?: number;
+}
diff --git a/client/src/app/metamodel/store/models/criteria-family.model.ts b/client/src/app/metamodel/store/models/criteria-family.model.ts
new file mode 100644
index 00000000..bc7c1adb
--- /dev/null
+++ b/client/src/app/metamodel/store/models/criteria-family.model.ts
@@ -0,0 +1,5 @@
+export interface CriteriaFamily {
+    id: number;
+    label: string;
+    display: number;
+}
diff --git a/client/src/app/metamodel/store/models/dataset-family.model.ts b/client/src/app/metamodel/store/models/dataset-family.model.ts
new file mode 100644
index 00000000..b7f9ef3a
--- /dev/null
+++ b/client/src/app/metamodel/store/models/dataset-family.model.ts
@@ -0,0 +1,5 @@
+export interface DatasetFamily {
+    id: number;
+    label: string;
+    display: number;
+}
diff --git a/client/src/app/metamodel/store/models/dataset.model.ts b/client/src/app/metamodel/store/models/dataset.model.ts
new file mode 100644
index 00000000..49adb32e
--- /dev/null
+++ b/client/src/app/metamodel/store/models/dataset.model.ts
@@ -0,0 +1,51 @@
+export interface Dataset {
+    name: string;
+    table_ref: string;
+    label: string;
+    description: string;
+    display: number;
+    count: number;
+    vo: boolean;
+    data_path: string;
+    survey_name: string;
+    id_dataset_family: number;
+    public: boolean;
+    config: {
+        images: any[],
+        cone_search: {
+            enabled: boolean;
+            opened: boolean;
+            column_ra: number;
+            column_dec: number;
+            plot_enabled: boolean;
+            sdss_enabled: boolean;
+            sdss_display: number;
+            background: {id: number, enabled: boolean, display: number}[];
+        },
+        download: {
+            enabled: boolean;
+            opened: boolean;
+            csv: boolean;
+            ascii: boolean;
+            vo: boolean;
+            archive: boolean;
+        },
+        summary: {
+            enabled: boolean;
+            opened: boolean;
+        },
+        server_link: {
+            enabled: boolean;
+            opened: boolean;
+        },
+        samp: {
+            enabled: boolean;
+            opened: boolean;
+        },
+        datatable: {
+            enabled: boolean;
+            opened: boolean;
+            selectable_row: boolean;
+        }
+    };
+}
diff --git a/client/src/app/metamodel/store/models/column.model.ts b/client/src/app/metamodel/store/models/db-table-column.model.ts
similarity index 54%
rename from client/src/app/metamodel/store/models/column.model.ts
rename to client/src/app/metamodel/store/models/db-table-column.model.ts
index 91d30c9a..10fc6f89 100644
--- a/client/src/app/metamodel/store/models/column.model.ts
+++ b/client/src/app/metamodel/store/models/db-table-column.model.ts
@@ -1,4 +1,4 @@
-export interface Column {
+export interface DbTableColumn {
     name: string;
     type: string;
 };
diff --git a/client/src/app/metamodel/store/models/group.model.ts b/client/src/app/metamodel/store/models/group.model.ts
new file mode 100644
index 00000000..b04388d9
--- /dev/null
+++ b/client/src/app/metamodel/store/models/group.model.ts
@@ -0,0 +1,6 @@
+export interface Group {
+    id: number;
+    role: string;
+    instance_name: string;
+    datasets: string[];
+}
diff --git a/client/src/app/metamodel/store/models/index.ts b/client/src/app/metamodel/store/models/index.ts
index 76f294eb..ea13dcb4 100644
--- a/client/src/app/metamodel/store/models/index.ts
+++ b/client/src/app/metamodel/store/models/index.ts
@@ -1,2 +1,11 @@
 export * from './database.model';
-export * from './column.model';
+export * from './db-table-column.model';
+export * from './survey.model';
+export * from './group.model';
+export * from './dataset.model';
+export * from './dataset-family.model';
+export * from './instance.model';
+export * from './attribute.model';
+export * from './criteria-family.model';
+export * from './output-category.model';
+export * from './output-family.model';
diff --git a/client/src/app/metamodel/store/models/instance.model.ts b/client/src/app/metamodel/store/models/instance.model.ts
new file mode 100644
index 00000000..8b0db4c7
--- /dev/null
+++ b/client/src/app/metamodel/store/models/instance.model.ts
@@ -0,0 +1,20 @@
+export interface Instance {
+    name: string;
+    label: string;
+    client_url: string;
+    config: {
+        authentication: {
+            allowed: boolean;
+        };
+        search: {
+            allowed: boolean;
+        };
+        search_multiple: {
+            allowed: boolean;
+            all_datasets_selected: boolean;
+        };
+        documentation: {
+            allowed: boolean;
+        };
+    };
+}
diff --git a/client/src/app/metamodel/store/models/option.model.ts b/client/src/app/metamodel/store/models/option.model.ts
new file mode 100644
index 00000000..674fb0f4
--- /dev/null
+++ b/client/src/app/metamodel/store/models/option.model.ts
@@ -0,0 +1,5 @@
+export interface Option {
+    label: string;
+    value: string;
+    display: number;
+}
diff --git a/client/src/app/metamodel/store/models/output-category.model.ts b/client/src/app/metamodel/store/models/output-category.model.ts
new file mode 100644
index 00000000..924f590e
--- /dev/null
+++ b/client/src/app/metamodel/store/models/output-category.model.ts
@@ -0,0 +1,6 @@
+export interface OutputCategory {
+    id: number;
+    label: string;
+    display: number;
+    id_output_family: number;
+}
diff --git a/client/src/app/metamodel/store/models/output-family.model.ts b/client/src/app/metamodel/store/models/output-family.model.ts
new file mode 100644
index 00000000..1e973030
--- /dev/null
+++ b/client/src/app/metamodel/store/models/output-family.model.ts
@@ -0,0 +1,5 @@
+export interface OutputFamily {
+    id: number;
+    label: string;
+    display: number;
+}
diff --git a/client/src/app/metamodel/store/models/renderers/renderer-config.model.ts b/client/src/app/metamodel/store/models/renderers/renderer-config.model.ts
new file mode 100644
index 00000000..d4ecedfa
--- /dev/null
+++ b/client/src/app/metamodel/store/models/renderers/renderer-config.model.ts
@@ -0,0 +1,3 @@
+export interface RendererConfig {
+    id: 'renderer-config';
+}
diff --git a/client/src/app/metamodel/store/models/survey.model.ts b/client/src/app/metamodel/store/models/survey.model.ts
new file mode 100644
index 00000000..3a222906
--- /dev/null
+++ b/client/src/app/metamodel/store/models/survey.model.ts
@@ -0,0 +1,9 @@
+export interface Survey {
+    name: string;
+    label: string;
+    description: string;
+    link: string;
+    manager: string;
+    id_database: number;
+    nb_datasets: number;
+}
diff --git a/client/src/app/metamodel/store/reducers/attribute.reducer.ts b/client/src/app/metamodel/store/reducers/attribute.reducer.ts
new file mode 100644
index 00000000..f87fc7a3
--- /dev/null
+++ b/client/src/app/metamodel/store/reducers/attribute.reducer.ts
@@ -0,0 +1,55 @@
+import { createReducer, on } from '@ngrx/store';
+import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
+
+import { Attribute } from '../models';
+import * as attributeActions from '../actions/attribute.actions';
+
+export interface State extends EntityState<Attribute> {
+    attributeListIsLoading: boolean;
+    attributeListIsLoaded: boolean;
+}
+
+export const adapter: EntityAdapter<Attribute> = createEntityAdapter<Attribute>();
+
+export const initialState: State = adapter.getInitialState({
+    attributeListIsLoading: false,
+    attributeListIsLoaded: false
+});
+
+export const attributeReducer = createReducer(
+    initialState,
+    on(attributeActions.loadAttributeList, (state) => {
+        return {
+            ...state,
+            attributeListIsLoading: true
+        }
+    }),
+    on(attributeActions.loadAttributeListSuccess, (state, { attributes }) => {
+        return adapter.setAll(
+            attributes, 
+            { 
+                ...state,
+                attributeListIsLoading: false,
+                attributeListIsLoaded: true
+            }
+        );
+    }),
+    on(attributeActions.loadAttributeListFail, (state) => {
+        return {
+            ...state,
+            attributeListIsLoaded: false
+        }
+    })
+);
+
+const {
+    selectIds,
+    selectEntities,
+    selectAll,
+    selectTotal,
+} = adapter.getSelectors();
+
+export const selectAttributeIds = selectIds;
+export const selectAttributeEntities = selectEntities;
+export const selectAllAttributes = selectAll;
+export const selectAttributeTotal = selectTotal;
diff --git a/client/src/app/metamodel/store/reducers/criteria-family.reducer.ts b/client/src/app/metamodel/store/reducers/criteria-family.reducer.ts
new file mode 100644
index 00000000..95d64387
--- /dev/null
+++ b/client/src/app/metamodel/store/reducers/criteria-family.reducer.ts
@@ -0,0 +1,55 @@
+import { createReducer, on } from '@ngrx/store';
+import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
+
+import { CriteriaFamily } from '../models';
+import * as criteriaFamilyActions from '../actions/criteria-family.actions';
+
+export interface State extends EntityState<CriteriaFamily> {
+    criteriaFamilyListIsLoading: boolean;
+    criteriaFamilyListIsLoaded: boolean;
+}
+
+export const adapter: EntityAdapter<CriteriaFamily> = createEntityAdapter<CriteriaFamily>();
+
+export const initialState: State = adapter.getInitialState({
+    criteriaFamilyListIsLoading: false,
+    criteriaFamilyListIsLoaded: false
+});
+
+export const criteriaFamilyReducer = createReducer(
+    initialState,
+    on(criteriaFamilyActions.loadCriteriaFamilyList, (state) => {
+        return {
+            ...state,
+            criteriaFamilyListIsLoading: true
+        }
+    }),
+    on(criteriaFamilyActions.loadCriteriaFamilyListSuccess, (state, { criteriaFamilies }) => {
+        return adapter.setAll(
+            criteriaFamilies, 
+            { 
+                ...state,
+                criteriaFamilyListIsLoading: false,
+                criteriaFamilyListIsLoaded: true
+            }
+        );
+    }),
+    on(criteriaFamilyActions.loadCriteriaFamilyListFail, (state) => {
+        return {
+            ...state,
+            criteriaFamilyListIsLoaded: false
+        }
+    })
+);
+
+const {
+    selectIds,
+    selectEntities,
+    selectAll,
+    selectTotal,
+} = adapter.getSelectors();
+
+export const selectCriteriaFamilyIds = selectIds;
+export const selectCriteriaFamilyEntities = selectEntities;
+export const selectAllCriteriaFamilies = selectAll;
+export const selectCriteriaFamilyTotal = selectTotal;
diff --git a/client/src/app/metamodel/store/reducers/database.reducer.ts b/client/src/app/metamodel/store/reducers/database.reducer.ts
index 2271a8d4..b7b2e39c 100644
--- a/client/src/app/metamodel/store/reducers/database.reducer.ts
+++ b/client/src/app/metamodel/store/reducers/database.reducer.ts
@@ -1,7 +1,7 @@
-import { Action, createReducer, on } from '@ngrx/store';
+import { createReducer, on } from '@ngrx/store';
 import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
 
-import { Database } from '../models/database.model';
+import { Database } from '../models';
 import * as databaseActions from '../actions/database.actions';
 
 export interface State extends EntityState<Database> {
@@ -20,7 +20,7 @@ export const initialState: State = adapter.getInitialState({
     databaseListIsLoaded: false
 });
 
-const databaseReducer = createReducer(
+export const databaseReducer = createReducer(
     initialState,
     on(databaseActions.selectDatabase, (state, { databaseId }) => {
         return {
@@ -52,10 +52,6 @@ const databaseReducer = createReducer(
     })
 );
 
-export function reducer(state: State | undefined, action: Action) {
-    return databaseReducer(state, action);
-}
-
 export const getSelectedDatabaseId = (state: State) => state.selectedDatabaseId;
 
 // get the selectors
@@ -76,4 +72,4 @@ export const selectDatabaseEntities = selectEntities;
 export const selectAllDatabases = selectAll;
 
 // select the total database count
-export const selectDatabaseTotal = selectTotal;
\ No newline at end of file
+export const selectDatabaseTotal = selectTotal;
diff --git a/client/src/app/metamodel/store/reducers/dataset-family.reducer.ts b/client/src/app/metamodel/store/reducers/dataset-family.reducer.ts
new file mode 100644
index 00000000..67695433
--- /dev/null
+++ b/client/src/app/metamodel/store/reducers/dataset-family.reducer.ts
@@ -0,0 +1,55 @@
+import { createReducer, on } from '@ngrx/store';
+import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
+
+import { DatasetFamily } from '../models';
+import * as datasetFamilyActions from '../actions/dataset-family.actions';
+
+export interface State extends EntityState<DatasetFamily> {
+    datasetFamilyListIsLoading: boolean;
+    datasetFamilyListIsLoaded: boolean;
+}
+
+export const adapter: EntityAdapter<DatasetFamily> = createEntityAdapter<DatasetFamily>();
+
+export const initialState: State = adapter.getInitialState({
+    datasetFamilyListIsLoading: false,
+    datasetFamilyListIsLoaded: false
+});
+
+export const datasetFamilyReducer = createReducer(
+    initialState,
+    on(datasetFamilyActions.loadDatasetFamilyList, (state) => {
+        return {
+            ...state,
+            datasetFamilyListIsLoading: true
+        }
+    }),
+    on(datasetFamilyActions.loadDatasetFamilyListSuccess, (state, { datasetFamilies }) => {
+        return adapter.setAll(
+            datasetFamilies, 
+            { 
+                ...state,
+                datasetFamilyListIsLoading: false,
+                datasetFamilyListIsLoaded: true
+            }
+        );
+    }),
+    on(datasetFamilyActions.loadDatasetFamilyListFail, (state) => {
+        return {
+            ...state,
+            datasetFamilyListIsLoaded: false
+        }
+    })
+);
+
+const {
+    selectIds,
+    selectEntities,
+    selectAll,
+    selectTotal,
+} = adapter.getSelectors();
+
+export const selectDatasetFamilyIds = selectIds;
+export const selectDatasetFamilyEntities = selectEntities;
+export const selectAllDatasetFamilies = selectAll;
+export const selectDatasetFamilyTotal = selectTotal;
diff --git a/client/src/app/metamodel/store/reducers/dataset.reducer.ts b/client/src/app/metamodel/store/reducers/dataset.reducer.ts
new file mode 100644
index 00000000..5b9dd2b5
--- /dev/null
+++ b/client/src/app/metamodel/store/reducers/dataset.reducer.ts
@@ -0,0 +1,56 @@
+import { createReducer, on } from '@ngrx/store';
+import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
+
+import { Dataset } from '../models';
+import * as datasetActions from '../actions/dataset.actions';
+
+export interface State extends EntityState<Dataset> {
+    datasetListIsLoading: boolean;
+    datasetListIsLoaded: boolean;
+}
+
+export const adapter: EntityAdapter<Dataset> = createEntityAdapter<Dataset>();
+
+export const initialState: State = adapter.getInitialState({
+    datasetListIsLoading: false,
+    datasetListIsLoaded: false
+});
+
+export const datasetReducer = createReducer(
+    initialState,
+    on(datasetActions.loadDatasetList, (state) => {
+        return {
+            ...state,
+            datasetListIsLoading: true
+        }
+    }),
+    on(datasetActions.loadDatasetListSuccess, (state, { datasets }) => {
+        return adapter.setAll(
+            datasets, 
+            { 
+                ...state,
+                datasetListIsLoading: false,
+                datasetListIsLoaded: true
+            }
+        );
+    }),
+    on(datasetActions.loadDatasetListFail, (state) => {
+        return {
+            ...state,
+            datasetListIsLoading: false
+        }
+    })
+);
+
+const {
+    selectIds,
+    selectEntities,
+    selectAll,
+    selectTotal,
+} = adapter.getSelectors();
+
+
+export const selectDatasetIds = selectIds;
+export const selectDatasetEntities = selectEntities;
+export const selectAllDatasets = selectAll;
+export const selectDatasetTotal = selectTotal;
diff --git a/client/src/app/metamodel/store/reducers/group.reducer.ts b/client/src/app/metamodel/store/reducers/group.reducer.ts
new file mode 100644
index 00000000..74fac263
--- /dev/null
+++ b/client/src/app/metamodel/store/reducers/group.reducer.ts
@@ -0,0 +1,56 @@
+import { createReducer, on } from '@ngrx/store';
+import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
+
+import { Group } from '../models';
+import * as groupActions from '../actions/group.actions';
+
+export interface State extends EntityState<Group> {
+    groupListIsLoading: boolean;
+    groupListIsLoaded: boolean;
+}
+
+export const adapter: EntityAdapter<Group> = createEntityAdapter<Group>();
+
+export const initialState: State = adapter.getInitialState({
+    groupListIsLoading: false,
+    groupListIsLoaded: false
+});
+
+export const groupReducer = createReducer(
+    initialState,
+    on(groupActions.loadGroupList, (state) => {
+        return {
+            ...state,
+            groupListIsLoading: true
+        }
+    }),
+    on(groupActions.loadGroupListSuccess, (state, { groups }) => {
+        return adapter.setAll(
+            groups, 
+            { 
+                ...state,
+                groupListIsLoading: false,
+                groupListIsLoaded: true
+            }
+        );
+    }),
+    on(groupActions.loadGroupListFail, (state) => {
+        return {
+            ...state,
+            groupListIsLoading: false
+        }
+    })
+);
+
+const {
+    selectIds,
+    selectEntities,
+    selectAll,
+    selectTotal,
+} = adapter.getSelectors();
+
+
+export const selectGroupIds = selectIds;
+export const selectGroupEntities = selectEntities;
+export const selectAllGroups = selectAll;
+export const selectGroupTotal = selectTotal;
diff --git a/client/src/app/metamodel/store/reducers/index.ts b/client/src/app/metamodel/store/reducers/index.ts
index 6cc59d14..3e3e5605 100644
--- a/client/src/app/metamodel/store/reducers/index.ts
+++ b/client/src/app/metamodel/store/reducers/index.ts
@@ -1,19 +1,41 @@
 import { combineReducers, createFeatureSelector } from '@ngrx/store';
 
 import * as database from './database.reducer';
+import * as survey from './survey.reducer';
+import * as group from './group.reducer';
+import * as dataset from './dataset.reducer';
+import * as datasetFamily from './dataset-family.reducer';
+import * as instance from './instance.reducer';
+import * as attribute from './attribute.reducer';
+import * as criteriaFamily from './criteria-family.reducer';
+import * as outputCategory from './output-category.reducer';
+import * as outputFamily from './output-family.reducer';
 
 export interface State {
     database: database.State;
+    survey: survey.State;
+    group: group.State;
+    dataset: dataset.State;
+    datasetFamily: datasetFamily.State;
+    instance: instance.State;
+    attribute: attribute.State;
+    criteriaFamily: criteriaFamily.State;
+    outputCategory: outputCategory.State;
+    outputFamily: outputFamily.State;
 }
 
 const reducers = {
-    database: database.reducer
+    database: database.databaseReducer,
+    survey: survey.surveyReducer,
+    group: group.groupReducer,
+    dataset: dataset.datasetReducer,
+    datasetFamily: datasetFamily.datasetFamilyReducer,
+    instance: instance.instanceReducer,
+    attribute: attribute.attributeReducer,
+    criteriaFamily: criteriaFamily.criteriaFamilyReducer,
+    outputCategory: outputCategory.outputCategoryReducer,
+    outputFamily: outputFamily.outputFamilyReducer
 };
 
-const productionReducer = combineReducers(reducers);
-
-export function reducer(state: any, action: any) {
-    return productionReducer(state, action);
-}
-
+export const metamodelReducer = combineReducers(reducers);
 export const getMetamodelState = createFeatureSelector<State>('metamodel');
diff --git a/client/src/app/metamodel/store/reducers/instance.reducer.ts b/client/src/app/metamodel/store/reducers/instance.reducer.ts
new file mode 100644
index 00000000..eee53cc9
--- /dev/null
+++ b/client/src/app/metamodel/store/reducers/instance.reducer.ts
@@ -0,0 +1,55 @@
+import { createReducer, on } from '@ngrx/store';
+import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
+
+import { Instance } from '../models';
+import * as instanceActions from '../actions/instance.actions';
+
+export interface State extends EntityState<Instance> {
+    instanceListIsLoading: boolean;
+    instanceListIsLoaded: boolean;
+}
+
+export const adapter: EntityAdapter<Instance> = createEntityAdapter<Instance>();
+
+export const initialState: State = adapter.getInitialState({
+    instanceListIsLoading: false,
+    instanceListIsLoaded: false
+});
+
+export const instanceReducer = createReducer(
+    initialState,
+    on(instanceActions.loadInstanceList, (state) => {
+        return {
+            ...state,
+            instanceListIsLoading: true
+        }
+    }),
+    on(instanceActions.loadInstanceListSuccess, (state, { instances }) => {
+        return adapter.setAll(
+            instances, 
+            { 
+                ...state,
+                instanceListIsLoading: false,
+                instanceListIsLoaded: true
+            }
+        );
+    }),
+    on(instanceActions.loadInstanceListFail, (state) => {
+        return {
+            ...state,
+            instanceListIsLoaded: false
+        }
+    })
+);
+
+const {
+    selectIds,
+    selectEntities,
+    selectAll,
+    selectTotal,
+} = adapter.getSelectors();
+
+export const selectInstanceIds = selectIds;
+export const selectInstanceEntities = selectEntities;
+export const selectAllInstances = selectAll;
+export const selectInstanceTotal = selectTotal;
diff --git a/client/src/app/metamodel/store/reducers/output-category.reducer.ts b/client/src/app/metamodel/store/reducers/output-category.reducer.ts
new file mode 100644
index 00000000..691f2204
--- /dev/null
+++ b/client/src/app/metamodel/store/reducers/output-category.reducer.ts
@@ -0,0 +1,55 @@
+import { createReducer, on } from '@ngrx/store';
+import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
+
+import { OutputCategory } from '../models';
+import * as outputCategoryActions from '../actions/output-category.actions';
+
+export interface State extends EntityState<OutputCategory> {
+    outputCategoryListIsLoading: boolean;
+    outputCategoryListIsLoaded: boolean;
+}
+
+export const adapter: EntityAdapter<OutputCategory> = createEntityAdapter<OutputCategory>();
+
+export const initialState: State = adapter.getInitialState({
+    outputCategoryListIsLoading: false,
+    outputCategoryListIsLoaded: false
+});
+
+export const outputCategoryReducer = createReducer(
+    initialState,
+    on(outputCategoryActions.loadOutputCategoryList, (state) => {
+        return {
+            ...state,
+            outputCategoryListIsLoading: true
+        }
+    }),
+    on(outputCategoryActions.loadOutputCategoryListSuccess, (state, { outputCategories }) => {
+        return adapter.setAll(
+            outputCategories, 
+            { 
+                ...state,
+                outputCategoryListIsLoading: false,
+                outputCategoryListIsLoaded: true
+            }
+        );
+    }),
+    on(outputCategoryActions.loadOutputCategoryListFail, (state) => {
+        return {
+            ...state,
+            outputCategoryListIsLoaded: false
+        }
+    })
+);
+
+const {
+    selectIds,
+    selectEntities,
+    selectAll,
+    selectTotal,
+} = adapter.getSelectors();
+
+export const selectOutputCategoryIds = selectIds;
+export const selectOutputCategoryEntities = selectEntities;
+export const selectAllOutputCategories = selectAll;
+export const selectOutputCategoryTotal = selectTotal;
diff --git a/client/src/app/metamodel/store/reducers/output-family.reducer.ts b/client/src/app/metamodel/store/reducers/output-family.reducer.ts
new file mode 100644
index 00000000..22e4ac63
--- /dev/null
+++ b/client/src/app/metamodel/store/reducers/output-family.reducer.ts
@@ -0,0 +1,55 @@
+import { createReducer, on } from '@ngrx/store';
+import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
+
+import { OutputFamily } from '../models';
+import * as outputFamilyActions from '../actions/output-family.actions';
+
+export interface State extends EntityState<OutputFamily> {
+    outputFamilyListIsLoading: boolean;
+    outputFamilyListIsLoaded: boolean;
+}
+
+export const adapter: EntityAdapter<OutputFamily> = createEntityAdapter<OutputFamily>();
+
+export const initialState: State = adapter.getInitialState({
+    outputFamilyListIsLoading: false,
+    outputFamilyListIsLoaded: false
+});
+
+export const outputFamilyReducer = createReducer(
+    initialState,
+    on(outputFamilyActions.loadOutputFamilyList, (state) => {
+        return {
+            ...state,
+            outputFamilyListIsLoading: true
+        }
+    }),
+    on(outputFamilyActions.loadOutputFamilyListSuccess, (state, { outputFamilies }) => {
+        return adapter.setAll(
+            outputFamilies, 
+            { 
+                ...state,
+                outputFamilyListIsLoading: false,
+                outputFamilyListIsLoaded: true
+            }
+        );
+    }),
+    on(outputFamilyActions.loadOutputFamilyListFail, (state) => {
+        return {
+            ...state,
+            outputFamilyListIsLoaded: false
+        }
+    })
+);
+
+const {
+    selectIds,
+    selectEntities,
+    selectAll,
+    selectTotal,
+} = adapter.getSelectors();
+
+export const selectOutputFamilyIds = selectIds;
+export const selectOutputFamilyEntities = selectEntities;
+export const selectAllOutputFamilies = selectAll;
+export const selectOutputFamilyTotal = selectTotal;
diff --git a/client/src/app/metamodel/store/reducers/survey.reducer.ts b/client/src/app/metamodel/store/reducers/survey.reducer.ts
new file mode 100644
index 00000000..09fc82b1
--- /dev/null
+++ b/client/src/app/metamodel/store/reducers/survey.reducer.ts
@@ -0,0 +1,55 @@
+import { createReducer, on } from '@ngrx/store';
+import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
+
+import { Survey } from '../models';
+import * as surveyActions from '../actions/survey.actions';
+
+export interface State extends EntityState<Survey> {
+    surveyListIsLoading: boolean;
+    surveyListIsLoaded: boolean;
+}
+
+export const adapter: EntityAdapter<Survey> = createEntityAdapter<Survey>();
+
+export const initialState: State = adapter.getInitialState({
+    surveyListIsLoading: false,
+    surveyListIsLoaded: false
+});
+
+export const surveyReducer = createReducer(
+    initialState,
+    on(surveyActions.loadSurveyList, (state) => {
+        return {
+            ...state,
+            surveyListIsLoading: true
+        }
+    }),
+    on(surveyActions.loadSurveyListSuccess, (state, { surveys }) => {
+        return adapter.setAll(
+            surveys, 
+            { 
+                ...state,
+                surveyListIsLoading: false,
+                surveyListIsLoaded: true
+            }
+        );
+    }),
+    on(surveyActions.loadSurveyListFail, (state) => {
+        return {
+            ...state,
+            surveyListIsLoaded: false
+        }
+    })
+);
+
+const {
+    selectIds,
+    selectEntities,
+    selectAll,
+    selectTotal,
+} = adapter.getSelectors();
+
+export const selectSurveyIds = selectIds;
+export const selectSurveyEntities = selectEntities;
+export const selectAllSurveys = selectAll;
+export const selectSurveyTotal = selectTotal;
diff --git a/client/src/app/metamodel/store/selectors/database.selectors.ts b/client/src/app/metamodel/store/selectors/database.selectors.ts
index c6b81492..023a7914 100644
--- a/client/src/app/metamodel/store/selectors/database.selectors.ts
+++ b/client/src/app/metamodel/store/selectors/database.selectors.ts
@@ -1,4 +1,4 @@
-import { createSelector, createFeatureSelector } from '@ngrx/store';
+import { createSelector } from '@ngrx/store';
 
 import * as reducer from '../reducers';
 import * as fromDatabase from '../reducers/database.reducer';
@@ -12,25 +12,23 @@ export const selectDatabaseIds = createSelector(
     selectDatabaseState,
     fromDatabase.selectDatabaseIds
 );
+
 export const selectDatabaseEntities = createSelector(
     selectDatabaseState,
     fromDatabase.selectDatabaseEntities
 );
+
 export const selectAllDatabases = createSelector(
     selectDatabaseState,
     fromDatabase.selectAllDatabases
 );
+
 export const selectDatabaseTotal = createSelector(
     selectDatabaseState,
     fromDatabase.selectDatabaseTotal
 );
+
 export const selectCurrentDatabaseId = createSelector(
     selectDatabaseState,
     fromDatabase.getSelectedDatabaseId
 );
- 
-// export const selectCurrentUser = createSelector(
-//     selectDatabaseState,
-//     selectCurrentDatabaseId,
-//     (databaseEntities, databaseId) => databaseEntities[databaseId]
-// );
\ No newline at end of file
diff --git a/client/src/app/metamodel/store/services/attribute.service.ts b/client/src/app/metamodel/store/services/attribute.service.ts
new file mode 100644
index 00000000..d4d18953
--- /dev/null
+++ b/client/src/app/metamodel/store/services/attribute.service.ts
@@ -0,0 +1,34 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+
+import { Observable } from 'rxjs';
+
+import { Attribute } from '../models';
+import { environment } from 'src/environments/environment';
+
+@Injectable()
+export class AttributeService {
+    private API_PATH: string = environment.apiUrl + '/';
+
+    constructor(private http: HttpClient) { }
+
+    retrieveAttributeList(datasetName: string): Observable<Attribute[]> {
+        return this.http.get<Attribute[]>(this.API_PATH + 'dataset/' + datasetName + '/attribute');
+    }
+
+    addAttribute(datasetName: string, attribute: Attribute): Observable<Attribute> {
+        return this.http.post<Attribute>(this.API_PATH + 'dataset/' + datasetName + '/attribute', attribute);
+    }
+
+    editAttribute(datasetName: string, attribute: Attribute): Observable<Attribute> {
+        return this.http.put<Attribute>(this.API_PATH + 'dataset/' + datasetName + '/attribute/' + attribute.id, attribute);
+    }
+
+    deleteAttribute(datasetName: string, attribute: Attribute) {
+        return this.http.delete(this.API_PATH + 'dataset/' + datasetName + '/attribute/' + attribute.id); 
+    }
+
+    generateOptionList(datasetName: string, attribute: Attribute): Observable<string[]> {
+        return this.http.get<string[]>(this.API_PATH + 'dataset/' + datasetName + '/attribute/' + attribute.id + '/distinct');
+    }
+}
diff --git a/client/src/app/metamodel/store/services/criteria-family.service.ts b/client/src/app/metamodel/store/services/criteria-family.service.ts
new file mode 100644
index 00000000..afb8fe87
--- /dev/null
+++ b/client/src/app/metamodel/store/services/criteria-family.service.ts
@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+
+import { Observable } from 'rxjs';
+
+import { CriteriaFamily } from '../models';
+import { environment } from 'src/environments/environment';
+
+@Injectable()
+export class CriteriaFamilyService {
+    private API_PATH: string = environment.apiUrl + '/';
+
+    constructor(private http: HttpClient) { }
+
+    retrieveCriteriaFamilyList(datasetName: string): Observable<CriteriaFamily[]> {
+        return this.http.get<CriteriaFamily[]>(this.API_PATH + 'dataset/' + datasetName + '/criteria-family');
+    }
+
+    addCriteriaFamily(datasetName: string, newCriteriaFamily: CriteriaFamily): Observable<CriteriaFamily> {
+        return this.http.post<CriteriaFamily>(this.API_PATH + 'dataset/' + datasetName + '/criteria-family', newCriteriaFamily);
+    }
+
+    editCriteriaFamily(criteriaFamily: CriteriaFamily): Observable<CriteriaFamily> {
+        return this.http.put<CriteriaFamily>(this.API_PATH + 'criteria-family/' + criteriaFamily.id, criteriaFamily);
+    }
+
+    deleteCriteriaFamily(criteriaFamilyId: number) {
+        return this.http.delete(this.API_PATH + 'criteria-family/' + criteriaFamilyId);
+    }
+}
diff --git a/client/src/app/metamodel/store/services/database.service.ts b/client/src/app/metamodel/store/services/database.service.ts
index 8ee883d2..f06ea28a 100644
--- a/client/src/app/metamodel/store/services/database.service.ts
+++ b/client/src/app/metamodel/store/services/database.service.ts
@@ -3,8 +3,8 @@ import { HttpClient } from '@angular/common/http';
 
 import { Observable } from 'rxjs';
 
-import { Database, Column } from '../models';
-import { environment } from '../../../../environments/environment';
+import { Database, DbTableColumn } from '../models';
+import { environment } from 'src/environments/environment';
 
 @Injectable()
 export class DatabaseService {
@@ -21,7 +21,7 @@ export class DatabaseService {
     }
     
     retrieveColumns(datasetName: string) {
-        return this.http.get<Column[]>(this.API_PATH + 'dataset/' + datasetName + '/column');
+        return this.http.get<DbTableColumn[]>(this.API_PATH + 'dataset/' + datasetName + '/column');
     }
 
     addDatabase(newDatabase: Database): Observable<Database> {
diff --git a/client/src/app/metamodel/store/services/dataset-family.service.ts b/client/src/app/metamodel/store/services/dataset-family.service.ts
new file mode 100644
index 00000000..e4286030
--- /dev/null
+++ b/client/src/app/metamodel/store/services/dataset-family.service.ts
@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+
+import { Observable } from 'rxjs';
+
+import { DatasetFamily } from '../models';
+import { environment } from 'src/environments/environment';
+
+@Injectable()
+export class DatasetFamilyService {
+    private API_PATH: string = environment.apiUrl + '/';
+
+    constructor(private http: HttpClient) { }
+
+    retrieveDatasetFamilyList(instanceName: string): Observable<DatasetFamily[]> {
+        return this.http.get<DatasetFamily[]>(this.API_PATH + 'instance/' + instanceName + '/dataset-family');
+    }
+
+    addDatasetFamily(instanceName: string, newDatasetFamily: DatasetFamily): Observable<DatasetFamily> {
+        return this.http.post<DatasetFamily>(this.API_PATH + 'instance/' + instanceName + '/dataset-family', newDatasetFamily);
+    }
+
+    editDatasetFamily(datasetFamily: DatasetFamily): Observable<DatasetFamily> {
+        return this.http.put<DatasetFamily>(this.API_PATH + 'dataset-family/' + datasetFamily.id, datasetFamily);
+    }
+
+    deleteDatasetFamily(datasetFamilyId: number) {
+        return this.http.delete(this.API_PATH + 'dataset-family/' + datasetFamilyId);
+    }
+}
diff --git a/client/src/app/metamodel/store/services/dataset.service.ts b/client/src/app/metamodel/store/services/dataset.service.ts
new file mode 100644
index 00000000..affc82d8
--- /dev/null
+++ b/client/src/app/metamodel/store/services/dataset.service.ts
@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+
+import { Observable } from 'rxjs';
+
+import { Dataset } from '../models';
+import { environment } from 'src/environments/environment';
+
+@Injectable()
+export class DatasetService {
+    private API_PATH: string = environment.apiUrl + '/';
+
+    constructor(private http: HttpClient) { }
+
+    retrieveDatasetList(instanceName: string): Observable<Dataset[]> {
+        return this.http.get<Dataset[]>(this.API_PATH + 'instance/' + instanceName + '/dataset');
+    }
+
+    addDataset(newDataset: Dataset): Observable<Dataset> {
+        return this.http.post<Dataset>(this.API_PATH + 'dataset-family/' + newDataset.id_dataset_family + '/dataset', newDataset);
+    }
+
+    editDataset(dataset: Dataset): Observable<Dataset> {
+        return this.http.put<Dataset>(this.API_PATH + 'dataset/' + dataset.name, dataset);
+    }
+
+    deleteDataset(datasetName: string) {
+        return this.http.delete(this.API_PATH + 'dataset/' + datasetName);
+    }
+}
diff --git a/client/src/app/metamodel/store/services/group.service.ts b/client/src/app/metamodel/store/services/group.service.ts
new file mode 100644
index 00000000..1b04541d
--- /dev/null
+++ b/client/src/app/metamodel/store/services/group.service.ts
@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+
+import { Observable } from 'rxjs';
+
+import { Group } from '../models';
+import { environment } from 'src/environments/environment';
+
+@Injectable()
+export class GroupService {
+    private API_PATH: string = environment.apiUrl + '/';
+
+    constructor(private http: HttpClient) { }
+
+    retrieveGroupList(instanceName: string): Observable<Group[]> {
+        return this.http.get<Group[]>(this.API_PATH + 'instance/' + instanceName +  '/group');
+    }
+
+    addGroup(instanceName: string, newGroup: Group): Observable<Group> {
+        return this.http.post<Group>(this.API_PATH + 'instance/' + instanceName + '/group', newGroup);
+    }
+
+    editGroup(group: Group): Observable<Group> {
+        return this.http.put<Group>(this.API_PATH + 'group/' + group.id, group);
+    }
+
+    deleteGroup(groupId: number) {
+        return this.http.delete(this.API_PATH + 'group/' + groupId);
+    }
+}
diff --git a/client/src/app/metamodel/store/services/index.ts b/client/src/app/metamodel/store/services/index.ts
index 0cd7bb34..8b1f27a7 100644
--- a/client/src/app/metamodel/store/services/index.ts
+++ b/client/src/app/metamodel/store/services/index.ts
@@ -1,5 +1,23 @@
 import { DatabaseService } from './database.service';
+import { SurveyService } from './survey.service';
+import { GroupService } from './group.service';
+import { DatasetService } from './dataset.service';
+import { DatasetFamilyService } from './dataset-family.service';
+import { InstanceService } from './instance.service';
+import { AttributeService } from './attribute.service';
+import { CriteriaFamilyService } from './criteria-family.service';
+import { OutputCategoryService } from './output-category.service';
+import { OutputFamilyService } from './output-family.service';
 
 export const metamodelServices = [
     DatabaseService,
+    SurveyService,
+    GroupService,
+    DatasetService,
+    DatasetFamilyService,
+    InstanceService,
+    AttributeService,
+    CriteriaFamilyService,
+    OutputCategoryService,
+    OutputFamilyService
 ];
diff --git a/client/src/app/metamodel/store/services/instance.service.ts b/client/src/app/metamodel/store/services/instance.service.ts
new file mode 100644
index 00000000..622d3a19
--- /dev/null
+++ b/client/src/app/metamodel/store/services/instance.service.ts
@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+
+import { Observable } from 'rxjs';
+
+import { Instance } from '../models';
+import { environment } from 'src/environments/environment';
+
+@Injectable()
+export class InstanceService {
+    private API_PATH: string = environment.apiUrl + '/';
+
+    constructor(private http: HttpClient) { }
+
+    retrieveInstanceList(): Observable<Instance[]> {
+        return this.http.get<Instance[]>(this.API_PATH + 'instance');
+    }
+
+    addInstance(newInstance: Instance): Observable<Instance> {
+        return this.http.post<Instance>(this.API_PATH + 'instance', newInstance);
+    }
+
+    editInstance(instance: Instance): Observable<Instance> {
+        return this.http.put<Instance>(this.API_PATH + 'instance/' + instance.name, instance);
+    }
+
+    deleteInstance(instanceName: string) {
+        return this.http.delete(this.API_PATH + 'instance/' + instanceName);
+    }
+}
diff --git a/client/src/app/metamodel/store/services/output-category.service.ts b/client/src/app/metamodel/store/services/output-category.service.ts
new file mode 100644
index 00000000..b1e75d93
--- /dev/null
+++ b/client/src/app/metamodel/store/services/output-category.service.ts
@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+
+import { Observable } from 'rxjs';
+
+import { OutputCategory } from '../models';
+import { environment } from 'src/environments/environment';
+
+@Injectable()
+export class OutputCategoryService {
+    private API_PATH: string = environment.apiUrl + '/';
+
+    constructor(private http: HttpClient) { }
+
+    retrieveOutputCategoryList(datasetName: string): Observable<OutputCategory[]> {
+        return this.http.get<OutputCategory[]>(this.API_PATH + 'dataset/' + datasetName + '/output-category');
+    }
+
+    addOutputCategory(newOutputCategory: OutputCategory): Observable<OutputCategory> {
+        return this.http.post<OutputCategory>(this.API_PATH + 'output-family/' + newOutputCategory.id_output_family + '/output-category', newOutputCategory);
+    }
+
+    editOutputCategory(outputCategory: OutputCategory): Observable<OutputCategory> {
+        return this.http.put<OutputCategory>(this.API_PATH + 'output-category/' + outputCategory.id, outputCategory);
+    }
+
+    deleteOutputCategory(outputCategoryId: number) {
+        return this.http.delete(this.API_PATH + 'output-category/' + outputCategoryId);
+    }
+}
diff --git a/client/src/app/metamodel/store/services/output-family.service.ts b/client/src/app/metamodel/store/services/output-family.service.ts
new file mode 100644
index 00000000..d62f395a
--- /dev/null
+++ b/client/src/app/metamodel/store/services/output-family.service.ts
@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+
+import { Observable } from 'rxjs';
+
+import { OutputFamily } from '../models';
+import { environment } from 'src/environments/environment';
+
+@Injectable()
+export class OutputFamilyService {
+    private API_PATH: string = environment.apiUrl + '/';
+
+    constructor(private http: HttpClient) { }
+
+    retrieveOutputFamilyList(datasetName: string): Observable<OutputFamily[]> {
+        return this.http.get<OutputFamily[]>(this.API_PATH + 'dataset/' + datasetName + '/output-family');
+    }
+
+    addOutputFamily(datasetName: string, newOutputFamily: OutputFamily): Observable<OutputFamily> {
+        return this.http.post<OutputFamily>(this.API_PATH + 'dataset/' + datasetName + '/output-family', newOutputFamily);
+    }
+
+    editOutputFamily(criteriaFamily: OutputFamily): Observable<OutputFamily> {
+        return this.http.put<OutputFamily>(this.API_PATH + 'output-family/' + criteriaFamily.id, criteriaFamily);
+    }
+
+    deleteOutputFamily(outputFamilyId: number) {
+        return this.http.delete(this.API_PATH + 'output-family/' + outputFamilyId);
+    }
+}
diff --git a/client/src/app/metamodel/store/services/survey.service.ts b/client/src/app/metamodel/store/services/survey.service.ts
new file mode 100644
index 00000000..a08c32e7
--- /dev/null
+++ b/client/src/app/metamodel/store/services/survey.service.ts
@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+
+import { Observable } from 'rxjs';
+
+import { Survey } from '../models';
+import { environment } from 'src/environments/environment';
+
+@Injectable()
+export class SurveyService {
+    private API_PATH: string = environment.apiUrl + '/';
+
+    constructor(private http: HttpClient) { }
+
+    retrieveSurveyList(): Observable<Survey[]> {
+        return this.http.get<Survey[]>(this.API_PATH + 'survey');
+    }
+
+    addSurvey(newSurvey: Survey): Observable<Survey> {
+        return this.http.post<Survey>(this.API_PATH + 'survey', newSurvey);
+    }
+
+    editSurvey(survey: Survey): Observable<Survey> {
+        return this.http.put<Survey>(this.API_PATH + 'survey/' + survey.name, survey);
+    }
+
+    deleteSurvey(surveyName: string) {
+        return this.http.delete(this.API_PATH + 'survey/' + surveyName);
+    }
+}
-- 
GitLab