Skip to content

Commit c0c1f2e

Browse files
committed
wip: Reorganize sticky map-based components #1085
1 parent 6c262ee commit c0c1f2e

File tree

6 files changed

+231
-58
lines changed

6 files changed

+231
-58
lines changed

core/client/components/layout/KPage.vue

+7-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
:offset="getStickyOffset(sticky)"
2525
class="k-sticky"
2626
>
27-
<KContent :content="sticky.content" />
27+
<KContent v-bind="sticky" />
2828
</q-page-sticky>
2929
</template>
3030
<!--
@@ -317,7 +317,12 @@ const fabBehavior = computed(() => {
317317
})
318318
const stickiesComponents = computed(() => {
319319
return _.map(stickies.components, sticky => {
320-
return _.merge(sticky, { content: [{ component: sticky.component }] })
320+
return _.merge(sticky, {
321+
content: [{
322+
component: sticky.component,
323+
visible: sticky.visible
324+
}]
325+
})
321326
})
322327
})
323328

core/client/layout.js

+11
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,17 @@ export const Layout = {
299299
clearStickies () {
300300
this.clearElement('stickies')
301301
},
302+
findSticky (stickyId) {
303+
return _.find(this.getStickies().components, { id: stickyId })
304+
},
305+
setStickyVisible (stickyId, visible) {
306+
const sticky = this.findSticky(stickyId)
307+
if (!sticky) {
308+
logger.error('[KDK] Cannot find sticky with id', stickyId)
309+
return
310+
}
311+
_.set(sticky, 'visible', visible)
312+
},
302313
getFab () {
303314
return this.getElement('fab')
304315
},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<template>
2+
<div v-if="CurrentActivity" class="q-pa-sm">
3+
<KShape
4+
class="text-weight-bold"
5+
:options="{
6+
shape: 'circle',
7+
color: 'white',
8+
stroke: {
9+
color: 'primary',
10+
width: '2'
11+
},
12+
text: {
13+
label: 'i',
14+
color: 'primary'
15+
}
16+
}"
17+
/>
18+
<q-popup-proxy
19+
id="attributions-popup"
20+
transition-show="scale"
21+
transition-hide="scale"
22+
anchor="center left"
23+
self="bottom right"
24+
>
25+
<div
26+
id="attributions-banner"
27+
class="bg-white text-primary text-center q-col-gutter-y-xs"
28+
>
29+
<!-- Header Content -->
30+
<div v-if="header">
31+
<KContent
32+
:content="header"
33+
:class="headerClass"
34+
/>
35+
</div>
36+
<!-- Main Content -->
37+
<div
38+
id="attributions-content"
39+
v-html="sanitizedAttributions"
40+
class="text-caption q-py-none q-px-sm"
41+
/>
42+
<!-- Footer Content -->
43+
<div v-if="footer">
44+
<KContent
45+
:content="footer"
46+
:class="footerClass"
47+
/>
48+
</div>
49+
</div>
50+
</q-popup-proxy>
51+
</div>
52+
</template>
53+
54+
<script setup>
55+
import _ from 'lodash'
56+
import logger from 'loglevel'
57+
import config from 'config'
58+
import { ref, computed, onBeforeUnmount, onMounted } from 'vue'
59+
import { Document } from '../../../../core/client/document.js'
60+
import { useCurrentActivity } from '../../composables'
61+
import KContent from '../../../../core/client/components/KContent.vue'
62+
import KShape from '../../../../core/client/components/media/KShape.vue'
63+
64+
// Data
65+
const { CurrentActivity } = useCurrentActivity({ selection: false, probe: false })
66+
const attributions = ref({})
67+
const header = ref(_.get(config, 'attribution.header', []))
68+
const headerClass = ref(_.get(config, 'attribution.headerClass', ''))
69+
const footer = ref(_.get(config, 'attribution.footer', []))
70+
const footerClass = ref(_.get(config, 'attribution.footerClass', ''))
71+
72+
// Computed
73+
const sanitizedAttributions = computed(() => {
74+
let content = ''
75+
_.forOwn(attributions.value, (attribution, layer) => {
76+
content += `${attribution}<br>`
77+
})
78+
return Document.sanitizeHtml(content)
79+
})
80+
81+
// Functions
82+
function onLayerShown (layer) {
83+
if (layer.attribution) {
84+
const key = _.kebabCase(layer.name)
85+
if (!_.has(attributions.value, key)) {
86+
logger.debug(`[KDK] Add ${layer.name} to attributions`)
87+
_.set(attributions.value, key, layer.attribution)
88+
}
89+
}
90+
}
91+
function onLayerHidden (layer) {
92+
if (layer.attribution) {
93+
logger.debug(`[KDK] Remove ${layer.name} from attributions`)
94+
_.unset(attributions.value, _.kebabCase(layer.name))
95+
}
96+
}
97+
98+
// Hooks
99+
onMounted(() => {
100+
if (CurrentActivity.value) {
101+
CurrentActivity.value.getLayers().forEach((layer) => {
102+
if (CurrentActivity.value.isLayerVisible(layer.name)) onLayerShown(layer)
103+
})
104+
CurrentActivity.value.$engineEvents.on('layer-shown', onLayerShown)
105+
CurrentActivity.value.$engineEvents.on('layer-hidden', onLayerHidden)
106+
}
107+
})
108+
onBeforeUnmount(() => {
109+
if (CurrentActivity.value) {
110+
CurrentActivity.value.$engineEvents.off('layer-shown', onLayerShown)
111+
CurrentActivity.value.$engineEvents.off('layer-hidden', onLayerHidden)
112+
}
113+
})
114+
</script>
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<template>
2+
<q-img
3+
:src="image"
4+
:width="width"
5+
:height="height"
6+
fit="scale-down"
7+
/>
8+
</template>
9+
10+
<script setup>
11+
// Props
12+
defineProps({
13+
image: {
14+
type: String,
15+
default: 'kdk/north.svg'
16+
},
17+
width: {
18+
type: String,
19+
default: '250px'
20+
},
21+
height: {
22+
type: String,
23+
default: '50px'
24+
}
25+
})
26+
</script>

