Skip to content

Commit

Permalink
feat: les stores gèrent la sauvegarde des données
Browse files Browse the repository at this point in the history
Signed-off-by: Maud Royer <hello@maudroyer.fr>
  • Loading branch information
jillro committed May 3, 2024
1 parent 914e6bc commit 1a10eba
Show file tree
Hide file tree
Showing 14 changed files with 170 additions and 245 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"type": "module",
"scripts": {
"dev": "vite",
"dev-sw": "vite build & (sleep 1 && vite preview --port 3000)",
"dev-sw": "vite build --watch & (sleep 1 && vite preview --port 3000)",
"build": "npm run build:app",
"build:app": "vite build",
"build:widget": "vite build --config vite.widget.config.js --mode lib",
Expand Down
79 changes: 1 addition & 78 deletions src/cartobio-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const { VUE_APP_API_ENDPOINT: baseURL } = import.meta.env
* @typedef {import('@agencebio/cartobio-types').CartoBioFeatureCollection} CartoBioFeatureCollection
*/

const apiClient = axios.create({ baseURL, timeout: 10000 })
export const apiClient = axios.create({ baseURL, timeout: 10000 })

/**
*
Expand Down Expand Up @@ -53,28 +53,6 @@ export async function pacageLookup (pacage) {
return data
}


/**
* @param {string} numeroBio
* @returns {Promise<import('@agencebio/cartobio-types').AgenceBioNormalizedOperator>}
*/
export async function getOperator (numeroBio) {
const { data } = await apiClient.get(`/v2/operator/${numeroBio}`)

return data
}

/**
* @param {string} numeroBio
* @return {Promise<import('@agencebio/cartobio-types').NormalizedRecordSummary[]>}
*/
export async function getOperatorRecords (numeroBio) {
const { data } = await apiClient.get(`/v2/operator/${numeroBio}/records`)

return data
}


/**
* Creates a new operator Record
*
Expand All @@ -86,61 +64,6 @@ export async function createOperatorRecord (numeroBio, payload) {
return data
}

/**
* @param {UUID} recordId
* @return {Promise<NormalizedRecord>}
*/
export async function getRecord (recordId) {
const { data } = await apiClient.get(`/v2/audits/${recordId}`)

return data
}

/**
* Delete a single feature
*
* @return {Promise<NormalizedRecord>}
*/
export async function deleteSingleFeature ({ recordId }, { id, reason }) {
const { data } = await apiClient.delete(`/v2/audits/${recordId}/parcelles/${id}`, {data: { reason }})

return data
}

/**
* Creates or updates a record based on geographical informations
*
* @returns {Promise<NormalizedRecord>}
*/
export async function updateFeatureCollectionProperties ({ recordId }, featureCollection) {
const { data } = await apiClient.patch(`/v2/audits/${recordId}/parcelles`, featureCollection)

return data
}

/**
* Update/replace properties of a single feature
*
* @returns {Promise<NormalizedRecord>}
*/
export async function updateSingleFeature ({ recordId }, { id, properties, geometry }) {
const { data } = await apiClient.put(`/v2/audits/${recordId}/parcelles/${id}`, { properties, geometry })

return data
}

/**
*
* @param {string} recordId
* @param {Object} patch
* @returns {Promise<NormalizedRecord>}
*/
export async function updateAuditState (recordId, patch) {
const { data } = await apiClient.patch(`/v2/audits/${recordId}`, patch)

return data
}

/**
* @param {string} recordId
* @returns {Promise<void>}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ describe("SingleItemCertificationBodyForm", () => {
await form.find('#downgraded_state').setValue(CERTIFICATION_BODY_DECISION.ACCEPTED)

// click and assess server update
axios.__createMock.put.mockResolvedValueOnce({ data: record })
await form.find('.fr-modal__footer button.fr-btn').trigger('click')

expect(wrapper.findComponent(EditForm).exists()).toEqual(false)
Expand Down
6 changes: 3 additions & 3 deletions src/components/Features/Table.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ describe("Features Table", () => {
await table.find('tr#parcelle-2 td').trigger('click')
await flushPromises()

axios.__createMock.put.mockResolvedValueOnce(record)
axios.__createMock.put.mockResolvedValueOnce({ data: record })

// this throws if the modal form does not exist
// it catches the Component reference even if it has been Teleport-ed in the <body>
Expand All @@ -138,7 +138,7 @@ describe("Features Table", () => {
await wrapper.find('#parcelle-3 .menu-container .fr-icon-delete-line').trigger('click')

// we trigger the deletion
axios.__createMock.delete.mockResolvedValueOnce(record)
axios.__createMock.delete.mockResolvedValueOnce({ data: record })

const modal = wrapper.getComponent(DeleteFeatureModal)
expect(modal.text()).toContain("parcelle 3")
Expand Down Expand Up @@ -182,7 +182,7 @@ describe("Features Table", () => {
expect(modal.exists()).toEqual(false)

// now, we change a field and we should not be able to close it
axios.__createMock.put.mockResolvedValueOnce(record)
axios.__createMock.put.mockResolvedValueOnce({ data: record })

table.find('tr.parcelle td').trigger('click')
await flushPromises()
Expand Down
69 changes: 15 additions & 54 deletions src/components/record/CertificationSection.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
<script setup>
import { computed, ref } from 'vue'
import { CERTIFICATION_STATE, isCertificationImmutable } from '@/referentiels/ab.js'
import { updateAuditState } from '@/cartobio-api.js'
import { useFeaturesSetsStore } from "@/stores/features-sets.js"
import { useOperatorStore } from "@/stores/operator.js"
import { usePermissions } from "@/stores/permissions.js"
import { useRecordStore } from "@/stores/record.js"
import CertificationModal from "@/components/record/modals/CertificationModal.vue"
import SaveAuditModal from "@/components/record/modals/SaveAuditModal.vue"
import toast from "@/components/toast.js"
const recordStore = useRecordStore()
const operatorStore = useOperatorStore()
Expand All @@ -23,64 +21,27 @@ const showCertificationModal = ref(false)
const canEndAudit = computed(() => permissions.isOc && recordStore.hasFeatures && !featuresSets.hasRequiredSets)
async function handleSaveAudit ({ record_id: recordId, patch }) {
let newRecord
try {
newRecord = await updateAuditState(recordId, {
...patch,
certification_state: CERTIFICATION_STATE.AUDITED
}
)
} catch (e) {
if (e.response?.status === 400) {
toast.error(e.response.data.error)
return
}
throw e
}
recordStore.update(newRecord)
async function handleSaveAudit ({ patch }) {
await recordStore.updateInfo({
...patch,
certification_state: CERTIFICATION_STATE.AUDITED
})
showSaveAuditModal.value = false
}
async function handleSendAudit () {
let newRecord
try {
newRecord = await updateAuditState(
record.record_id,
{ certification_state: CERTIFICATION_STATE.PENDING_CERTIFICATION }
)
} catch (e) {
if (e.response?.status === 400) {
toast.error(e.response.data.error)
return
}
throw e
}
recordStore.update(newRecord)
await recordStore.updateInfo({
certification_state: CERTIFICATION_STATE.PENDING_CERTIFICATION
})
}
async function handleCertify ({ record_id: recordId, patch }) {
let newRecord
try {
newRecord = await updateAuditState(recordId, {
...patch,
certification_state: CERTIFICATION_STATE.CERTIFIED
}
)
} catch (e) {
if (e.response?.status === 400) {
toast.error(e.response.data.error)
return
}
throw e
}
recordStore.update(newRecord)
async function handleCertify ({ patch }) {
await recordStore.updateInfo({
...patch,
certification_state: CERTIFICATION_STATE.CERTIFIED
})
showCertificationModal.value = false
}
</script>
Expand Down
2 changes: 0 additions & 2 deletions src/components/record/Header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,6 @@
<AsyncFeaturesExportModal v-if="exportModal" :operator="operator" :collection="collection" :record="record" @close="exportModal = false" />
<DeleteParcellaireModal :record="record" v-if="deleteModal" @close="deleteModal = false" />
<EditVersionModal
:model-value="record"
@update:model-value="recordStore.update($event)"
v-if="showEditVersionModal"
@close="showEditVersionModal = false"
/>
Expand Down
48 changes: 8 additions & 40 deletions src/components/record/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ import {
inHa,
legalProjectionSurface,
} from '../Features/index.js'
import { deleteSingleFeature, updateFeatureCollectionProperties, updateSingleFeature } from '@/cartobio-api.js'
import toast from "@/components/toast.js"
import { statsPush } from "@/stats.js"
Expand Down Expand Up @@ -159,33 +158,27 @@ const maybeDeletedFeatureId = ref(null)
const userGroupingChoice = ref('CULTURE')
const featureGroups = computed(() => getFeatureGroups({ features: features.value }, userGroupingChoice.value))
const isSaving = ref(false)
async function handleSingleFeatureSubmit ({ id, properties }) {
statsPush(['trackEvent', 'Parcelles', 'Modification individuelle (sauvegarde)'])
featuresStore.updateMatchingFeatures([{ id, properties }])
editedFeatureId.value = null
await performAsyncRecordAction(
updateSingleFeature({ recordId: record.value.record_id }, { id, properties }),
`Parcelle « ${featureName(featuresStore.getFeatureById(id))} » modifiée.`
)
await featuresStore.updateSingleFeature({ id, properties })
toast.success(`Parcelle « ${featureName(featuresStore.getFeatureById(id))} » modifiée.`)
}
async function handleSingleFeatureDeletion ({ id, reason }) {
statsPush(['trackEvent', 'Parcelles', 'Suppression individuelle (sauvegarde)'])
maybeDeletedFeatureId.value = null
await performAsyncRecordAction(
deleteSingleFeature({ recordId: record.value.record_id }, { id, reason }),
`Parcelle « ${featureName(featuresStore.getFeatureById(id))} » supprimée.`
)
const deletedFeatureName = featureName(featuresStore.getFeatureById(id))
await featuresStore.deleteSingleFeature({ id, reason })
toast.success(`Parcelle « ${deletedFeatureName} » supprimée.`)
}
async function handleFeatureCollectionSubmit ({ ids, patch }) {
statsPush(['trackEvent', 'Parcelles', 'Modification multiple (sauvegarde)'])
editedFeatureId.value = null
const featureCollection = {
type: 'FeatureCollection',
Expand All @@ -194,14 +187,8 @@ async function handleFeatureCollectionSubmit ({ ids, patch }) {
properties: { ...patch }
}))
}
featuresStore.updateMatchingFeatures(featureCollection.features)
editedFeatureId.value = null
performAsyncRecordAction(
updateFeatureCollectionProperties({ recordId: record.value.record_id }, featureCollection),
'Parcelles modifiées.'
)
await featuresStore.updateFeatureCollectionProperties(featureCollection)
toast.success('Parcelles modifiées.')
}
function handleFilterClick (id) {
Expand All @@ -211,25 +198,6 @@ function handleFilterClick (id) {
statsPush(['trackEvent', 'Filtre parcelles', id])
}
}
async function performAsyncRecordAction (promise, text = 'Modification enregistrée.') {
isSaving.value = true
try {
const updatedRecord = await promise
recordStore.update(updatedRecord)
toast.success(text)
}
catch (error) {
toast.error(
"Une erreur d'enregistrement s'est produite. Les données n'ont pas été sauvegardées sur les serveurs CartoBio."
)
}
finally {
isSaving.value = false
}
}
</script>

<style>
Expand Down
2 changes: 1 addition & 1 deletion src/components/record/modals/SaveAuditModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<h2 class="fr-text--lead">{{ operator.nom }}</h2>

<form id="sendoff-form" @submit.prevent="emit('submit', { record_id: record.record_id, patch })">
<form id="sendoff-form" @submit.prevent="emit('submit', { patch })">
<div class="fr-input-group">
<label class="fr-label" for="audit_notes">
Notes finales de l'audit
Expand Down
Loading

0 comments on commit 1a10eba

Please sign in to comment.