Browse Source

data provider

Vincent GUFFON 4 years ago
parent
commit
116f9270de
73 changed files with 1399 additions and 737 deletions
  1. 1 1
      config/nuxtConfig/build.js
  2. 8 0
      config/nuxtConfig/env.js
  3. 4 4
      config/nuxtConfig/modules.js
  4. 5 2
      config/nuxtConfig/plugins.js
  5. 1 0
      nuxt.config.js
  6. 11 5
      package.json
  7. 19 0
      plugins/Data/axios.js
  8. 12 0
      plugins/Data/dataPersister.ts
  9. 12 0
      plugins/Data/dataProvider.ts
  10. 0 20
      plugins/Queries/http.js
  11. 0 9
      plugins/Queries/rest.ts
  12. 8 0
      plugins/helpersInit.ts
  13. 20 0
      plugins/route.ts
  14. 48 0
      services/connection/connection.ts
  15. 61 0
      services/connection/constructUrl.ts
  16. 71 0
      services/dataPersister/dataPersister.ts
  17. 4 0
      services/dataPersister/hook/_import.ts
  18. 14 0
      services/dataPersister/hook/baseHook.ts
  19. 31 0
      services/dataPersister/hook/hook_example.ts
  20. 42 42
      services/dataProvider/dataProvider.ts
  21. 0 40
      services/dataProvider/enumDataProvider.ts
  22. 9 0
      services/dataProvider/provider/_import.ts
  23. 40 0
      services/dataProvider/provider/baseProvider.ts
  24. 20 0
      services/dataProvider/provider/defaultProvider.ts
  25. 39 0
      services/dataProvider/provider/enumProvider.ts
  26. 5 0
      services/dataProvider/provider/hook/_import.ts
  27. 14 0
      services/dataProvider/provider/hook/baseHook.ts
  28. 31 0
      services/dataProvider/provider/hook/hook_example.ts
  29. 29 0
      services/dataProvider/provider/modelProvider.ts
  30. 1 1
      services/profile/accessProfile.ts
  31. 1 1
      services/profile/organizationProfile.ts
  32. 0 29
      services/queries/rest.ts
  33. 5 3
      services/rights/abilitiesUtils.ts
  34. 1 1
      services/rights/roleUtils.ts
  35. 7 0
      services/serializer/denormalizer/_import.ts
  36. 12 0
      services/serializer/denormalizer/baseDenormalizer.ts
  37. 118 0
      services/serializer/denormalizer/hydra.ts
  38. 32 0
      services/serializer/denormalizer/yaml.ts
  39. 5 0
      services/serializer/normalizer/_import.ts
  40. 12 0
      services/serializer/normalizer/baseNormalizer.ts
  41. 14 0
      services/serializer/normalizer/model.ts
  42. 24 0
      services/serializer/serializer.ts
  43. 0 112
      services/utils/hydraParser.ts
  44. 1 1
      services/utils/objectProperties.ts
  45. 0 27
      services/utils/yamlParser.ts
  46. 7 1
      tsconfig.json
  47. 23 0
      types/enums.ts
  48. 128 0
      types/interfaces.d.ts
  49. 1 85
      types/types.d.ts
  50. 0 21
      use/form/useFormInputSetup.ts
  51. 8 2
      use/form/utils.ts
  52. 1 1
      use/layout/Menus/accessMenu.ts
  53. 1 1
      use/layout/Menus/accountMenu.ts
  54. 1 1
      use/layout/Menus/admin2iosMenu.ts
  55. 1 1
      use/layout/Menus/agendaMenu.ts
  56. 1 1
      use/layout/Menus/baseMenu.ts
  57. 1 1
      use/layout/Menus/billingMenu.ts
  58. 1 1
      use/layout/Menus/communicationMenu.ts
  59. 1 1
      use/layout/Menus/configurationMenu.ts
  60. 1 1
      use/layout/Menus/cotisationsMenu.ts
  61. 1 1
      use/layout/Menus/donorsMenu.ts
  62. 1 1
      use/layout/Menus/educationalMenu.ts
  63. 1 1
      use/layout/Menus/equipmentMenu.ts
  64. 1 1
      use/layout/Menus/medalsMenu.ts
  65. 1 1
      use/layout/Menus/myAccessesMenu.ts
  66. 1 1
      use/layout/Menus/myFamilyMenu.ts
  67. 1 1
      use/layout/Menus/statsMenu.ts
  68. 1 1
      use/layout/Menus/websiteMenu.ts
  69. 1 1
      use/layout/menu.ts
  70. 1 1
      use/store/useQuery.ts
  71. 13 25
      use/store/useRepository.ts
  72. 15 0
      use/utils/useSorter.ts
  73. 393 286
      yarn.lock

+ 1 - 1
config/nuxtConfig/build.js

