basic pinia store

This commit is contained in:
vabene1111 2023-02-12 16:06:00 +01:00
parent cb363d6321
commit 3af7e98216
6 changed files with 134 additions and 17 deletions

View File

@ -13,6 +13,7 @@
"@popperjs/core": "^2.11.6",
"@riophae/vue-treeselect": "^0.4.0",
"@vue/cli": "^5.0.8",
"@vue/composition-api": "1.7.1",
"axios": "^1.2.0",
"babel": "^6.23.0",
"babel-core": "^6.26.3",
@ -25,6 +26,7 @@
"lodash": "^4.17.21",
"mavon-editor": "^2.10.4",
"moment": "^2.29.4",
"pinia": "^2.0.30",
"prismjs": "^1.29.0",
"string-similarity": "^4.0.4",
"vue": "^2.6.14",
@ -42,7 +44,6 @@
"vue-template-compiler": "2.6.14",
"vue2-touch-events": "^3.2.2",
"vuedraggable": "^2.24.3",
"vuex": "^3.6.0",
"workbox-webpack-plugin": "^6.5.4",
"workbox-window": "^6.5.4"
},

View File

@ -1,6 +1,7 @@
import Vue from 'vue'
import App from './RecipeView.vue'
import i18n from "@/i18n";
import {createPinia, PiniaVuePlugin} from 'pinia'
Vue.config.productionTip = false
@ -11,8 +12,11 @@ if (process.env.NODE_ENV === 'development') {
}
export default __webpack_public_path__ = publicPath // eslint-disable-line
Vue.use(PiniaVuePlugin)
const pinia = createPinia()
new Vue({
pinia,
i18n,
render: h => h(App),
}).$mount('#app')

View File

