Skip to content

Commit 26230fa

Browse files
authored
Merge pull request #1108 from geoadmin/bug-PB-1116-drawing-name-fix
2 parents d19e1e0 + c0d9364 commit 26230fa

File tree

5 files changed

+64
-38
lines changed

5 files changed

+64
-38
lines changed

src/api/layers/KMLLayer.class.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ export default class KMLLayer extends AbstractLayer {
8181
this.kmlMetadata = kmlMetadata
8282
if (kmlData) {
8383
this.name = parseKmlName(kmlData)
84+
if (!this.name || this.name === '') {
85+
this.name = isLocalFile
86+
? kmlFileUrl
87+
: // only keeping what is after the last slash
88+
kmlFileUrl.split('/').pop()
89+
}
8490
this.isLoading = false
8591
} else {
8692
this.isLoading = true

src/modules/drawing/DrawingModule.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import VectorLayer from 'ol/layer/Vector'
33
import VectorSource from 'ol/source/Vector'
44
import { computed, inject, onBeforeUnmount, onMounted, provide, ref, watch } from 'vue'
5+
import { useI18n } from 'vue-i18n'
56
import { useStore } from 'vuex'
67
78
import { IS_TESTING_WITH_CYPRESS } from '@/config/staging.config'
@@ -22,6 +23,7 @@ const olMap = inject('olMap')
2223
const drawingInteractions = ref(null)
2324
const isNewDrawing = ref(true)
2425
26+
const i18n = useI18n()
2527
const store = useStore()
2628
const availableIconSets = computed(() => store.state.drawing.iconSets)
2729
const projection = computed(() => store.state.position.projection)
@@ -130,6 +132,11 @@ onMounted(() => {
130132
if (hasKml.value) {
131133
isNewDrawing.value = false
132134
addKmlToDrawing()
135+
} else {
136+
store.dispatch('setDrawingName', {
137+
name: i18n.t('draw_layer_label'),
138+
...dispatcher,
139+
})
133140
}
134141
olMap.addLayer(drawingLayer)
135142

src/modules/drawing/components/DrawingToolbox.vue

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ import { useStore } from 'vuex'
77
88
import { EditableFeatureTypes } from '@/api/features/EditableFeature.class'
99
import DrawingExporter from '@/modules/drawing/components/DrawingExporter.vue'
10+
import DrawingHeader from '@/modules/drawing/components/DrawingHeader.vue'
1011
import DrawingToolboxButton from '@/modules/drawing/components/DrawingToolboxButton.vue'
1112
import SharePopup from '@/modules/drawing/components/SharePopup.vue'
1213
import { DrawingState } from '@/modules/drawing/lib/export-utils'
1314
import useSaveKmlOnChange from '@/modules/drawing/useKmlDataManagement.composable'
1415
import ModalWithBackdrop from '@/utils/components/ModalWithBackdrop.vue'
15-
import { useTippyTooltip } from '@/utils/composables/useTippyTooltip.js'
16-
17-
import DrawingHeader from './DrawingHeader.vue'
16+
import { useTippyTooltip } from '@/utils/composables/useTippyTooltip'
17+
import debounce from '@/utils/debounce'
1818
1919
const dispatcher = { dispatcher: 'DrawingToolbox.vue' }
2020
@@ -39,7 +39,10 @@ const isDrawingLineOrMeasure = computed(() =>
3939
)
4040
)
4141
const activeKmlLayer = computed(() => store.getters.activeKmlLayer)
42-
const drawingName = ref(activeKmlLayer.value?.name || i18n.t('draw_layer_label'))
42+
const drawingName = computed({
43+
get: () => store.state.drawing.name,
44+
set: (value) => debounceSaveDrawingName(value),
45+
})
4346
const isDrawingStateError = computed(() => saveState.value < 0)
4447
/** Return a different translation key depending on the saving status */
4548
const drawingStateMessage = computed(() => {
@@ -64,7 +67,7 @@ function onCloseClearConfirmation(confirmed) {
6467
store.dispatch('clearDrawingFeatures', dispatcher)
6568
store.dispatch('clearAllSelectedFeatures', dispatcher)
6669
drawingLayer.getSource().clear()
67-
debounceSaveDrawing({ drawingName: drawingName.value })
70+
debounceSaveDrawing()
6871
store.dispatch('setDrawingMode', { mode: null, ...dispatcher })
6972
}
7073
}
@@ -78,40 +81,35 @@ onMounted(() => {
7881
}
7982
})
8083
81-
watch(drawingName, () => {
82-
sanitizeDrawingName()
83-
debounceSaveDrawing({
84-
// Lowering the risk of the user changing the name and leaving the drawing module without the name being saved.
85-
// It is terrible design that this can occur, but moving the drawing name management other places raises the complexity tenfold
86-
// so that is a trade-off we can live with.
87-
debounceTime: 500,
88-
drawingName: drawingName.value.trim(),
89-
})
90-
})
91-
9284
watch(activeKmlLayer, () => {
9385
if (activeKmlLayer.value) {
9486
// no need for the message telling the user the drawing is empty, and he can't edit the drawing name
9587
removeNoActiveKmlWarning()
9688
}
9789
})
9890
99-
function sanitizeDrawingName() {
100-
drawingName.value = DOMPurify.sanitize(drawingName.value, {
101-
USE_PROFILES: { xml: true },
102-
})
103-
}
104-
10591
function closeDrawing() {
10692
emits('closeDrawing')
10793
}
94+
10895
function selectDrawingMode(drawingMode) {
10996
store.dispatch('setDrawingMode', { mode: drawingMode, ...dispatcher })
11097
}
11198
11299
function onDeleteLastPoint() {
113100
emits('removeLastPoint')
114101
}
102+
103+
const debounceSaveDrawingName = debounce(async (newName) => {
104+
await store.dispatch('setDrawingName', {
105+
// sanitizing to avoid any XSS vector
106+
name: DOMPurify.sanitize(newName, {
107+
USE_PROFILES: { xml: true },
108+
}).trim(),
109+
...dispatcher,
110+
})
111+
debounceSaveDrawing()
112+
}, 200)
115113
</script>
116114

117115
<template>

src/modules/drawing/useKmlDataManagement.composable.js

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { computed, inject, ref } from 'vue'
2+
import { useI18n } from 'vue-i18n'
23
import { useStore } from 'vuex'
34

45
import { createKml, getKmlUrl, updateKml } from '@/api/files.api'
@@ -17,6 +18,7 @@ const saveState = ref(DrawingState.INITIAL)
1718
export default function useSaveKmlOnChange(drawingLayerDirectReference) {
1819
const drawingLayer = inject('drawingLayer', drawingLayerDirectReference)
1920

21+
const i18n = useI18n()
2022
const store = useStore()
2123
const online = computed(() => store.state.drawing.online)
2224
const projection = computed(() => store.state.position.projection)
@@ -26,6 +28,9 @@ export default function useSaveKmlOnChange(drawingLayerDirectReference) {
2628
const temporaryKml = computed(() =>
2729
store.state.layers.systemLayers.find((l) => l.id === temporaryKmlId.value)
2830
)
31+
const drawingName = computed(
32+
() => store.state.drawing.name ?? activeKmlLayer.value?.name ?? i18n.t('draw_layer_label')
33+
)
2934

3035
let addKmlLayerTimeout = null
3136
const savesInProgress = ref([])
@@ -46,6 +51,10 @@ export default function useSaveKmlOnChange(drawingLayerDirectReference) {
4651
const features = parseKml(availableKmlLayer, projection.value, availableIconSets.value)
4752
log.debug('Add features to drawing layer', features, drawingLayer)
4853
drawingLayer.getSource().addFeatures(features)
54+
store.dispatch('setDrawingName', {
55+
name: availableKmlLayer.name,
56+
...dispatcher,
57+
})
4958
store.dispatch('setDrawingFeatures', {
5059
featureIds: features.map((feature) => feature.getId()),
5160
...dispatcher,
@@ -75,7 +84,7 @@ export default function useSaveKmlOnChange(drawingLayerDirectReference) {
7584
}
7685
}
7786

78-
async function saveDrawing({ retryOnError = true, drawingName = null }) {
87+
async function saveDrawing({ retryOnError = true }) {
7988
try {
8089
log.debug(
8190
`Save drawing retryOnError ${retryOnError}, differSaveDrawing=${differSaveDrawingTimeout}`
@@ -85,35 +94,34 @@ export default function useSaveKmlOnChange(drawingLayerDirectReference) {
8594
const kmlData = generateKmlString(
8695
projection.value,
8796
drawingLayer.getSource().getFeatures(),
88-
drawingName ?? activeKmlLayer.value?.name
97+
drawingName.value
8998
)
9099
if (online.value) {
91-
await saveOnlineDrawing(kmlData, drawingName)
100+
await saveOnlineDrawing(kmlData)
92101
} else {
93-
await saveLocalDrawing(kmlData, drawingName)
102+
await saveLocalDrawing(kmlData)
94103
}
95104
saveState.value = DrawingState.SAVED
96105
} catch (e) {
97106
log.error('Could not save KML layer: ', e)
98107
saveState.value = DrawingState.SAVE_ERROR
99108
if (!IS_TESTING_WITH_CYPRESS && retryOnError) {
100109
// Retry saving in 5 seconds
101-
debounceSaveDrawing({ debounceTime: 5000, retryOnError: false, drawingName })
110+
debounceSaveDrawing({ debounceTime: 5000, retryOnError: false })
102111
}
103112
}
104113
}
105114

106115
/**
107116
* @param {String} kmlData
108-
* @param {String} [drawingName=null] Default is `null`
109117
* @returns {Promise<void>}
110118
*/
111-
async function saveOnlineDrawing(kmlData, drawingName = null) {
119+
async function saveOnlineDrawing(kmlData) {
112120
if (!activeKmlLayer.value?.adminId) {
113121
// creation of the new KML (copy or new)
114122
const kmlMetadata = await createKml(kmlData)
115123
const kmlLayer = new KMLLayer({
116-
name: drawingName ?? activeKmlLayer.value?.name,
124+
name: drawingName.value,
117125
kmlFileUrl: getKmlUrl(kmlMetadata.id),
118126
visible: true,
119127
opacity: activeKmlLayer.value?.opacity, // re-use current KML layer opacity, or null
@@ -152,12 +160,11 @@ export default function useSaveKmlOnChange(drawingLayerDirectReference) {
152160

153161
/**
154162
* @param {String} kmlData
155-
* @param {String} [drawingName=null] Default is `null`
156163
* @returns {Promise<void>}
157164
*/
158-
async function saveLocalDrawing(kmlData, drawingName = null) {
165+
async function saveLocalDrawing(kmlData) {
159166
const kmlLayer = new KMLLayer({
160-
name: drawingName,
167+
name: drawingName.value,
161168
kmlFileUrl: temporaryKmlId.value,
162169
visible: true,
163170
opacity: 1,
@@ -170,11 +177,7 @@ export default function useSaveKmlOnChange(drawingLayerDirectReference) {
170177
}
171178
}
172179

173-
async function debounceSaveDrawing({
174-
debounceTime = 2000,
175-
retryOnError = true,
176-
drawingName = null,
177-
} = {}) {
180+
async function debounceSaveDrawing({ debounceTime = 2000, retryOnError = true } = {}) {
178181
log.debug(
179182
`Debouncing save drawing debounceTime=${debounceTime} differSaveDrawingTimeout=${differSaveDrawingTimeout}`
180183
)

src/store/modules/drawing.store.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ export default {
6363
* @type {String | null}
6464
*/
6565
temporaryKmlId: null,
66+
/**
67+
* The name of the drawing, or null if no drawing is currently edited.
68+
*
69+
* @type {String | null}
70+
*/
71+
name: null,
6672
},
6773
getters: {
6874
isDrawingEmpty(state) {
@@ -118,6 +124,9 @@ export default {
118124
dispatcher,
119125
})
120126
},
127+
setDrawingName({ commit }, { name, dispatcher }) {
128+
commit('setDrawingName', { name, dispatcher })
129+
},
121130
},
122131
mutations: {
123132
setDrawingMode: (state, { mode }) => (state.mode = mode),
@@ -132,5 +141,8 @@ export default {
132141
state.online = online
133142
state.temporaryKmlId = kmlId
134143
},
144+
setDrawingName(state, { name }) {
145+
state.name = name
146+
},
135147
},
136148
}

0 commit comments

Comments
 (0)