import axios from '@/axios-client.js'; import router from '../../router'; const feature = { namespaced: true, state: { attachmentFormset: [], attachmentsToDelete: [], checkedFeatures: [], extra_form: [], features: [], features_count: 0, current_feature: [], form: null, linkedFormset: [], linked_features: [], statusChoices: [ { name: 'Brouillon', value: 'draft', }, { name: 'En attente de publication', value: 'pending', }, { name: 'Publié', value: 'published', }, { name: 'Archivé', value: 'archived', }, ], }, mutations: { SET_FEATURES(state, features) { state.features = features.sort((a, b) => { return new Date(b.created_on) - new Date(a.created_on); // sort features chronologically }); }, SET_FEATURES_COUNT(state, features_count) { state.features_count = features_count; }, SET_CURRENT_FEATURE(state, feature) { state.current_feature = feature; }, UPDATE_FORM(state, payload) { state.form = payload; }, UPDATE_EXTRA_FORM(state, extra_form) { const index = state.extra_form.findIndex(el => el.label === extra_form.label); if (index !== -1) { state.extra_form[index] = extra_form; } }, SET_EXTRA_FORM(state, extra_form) { state.extra_form = extra_form; }, CLEAR_EXTRA_FORM(state) { state.extra_form = []; }, ADD_ATTACHMENT_FORM(state, attachmentFormset) { state.attachmentFormset = [...state.attachmentFormset, attachmentFormset]; }, UPDATE_ATTACHMENT_FORM(state, payload) { const index = state.attachmentFormset.findIndex((el) => el.dataKey === payload.dataKey); if (index !== -1) state.attachmentFormset[index] = payload; }, REMOVE_ATTACHMENT_FORM(state, payload) { state.attachmentFormset = state.attachmentFormset.filter(form => form.dataKey !== payload); }, CLEAR_ATTACHMENT_FORM(state) { state.attachmentFormset = []; }, ADD_LINKED_FORM(state, linkedFormset) { state.linkedFormset = [...state.linkedFormset, linkedFormset]; }, UPDATE_LINKED_FORM(state, payload) { const index = state.linkedFormset.findIndex((el) => el.dataKey === payload.dataKey); if (index !== -1) state.linkedFormset[index] = payload; }, REMOVE_LINKED_FORM(state, payload) { state.linkedFormset = state.linkedFormset.filter(form => form.dataKey !== payload); }, SET_LINKED_FEATURES(state, payload) { state.linked_features = payload; }, CLEAR_LINKED_FORM(state) { state.linkedFormset = []; }, ADD_ATTACHMENT_TO_DELETE(state, attachementId) { state.attachmentsToDelete.push(attachementId); }, REMOVE_ATTACHMENTS_ID_TO_DELETE(state, attachementId) { state.attachmentsToDelete = state.attachmentsToDelete.filter(el => el !== attachementId); }, UPDATE_CHECKED_FEATURES(state, checkedFeatures) { state.checkedFeatures = checkedFeatures; } }, getters: { }, actions: { async GET_PROJECT_FEATURES({ commit, rootState }, { project_slug, feature_type__slug, ordering, search, limit, geojson = false }) { if (rootState.cancellableSearchRequest.length > 0) { const currentRequestCancelToken = rootState.cancellableSearchRequest[rootState.cancellableSearchRequest.length - 1]; currentRequestCancelToken.cancel(); } const cancelToken = axios.CancelToken.source(); commit('SET_CANCELLABLE_SEARCH_REQUEST', cancelToken, { root: true }); commit('SET_FEATURES', []); commit('SET_FEATURES_COUNT', 0); let url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}projects/${project_slug}/feature/`; if (feature_type__slug) { url = url.concat('', `${url.includes('?') ? '&' : '?'}feature_type__slug=${feature_type__slug}`); } if (ordering) { url = url.concat('', `${url.includes('?') ? '&' : '?'}ordering=${ordering}`); } if (search) { url = url.concat('', `${url.includes('?') ? '&' : '?'}title__icontains=${search}`); } if (limit) { url = url.concat('', `${url.includes('?') ? '&' : '?'}limit=${limit}`); } if (geojson) url = url.concat('', '&output=geojson'); try { const response = await axios.get(url, { cancelToken: cancelToken.token }); if (response.status === 200 && response.data) { const features = response.data.features; commit('SET_FEATURES', features); const features_count = response.data.count; commit('SET_FEATURES_COUNT', features_count); } return response; } catch (error) { console.error(error); return error; } }, GET_PROJECT_FEATURE({ commit, rootState }, { project_slug, feature_id }) { if (rootState.cancellableSearchRequest.length > 0) { const currentRequestCancelToken = rootState.cancellableSearchRequest[rootState.cancellableSearchRequest.length - 1]; currentRequestCancelToken.cancel(); } const cancelToken = axios.CancelToken.source(); commit('SET_CANCELLABLE_SEARCH_REQUEST', cancelToken, { root: true }); commit('SET_CURRENT_FEATURE', null); let url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}projects/${project_slug}/feature/?id=${feature_id}`; return axios .get(url, { cancelToken: cancelToken.token }) .then((response) => { if (response.status === 200 && response.data.features) { const feature = response.data.features[0]; commit('SET_CURRENT_FEATURE', feature); } return response; }) .catch((error) => { throw error; }); }, SEND_FEATURE({ state, rootState, commit, dispatch }, routeName) { commit('DISPLAY_LOADER', 'Le signalement est en cours de création', { root: true }); function redirect(featureId) { dispatch( 'GET_PROJECT_FEATURE', { project_slug: rootState.project_slug, feature_id: featureId } ) .then(() => { commit('DISCARD_LOADER', null, { root: true }); router.push({ name: 'details-signalement', params: { slug_type_signal: rootState.feature_type.current_feature_type_slug, slug_signal: featureId, message: routeName === "editer-signalement" ? "Le signalement a été mis à jour" : "Le signalement a été crée" }, }); dispatch('projects/GET_ALL_PROJECTS', null, { root:true }) //* & refresh project list }); } async function handleOtherForms(featureId) { await dispatch('SEND_ATTACHMENTS', featureId); await dispatch('PUT_LINKED_FEATURES', featureId); redirect(featureId); } function createGeojson() { //* prepare feature data to send let extraFormObject = {}; //* prepare an object to be flatten in properties of geojson for (const field of state.extra_form) { extraFormObject[field.name] = field.value; } return { "id": state.form.feature_id, "type": "Feature", "geometry": state.form.geometry, "properties": { "title": state.form.title, "description": state.form.description.value, "status": state.form.status.value, "project": rootState.project_slug, "feature_type": rootState.feature_type.current_feature_type_slug, ...extraFormObject } } } const geojson = createGeojson(); let url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}features/` if (routeName === "editer-signalement") { url += `${state.form.feature_id}/? feature_type__slug=${rootState.feature_type.current_feature_type_slug} &project__slug=${rootState.project_slug}` } return axios({ url, method: routeName === 'editer-signalement' ? 'PUT' : 'POST', data: geojson }).then((response) => { if ((response.status === 200 || response.status === 201) && response.data) { if (state.attachmentFormset.length > 0 || state.linkedFormset.length > 0 || state.attachmentsToDelete.length > 0) { handleOtherForms(response.data.id); } else { redirect(response.data.id); } } }) .catch((error) => { commit('DISCARD_LOADER', null, { root: true }); if (error.message === 'Network Error' || window.navigator.onLine === false) { let arraysOffline = []; let localStorageArray = localStorage.getItem('geocontrib_offline'); if (localStorageArray) { arraysOffline = JSON.parse(localStorageArray); } let updateMsg = { project: rootState.project_slug, type: routeName === "editer-signalement" ? "put" : "post", featureId: state.form.feature_id, geojson: geojson }; arraysOffline.push(updateMsg); localStorage.setItem('geocontrib_offline', JSON.stringify(arraysOffline)); router.push({ name: 'offline-signalement', params: { slug_type_signal: rootState.feature_type.current_feature_type_slug }, }); } else { console.error(error); throw error; } throw error; }); }, async SEND_ATTACHMENTS({ state, rootState, dispatch }, featureId) { const DJANGO_API_BASE = rootState.configuration.VUE_APP_DJANGO_API_BASE; function addFile(attachment, attchmtId) { let formdata = new FormData(); formdata.append('file', attachment.fileToImport, attachment.fileToImport.name); return axios .put(`${DJANGO_API_BASE}features/${featureId}/attachments/${attchmtId}/upload-file/`, formdata) .then((response) => { return response; }) .catch((error) => { console.error(error); return error; }); } function putOrPostAttachement(attachment) { let formdata = new FormData(); formdata.append('title', attachment.title); formdata.append('info', attachment.info); let url = `${DJANGO_API_BASE}features/${featureId}/attachments/`; if (attachment.id) { url += `${attachment.id}/`; } return axios({ url, method: attachment.id ? 'PUT' : 'POST', data: formdata }).then((response) => { if (response && (response.status === 200 || response.status === 201) && attachment.fileToImport) { return addFile(attachment, response.data.id); } return response; }) .catch((error) => { console.error(error); return error; }); } function deleteAttachement(attachmentsId, featureId) { let payload = { attachmentsId: attachmentsId, featureId: featureId }; return dispatch('DELETE_ATTACHMENTS', payload) .then((response) => response); } const promisesResult = await Promise.all([ ...state.attachmentFormset.map((attachment) => putOrPostAttachement(attachment)), ...state.attachmentsToDelete.map((attachmentsId) => deleteAttachement(attachmentsId, featureId)) ] ); state.attachmentsToDelete = []; return promisesResult; }, DELETE_ATTACHMENTS({ commit }, payload) { let url = `${this.state.configuration.VUE_APP_DJANGO_API_BASE}features/${payload.featureId}/attachments/${payload.attachmentsId}/`; return axios .delete(url) .then((response) => { if (response && response.status === 204) { commit('REMOVE_ATTACHMENTS_ID_TO_DELETE', payload.attachmentsId); return response; } }) .catch((error) => { console.error(error); return error; }); }, PUT_LINKED_FEATURES({ state, rootState }, featureId) { return axios .put(`${rootState.configuration.VUE_APP_DJANGO_API_BASE}features/${featureId}/feature-links/`, state.linkedFormset) .then((response) => { if (response.status === 200 && response.data) { return 'La relation a bien été ajouté'; } }) .catch((error) => { throw error; }); }, DELETE_FEATURE({ rootState }, feature_id) { const url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}features/${feature_id}/?` + `feature_type__slug=${rootState.feature_type.current_feature_type_slug}` + `&project__slug=${rootState.project_slug}`; return axios .delete(url) .then((response) => response) .catch(() => { return false; }); }, }, }; export default feature;