@ -16,7 +16,7 @@
<small tabindex="-1" class="form-text text-muted" v-if="!missing_recipe">{{ $t("Title") }}</small>
</div>
<div class="col-6 col-lg-3">
<input type="date" id="DateInput" class="form-control" v-model="entryEditing.date" />
<input type="date" id="DateInput" class="form-control" v-model="entryEditing.date"/>
<small tabindex="-1" class="form-text text-muted">{{ $t("Date") }}</small>
</div>
</div>
@ -75,11 +75,11 @@
<small tabindex="-1" class="form-text text-muted">{{ $t("Share") }}</small>
</b-form-group>
<b-input-group v-if="!autoMealPlan">
<b-form-checkbox id="AddToShopping" v-model="mealplan_settings.addshopping" />
<b-form-checkbox id="AddToShopping" v-model="mealplan_settings.addshopping"/>
<small tabindex="-1" class="form-text text-muted">{{ $t("AddToShopping") }}</small>
</b-input-group>
<b-input-group v-if="mealplan_settings.addshopping">
<b-form-checkbox id="reviewShopping" v-model="mealplan_settings.reviewshopping" />
<b-form-checkbox id="reviewShopping" v-model="mealplan_settings.reviewshopping"/>
<small tabindex="-1" class="form-text text-muted">{{ $t("review_shopping") }}</small>
</b-input-group>
</div>
@ -89,7 +89,7 @@
</div>
<div class="row mt-3 mb-3">
<div class="col-12">
<b-button variant="danger" @click="deleteEntry" v-if="allow_delete">{{ $t("Delete") }} </b-button>
<b-button variant="danger" @click="deleteEntry" v-if="allow_delete">{{ $t("Delete") }}</b-button>
<b-button class="float-right" variant="primary" @click="editEntry">{{ $t("Save") }}</b-button>
</div>
</div>
@ -103,12 +103,14 @@
<script>
import Vue from "vue"
import VueCookies from "vue-cookies"
import { BootstrapVue } from "bootstrap-vue"
import {BootstrapVue} from "bootstrap-vue"
import GenericMultiselect from "@/components/GenericMultiselect"
import { ApiMixin, getUserPreference } from "@/utils/utils"
import {ApiMixin, getUserPreference} from "@/utils/utils"
const { ApiApiFactory } = require("@/utils/openapi/api")
const { StandardToasts } = require("@/utils/utils")
const {ApiApiFactory} = require("@/utils/openapi/api")
const {StandardToasts} = require("@/utils/utils")
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
Vue.use(BootstrapVue)
Vue.use(VueCookies)
@ -158,7 +160,8 @@ export default {
deep: true,
},
entryEditing: {
handler(newVal) {},
handler(newVal) {
},
deep: true,
},
mealplan_settings: {
@ -172,11 +175,11 @@ export default {
},
},
mounted: function () {
useUserPreferenceStore().updateIfStaleOrEmpty()
},
computed: {
autoMealPlan: function () {
return getUserPreference("mealplan_autoadd_shopping")
return useUserPreferenceStore().getStaleData()?.mealplan_autoadd_shopping
},
},
methods: {
@ -184,15 +187,13 @@ export default {
if (this.$cookies.isKey(MEALPLAN_COOKIE_NAME)) {
this.mealplan_settings = Object.assign({}, this.mealplan_settings, this.$cookies.get(MEALPLAN_COOKIE_NAME))
}
let apiClient = new ApiApiFactory()
apiClient.listUserPreferences().then((result) => {
useUserPreferenceStore().getData().then(userPreference => {
if (this.entry.id === -1) {
this.entryEditing.shared = result.data[0].plan_share
this.entryEditing.shared = userPreference.plan_share
}
})
},
editEntry() {
this.missing_meal_type = false
this.missing_recipe = false
@ -207,7 +208,7 @@ export default {
}
if (!cancel) {
this.$bvModal.hide(`edit-modal`)
this.$emit("save-entry", { ...this.mealplan_settings, ...this.entryEditing, ...{ addshopping: this.mealplan_settings.addshopping && !this.autoMealPlan } })
this.$emit("save-entry", {...this.mealplan_settings, ...this.entryEditing, ...{addshopping: this.mealplan_settings.addshopping && !this.autoMealPlan}})
}
},
deleteEntry() {

View File

@ -0,0 +1,33 @@
https://pinia.vuejs.org/core-concepts/plugins.html#adding-new-state
export function BaseStorePlugin () {
return {
collection: [],
item: {},
getCollection: function (url) {
api.get(url)
.then((response) => {
this.collection = response.data;
})
.catch((error) => {
this.handleError(error);
});
},
getItem: function (url) {
api.get(url)
.then((response) => {
this.item = response.data;
})
.catch((error) => {
this.handleError(error);
});
},
handleError: function (error) {
window.alert(error);
},
};
}

View File

@ -0,0 +1,78 @@
import {defineStore} from 'pinia'
import {ApiApiFactory} from "@/utils/openapi/api";
const _STALE_TIME_IN_MS = 1000 * 30
const _STORE_ID = 'user_preference_store'
export const useUserPreferenceStore = defineStore(_STORE_ID, {
state: () => ({
data: null,
updated_at: null,
}),
getters: {
},
actions: {
/**
* gets data from the store either directly or refreshes from API if data is considered stale
* @returns {UserPreference|*|Promise<axios.AxiosResponse<UserPreference>>}
*/
getData: function () {
if (this.isStaleOrEmpty) {
return this.refreshFromAPI()
} else {
return this.data
}
},
/**
* get data from store. Does not use API, if store is not initialized returns null.
* @returns {null|UserPreference|*}
*/
getStaleData: function () {
return this.data
},
/**
* checks if update timestamp is older than configured stale time interval
* @returns {boolean} true if data is considered stale and should be updated
*/
isStale() {
return this.updated_at === null || ((new Date()) - this.updated_at) > _STALE_TIME_IN_MS;
},
/**
* checks if data of store is empty/not initialized
* @returns {boolean} true if store is empty
*/
isEmpty() {
return this.data === null
},
/**
* checks if store is empty or data is considered stale, see isStale() and isEmpty()
* @returns {boolean}
*/
isStaleOrEmpty() {
return this.isStale() || this.isEmpty()
},
/**
* refreshes store data if isStaleOrEmpty() is true
* @returns {Promise<axios.AxiosResponse<UserPreference>>} returns promise with data
*/
updateIfStaleOrEmpty() {
if (this.isStaleOrEmpty) {
return this.refreshFromAPI()
}
},
/**
* refreshes store data from API
* @returns {Promise<axios.AxiosResponse<UserPreference>>} returns promise with data
*/
refreshFromAPI() {
let apiClient = new ApiApiFactory()
return apiClient.retrieveUserPreference(localStorage.getItem('USER_ID')).then(r => {
this.data = r.data
this.updated_at = new Date()
return this.data
})
},
},
})

0
vue/src/stores/root.js Normal file
View File