Commit 47413908 authored by Vincent Laroye's avatar Vincent Laroye

Merge branch 'feature/remove-unused-entities' into 'develop'

feature/remove-unused-entities

See merge request !629
parents 3785365b b0005ed0
Pipeline #4464 passed with stage
in 1 minute and 46 seconds
......@@ -57,8 +57,11 @@
</template>
<script>
import { groupSchema } from '@/store/schemas';
import versionMixin from '@/mixins/entities/version';
import layoutNavigationGroupMenuMixin from '@/mixins/layout/navigation/group-menu';
import registrableMixin from '@/mixins/registrable';
import GroupsSettingsButton from './groups-settings-button.vue';
......@@ -71,7 +74,12 @@ import GroupsSettingsButton from './groups-settings-button.vue';
*/
export default {
components: { GroupsSettingsButton },
mixins: [versionMixin, layoutNavigationGroupMenuMixin],
mixins: [
versionMixin,
layoutNavigationGroupMenuMixin,
registrableMixin([groupSchema], 'groups'),
],
props: {
value: {
type: Boolean,
......
......@@ -57,15 +57,24 @@
</template>
<script>
import { groupSchema } from '@/store/schemas';
import vuetifyTabsMixin from '@/mixins/vuetify/tabs';
import entitiesViewGroupMixin from '@/mixins/entities/view/group/index';
import layoutNavigationGroupMenuMixin from '@/mixins/layout/navigation/group-menu';
import registrableMixin from '@/mixins/registrable';
import GroupsSettingsButton from './groups-settings-button.vue';
export default {
components: { GroupsSettingsButton },
mixins: [vuetifyTabsMixin, entitiesViewGroupMixin, layoutNavigationGroupMenuMixin],
mixins: [
vuetifyTabsMixin,
entitiesViewGroupMixin,
layoutNavigationGroupMenuMixin,
registrableMixin([groupSchema], 'groups'),
],
watch: {
groups() {
this.$nextTick(this.callTabsOnResizeMethod);
......
import { createNamespacedHelpers } from 'vuex';
import { normalize } from 'normalizr';
import uid from '@/helpers/uid';
const { mapActions } = createNamespacedHelpers('entities');
const registerGetterMethodName = uid('registerGetter');
const unregisterGetterMethodName = uid('unregisterGetter');
/**
* Create registrable mixin for components
*
* @param {Object} entitySchema - Normalizr schema of entity
* @param {string} entityFieldName - Entity field name
* @return {{methods: {}, beforeDestroy(): void, mounted(): void}}
*/
export default (entitySchema, entityFieldName) => {
const dependenciesPreparer = (entities) => {
const { entities: normalizedEntities } = normalize(entities, entitySchema);
return Object.keys(normalizedEntities).map(type => ({
type,
ids: Object.keys(normalizedEntities[type]),
}));
};
return {
mounted() {
this[registerGetterMethodName]({
getDependencies: () => dependenciesPreparer(this[entityFieldName]),
instance: this,
});
},
beforeDestroy() {
this[unregisterGetterMethodName](this);
},
methods: {
...mapActions({
[registerGetterMethodName]: 'registerGetter',
[unregisterGetterMethodName]: 'unregisterGetter',
}),
},
};
};
......@@ -169,4 +169,8 @@ router.beforeResolve((to, from, next) => {
}
});
router.afterEach(() => {
store.dispatch('entities/sweep');
});
export default router;
/**
* @typedef {Object} VuexActionContext
* @property {Object} state
* @property {Object} rootState
* @property {Object} getters
* @property {Object} rootGetters
* @property {function} commit
* @property {function} dispatch
*/
import Vue from 'vue';
import Vuex from 'vuex';
......
......@@ -89,9 +89,9 @@ export default {
return dispatch('entities/fetch', {
route: API_ROUTES.context,
schema: [entitySchema],
method: 'POST',
params,
dataPreparer: d => d.data,
isPost: true,
}, { root: true });
},
......
import Vue from 'vue';
import { get, omit, uniq, mergeWith } from 'lodash';
import { get, omit, pick, uniq, mergeWith } from 'lodash';
import { normalize, denormalize } from 'normalizr';
import request from '@/services/request';
......@@ -11,9 +11,12 @@ const entitiesModuleName = 'entities';
const internalTypes = {
ENTITIES_UPDATE: 'ENTITIES_UPDATE',
ENTITIES_MERGE: 'ENTITIES_MERGE',
ENTITIES_REPLACE: 'ENTITIES_REPLACE',
ENTITIES_DELETE: 'ENTITIES_DELETE',
};
let registeredGetters = [];
const entitiesModule = {
namespaced: true,
getters: {
......@@ -47,6 +50,16 @@ const entitiesModule = {
},
},
mutations: {
/**
* @param {Object} state - state of the module
* @param {Object.<string, Object>} entities - Object of entities
*/
[internalTypes.ENTITIES_REPLACE](state, entities) {
Object.keys(entities).forEach((type) => {
Vue.set(state, type, entities[type]);
});
},
/**
* @param {Object} state - state of the module
* @param {Object.<string, Object>} entities - Object of entities
......@@ -66,13 +79,16 @@ const entitiesModule = {
*/
[internalTypes.ENTITIES_MERGE](state, entities) {
Object.keys(entities).forEach((type) => {
Vue.set(state, type, mergeWith({}, state[type] || {}, entities[type]), (objValue, srcValue) => {
if (Array.isArray(objValue)) {
return uniq(objValue.concat(srcValue));
}
Vue.set(
state, type, mergeWith({}, state[type] || {}, entities[type]),
(objValue, srcValue) => {
if (Array.isArray(objValue)) {
return uniq(objValue.concat(srcValue));
}
return undefined;
});
return undefined;
},
);
});
},
......@@ -87,16 +103,82 @@ const entitiesModule = {
},
},
actions: {
/**
* Register getterObject
*
* @param {VuexActionContext} context
* @param {Object} getterObject - getter object for registration
* @param {function} getterObject.getDependencies - Method for getting component dependencies
* @param {Vue.component} getterObject.instance - Instance of component
*/
registerGetter(context, getterObject) {
registeredGetters.push(getterObject);
},
/**
* Unregister getterObject by instance
*
* @param {VuexActionContext} context
* @param {Vue.component} instance - Instance of component
*/
unregisterGetter(context, instance) {
registeredGetters = registeredGetters.filter(getterObject => getterObject.instance !== instance);
},
/**
* Sweep unregistered entities
*
* @param {VuexActionContext} context
*/
sweep({ commit, state }) {
const entities = registeredGetters
.reduce((acc, { getDependencies }) => acc.concat(getDependencies()), [])
.reduce((acc, { type, ids }) => {
acc[type] = { ...(acc[type]), ...pick(state[type], ids) };
return acc;
}, {});
commit(internalTypes.ENTITIES_REPLACE, entities);
},
/**
* @typedef {Object} EntitiesRequestConfig
* @property {string} route - Route of resource
* @property {Object} schema - Schema for the resource
* @property {Object|string} body - Request body
* @property {string} method - Method of the request
* @property {Object} headers - Request headers
* @property {Object} params - Request query params
* @property {function} dataPreparer - Response data preparer before normalizing
* @property {string} mutationType - Mutation type after normalization
*/
/**
* @typedef {Object} EntitiesResponseData
* @property {any} data - Response data
* @property {Object} normalizedData - Response normalized data
* @property {Object} normalizedData.entities - Object based entities
* @property {Array} normalizedData.result - Ids of main entities
*/
/**
* Send request by our request service
*
* @param {VuexActionContext} context
* @param {EntitiesRequestConfig} config
* @returns {Promise<EntitiesResponseData>}
*/
async sendRequest(
{ commit },
{
route,
schema,
body,
method = 'GET',
headers = {},
dataPreparer = d => d,
params = {},
method = 'GET',
dataPreparer = d => d,
mutationType = internalTypes.ENTITIES_UPDATE,
},
) {
......@@ -124,27 +206,58 @@ const entitiesModule = {
return { data, normalizedData };
},
async fetch({ dispatch }, config) {
const newConfig = omit(config, ['isPost']);
if (config.isPost) {
newConfig.method = 'POST';
}
return dispatch('sendRequest', newConfig);
/**
* Send GET request
*
* @param {VuexActionContext} context
* @param {EntitiesRequestConfig} config
* @returns {Promise<EntitiesResponseData>}
*/
async fetch({ dispatch }, config) {
return dispatch('sendRequest', config);
},
/**
* Send POST request
*
* @param {VuexActionContext} context
* @param {EntitiesRequestConfig} config
* @returns {Promise<EntitiesResponseData>}
*/
async create({ dispatch }, config) {
return dispatch('sendRequest', { ...config, method: 'POST' });
},
/**
* Send PUT request
*
* @param {VuexActionContext} context
* @param {EntitiesRequestConfig} config
* @returns {Promise<EntitiesResponseData>}
*/
async update({ dispatch }, config) {
return dispatch('sendRequest', { ...config, method: 'PUT' });
},
/**
* Send DELETE request
*
* @param {VuexActionContext} context
* @param {EntitiesRequestConfig} config
* @returns {Promise<EntitiesResponseData>}
*/
async delete({ dispatch }, config) {
return dispatch('sendRequest', { ...config, method: 'DELETE' });
},
/**
* Remove entity by id and type from store
*
* @param {VuexActionContext} context
* @param {Object} payload
* @param {string|number} payload.id - Id of entity for deletion
* @param {string} payload.type - Type of entity for deletion
*/
removeFromStore({ commit, getters, state }, { id, type }) {
const data = getters.getItem(type, id);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment