Skip to content

Commit f0dcac7

Browse files
committed
Merge branch 'development' into tw_otu_distribution_n_plus_one
2 parents 15f795a + 1d6bf74 commit f0dcac7

File tree

5 files changed

+136
-26
lines changed

5 files changed

+136
-26
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ New TaxonName Relationship: nomen oblitum rejected between 1961 and 1972
1919
### Changed
2020

2121
- Updated Ruby gems
22+
- Save taxonomic tree settings in user preferences [#4577]
2223

2324
[#4321]: https://github.com/SpeciesFileGroup/taxonworks/issues/4321
2425

app/javascript/vue/components/ui/VMap/VMap.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,9 +439,10 @@ function addGeoJsonLayer(geoJsonLayers) {
439439
440440
geojsonLayer.eachLayer((layer) => {
441441
addEventsToLayer(layer)
442-
drawnItems.addLayer(layer)
443442
})
444443
444+
geojsonLayer.addTo(drawnItems)
445+
445446
if (props.fitBounds && !isShapeToolActive) {
446447
centerShapesInMap()
447448
}

app/javascript/vue/composables/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export * from './useWindowSize'
88
export * from './useHotkey/useHotkey.js'
99
export * from './useEventListener.js'
1010
export * from './useBroadcastChannel.js'
11+
export * from './useUserPreferences.js'
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
2+
import { User } from '@/routes/endpoints'
3+
import { useBroadcastChannel } from './useBroadcastChannel'
4+
5+
const preferences = ref(null)
6+
const isLoading = ref(false)
7+
const error = ref(null)
8+
const loaded = ref(false)
9+
10+
const STORAGE_KEY = 'tw_user_preferences'
11+
12+
export function useUserPreferences() {
13+
const { post } = useBroadcastChannel({
14+
name: 'tw_user_preferences',
15+
onMessage({ data }) {
16+
preferences.value = data
17+
}
18+
})
19+
20+
const loadPreferences = async (forceReload = false) => {
21+
if (loaded.value && !forceReload) return preferences.value
22+
23+
const saved = sessionStorage.getItem(STORAGE_KEY)
24+
25+
if (!forceReload && saved) {
26+
preferences.value = JSON.parse(saved)
27+
loaded.value = true
28+
29+
return preferences.value
30+
}
31+
32+
isLoading.value = true
33+
error.value = null
34+
35+
try {
36+
const { body } = await User.preferences()
37+
38+
preferences.value = body
39+
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(body))
40+
loaded.value = true
41+
42+
return body
43+
} catch (err) {
44+
error.value = err
45+
console.error('Error loading preferences:', err)
46+
47+
throw err
48+
} finally {
49+
isLoading.value = false
50+
}
51+
}
52+
53+
const syncStorage = () => {
54+
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(preferences.value))
55+
56+
post(preferences.value)
57+
}
58+
59+
const setPreference = async (key, value, opts = { persist: true }) => {
60+
if (!preferences.value?.layout) {
61+
preferences.value.layout = {}
62+
}
63+
64+
if (!preferences.value) {
65+
preferences.value = {
66+
layout: {}
67+
}
68+
}
69+
70+
preferences.value.layout[key] = value
71+
72+
syncStorage()
73+
74+
if (opts.persist) {
75+
try {
76+
await User.update(preferences.value.id, {
77+
user: {
78+
layout: {
79+
[key]: value
80+
}
81+
}
82+
})
83+
} catch (err) {
84+
console.error('Failed to persist user preference:', err)
85+
}
86+
}
87+
}
88+
89+
const clearPreferences = () => {
90+
preferences.value = null
91+
sessionStorage.removeItem(STORAGE_KEY)
92+
loaded.value = false
93+
post(preferences.value)
94+
}
95+
96+
if (!isLoading.value && !loaded.value) {
97+
loadPreferences()
98+
}
99+
100+
return {
101+
preferences: computed(() => preferences.value),
102+
isLoading: computed(() => isLoading.value),
103+
error: computed(() => error.value),
104+
loaded: computed(() => loaded.value),
105+
loadPreferences,
106+
setPreference,
107+
clearPreferences
108+
}
109+
}

app/javascript/vue/tasks/nomenclature/browse/components/Taxonomy/TaxonomyOptions.vue

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@
5252
import VModal from '@/components/ui/Modal.vue'
5353
import VBtn from '@/components/ui/VBtn/index.vue'
5454
import VIcon from '@/components/ui/VIcon/index.vue'
55-
import { convertType } from '@/helpers'
56-
import { onBeforeMount, ref } from 'vue'
55+
import { useUserPreferences } from '@/composables'
56+
import { ref, watch } from 'vue'
57+
58+
const STORAGE_LAYOUT_KEY = 'tasks::BrowseNomenclature::Layout'
5759
5860
const count = defineModel('count', {
5961
type: Boolean,
@@ -71,32 +73,28 @@ const rainbow = defineModel('rainbow', {
7173
})
7274
7375
const isModalVisible = ref(false)
74-
75-
const STORAGE_COUNT_KEY = 'TW::TaxonomyTree::Count'
76-
const STORAGE_ONLY_VALID_KEY = 'TW::TaxonomyTree::OnlyValid'
77-
const STORAGE_RAINBOW_KEY = 'TW::TaxonomyTree::RainbowMode'
76+
const { preferences, setPreference } = useUserPreferences()
7877
7978
function updateStorage() {
80-
localStorage.setItem(STORAGE_COUNT_KEY, count.value)
81-
localStorage.setItem(STORAGE_ONLY_VALID_KEY, onlyValid.value)
82-
localStorage.setItem(STORAGE_RAINBOW_KEY, rainbow.value)
79+
setPreference(STORAGE_LAYOUT_KEY, {
80+
count: count.value,
81+
onlyValid: onlyValid.value,
82+
rainbow: rainbow.value
83+
})
8384
}
8485
85-
onBeforeMount(() => {
86-
const c = convertType(localStorage.getItem(STORAGE_COUNT_KEY))
87-
const r = convertType(localStorage.getItem(STORAGE_RAINBOW_KEY))
88-
const v = convertType(localStorage.getItem(STORAGE_ONLY_VALID_KEY))
89-
90-
if (v !== null) {
91-
onlyValid.value = v
92-
}
93-
94-
if (c !== null) {
95-
count.value = c
96-
}
97-
98-
if (r !== null) {
99-
rainbow.value = r
86+
watch(
87+
() => preferences.value?.layout?.[STORAGE_LAYOUT_KEY],
88+
(newVal) => {
89+
if (newVal) {
90+
onlyValid.value = newVal?.onlyValid
91+
count.value = newVal?.count
92+
rainbow.value = newVal?.rainbow
93+
}
94+
},
95+
{
96+
immediate: true,
97+
deep: true
10098
}
101-
})
99+
)
102100
</script>

0 commit comments

Comments
 (0)