@@ -4,7 +4,7 @@ export default {
   // Disable server-side rendering (https://go.nuxtjs.dev/ssr-mode)
   ssr: true,
 
-  // Auto import components (https://go.nuxtjs.dev/config-components)
+  // // Auto import components (https://go.nuxtjs.dev/config-components)
   components: true,
 
   // Build Configuration (https://go.nuxtjs.dev/config-build)

+ 8 - 0
config/nuxtConfig/env.js

@@ -12,12 +12,20 @@ export default {
     http: {
       browserBaseURL: process.env.NODE_ENV !== 'production' ? 'https://local.new.api.opentalent.fr' : 'https://local.new.api.opentalent.fr'
     },
+    axios: {
+      https: true,
+      browserBaseURL: process.env.NODE_ENV !== 'production' ? 'https://local.new.api.opentalent.fr' : 'https://local.new.api.opentalent.fr'
+    },
     baseURL_Legacy: process.env.NODE_ENV !== 'production' ? 'https://local.api.opentalent.fr' : 'https://local.api.opentalent.fr',
     baseURL_adminLegacy: process.env.NODE_ENV !== 'production' ? 'https://local.admin.opentalent.fr/#' : 'https://admin.opentalent.fr/#',
     baseURL_typo3: process.env.NODE_ENV !== 'production' ? `https://local.sub.opentalent.fr/###subDomain###` : `https://###subDomain###.opentalent.fr/#`,
   },
   privateRuntimeConfig: {
     http: {
+      https:true,
+      baseURL: process.env.NODE_ENV !== 'production' ? 'http://nginx_new' : 'https://local.api.opentalent.fr'
+    },
+    axios: {
       baseURL: process.env.NODE_ENV !== 'production' ? 'http://nginx_new' : 'https://local.api.opentalent.fr'
     },
     baseURL_Legacy: process.env.NODE_ENV !== 'production' ? 'http://nginx' : 'https://local.api.opentalent.fr'

+ 4 - 4
config/nuxtConfig/modules.js

@@ -1,17 +1,17 @@
 export default {
   // Modules for dev and build (recommended) (https://go.nuxtjs.dev/config-modules)
   buildModules: [
-    // https://go.nuxtjs.dev/typescript
+    // // https://go.nuxtjs.dev/typescript
     '@nuxt/typescript-build',
-    // https://go.nuxtjs.dev/vuetify
+    // // https://go.nuxtjs.dev/vuetify
     '@nuxtjs/vuetify',
     '@nuxtjs/moment',
-    '@nuxtjs/composition-api'
+    '@nuxtjs/composition-api/module'
   ],
 
   // Modules (https://go.nuxtjs.dev/config-modules)
   modules: [
-    '@nuxt/http',
+    '@nuxtjs/axios',
     'nuxt-i18n'
   ]
 }

+ 5 - 2
config/nuxtConfig/plugins.js

@@ -1,9 +1,12 @@
 export default {
   // Plugins to run before rendering page (https://go.nuxtjs.dev/config-plugins)
   plugins: [
+    '~/plugins/route',
+    '~/plugins/helpersInit',
     '~/plugins/Rights/ability',
     './plugins/Rights/casl.js',
-    '~/plugins/Queries/http',
-    '~/plugins/Queries/rest'
+    '~/plugins/Data/axios',
+    '~/plugins/Data/dataPersister',
+    '~/plugins/Data/dataProvider',
   ]
 }

+ 1 - 0
nuxt.config.js

@@ -17,3 +17,4 @@ export default {
   ...vuetify,
   ...moment,
 }
+

+ 11 - 5
package.json

@@ -15,18 +15,19 @@
   "dependencies": {
     "@casl/ability": "^5.1.0",
     "@casl/vue": "^1.2.1",
-    "@nuxt/http": "^0.6.1",
+    "@nuxt/components": "^2.1.8",
     "@nuxt/typescript-runtime": "^2.0.0",
-    "@nuxtjs/composition-api": "0.22.0",
+    "@nuxtjs/axios": "^5.13.1",
+    "@nuxtjs/composition-api": "0.24.2",
     "@types/lodash": "^4.14.168",
-    "@vuex-orm/core": "1.0.0-draft.9",
+    "@vuex-orm/core": "1.0.0-draft.14",
     "cookieparser": "^0.1.0",
     "core-js": "^3.6.5",
     "js-yaml": "^4.0.0",
     "lodash": "^4.17.20",
     "marked": "^1.2.7",
-    "nuxt": "^2.14.6",
-    "nuxt-i18n": "^6.18.0",
+    "nuxt": "2.15.6",
+    "nuxt-i18n": "6.27.0",
     "vue-i18n-composable": "^0.2.1",
     "yaml-import": "^2.0.0"
   },
@@ -44,10 +45,15 @@
     "babel-eslint": "^10.1.0",
     "babel-jest": "^26.5.0",
     "better-docs": "^2.3.2",
+    "css-loader": "^5.0.0",
     "eslint": "^7.10.0",
     "eslint-plugin-nuxt": "^1.0.0",
     "jest": "^26.5.0",
     "jsdoc": "^3.6.6",
+    "postcss": "^8.1.10",
+    "postcss-import": "^13.0.0",
+    "postcss-loader": "^4.1.0",
+    "postcss-url": "^10.1.1",
     "ts-jest": "^26.4.1",
     "vue-jest": "^3.0.4"
   }

+ 19 - 0
plugins/Data/axios.js

@@ -0,0 +1,19 @@
+export default function ({ $axios, redirect, store }) {
+  $axios.onRequest(config => {
+    $axios.setHeader('x-accessid', `${store.state.profile.access.accessId}`)
+    $axios.setToken(`${store.state.profile.access.bearer}`, 'Bearer')
+  })
+
+  $axios.onResponse(response => {
+  })
+
+  $axios.onError((error) => {
+    // In case of unauthorized, redirect to a specific page
+    if (error.statusCode === 401) {
+      redirect('/login')
+    }
+    if (error.statusCode === 403) {
+      console.debug('forbidden');
+    }
+  })
+}

+ 12 - 0
plugins/Data/dataPersister.ts

@@ -0,0 +1,12 @@
+import {Plugin} from '@nuxt/types'
+import DataPersister from "~/services/dataPersister/dataPersister";
+
+const dataPersisterPlugin: Plugin = (ctx) => {
+  const dataPersister = new DataPersister();
+  dataPersister.initCtx(ctx)
+
+  //Déclare un nouvel accesseur de service via le context Nuxt
+  ctx.$dataPersister = dataPersister
+}
+
+export default dataPersisterPlugin

+ 12 - 0
plugins/Data/dataProvider.ts

@@ -0,0 +1,12 @@
+import {Plugin} from '@nuxt/types'
+import DataProvider from "~/services/dataProvider/dataProvider";
+
+const dataProviderPlugin: Plugin = (ctx) => {
+  const dataProvider = new DataProvider();
+  dataProvider.initCtx(ctx)
+
+  //Déclare un nouvel accesseur de service via le context Nuxt
+  ctx.$dataProvider = dataProvider
+}
+
+export default dataProviderPlugin

+ 0 - 20
plugins/Queries/http.js

@@ -1,20 +0,0 @@
-export default function ({ $http, redirect, store }) {
-  $http.onRequest(config => {
-    config.headers.set('Authorization', `Bearer ${store.state.profile.access.bearer}`)
-    config.headers.set('x-accessid', `${store.state.profile.access.accessId}`)
-  })
-
-  $http.onResponse(async (request, options, response) => {
-
-  })
-
-  $http.onError((error) => {
-    // In case of unauthorized, redirect to a specific page
-    if (error.statusCode === 401) {
-      redirect('/login')
-    }
-    if (error.statusCode === 403) {
-      console.debug('forbidden');
-    }
-  })
-}

+ 0 - 9
plugins/Queries/rest.ts

@@ -1,9 +0,0 @@
-import {Plugin} from '@nuxt/types'
-import {$rest} from "~/services/queries/rest";
-
-const restPlugin: Plugin = (ctx) => {
-  //Déclare un nouvel accesseur de service via le context Nuxt
-  ctx.$rest = $rest(ctx.$http)
-}
-
-export default restPlugin

+ 8 - 0
plugins/helpersInit.ts

@@ -0,0 +1,8 @@
+import {Plugin} from '@nuxt/types'
+import {useRepositoryHelper} from "~/use/store/useRepository";
+
+const helpersInitPlugin: Plugin = (ctx) => {
+  useRepositoryHelper.setStore(ctx.store)
+}
+
+export default helpersInitPlugin

+ 20 - 0
plugins/route.ts

@@ -0,0 +1,20 @@
+import {Plugin} from '@nuxt/types'
+
+const routePlugin: Plugin = (ctx) => {
+  if(ctx.app.router){
+    ctx.app.router.beforeEach((to, from, next)=>{
+      if(ctx.store.state.form.dirty){
+        ctx.store.commit('form/setShowConfirmToLeave', true)
+        ctx.store.commit('form/setGoAfterLeave', to)
+      }else{
+        next()
+      }
+    })
+
+    ctx.app.router.afterEach(()=>{
+      ctx.store.commit('form/setDirty', false)
+    })
+  }
+}
+
+export default routePlugin

+ 48 - 0
services/connection/connection.ts

@@ -0,0 +1,48 @@
+import {DataPersisterArgs, DataProviderArgs} from "~/types/interfaces";
+import {HTTP_METHOD} from "~/types/enums";
+import {NuxtAxiosInstance} from "@nuxtjs/axios";
+import {AxiosRequestConfig} from "axios";
+
+class Connection{
+  static connector:NuxtAxiosInstance;
+
+  constructor() {
+  }
+
+  static initConnector(connector: NuxtAxiosInstance){
+    Connection.connector = connector
+  }
+
+  async invoke(method: HTTP_METHOD, url: string, args:DataProviderArgs|DataPersisterArgs): Promise<any>{
+    switch (method) {
+      case HTTP_METHOD.GET:
+        if(args.id)
+          return await this.getItem(url, args.id)
+        else
+          return await this.getCollection(url)
+    }
+    return null
+  }
+
+  private async getItem(url: string, id: number): Promise<any>{
+    const config:AxiosRequestConfig = {
+      url: `${url}/${id}`,
+      method: HTTP_METHOD.GET,
+    }
+    return await this.request(config)
+  }
+
+  private async getCollection(url: string): Promise<any>{
+    const config:AxiosRequestConfig = {
+      url: `${url}`,
+      method: HTTP_METHOD.GET,
+    }
+    return await this.request(config)
+  }
+
+  private async request(config:AxiosRequestConfig){
+    return await Connection.connector.$request(config)
+  }
+}
+
+export default Connection

+ 61 - 0
services/connection/constructUrl.ts

@@ -0,0 +1,61 @@
+import {UrlArgs} from "~/types/interfaces";
+import {QUERY_TYPE} from "~/types/enums";
+import {Context} from "@nuxt/types/app";
+import {Model} from "@vuex-orm/core";
+
+class ConstructUrl{
+  static ROOT = '/api/'
+
+  private ctx !: Context
+
+  constructor(ctx: Context) {
+    this.ctx = ctx
+  }
+
+  invoke(args:UrlArgs): string{
+    switch (args.type) {
+      case QUERY_TYPE.DEFAULT:
+        return this.getDefaultUrl(args.url)
+
+      case QUERY_TYPE.ENUM:
+        return this.getEnumUrl(args.enumType)
+
+      case QUERY_TYPE.MODEL:
+        return this.getModelUrl(args.model, args.root_model, args.root_id)
+
+      default:
+        throw new Error('url, model or enum must be defined');
+    }
+  }
+
+  private getDefaultUrl(url?: string){
+    if(typeof url === 'undefined')
+      throw new Error('url must be defined');
+    return String(ConstructUrl.ROOT + url).toString()
+  }
+
+  private getEnumUrl(enumType?: string){
+    if(typeof enumType === 'undefined')
+      throw new Error('enumType must be defined');
+    return String(ConstructUrl.ROOT + 'enum/' + enumType).toString()
+  }
+
+  private getModelUrl(model ?: typeof Model, rootModel ?: typeof Model, rootId ?: number){
+    if(typeof model === 'undefined')
+      throw new Error('model must be defined');
+    const repository = this.ctx.store.$repo(model);
+    const entity = repository.getModel().$entity();
+
+    if(typeof rootModel !== 'undefined'){
+      if(typeof rootId === 'undefined')
+        throw new Error('Root ID must be defined');
+
+      const rootUrl = this.getModelUrl(rootModel) as string
+      return String(`${rootUrl}/${rootId}/${entity}`).toString()
+    }
+
+    return String(ConstructUrl.ROOT  + entity).toString()
+  }
+}
+
+export default ConstructUrl

+ 71 - 0
services/dataPersister/dataPersister.ts

@@ -0,0 +1,71 @@
+import {hooks} from "~/services/dataPersister/hook/_import";
+import {DataPersisterArgs} from "~/types/interfaces";
+import {Context} from "@nuxt/types/app";
+import Connection from "~/services/connection/connection";
+import ConstructUrl from "~/services/connection/constructUrl";
+import {HTTP_METHOD} from "~/types/enums";
+
+class DataPersister{
+  private ctx !: Context;
+  private arguments!: DataPersisterArgs;
+
+  constructor() {
+    this.sort()
+  }
+
+  initCtx(ctx:Context){
+    Connection.initConnector(ctx.$axios)
+    this.ctx = ctx
+  }
+
+  async invoke(args:DataPersisterArgs): Promise<any>{
+    this.arguments = args
+    try{
+      this.preHook()
+
+      await this.serialization()
+
+      const url = this.constructUrl()
+
+      const response = await this.connection(url)
+    }catch(error){
+     throw new Error(error.message);
+    }
+  }
+
+  async preHook(){
+    for(const hook of hooks){
+      if(hook.support(this.arguments)){
+        await new hook().invoke(this.arguments);
+      }
+    }
+  }
+
+  serialization(){
+    console.log('serialization')
+  }
+
+  constructUrl(): string{
+    const constructUrl = new ConstructUrl(this.ctx);
+    return constructUrl.invoke(this.arguments)
+  }
+
+  connection(url: string): Promise<any>{
+    const connection = new Connection()
+    return connection.invoke(HTTP_METHOD.GET, url, this.arguments)
+  }
+
+  sort(){
+    hooks.sort(function(a, b) {
+      if (a.priority > b.priority) {
+        return 1;
+      }
+      if (a.priority < b.priority) {
+        return -1;
+      }
+      return 0;
+    });
+  }
+}
+
+export default DataPersister

+ 4 - 0
services/dataPersister/hook/_import.ts

@@ -0,0 +1,4 @@
+import Hook_example from "~/services/dataPersister/hook/hook_example";
+export const hooks = [
+  Hook_example
+]

+ 14 - 0
services/dataPersister/hook/baseHook.ts

@@ -0,0 +1,14 @@
+import {DataPersisterArgs} from "~/types/interfaces";
+
+class BaseHook{
+  static priority = 255
+
+  constructor() {
+  }
+
+  static support(args:DataPersisterArgs): boolean{
+    throw new Error('Need to be implement into static method')
+  }
+}
+
+export default BaseHook

+ 31 - 0
services/dataPersister/hook/hook_example.ts

@@ -0,0 +1,31 @@
+import {DataPersisterArgs, HookPersister} from "~/types/interfaces";
+import BaseHook from "~/services/dataPersister/hook/baseHook";
+
+class Hook_example extends BaseHook implements HookPersister{
+  static priority = 10
+
+  constructor() {
+    super()
+  }
+
+  async invoke(args: DataPersisterArgs): Promise<any>{
+    await timeoutPromise(3000)
+    console.log('Hook 1');
+    throw new Error('STOP!')
+  }
+
+  static support(args:DataPersisterArgs): boolean{
+    return args.hook === 'test'
+  }
+}
+
+export default Hook_example
+
+function timeoutPromise(interval:number) {
+  return new Promise((resolve, reject) => {
+    setTimeout(function(){
+      console.log('done')
+      resolve("done");
+    }, interval);
+  });
+};

+ 42 - 42
services/dataProvider/dataProvider.ts

@@ -1,60 +1,60 @@
-import {Store} from "vuex";
-import {Rest} from "~/services/queries/rest";
-import {Model} from "@/models/Model"
+import {AnyJson, DataProviderArgs} from "~/types/interfaces";
+import {DENORMALIZER_TYPE, HTTP_METHOD} from "~/types/enums";
+import {providers} from "~/services/dataProvider/provider/_import";
+import ConstructUrl from "~/services/connection/constructUrl";
+import Connection from "~/services/connection/connection";
+import Serializer from "~/services/serializer/serializer";
+import {Context} from "@nuxt/types/app";
 
 class DataProvider{
-  private store: Store<any>
-  private $rest: Rest
+  private ctx !: Context;
+  private arguments!: DataProviderArgs;
 
-  constructor(store:Store<any>, $rest: Rest) {
-    this.store = store
-    this.$rest = $rest
+  constructor() {
   }
 
-  public async getItem(model: typeof Model, id: number){
-    const repository = this.store.$repo(model);
-    const entity = repository.getModel().$entity();
-
-    const response = await this.$rest.getItem(`/api/${entity}`, id)
-    if(response)
-      repository.insert(response);
+  initCtx(ctx:Context){
+    Connection.initConnector(ctx.$axios)
+    this.ctx = ctx
   }
 
-  public async getCollection(model: typeof Model){
-    const repository = this.store.$repo(model);
-    const entity = repository.getModel().$entity();
-
-    const response = await this.$rest.getCollection(`/api/${entity}`)
-    if(response)
-      repository.insert(response);
-  }
+  async invoke(args:DataProviderArgs): Promise<any>{
+    this.arguments = args
+    try{
+      const url = this.constructUrl()
 
-  public async getSubResourceCollection(root_model: typeof Model, root_id: number, model: typeof Model){
-    const root_repository = this.store.$repo(root_model);
-    const root_entity = root_repository.getModel().$entity();
+      const response = await this.connection(url)
 
-    const repository = this.store.$repo(model);
-    const entity = repository.getModel().$entity();
+      const deserializeResponse = await this.deserialization(response)
 
-    const response = await this.$rest.getCollection(`/api/${root_entity}/${root_id}/${entity}`)
-    if(response){
-      repository.insert(response)
-      return repository.all();
+      return await this.provide(deserializeResponse)
+    }catch(error){
+      throw new Error(error.message);
     }
-    return [];
   }
 
-  public async getSubResourceItem(root_model: typeof Model, root_id: number, model: typeof Model, id: number) {
-    const root_repository = this.store.$repo(root_model);
-    const root_entity = root_repository.getModel().$entity();
+  constructUrl(): string{
+    const constructUrl = new ConstructUrl(this.ctx);
+    return constructUrl.invoke(this.arguments)
+  }
+
+  connection(url: string): Promise<any>{
+    const connection = new Connection()
+    return connection.invoke(HTTP_METHOD.GET, url, this.arguments)
+  }
 
-    const repository = this.store.$repo(model);
-    const entity = repository.getModel().$entity();
+  provide(data: AnyJson): any{
+    for(const provider of providers){
+      if(provider.support(this.arguments)){
+         return new provider(this.ctx, this.arguments).invoke(data);
+      }
+    }
+  }
 
-    const response = await this.$rest.getItem(`/api/${root_entity}/${root_id}/${entity}`, id)
-    if(response)
-      repository.insert(response);
+  deserialization(data: AnyJson): AnyJson{
+    const serializer = new Serializer()
+    return serializer.denormalize(data, DENORMALIZER_TYPE.DEFAULT)
   }
 }
 
-export const $dataProvider = (store:Store<any>, $rest:Rest) => new DataProvider(store, $rest);
+export default DataProvider

+ 0 - 40
services/dataProvider/enumDataProvider.ts

@@ -1,40 +0,0 @@
-import {EnumChoice, EnumChoices} from "~/types/types";
-import * as _ from "lodash";
-import {Rest} from "~/services/queries/rest";
-
-class EnumDataProvider{
-  private $rest: Rest
-  private i18n:any
-
-  constructor($rest: Rest, i18n:any) {
-    this.$rest = $rest
-    this.i18n = i18n
-  }
-
-  public async get(type: string){
-    const enums:EnumChoices = []
-    const response = await this.$rest.getCollection(`/api/enum/${type}`)
-    if(response){
-      _.each(response['items'], (item, key) =>{
-        const entry:EnumChoice = {
-          value: key,
-          label: this.i18n.t(item)
-        };
-        enums.push(entry)
-      })
-    }
-    return this.sortEnum(enums)
-  }
-
-  public sortEnum(enums:EnumChoices){
-    return enums.sort( (a, b) => {
-      if (a.label > b.label)
-        return 1;
-      if (a.label < b.label)
-        return -1;
-      return 0;
-    });
-  }
-}
-
-export const $enumDataProvider = ($rest:Rest, i18n:any) => new EnumDataProvider($rest,i18n);

+ 9 - 0
services/dataProvider/provider/_import.ts

@@ -0,0 +1,9 @@
+import ModelProvider from "~/services/dataProvider/provider/modelProvider";
+import EnumProvider from "~/services/dataProvider/provider/enumProvider";
+import DefaultProvider from "~/services/dataProvider/provider/defaultProvider";
+
+export const providers = [
+  DefaultProvider,
+  ModelProvider,
+  EnumProvider
+]

+ 40 - 0
services/dataProvider/provider/baseProvider.ts

@@ -0,0 +1,40 @@
+import {hooks} from "~/services/dataProvider/provider/hook/_import";
+import {DataProviderArgs} from "~/types/interfaces";
+import {Context} from "@nuxt/types/app";
+
+class BaseProvider{
+  protected arguments!: DataProviderArgs;
+  protected ctx!: Context;
+
+  constructor(ctx: Context, args: DataProviderArgs) {
+    this.arguments = args
+    this.ctx = ctx
+    this.sortHook()
+  }
+
+  static support(args:DataProviderArgs): boolean{
+    throw new Error('Need to be implement into static method')
+  }
+
+  async postHook(){
+    for(const hook of hooks){
+      if(hook.support(this.arguments)){
+        await new hook().invoke(this.arguments);
+      }
+    }
+  }
+
+  sortHook(){
+    hooks.sort(function(a, b) {
+      if (a.priority > b.priority) {
+        return 1;
+      }
+      if (a.priority < b.priority) {
+        return -1;
+      }
+      return 0;
+    });
+  }
+}
+
+export default BaseProvider

+ 20 - 0
services/dataProvider/provider/defaultProvider.ts

@@ -0,0 +1,20 @@
+import {AnyJson, DataProviderArgs, Provider} from "~/types/interfaces";
+import BaseProvider from "~/services/dataProvider/provider/baseProvider";
+import {QUERY_TYPE} from "~/types/enums";
+import {Context} from "@nuxt/types/app";
+
+class DefaultProvider extends BaseProvider implements Provider{
+  constructor(ctx: Context, args: DataProviderArgs) {
+    super(ctx, args);
+  }
+
+  async invoke(data: AnyJson): Promise<any>{
+    return data
+  }
+
+  static support(args:DataProviderArgs): boolean{
+    return args.type ===  QUERY_TYPE.DEFAULT
+  }
+}
+
+export default DefaultProvider

+ 39 - 0
services/dataProvider/provider/enumProvider.ts

@@ -0,0 +1,39 @@
+import {AnyJson, DataProviderArgs, EnumChoice, EnumChoices, Provider} from "~/types/interfaces";
+import BaseProvider from "~/services/dataProvider/provider/baseProvider";
+import {QUERY_TYPE} from "~/types/enums";
+import * as _ from "lodash";
+import {Context} from "@nuxt/types/app";
+
+class EnumProvider extends BaseProvider implements Provider{
+  constructor(ctx: Context, args: DataProviderArgs) {
+    super(ctx, args);
+  }
+
+  async invoke(data: AnyJson): Promise<any>{
+    const enums:EnumChoices = []
+    _.each(data['items'], (item, key) =>{
+      const entry:EnumChoice = {
+        value: key,
+        label: this.ctx.app.i18n.t(item) as string
+      };
+      enums.push(entry)
+    })
+    return this.sortEnum(enums)
+  }
+
+  private sortEnum(enums:EnumChoices){
+    return enums.sort( (a, b) => {
+      if (a.label > b.label)
+        return 1;
+      if (a.label < b.label)
+        return -1;
+      return 0;
+    });
+  }
+
+  static support(args:DataProviderArgs): boolean{
+    return args.type ===  QUERY_TYPE.ENUM
+  }
+}
+
+export default EnumProvider

+ 5 - 0
services/dataProvider/provider/hook/_import.ts

@@ -0,0 +1,5 @@
+import Hook_example from "~/services/dataProvider/provider/hook/hook_example";
+
+export const hooks = [
+  Hook_example
+]

+ 14 - 0
services/dataProvider/provider/hook/baseHook.ts

@@ -0,0 +1,14 @@
+import {DataProviderArgs} from "~/types/interfaces";
+
+class BaseHook{
+  static priority = 255
+
+  constructor() {
+  }
+
+  static support(args:DataProviderArgs): boolean{
+    throw new Error('Need to be implement into static method')
+  }
+}
+
+export default BaseHook

+ 31 - 0
services/dataProvider/provider/hook/hook_example.ts

@@ -0,0 +1,31 @@
+import {DataProviderArgs, HookProvider} from "~/types/interfaces";
+import BaseHook from "~/services/dataProvider/provider/hook/baseHook";
+
+class Hook_example extends BaseHook implements HookProvider{
+  static priority = 10
+
+  constructor() {
+    super()
+  }
+
+  async invoke(args: DataProviderArgs): Promise<any> {
+    await timeoutPromise(3000)
+    console.log('Hook 1');
+    throw new Error('STOP!')
+  }
+
+  static support(args:DataProviderArgs): boolean{
+    return args.hook === 'test'
+  }
+}
+
+export default Hook_example
+
+function timeoutPromise(interval:number) {
+  return new Promise((resolve, reject) => {
+    setTimeout(function(){
+      console.log('done')
+      resolve("done");
+    }, interval);
+  });
+};

+ 29 - 0
services/dataProvider/provider/modelProvider.ts

@@ -0,0 +1,29 @@
+import {AnyJson, DataProviderArgs, Provider} from "~/types/interfaces";
+import BaseProvider from "~/services/dataProvider/provider/baseProvider";
+import {QUERY_TYPE} from "~/types/enums";
+import {Context} from "@nuxt/types/app";
+import * as _ from "lodash";
+import {useRepositoryHelper} from "~/use/store/useRepository";
+
+class ModelProvider extends BaseProvider implements Provider{
+  constructor(ctx: Context, args: DataProviderArgs) {
+    super(ctx, args);
+  }
+
+  async invoke(data: AnyJson): Promise<any>{
+    if(typeof this.arguments.model === 'undefined')
+      throw new Error('model must be defined');
+
+    data['originalState'] = _.cloneDeep(data)
+    const repository = useRepositoryHelper.getRepository(this.arguments.model);
+    await useRepositoryHelper.updateStore(repository, data)
+
+    await this.postHook()
+  }
+
+  static support(args:DataProviderArgs): boolean{
+    return args.type === QUERY_TYPE.MODEL
+  }
+}
+
+export default ModelProvider

+ 1 - 1
services/profile/accessProfile.ts

@@ -1,4 +1,4 @@
-import {AbilitiesType, accessState, AccessStore, AnyJson} from "~/types/types";
+import {AbilitiesType, accessState, AccessStore, AnyJson} from "~/types/interfaces";
 import {Ability} from "@casl/ability";
 
 /**

+ 1 - 1
services/profile/organizationProfile.ts

@@ -1,4 +1,4 @@
-import {AnyJson, organizationState, OrganizationStore} from "~/types/types";
+import {AnyJson, organizationState, OrganizationStore} from "~/types/interfaces";
 
 /**
  * @category Services/profiles

+ 0 - 29
services/queries/rest.ts

@@ -1,29 +0,0 @@
-import  {$hydraParser} from '../../services/utils/hydraParser'
-import {NuxtHTTPInstance} from "@nuxt/http";
-
-export class Rest{
-  private $http: NuxtHTTPInstance
-
-  constructor($http: NuxtHTTPInstance) {
-    this.$http = $http
-  }
-  public getCollection = async (uri: string) => {
-    const responseQuery = await this.$http.get(`${uri}`);
-    return await this.queries(responseQuery);
-  }
-
-  public getItem = async (uri: string, key: number|string) => {
-    const query = await this.$http.get(`${uri}/${key}`);
-    return await this.queries(query);
-  }
-
-  private queries = async (responseQuery: any) => {
-    try {
-      let response = await responseQuery.json();
-      return $hydraParser.parse(response);
-    } catch (err) {
-      console.log(err)
-    }
-  }
-}
-export const $rest = ($http: NuxtHTTPInstance) => new Rest($http)

+ 5 - 3
services/rights/abilitiesUtils.ts

@@ -1,10 +1,11 @@
 import {$accessProfile} from "@/services/profile/accessProfile"
 import {$organizationProfile} from "@/services/profile/organizationProfile"
 import {$roleUtils} from "~/services/rights/roleUtils";
-import {AbilitiesType, AnyJson, AnyStore} from "~/types/types";
+import {AbilitiesType, AnyJson, AnyStore} from "~/types/interfaces";
 import {Ability} from "@casl/ability";
-import {$yamlParser} from "~/services/utils/yamlParser";
 import * as _ from "lodash";
+import Serializer from "~/services/serializer/serializer";
+import {DENORMALIZER_TYPE} from "~/types/enums";
 
 /**
  * @category Services/droits
@@ -94,7 +95,8 @@ class AbilitiesUtils {
   getAbilitiesByConfig(configPath:string): Array<AbilitiesType> {
     let abilitiesByConfig: Array<AbilitiesType> = []
    try {
-      const doc = $yamlParser.parse(configPath);
+      const serializer = new Serializer()
+      const doc = serializer.denormalize({path: configPath}, DENORMALIZER_TYPE.YAML);
       const abilitiesAvailable = doc['abilities']
       const abilitiesFiltered = this.abilitiesAvailableFilter(abilitiesAvailable)
       abilitiesByConfig = this.transformAbilitiesConfigToAbility(abilitiesFiltered)

+ 1 - 1
services/rights/roleUtils.ts

@@ -1,4 +1,4 @@
-import {AbilitiesType, AnyJson} from "~/types/types";
+import {AbilitiesType, AnyJson} from "~/types/interfaces";
 import * as _ from "lodash";
 
 const roles_by_function = [

+ 7 - 0
services/serializer/denormalizer/_import.ts

@@ -0,0 +1,7 @@
+import Hydra from "~/services/serializer/denormalizer/hydra";
+import Yaml from "~/services/serializer/denormalizer/yaml";
+
+export const denormalizers = [
+  Yaml,
+  Hydra
+]

+ 12 - 0
services/serializer/denormalizer/baseDenormalizer.ts

@@ -0,0 +1,12 @@
+import {DENORMALIZER_TYPE} from "~/types/enums";
+
+class BaseDenormalizer{
+  constructor() {
+  }
+
+  static support(type: DENORMALIZER_TYPE): boolean {
+    throw new Error('Need to be implement into static method')
+  }
+}
+
+export default BaseDenormalizer

+ 118 - 0
services/serializer/denormalizer/hydra.ts

@@ -0,0 +1,118 @@
+import {AnyJson, Denormalizer} from "~/types/interfaces";
+import BaseDenormalizer from "~/services/serializer/denormalizer/baseDenormalizer";
+import {DENORMALIZER_TYPE} from "~/types/enums";
+
+/**
+ * @category Services/utils
+ * @class HydraParser
+ * Classe permettant d'assurer le parsing d'une réponse Hydra
+ */
+class Hydra extends BaseDenormalizer implements Denormalizer{
+  static support(type: DENORMALIZER_TYPE): boolean {
+    return type === DENORMALIZER_TYPE.DEFAULT
+  }
+
+  /**
+   * Parcours une réponse Hydra pour retourner son équivalent en Json
+   * @param {AnyJson} hydraData
+   * @return {AnyJson} réponse parsée
+   */
+  public denormalize(hydraData: AnyJson): AnyJson {
+    if (hydraData['hydra:member']) {
+      hydraData.totalCount = hydraData['hydra:totalItems'];
+      return this.parseCollection(hydraData);
+    } else {
+      return this.parseItem(hydraData);
+    }
+  }
+
+  /**
+   * Méthode de parsing appelé si on est dans un GET
+   * @param {AnyJson} hydraData
+   */
+  private parseItem(hydraData: AnyJson): AnyJson {
+    this.populateId(hydraData);
+
+    if (hydraData['hydra:previous']) {
+      let iriParts = hydraData['hydra:previous'].split('/');
+      hydraData.previous = iriParts[iriParts.length - 1];
+    }
+    if (hydraData['hydra:next']) {
+      let iriParts = hydraData['hydra:next'].split('/');
+      hydraData.next = iriParts[iriParts.length - 1];
+    }
+    if (hydraData['hydra:totalItems']) {
+      hydraData.totalItems = hydraData['hydra:totalItems'];
+    }
+    if (hydraData['hydra:itemPosition']) {
+      hydraData.itemPosition = hydraData['hydra:itemPosition'];
+    }
+    return hydraData;
+  }
+
+  /**
+   * Méthode de parsing appelé si on est dans un GET Collection
+   * @param {AnyJson} hydraData
+   */
+  private parseCollection(hydraData: AnyJson): AnyJson {
+    let collectionResponse = hydraData['hydra:member'];
+    collectionResponse.metadata = {};
+    collectionResponse.order = {};
+    collectionResponse.search = {};
+
+    // Put metadata in a property of the collection
+    for (const key in hydraData) {
+      const value = hydraData[key];
+      if ('hydra:member' !== key) {
+        collectionResponse.metadata[key] = value;
+      }
+    }
+
+    // Populate href property for all elements of the collection
+    for (const key in collectionResponse) {
+      const value = collectionResponse[key];
+      this.populateAllData(value);
+    }
+
+    if ('undefined' !== typeof (hydraData['hydra:search'])) {
+      let collectionSearch = hydraData['hydra:search']['hydra:mapping'];
+      for (const key in collectionSearch) {
+        const value = collectionSearch[key];
+        if (value['variable'].indexOf("filter[order]") === 0) {
+          collectionResponse.order[value['property']] = value;
+        } else if (value['variable'].indexOf("filter[where]") === 0) {
+          collectionResponse.search[value['property']] = value;
+        }
+      }
+    }
+    return collectionResponse;
+  }
+
+
+  /**
+   * Hydrate l'objet Json avec la valeur id correspondant à l'uri de l'objet
+   * @param {AnyJson} data
+   */
+  private populateId(data: AnyJson): void{
+    if (data['@id'] && data['@id'] instanceof String) {
+      var iriParts = data['@id'].split('/');
+      data.id = iriParts[iriParts.length - 1];
+    }
+  }
+
+  /**
+   * Hydrate l'objet JSON de façon récursive (afin de gérer les objet nested)
+   * @param {AnyJson} data
+   */
+  private populateAllData(data: AnyJson):void {
+    this.populateId(data);
+    for (const key in data) {
+      const value = data[key];
+      if (value instanceof Object) {
+        this.populateAllData(value);
+      }
+    }
+  }
+}
+
+export default Hydra

+ 32 - 0
services/serializer/denormalizer/yaml.ts

@@ -0,0 +1,32 @@
+import {AnyJson, Denormalizer} from "~/types/interfaces";
+import { read } from 'yaml-import';
+import BaseDenormalizer from "~/services/serializer/denormalizer/baseDenormalizer";
+import {DENORMALIZER_TYPE} from "~/types/enums";
+const yaml = require('js-yaml');
+
+/**
+ * @category Services/utils
+ * @class YamlParser
+ * Classe permettant d'assurer le parsing d'un fichier Yaml
+ */
+class Yaml extends BaseDenormalizer implements Denormalizer{
+  static support(type: DENORMALIZER_TYPE): boolean {
+    return type === DENORMALIZER_TYPE.YAML
+  }
+
+  /**
+   * Parse un fichier Yaml pour en retourner son équivalent en Json
+   * @param {AnyJson} data
+   * @return {AnyJson}
+   */
+  denormalize(data: AnyJson): AnyJson {
+    try {
+      return yaml.load(yaml.dump(read(data.path)));
+    }catch (e) {
+      console.debug(e);
+      return {}
+    }
+  }
+}
+
+export default Yaml

+ 5 - 0
services/serializer/normalizer/_import.ts

@@ -0,0 +1,5 @@
+import Model from "~/services/serializer/normalizer/model";
+
+export const normalizers = [
+  Model
+]

+ 12 - 0
services/serializer/normalizer/baseNormalizer.ts

@@ -0,0 +1,12 @@
+import {QUERY_TYPE} from "~/types/enums";
+
+class BaseNormalizer{
+  constructor() {
+  }
+
+  static support(type: QUERY_TYPE): boolean {
+    throw new Error('Need to be implement into static method')
+  }
+}
+
+export default BaseNormalizer

+ 14 - 0
services/serializer/normalizer/model.ts

@@ -0,0 +1,14 @@
+import BaseNormalizer from "~/services/serializer/normalizer/baseNormalizer";
+import {DataPersisterArgs, Normalizer} from "~/types/interfaces";
+import {QUERY_TYPE} from "~/types/enums";
+
+class Model extends BaseNormalizer implements Normalizer{
+  static support(type: QUERY_TYPE): boolean {
+    return type === QUERY_TYPE.MODEL
+  }
+
+  normalize(args:DataPersisterArgs): any {
+    console.log(args)
+  }
+}
+export default Model

+ 24 - 0
services/serializer/serializer.ts

@@ -0,0 +1,24 @@
+import {AnyJson, DataPersisterArgs} from "~/types/interfaces";
+import {denormalizers} from "~/services/serializer/denormalizer/_import";
+import {normalizers} from "~/services/serializer/normalizer/_import";
+import {DENORMALIZER_TYPE} from "~/types/enums";
+
+class Serializer {
+  public normalize(args:DataPersisterArgs){
+    for(const normalizer of normalizers){
+      if(normalizer.support(args.type)){
+        return new normalizer().normalize(args);
+      }
+    }
+  }
+
+  public denormalize(data: AnyJson, type: DENORMALIZER_TYPE): any {
+    for(const denormalizer of denormalizers){
+      if(denormalizer.support(type)){
+        return new denormalizer().denormalize(data);
+      }
+    }
+  }
+}
+
+export default Serializer

+ 0 - 112
services/utils/hydraParser.ts

@@ -1,112 +0,0 @@
-import {AnyJson} from "~/types/types";
-
-/**
- * @category Services/utils
- * @class HydraParser
- * Classe permettant d'assurer le parsing d'une réponse Hydra
- */
-class HydraParser {
-  /**
-   * Parcours une réponse Hydra pour retourner son équivalent en Json
-   * @param {AnyJson} hydraData
-   * @return {AnyJson} réponse parsée
-   */
-  parse(hydraData: AnyJson): AnyJson {
-    if (hydraData['hydra:member']) {
-      hydraData.totalCount = hydraData['hydra:totalItems'];
-      return this.parseCollection(hydraData);
-    } else {
-      return this.parseItem(hydraData);
-    }
-  }
-
-  /**
-   * Méthode de parsing appelé si on est dans un GET
-   * @param {AnyJson} hydraData
-   */
-  parseItem(hydraData: AnyJson): AnyJson {
-    this.populateId(hydraData);
-
-    if (hydraData['hydra:previous']) {
-      let iriParts = hydraData['hydra:previous'].split('/');
-      hydraData.previous = iriParts[iriParts.length - 1];
-    }
-    if (hydraData['hydra:next']) {
-      let iriParts = hydraData['hydra:next'].split('/');
-      hydraData.next = iriParts[iriParts.length - 1];
-    }
-    if (hydraData['hydra:totalItems']) {
-      hydraData.totalItems = hydraData['hydra:totalItems'];
-    }
-    if (hydraData['hydra:itemPosition']) {
-      hydraData.itemPosition = hydraData['hydra:itemPosition'];
-    }
-    return hydraData;
-  }
-
-  /**
-   * Méthode de parsing appelé si on est dans un GET Collection
-   * @param {AnyJson} hydraData
-   */
-  parseCollection(hydraData: AnyJson): AnyJson {
-    let collectionResponse = hydraData['hydra:member'];
-    collectionResponse.metadata = {};
-    collectionResponse.order = {};
-    collectionResponse.search = {};
-
-    // Put metadata in a property of the collection
-    for (const key in hydraData) {
-      const value = hydraData[key];
-      if ('hydra:member' !== key) {
-        collectionResponse.metadata[key] = value;
-      }
-    }
-
-    // Populate href property for all elements of the collection
-    for (const key in collectionResponse) {
-      const value = collectionResponse[key];
-      this.populateAllData(value);
-    }
-
-    if ('undefined' !== typeof (hydraData['hydra:search'])) {
-      let collectionSearch = hydraData['hydra:search']['hydra:mapping'];
-      for (const key in collectionSearch) {
-        const value = collectionSearch[key];
-        if (value['variable'].indexOf("filter[order]") === 0) {
-          collectionResponse.order[value['property']] = value;
-        } else if (value['variable'].indexOf("filter[where]") === 0) {
-          collectionResponse.search[value['property']] = value;
-        }
-      }
-    }
-    return collectionResponse;
-  }
-
-
-  /**
-   * Hydrate l'objet Json avec la valeur id correspondant à l'uri de l'objet
-   * @param {AnyJson} data
-   */
-  populateId(data: AnyJson): void{
-    if (data['@id'] && data['@id'] instanceof String) {
-      var iriParts = data['@id'].split('/');
-      data.id = iriParts[iriParts.length - 1];
-    }
-  }
-
-  /**
-   * Hydrate l'objet JSON de façon récursive (afin de gérer les objet nested)
-   * @param {AnyJson} data
-   */
-  populateAllData(data: AnyJson):void {
-    this.populateId(data);
-    for (const key in data) {
-      const value = data[key];
-      if (value instanceof Object) {
-        this.populateAllData(value);
-      }
-    }
-  }
-}
-
-export const $hydraParser = new HydraParser()

+ 1 - 1
services/utils/objectProperties.ts

@@ -3,7 +3,7 @@
  * @class ObjectProperties
  * Classe aidant à manipuler des Objets
  */
-import {AnyJson} from "~/types/types";
+import {AnyJson} from "~/types/interfaces";
 
 class ObjectProperties {
   /**

+ 0 - 27
services/utils/yamlParser.ts

@@ -1,27 +0,0 @@
-import {AnyJson} from "~/types/types";
-import { read } from 'yaml-import';
-const yaml = require('js-yaml');
-
-/**
- * @category Services/utils
- * @class YamlParser
- * Classe permettant d'assurer le parsing d'un fichier Yaml
- */
-class YamlParser {
-
-  /**
-   * Parse un fichier Yaml pour en retourner son équivalent en Json
-   * @param {string} inPath
-   * @return {AnyJson}
-   */
-  parse(inPath: string): AnyJson {
-    try {
-      return yaml.load(yaml.dump(read(inPath)));
-    }catch (e) {
-      console.debug(e);
-      return {}
-    }
-  }
-}
-
-export const $yamlParser = new YamlParser()

+ 7 - 1
tsconfig.json

@@ -8,6 +8,12 @@
       "ESNext.AsyncIterable",
       "DOM"
     ],
+    "preserveConstEnums": true,
+    "typeRoots": [
+      "./types/types.d.ts",
+      "./types/interfaces.d.ts",
+      "./types/enums.d.ts"
+    ],
     "esModuleInterop": true,
     "allowJs": true,
     "sourceMap": true,
@@ -26,7 +32,7 @@
     "types": [
       "@types/node",
       "@nuxt/types",
-      "@nuxt/http",
+      "@nuxtjs/axios",
       "@nuxtjs/vuetify",
       "@nuxtjs/moment",
       "nuxt-i18n"

+ 23 - 0
types/enums.ts

@@ -0,0 +1,23 @@
+export const enum HTTP_METHOD {
+  POST = 'POST',
+  PUT = 'PUT',
+  GET = 'GET',
+  DELETE = 'DELETE'
+}
+
+export const enum DENORMALIZER_TYPE {
+  DEFAULT,
+  YAML
+}
+
+export const enum QUERY_TYPE {
+  DEFAULT,
+  MODEL,
+  ENUM
+}
+
+export const enum ABILITIES {
+  DISPLAY = 'diplay',
+  READ = 'read',
+  MANAGE = 'manage'
+}

+ 128 - 0
types/interfaces.d.ts

@@ -0,0 +1,128 @@
+import {Model} from "@vuex-orm/core";
+import {Ability} from "@casl/ability";
+import DataPersister from "~/services/dataPersister/dataPersister";
+import DataProvider from "~/services/dataProvider/dataProvider";
+import {Store} from "vuex";
+import {ABILITIES, QUERY_TYPE} from "~/types/enums";
+
+/**
+ * Upgrade du @nuxt/types pour TypeScript
+ */
+declare module '@nuxt/types' {
+  interface Context {
+    $ability(): Ability,
+    $dataPersister: DataPersister,
+    $dataProvider: DataProvider,
+  }
+}
+
+interface ItemMenu {
+  title: string,
+  icon?: string,
+  to?: string,
+  children?: ItemsMenu,
+  isExternalLink?: boolean,
+}
+interface ItemsMenu extends Array<ItemMenu> {}
+
+interface AbilitiesType {
+  action: ABILITIES,
+
+  subject: string,
+  /** an array of fields to which user has (or not) access */
+  fields?: string[]
+  /** an object of conditions which restricts the rule scope */
+  conditions?: any
+  /** indicates whether rule allows or forbids something */
+  inverted?: boolean
+  /** message which explains why rule is forbidden */
+  reason?: string
+}
+
+interface formState {
+  dirty: boolean,
+  showConfirmToLeave: boolean,
+  goAfterLeave: string
+}
+
+interface accessState {
+  bearer: string,
+  accessId: number,
+  name: string,
+  givenName: string,
+  roles: Array<string>,
+  abilities: Array<AbilitiesType>,
+  isAdminAccess: boolean,
+  isAdmin: boolean,
+  isAdministratifManager: boolean,
+  isPedagogicManager: boolean,
+  isFinancialManager: boolean,
+  isCaMember: boolean,
+  isStudent: boolean,
+  isTeacher: boolean,
+  isMember: boolean,
+  isOther: boolean,
+  hasLateralMenu: boolean,
+  hasConfigurationMenu: boolean,
+  hasAccessesMenu: boolean,
+  hasFamilyMenu: boolean
+}
+interface AccessStore extends Store<{profile:{access:accessState}}> {}
+
+interface organizationState {
+  id: number,
+  name: string,
+  product?: string,
+  modules?: Array<string>,
+  hasChildren?: boolean,
+  networks: Array<string>,
+  website?: string,
+  subDomain?: string,
+  parents: Array<organizationState>,
+}
+interface OrganizationStore extends Store<{profile:{organization:organizationState}}> {}
+
+interface AnyJson extends Record<string, any> {}
+interface AnyStore extends Store<any> {}
+
+interface EnumChoice {
+  value: string,
+  label: string
+}
+interface EnumChoices extends Array<EnumChoice> {}
+
+interface UrlArgs {
+  readonly type: QUERY_TYPE,
+  readonly url?:string,
+  readonly enumType?:string,
+  readonly model?: typeof Model,
+  readonly root_model?: typeof Model,
+  readonly id?:any,
+  readonly root_id?:number
+}
+
+interface DataPersisterArgs extends UrlArgs{
+  readonly hook?:string
+}
+
+interface HookPersister{
+  invoke(args:DataPersisterArgs): Promise<any>,
+}
+
+interface DataProviderArgs extends UrlArgs{
+  readonly hook?:string
+}
+
+interface HookProvider{
+  invoke(args:DataProviderArgs): Promise<any>,
+}
+interface Provider{
+  invoke(data: AnyJson): Promise<any>,
+}
+interface Denormalizer{
+  denormalize(data:any): any,
+}
+interface Normalizer{
+  normalize(args:DataPersisterArgs): any,
+}
+

+ 1 - 85
types/types.d.ts

@@ -1,86 +1,2 @@
-import {
-  Store
-} from "vuex";
-import {Ability} from "@casl/ability";
-import {Rest} from "~/services/queries/rest";
-
-/**
- * Upgrade du @nuxt/types pour TypeScript
- */
-declare module '@nuxt/types' {
-  interface Context {
-    $ability(): Ability,
-    $rest: Rest
-  }
-}
-
-interface ItemMenu {
-  title: string,
-  icon?: string,
-  to?: string,
-  children?: ItemsMenu,
-  isExternalLink?: boolean,
-}
-interface ItemsMenu extends Array<ItemMenu> {}
-
-interface AbilitiesType {
-  action: 'display' | 'read' | 'manage',
-  subject: string,
-  /** an array of fields to which user has (or not) access */
-  fields?: string[]
-  /** an object of conditions which restricts the rule scope */
-  conditions?: any
-  /** indicates whether rule allows or forbids something */
-  inverted?: boolean
-  /** message which explains why rule is forbidden */
-  reason?: string
-}
-
-interface accessState {
-  bearer: string,
-  accessId: number,
-  name: string,
-  givenName: string,
-  roles: Array<string>,
-  abilities: Array<AbilitiesType>,
-  isAdminAccess: boolean,
-  isAdmin: boolean,
-  isAdministratifManager: boolean,
-  isPedagogicManager: boolean,
-  isFinancialManager: boolean,
-  isCaMember: boolean,
-  isStudent: boolean,
-  isTeacher: boolean,
-  isMember: boolean,
-  isOther: boolean,
-  hasLateralMenu: boolean,
-  hasConfigurationMenu: boolean,
-  hasAccessesMenu: boolean,
-  hasFamilyMenu: boolean
-}
-interface AccessStore extends Store<{profile:{access:accessState}}> {}
-
-interface organizationState {
-  id: number,
-  name: string,
-  product?: string,
-  modules?: Array<string>,
-  hasChildren?: boolean,
-  networks: Array<string>,
-  website?: string,
-  subDomain?: string,
-  parents: Array<organizationState>,
-}
-interface OrganizationStore extends Store<{profile:{organization:organizationState}}> {}
-
-interface AnyJson extends Record<string, any> {}
-interface AnyStore extends Store<any> {}
-
-interface EnumChoice {
-  value: string,
-  label: string
-}
-interface EnumChoices extends Array<EnumChoice> {}
-
-import {Query, Repository} from "@vuex-orm/core";
+import {Query, Repository, Model} from "@vuex-orm/core";
 export type RepositoryOrQuery<R extends Repository = Repository, Q extends Query = Query> = R | Q;

+ 0 - 21
use/form/useFormInputSetup.ts

@@ -1,21 +0,0 @@
-import {ref, useContext, computed} from '@nuxtjs/composition-api'
-import {$objectProperties} from "~/services/utils/objectProperties";
-import {AnyJson} from "~/types/types";
-import {ModelsOrRepositories} from "@vuex-orm/core";
-
-class useFormInputSetup{
-  public getData(repository: ModelsOrRepositories, id:number, field:string){
-    const entry = $objectProperties.cloneAndFlatten(repository.find(id) as AnyJson);
-    const data = ref(entry[field])
-
-    const readOnly = false;
-
-    return {
-      data,
-      entry,
-      readOnly
-    }
-  }
-}
-
-export const useFormInputSetupGetData = (repository: ModelsOrRepositories, id:number, field:string) => new useFormInputSetup().getData(repository, id, field)

+ 8 - 2
use/form/utils.ts

@@ -1,13 +1,19 @@
 import {ref, useContext} from "@nuxtjs/composition-api";
+import {QUERY_TYPE} from "~/types/enums";
 
 export class Utils{
   public static useHandleSiret(){
-    const {app:{i18n}, $rest} = useContext()
+    const {app:{i18n}, $dataProvider} = useContext()
     const siretError = ref(false)
     const siretErrorMessage = ref('')
 
     const checkSiret = async (siret:string) => {
-      const response = await $rest.getItem(`/api/siret-checking`, siret)
+      const response = await $dataProvider.invoke({
+        type: QUERY_TYPE.DEFAULT,
+        url: 'siret-checking',
+        id: siret
+      })
+
       if(response){
         siretError.value = !response.isCorrect
         siretErrorMessage.value = response.isCorrect ? '' : i18n.t('siret_error') as string

+ 1 - 1
use/layout/Menus/accessMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu, ItemsMenu} from "~/types/types";
+import {ItemMenu, ItemsMenu} from "~/types/interfaces";
 import {$organizationProfile} from "~/services/profile/organizationProfile";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 

+ 1 - 1
use/layout/Menus/accountMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu, ItemsMenu} from "~/types/types";
+import {ItemMenu, ItemsMenu} from "~/types/interfaces";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 
 class AccountMenu extends BaseMenu{

+ 1 - 1
use/layout/Menus/admin2iosMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu, ItemsMenu} from "~/types/types";
+import {ItemMenu, ItemsMenu} from "~/types/interfaces";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 
 class Admin2iosMenu extends BaseMenu{

+ 1 - 1
use/layout/Menus/agendaMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu, ItemsMenu} from "~/types/types";
+import {ItemMenu, ItemsMenu} from "~/types/interfaces";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 
 class AgendaMenu extends BaseMenu{

+ 1 - 1
use/layout/Menus/baseMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu} from "~/types/types";
+import {ItemMenu} from "~/types/interfaces";
 
 class BaseMenu{
   protected $config:any;

+ 1 - 1
use/layout/Menus/billingMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu, ItemsMenu} from "~/types/types";
+import {ItemMenu, ItemsMenu} from "~/types/interfaces";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 
 class BillingMenu extends BaseMenu{

+ 1 - 1
use/layout/Menus/communicationMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu, ItemsMenu} from "~/types/types";
+import {ItemMenu, ItemsMenu} from "~/types/interfaces";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 
 class CommunicationMenu extends BaseMenu{

+ 1 - 1
use/layout/Menus/configurationMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu, ItemsMenu} from "~/types/types";
+import {ItemMenu, ItemsMenu} from "~/types/interfaces";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 
 class ConfigurationMenu extends BaseMenu{

+ 1 - 1
use/layout/Menus/cotisationsMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu, ItemsMenu} from "~/types/types";
+import {ItemMenu, ItemsMenu} from "~/types/interfaces";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 
 class CotisationsMenu extends BaseMenu{

+ 1 - 1
use/layout/Menus/donorsMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu, ItemsMenu} from "~/types/types";
+import {ItemMenu, ItemsMenu} from "~/types/interfaces";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 
 class DonorsMenu extends BaseMenu{

+ 1 - 1
use/layout/Menus/educationalMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu, ItemsMenu} from "~/types/types";
+import {ItemMenu, ItemsMenu} from "~/types/interfaces";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 
 class EducationalMenu extends BaseMenu{

+ 1 - 1
use/layout/Menus/equipmentMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu} from "~/types/types";
+import {ItemMenu} from "~/types/interfaces";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 
 class EquipmentMenu extends BaseMenu{

+ 1 - 1
use/layout/Menus/medalsMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu, ItemsMenu} from "~/types/types";
+import {ItemMenu, ItemsMenu} from "~/types/interfaces";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 
 class MedalsMenu extends BaseMenu{

+ 1 - 1
use/layout/Menus/myAccessesMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu, ItemsMenu} from "~/types/types";
+import {ItemMenu, ItemsMenu} from "~/types/interfaces";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 
 class MyAccessesMenu extends BaseMenu{

+ 1 - 1
use/layout/Menus/myFamilyMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu, ItemsMenu} from "~/types/types";
+import {ItemMenu, ItemsMenu} from "~/types/interfaces";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 
 class MyFamilyMenu extends BaseMenu{

+ 1 - 1
use/layout/Menus/statsMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu, ItemsMenu} from "~/types/types";
+import {ItemMenu, ItemsMenu} from "~/types/interfaces";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 
 class StatsMenu extends BaseMenu{

+ 1 - 1
use/layout/Menus/websiteMenu.ts

@@ -1,4 +1,4 @@
-import {ItemMenu, ItemsMenu, organizationState} from "~/types/types";
+import {ItemMenu, ItemsMenu, organizationState} from "~/types/interfaces";
 import BaseMenu from "~/use/layout/Menus/baseMenu";
 import *  as _ from "lodash"
 

+ 1 - 1
use/layout/menu.ts

@@ -1,5 +1,5 @@
 import {ref, useContext} from "@nuxtjs/composition-api";
-import {ItemMenu, ItemsMenu} from "~/types/types";
+import {ItemsMenu} from "~/types/interfaces";
 import {getAccessMenu} from "~/use/layout/Menus/accessMenu";
 import {getAgendaMenu} from "~/use/layout/Menus/agendaMenu";
 import {getEquipmentMenu} from "~/use/layout/Menus/equipmentMenu";

+ 1 - 1
use/store/useQuery.ts

@@ -1,6 +1,6 @@
 import {Query} from "@vuex-orm/core";
 import {$objectProperties} from "~/services/utils/objectProperties";
-import {AnyJson} from "~/types/types";
+import {AnyJson} from "~/types/interfaces";
 import {Collection, Item} from "@vuex-orm/core/dist/src/data/Data";
 
 class useQuery{

+ 13 - 25
use/store/useRepository.ts

@@ -1,38 +1,26 @@
-import {useContext} from '@nuxtjs/composition-api'
-import {Repository} from "@vuex-orm/core";
+import {Model, Repository} from "@vuex-orm/core";
 import {$objectProperties} from "~/services/utils/objectProperties";
-import {Model} from '@/models/Model'
-import {AnyJson} from "~/types/types";
+import {AnyJson} from "~/types/interfaces";
+import {Store} from "vuex";
 
 class useRepository{
-  public getRepository(model: typeof Model): Repository<Model>{
-    const {store} = useContext()
-    return store.$repo(model)
-  }
+  private store !: Store<any>
 
-  public initRepository(model: typeof Model, readOnly:boolean = true): Repository<Model>{
-    const repository = this.getRepository(model)
-    this.setReadOnly(repository, readOnly)
-    return repository
+  public setStore(store: Store<any>){
+    this.store = store
   }
 
-  public setReadOnly(repository: Repository<Model>, readOnly:boolean): void{
-    repository.getModel().setReadOnly(readOnly)
-  }
-
-  public getReadOnly(repository: Repository<Model>): boolean{
-    return repository.getModel().getReadOnly()
+  public getRepository(model: typeof Model): Repository<Model>{
+    return this.store.$repo(model)
   }
 
-  public editRepository(repository: Repository<Model>){
-    return () => {
-      this.setReadOnly(repository, false)
-    }
+  public updateStoreFromField(repository: Repository<Model>, entry:AnyJson, value:any, field:string): void{
+    entry[field] = value
+    this.updateStore(repository, $objectProperties.cloneAndNest(entry))
   }
 
-  public updateStoreFromField(repository: Repository, entry:AnyJson, value:any, field:string): void{
-    entry[field] = value
-    repository.update($objectProperties.cloneAndNest(entry))
+  public updateStore(repository: Repository<Model>, entry:AnyJson): void{
+    repository.save(entry)
   }
 
   public cleanRepository(repository: Repository){

+ 15 - 0
use/utils/useSorter.ts

@@ -0,0 +1,15 @@
+import {EnumChoices} from "~/types/interfaces";
+
+class useSorter{
+  public sortEnum(enums:EnumChoices){
+    return enums.sort( (a, b) => {
+      if (a.label > b.label)
+        return 1;
+      if (a.label < b.label)
+        return -1;
+      return 0;
+    });
+  }
+}
+
+export const useSorterHelper = new useSorter()

File diff suppressed because it is too large
+ 393 - 286
yarn.lock


Some files were not shown because too many files changed in this diff