map/client/components/KPosition.vue map/client/components/stickies/KPosition.vue

+29-56
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div
3-
v-if="CurrentActivity && state.position"
3+
v-if="CurrentActivity"
44
id="position"
55
class="row items-center no-padding k-position"
66
>
@@ -14,85 +14,47 @@
1414
size="sm"
1515
:handler="onCopy"
1616
/>
17-
<KAction
17+
<!--KAction
1818
id="hide-position"
1919
icon="cancel"
2020
tooltip="KPosition.HIDE"
2121
size="sm"
2222
:handler="onHide"
23-
/>
23+
/-->
2424
</div>
2525
</template>
2626

2727
<script setup>
2828
import _ from 'lodash'
29-
import { ref, computed, watch, onBeforeUnmount } from 'vue'
29+
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
3030
import { Notify, copyToClipboard } from 'quasar'
31-
import { Store, Layout, i18n, utils as kdkCoreUtils } from '../../../core.client'
32-
import { formatUserCoordinates } from '../utils'
33-
import { useCurrentActivity } from '../composables/activity.js'
34-
import KAction from '../../../core/client/components/action/KAction.vue'
31+
import { Store, Layout, i18n } from '../../../../core.client.js'
32+
import { formatUserCoordinates } from '../../utils.js'
33+
import { useCurrentActivity } from '../../composables/activity.js'
34+
import KAction from '../../../../core/client/components/action/KAction.vue'
3535
3636
// Props
3737
const props = defineProps({
38-
size: {
39-
type: Number,
40-
default: 48
38+
target: {
39+
type: String,
40+
default: 'target'
4141
}
4242
})
4343
4444
// Data
45-
const { CurrentActivityContext, CurrentActivity } = useCurrentActivity()
46-
const { state } = CurrentActivityContext
47-
const position = ref(state.position)
45+
const { CurrentActivity } = useCurrentActivity()
46+
const position = ref(null)
4847
4948
// Computed
5049
const formattedPosition = computed(() => {
5150
if (_.isNil(position.value)) return i18n.t('KPositionIndicator.OUTSIDE_MAP')
5251
return formatUserCoordinates(position.value.latitude, position.value.longitude, Store.get('locationFormat', 'FFf'))
5352
})
5453
55-
// Watch
56-
watch(() => state.position, () => {
57-
if (state.position) show()
58-
else hide()
59-
})
60-
6154
// Function
6255
function updatePosition () {
6356
position.value = CurrentActivity.value.is2D() ? CurrentActivity.value.getCenter() : CurrentActivity.value.getCameraEllipsoidTarget()
64-
}
65-
function show () {
66-
// Update page content with sticky target
67-
const target = {
68-
id: 'position-target',
69-
component: 'QImg',
70-
src: 'icons/kdk/target.svg',
71-
height: `${props.size}px`,
72-
width: `${props.size}px`,
73-
position: 'center',
74-
offset: [0, -props.size / 2],
75-
style: 'pointer-events: none; background-color: #00000020; border-radius: 50%;'
76-
}
77-
console.log(target)
78-
kdkCoreUtils.bindContent(target, CurrentActivity.value)
79-
const stickies = Layout.getStickies().components
80-
stickies.splice(stickies.length, 0, target)
81-
// Listen move events
82-
CurrentActivity.value.$engineEvents.on('movestart', updatePosition)
83-
CurrentActivity.value.$engineEvents.on('move', updatePosition)
84-
CurrentActivity.value.$engineEvents.on('moveend', updatePosition)
85-
// Update the position
86-
updatePosition()
87-
}
88-
function hide () {
89-
const stickies = Layout.getStickies().components
90-
const index = _.findIndex(stickies, component => component.id === 'position-target')
91-
if (index >= 0) stickies.splice(index, 1)
92-
// Stop listening move events
93-
CurrentActivity.value.$engineEvents.off('movestart', updatePosition)
94-
CurrentActivity.value.$engineEvents.off('move', updatePosition)
95-
CurrentActivity.value.$engineEvents.off('moveend', updatePosition)
57+
console.log(position.value)
9658
}
9759
async function onCopy () {
9860
try {
@@ -102,13 +64,24 @@ async function onCopy () {
10264
Notify.create({ type: 'negative', message: i18n.t('KPositionIndicator.CANNOT_COPY_POSITION') })
10365
}
10466
}
105-
function onHide () {
106-
Object.assign(state, { position: false })
107-
}
10867
68+
onMounted(() => {
69+
// Show target sticky
70+
if (props.target) Layout.setStickyVisible(props.target, true)
71+
// Listen move events
72+
CurrentActivity.value.$engineEvents.on('movestart', updatePosition)
73+
CurrentActivity.value.$engineEvents.on('move', updatePosition)
74+
CurrentActivity.value.$engineEvents.on('moveend', updatePosition)
75+
// Update the position
76+
updatePosition()
77+
})
10978
// Hooks
11079
onBeforeUnmount(() => {
111-
if (state.position) onHide()
80+
if (props.target) Layout.setStickyVisible(props.target, false)
81+
// Stop listening move events
82+
CurrentActivity.value.$engineEvents.off('movestart', updatePosition)
83+
CurrentActivity.value.$engineEvents.off('move', updatePosition)
84+
CurrentActivity.value.$engineEvents.off('moveend', updatePosition)
11285
})
11386
</script>
11487

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<template>
2+
<q-img
3+
:src="image"
4+
:width="width"
5+
:height="height"
6+
class="k-target"
7+
/>
8+
</template>
9+
10+
<script setup>
11+
import { computed } from 'vue'
12+
13+
// Props
14+
const props = defineProps({
15+
image: {
16+
type: String,
17+
default: 'kdk/target.svg'
18+
},
19+
width: {
20+
type: String,
21+
default: '40px'
22+
},
23+
height: {
24+
type: String,
25+
default: '40px'
26+
}
27+
})
28+
29+
// Computed
30+
const width = computed(() => {
31+
return `${props.size}px`
32+
})
33+
const height = computed(() => {
34+
return `${props.size}px`
35+
})
36+
</script>
37+
38+
<style lang="scss" scoped>
39+
.k-target {
40+
pointer-events: none;
41+
background-color: #00000020;
42+
border-radius: 50%;
43+
}
44+
</style>

0 commit comments

Comments
 (0)