@api-platform/client-generator
Version:
Generate apps built with Next, Nuxt, Quasar, React, React Native, Vue or Vuetify for any API documented using Hydra or OpenAPI
274 lines (254 loc) • 7.54 kB
JavaScript
import Vue from 'vue';
import { getField, updateField } from 'vuex-map-fields';
import remove from 'lodash/remove';
import SubmissionError from '../../error/SubmissionError';
const initialState = () => ({
allIds: [],
byId: {},
created: null,
deleted: null,
error: "",
isLoading: false,
resetList: false,
selectItems: null,
totalItems: 0,
updated: null,
view: null,
violations: null
});
const handleError = (commit, e) => {
commit(ACTIONS.TOGGLE_LOADING);
if (e instanceof SubmissionError) {
commit(ACTIONS.SET_VIOLATIONS, e.errors);
// eslint-disable-next-line
commit(ACTIONS.SET_ERROR, e.errors._error);
return Promise.reject(e);
}
// eslint-disable-next-line
commit(ACTIONS.SET_ERROR, e.message);
return Promise.reject(e);
};
export const ACTIONS = {
ADD: 'ADD',
RESET_CREATE: 'RESET_CREATE',
RESET_DELETE: 'RESET_DELETE',
RESET_LIST: 'RESET_LIST',
RESET_SHOW: 'RESET_SHOW',
RESET_UPDATE: 'RESET_UPDATE',
SET_CREATED: 'SET_CREATED',
SET_DELETED: 'SET_DELETED',
SET_ERROR: 'SET_ERROR',
SET_SELECT_ITEMS: 'SET_SELECT_ITEMS',
SET_TOTAL_ITEMS: 'SET_TOTAL_ITEMS',
SET_UPDATED: 'SET_UPDATED',
SET_VIEW: 'SET_VIEW',
SET_VIOLATIONS: 'SET_VIOLATIONS',
TOGGLE_LOADING: 'TOGGLE_LOADING'
};
export default function makeCrudModule({
normalizeRelations = x => x,
resolveRelations = x => x,
service
} = {}) {
return {
actions: {
create: ({ commit }, values) => {
commit(ACTIONS.SET_ERROR, '');
commit(ACTIONS.TOGGLE_LOADING);
return service
.create(values)
.then(response => response.json())
.then(data => {
commit(ACTIONS.TOGGLE_LOADING);
commit(ACTIONS.ADD, data);
commit(ACTIONS.SET_CREATED, data);
})
.catch(e => handleError(commit, e));
},
del: ({ commit }, item) => {
commit(ACTIONS.TOGGLE_LOADING);
return service
.del(item)
.then(() => {
commit(ACTIONS.TOGGLE_LOADING);
commit(ACTIONS.SET_DELETED, item);
})
.catch(e => handleError(commit, e));
},
fetchAll: ({ commit, state }, params) => {
if (!service) throw new Error('No service specified!');
commit(ACTIONS.TOGGLE_LOADING);
return service
.findAll({ params })
.then(response => response.json())
.then(retrieved => {
commit(ACTIONS.TOGGLE_LOADING);
commit(
ACTIONS.SET_TOTAL_ITEMS,
retrieved['{{{hydraPrefix}}}totalItems']
);
commit(ACTIONS.SET_VIEW, retrieved['{{{hydraPrefix}}}view']);
if (true === state.resetList) {
commit(ACTIONS.RESET_LIST);
}
retrieved['{{{hydraPrefix}}}member'].forEach(item => {
commit(ACTIONS.ADD, normalizeRelations(item));
});
})
.catch(e => handleError(commit, e));
},
fetchSelectItems: (
{ commit },
{ params = { properties: ['@id', 'name'] } } = {}
) => {
commit(ACTIONS.TOGGLE_LOADING);
if (!service) throw new Error('No service specified!');
return service
.findAll({ params })
.then(response => response.json())
.then(retrieved => {
commit(
ACTIONS.SET_SELECT_ITEMS,
retrieved['{{{hydraPrefix}}}member']
);
})
.catch(e => handleError(commit, e));
},
load: ({ commit }, id) => {
if (!service) throw new Error('No service specified!');
commit(ACTIONS.TOGGLE_LOADING);
return service
.find(id)
.then(response => response.json())
.then(item => {
commit(ACTIONS.TOGGLE_LOADING);
commit(ACTIONS.ADD, normalizeRelations(item));
})
.catch(e => handleError(commit, e));
},
resetCreate: ({ commit }) => {
commit(ACTIONS.RESET_CREATE);
},
resetDelete: ({ commit }) => {
commit(ACTIONS.RESET_DELETE);
},
resetShow: ({ commit }) => {
commit(ACTIONS.RESET_SHOW);
},
resetUpdate: ({ commit }) => {
commit(ACTIONS.RESET_UPDATE);
},
update: ({ commit }, item) => {
commit(ACTIONS.SET_ERROR, '');
commit(ACTIONS.TOGGLE_LOADING);
return service
.update(item)
.then(response => response.json())
.then(data => {
commit(ACTIONS.TOGGLE_LOADING);
commit(ACTIONS.SET_UPDATED, data);
})
.catch(e => handleError(commit, e));
}
},
getters: {
find: state => id => {
return resolveRelations(state.byId[id]);
},
getField,
list: (state, getters) => {
return state.allIds.map(id => getters.find(id));
}
},
mutations: {
updateField,
[ACTIONS.ADD]: (state, item) => {
Vue.set(state.byId, item['@id'], item);
Vue.set(state, 'isLoading', false);
if (state.allIds.includes(item['@id'])) return;
state.allIds.push(item['@id']);
},
[ACTIONS.RESET_CREATE]: state => {
Object.assign(state, {
isLoading: false,
error: '',
created: null,
violations: null
});
},
[ACTIONS.RESET_DELETE]: state => {
Object.assign(state, {
isLoading: false,
error: '',
deleted: null
});
},
[ACTIONS.RESET_LIST]: state => {
Object.assign(state, {
allIds: [],
byId: {},
error: '',
isLoading: false,
resetList: false
});
},
[ACTIONS.RESET_SHOW]: state => {
Object.assign(state, {
error: '',
isLoading: false
});
},
[ACTIONS.RESET_UPDATE]: state => {
Object.assign(state, {
error: '',
isLoading: false,
updated: null,
violations: null
});
},
[ACTIONS.SET_CREATED]: (state, created) => {
Object.assign(state, { created });
},
[ACTIONS.SET_DELETED]: (state, deleted) => {
if (!state.allIds.includes(deleted['@id'])) return;
Object.assign(state, {
allIds: remove(state.allIds, item => item['@id'] === deleted['@id']),
byId: remove(state.byId, id => id === deleted['@id']),
deleted
});
},
[ACTIONS.SET_ERROR]: (state, error) => {
Object.assign(state, { error, isLoading: false });
},
[ACTIONS.SET_SELECT_ITEMS]: (state, selectItems) => {
Object.assign(state, {
error: '',
isLoading: false,
selectItems
});
},
[ACTIONS.SET_TOTAL_ITEMS]: (state, totalItems) => {
Object.assign(state, { totalItems });
},
[ACTIONS.SET_UPDATED]: (state, updated) => {
Object.assign(state, {
byId: {
[updated['@id']]: updated
},
updated
});
},
[ACTIONS.SET_VIEW]: (state, view) => {
Object.assign(state, { view });
},
[ACTIONS.SET_VIOLATIONS]: (state, violations) => {
Object.assign(state, { violations });
},
[ACTIONS.TOGGLE_LOADING]: state => {
Object.assign(state, { error: '', isLoading: !state.isLoading });
}
},
namespaced: true,
state: initialState
};
}