chore(vue3): migrate appointment config store to pinia

Co-authored-by: Grigory V <scratchx@gmx.com>
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
This commit is contained in:
Grigory V 2024-01-11 22:10:31 +01:00 committed by Richard Steinmetz
parent c904b20114
commit 1c1e3ecc6b
No known key found for this signature in database
GPG Key ID: 27137D9E7D273FB2
7 changed files with 140 additions and 78 deletions

58
package-lock.json generated
View File

@ -43,6 +43,7 @@
"lodash": "^4.17.21",
"md5": "^2.3.0",
"p-limit": "^5.0.0",
"pinia": "^2.1.7",
"v-tooltip": "^2.1.3",
"vue": "^2.7.16",
"vue-click-outside": "^1.1.0",
@ -5690,6 +5691,11 @@
"url": "https://opencollective.com/postcss/"
}
},
"node_modules/@vue/devtools-api": {
"version": "6.6.1",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.1.tgz",
"integrity": "sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA=="
},
"node_modules/@vue/eslint-config-typescript": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-12.0.0.tgz",
@ -15608,6 +15614,56 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pinia": {
"version": "2.1.7",
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz",
"integrity": "sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==",
"dependencies": {
"@vue/devtools-api": "^6.5.0",
"vue-demi": ">=0.14.5"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"@vue/composition-api": "^1.4.0",
"typescript": ">=4.4.4",
"vue": "^2.6.14 || ^3.3.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
},
"typescript": {
"optional": true
}
}
},
"node_modules/pinia/node_modules/vue-demi": {
"version": "0.14.7",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
"integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/pirates": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
@ -18897,7 +18953,7 @@
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
"dev": true,
"devOptional": true,
"peer": true,
"bin": {
"tsc": "bin/tsc",

View File

@ -70,6 +70,7 @@
"lodash": "^4.17.21",
"md5": "^2.3.0",
"p-limit": "^5.0.0",
"pinia": "^2.1.7",
"v-tooltip": "^2.1.3",
"vue": "^2.7.16",
"vue-click-outside": "^1.1.0",

View File

@ -68,8 +68,9 @@ import PlusIcon from 'vue-material-design-icons/Plus.vue'
import AppointmentConfigModal from '../AppointmentConfigModal.vue'
import AppointmentConfig from '../../models/appointmentConfig.js'
import logger from '../../utils/logger.js'
import { mapGetters } from 'vuex'
import NoEmailAddressWarning from '../AppointmentConfigModal/NoEmailAddressWarning.vue'
import useAppointmentConfigStore from '../../store/appointmentConfigs.js'
import { mapStores } from 'pinia'
export default {
name: 'AppointmentConfigList',
@ -87,9 +88,10 @@ export default {
}
},
computed: {
...mapGetters({
configs: 'allConfigs',
}),
...mapStores(useAppointmentConfigStore),
configs() {
return this.appointmentConfigStore.allConfigs
},
defaultConfig() {
return AppointmentConfig.createDefault(
this.calendarUrlToUri(this.$store.getters.ownSortedCalendars[0].url),
@ -126,7 +128,7 @@ export default {
logger.info('Deleting config', { config })
try {
await this.$store.dispatch('deleteConfig', config)
await this.appointmentConfigStore.deleteConfig({ id: config.id })
logger.info('Config deleted', { config })
} catch (error) {

View File

@ -157,6 +157,7 @@ import TextInput from './AppointmentConfigModal/TextInput.vue'
import TextArea from './AppointmentConfigModal/TextArea.vue'
import AppointmentConfig from '../models/appointmentConfig.js'
import { mapGetters } from 'vuex'
import { mapStores } from 'pinia'
import CalendarPicker from './Shared/CalendarPicker.vue'
import DurationInput from './AppointmentConfigModal/DurationInput.vue'
import NumberInput from './AppointmentConfigModal/NumberInput.vue'
@ -165,6 +166,7 @@ import CheckedDurationSelect from './AppointmentConfigModal/CheckedDurationSelec
import VisibilitySelect from './AppointmentConfigModal/VisibilitySelect.vue'
import logger from '../utils/logger.js'
import Confirmation from './AppointmentConfigModal/Confirmation.vue'
import useAppointmentConfigStore from '../store/appointmentConfigs.js'
export default {
name: 'AppointmentConfigModal',
@ -209,6 +211,7 @@ export default {
'ownSortedCalendars',
'isTalkEnabled',
]),
...mapStores(useAppointmentConfigStore),
formTitle() {
if (this.isNew) {
return this.$t('calendar', 'Create appointment')
@ -309,10 +312,10 @@ export default {
try {
if (this.isNew) {
logger.info('Creating new config', { config })
this.editing = await this.$store.dispatch('createConfig', { config })
this.editing = await this.appointmentConfigStore.createConfig({ config })
} else {
logger.info('Saving config', { config })
this.editing = await this.$store.dispatch('updateConfig', { config })
this.editing = await this.appointmentConfigStore.updateConfig({ config })
}
this.showConfirmation = true
} catch (error) {

View File

@ -41,6 +41,11 @@ import ClickOutside from 'vue-click-outside'
import VTooltip from 'v-tooltip'
import VueShortKey from 'vue-shortkey'
import windowTitleService from './services/windowTitleService.js'
import { createPinia, PiniaVuePlugin } from 'pinia'
import useAppointmentConfigsStore from './store/appointmentConfigs.js'
Vue.use(PiniaVuePlugin)
const pinia = createPinia()
// register global components
Vue.directive('ClickOutside', ClickOutside)
@ -69,14 +74,13 @@ Vue.prototype.n = translatePlural
windowTitleService(router, store)
store.commit(
'addInitialConfigs',
loadState('calendar', 'appointmentConfigs', []).map(config => new AppointmentConfig(config))
)
export default new Vue({
el: '#content',
router,
store,
render: h => h(App),
pinia,
})
const appointmentsConfigsStore = useAppointmentConfigsStore()
appointmentsConfigsStore.addInitialConfigs(loadState('calendar', 'appointmentConfigs', []).map(config => new AppointmentConfig(config)))

View File

@ -21,74 +21,72 @@
*/
import Vue from 'vue'
import { defineStore } from 'pinia'
import { createConfig, deleteConfig, updateConfig } from '../services/appointmentConfigService.js'
import logger from '../utils/logger.js'
const state = {
configs: {},
}
const mutations = {
addInitialConfigs(state, configs) {
for (const config of configs) {
Vue.set(state.configs, config.id, config)
export default defineStore('appointmentConfig', {
state: () => {
return {
configs: {},
}
},
updateConfig(state, { config }) {
if (!state.configs[config.id]) {
return
}
getters: {
allConfigs() {
return Object.values(this.configs)
},
},
actions: {
addInitialConfigs(configs) {
for (const config of configs) {
Vue.set(this.configs, config.id, config)
}
},
async updateConfig({ config }) {
try {
const updatedConfig = await updateConfig(config)
this.updateConfigMutation(updatedConfig)
return updatedConfig
} catch (error) {
logger.error('Failed to update config', { error })
throw error
}
},
async createConfig({ config }) {
try {
const fullConfig = await createConfig(config)
this.addConfigMutation(fullConfig)
return fullConfig
} catch (error) {
logger.error('Failed to create config', { error })
throw error
}
},
async deleteConfig({ id }) {
try {
await deleteConfig(id)
this.deleteConfigMutation(id)
} catch (error) {
logger.error('Failed to delete config', { error })
throw error
}
},
updateConfigMutation(config) {
if (!this.configs[config.id]) {
return
}
Vue.set(state.configs, config.id, config.clone())
},
addConfig(state, { config }) {
Vue.set(state.configs, config.id, config)
},
deleteConfig(state, { id }) {
if (!state.configs[id]) {
return
}
Vue.set(this.configs, config.id, config.clone())
},
addConfigMutation(config) {
Vue.set(this.configs, config.id, config)
},
deleteConfigMutation(id) {
if (!this.configs[id]) {
return
}
Vue.delete(state.configs, id)
Vue.delete(this.configs, id)
},
},
}
const getters = {
allConfigs(state) {
return Object.values(state.configs)
},
}
const actions = {
async updateConfig({ commit }, { config }) {
try {
const updatedConfig = await updateConfig(config)
commit('updateConfig', { config: updatedConfig })
return updatedConfig
} catch (error) {
logger.error('Failed to update config', { error })
throw error
}
},
async createConfig({ commit }, { config }) {
try {
const fullConfig = await createConfig(config)
commit('addConfig', { config: fullConfig })
return fullConfig
} catch (error) {
logger.error('Failed to create config', { error })
throw error
}
},
async deleteConfig({ commit }, { id }) {
try {
await deleteConfig(id)
commit('deleteConfig', { id })
} catch (error) {
logger.error('Failed to delete config', { error })
throw error
}
},
}
export default { state, mutations, getters, actions }
})

View File

@ -36,13 +36,11 @@ import importFiles from './importFiles.js'
import importState from './importState.js'
import principals from './principals.js'
import settings from './settings.js'
import appointmentConfigs from './appointmentConfigs.js'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
appointmentConfigs,
calendarObjectInstance,
calendarObjects,
calendars,