properly edit settings

This commit is contained in:
vabene1111 2024-01-20 02:37:28 +08:00
parent 7de9758ee1
commit 7d74979859
4 changed files with 46 additions and 76 deletions

View File

@ -1,7 +1,7 @@
<template> <template>
<div id="app"> <div id="app">
<b-alert :show="shopping_list_store.has_failed_items" class="float-up mt-2" variant="warning"> <b-alert :show="shopping_list_store.has_failed_items" class="float-up mt-2" variant="warning">
{{$t('ShoppingBackgroundSyncWarning')}} {{ $t('ShoppingBackgroundSyncWarning') }}
</b-alert> </b-alert>
<div class="row float-top w-100"> <div class="row float-top w-100">
@ -37,7 +37,8 @@
<template #title> <template #title>
<i v-if="!shopping_list_store.currently_updating && useShoppingListStore().autosync_has_focus" <i v-if="!shopping_list_store.currently_updating && useShoppingListStore().autosync_has_focus"
class="fas fa-shopping-cart fa-fw"></i> class="fas fa-shopping-cart fa-fw"></i>
<i v-if="!shopping_list_store.currently_updating && !useShoppingListStore().autosync_has_focus" class="fas fa-eye-slash"></i> <i v-if="!shopping_list_store.currently_updating && !useShoppingListStore().autosync_has_focus"
class="fas fa-eye-slash"></i>
<b-spinner v-if="shopping_list_store.currently_updating" type="border" small <b-spinner v-if="shopping_list_store.currently_updating" type="border" small
style="width: 1.25em!important; height: 1.25em!important;"></b-spinner> style="width: 1.25em!important; height: 1.25em!important;"></b-spinner>
<span class="d-none d-md-inline-block ml-1"> <span class="d-none d-md-inline-block ml-1">
@ -337,8 +338,7 @@
</template> </template>
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-12 col-md-8"> <div class="col-12 col-md-8">
<shopping-settings-component @updated="user_preference_store.updateUserSettings()" <shopping-settings-component></shopping-settings-component>
:user_id="user_id"></shopping-settings-component>
</div> </div>
</div> </div>
</b-tab> </b-tab>
@ -512,7 +512,6 @@ export default {
new_category: {entrymode: false, value: undefined}, new_category: {entrymode: false, value: undefined},
autosync_id: undefined, autosync_id: undefined,
new_item: {amount: 1, unit: undefined, food: undefined, ingredient: undefined}, new_item: {amount: 1, unit: undefined, food: undefined, ingredient: undefined},
online: true,
new_recipe: { new_recipe: {
id: undefined, id: undefined,
}, },
@ -543,15 +542,14 @@ export default {
}, },
watch: {}, watch: {},
mounted() { mounted() {
window.addEventListener("online", this.updateOnlineStatus) addEventListener("visibilitychange", (event) => {
window.addEventListener("offline", this.updateOnlineStatus) useShoppingListStore().autosync_has_focus = (document.visibilityState === 'visible')
});
addEventListener("visibilitychange", (event) => {useShoppingListStore().autosync_has_focus = (document.visibilityState === 'visible')});
this.$i18n.locale = window.CUSTOM_LOCALE this.$i18n.locale = window.CUSTOM_LOCALE
this.shopping_list_store.refreshFromAPI() this.shopping_list_store.refreshFromAPI()
useUserPreferenceStore().loadUserSettings() useUserPreferenceStore().loadUserSettings(true)
useUserPreferenceStore().loadDeviceSettings() useUserPreferenceStore().loadDeviceSettings()
this.autoSyncLoop() this.autoSyncLoop()
}, },
@ -567,12 +565,12 @@ export default {
this.autosync_id = undefined this.autosync_id = undefined
let timeout = Math.max(this.user_preference_store.user_settings.shopping_auto_sync, 1) * 1000 // if disabled (shopping_auto_sync=0) check again after 1 second if enabled let timeout = Math.max(this.user_preference_store.user_settings.shopping_auto_sync, 1) * 1000 // if disabled (shopping_auto_sync=0) check again after 1 second if enabled
console.log('setting', this.user_preference_store.user_settings.shopping_auto_sync, 'timeout ', timeout)
this.autosync_id = setTimeout(() => { this.autosync_id = setTimeout(() => {
if (this.online && this.user_preference_store.user_settings.shopping_auto_sync > 0) { if (this.user_preference_store.user_settings.shopping_auto_sync > 0) {
this.shopping_list_store.autosync() this.shopping_list_store.autosync()
this.autoSyncLoop()
} }
this.autoSyncLoop()
}, timeout) }, timeout)
}, },
/** /**
@ -659,7 +657,7 @@ export default {
checkGroup(group, checked_state) { checkGroup(group, checked_state) {
let all_entries = {} let all_entries = {}
for (let f in group.foods) { for (let f in group.foods) {
all_entries = Object.assign({},all_entries, group.foods[f].entries) all_entries = Object.assign({}, all_entries, group.foods[f].entries)
} }
useShoppingListStore().setEntriesCheckedState(all_entries, checked_state, true) useShoppingListStore().setEntriesCheckedState(all_entries, checked_state, true)
}, },
@ -881,14 +879,6 @@ export default {
}) })
} }
}, },
updateOnlineStatus(e) {
const {type} = e
this.online = type === "online"
},
beforeDestroy() {
window.removeEventListener("online", this.updateOnlineStatus)
window.removeEventListener("offline", this.updateOnlineStatus)
},
/** /**
* open standard shopping modal to add selected recipe to shopping list * open standard shopping modal to add selected recipe to shopping list
* @param recipe recipe object to add to shopping * @param recipe recipe object to add to shopping

View File

@ -1,10 +1,10 @@
<template> <template>
<div v-if="user_preferences !== undefined"> <div v-if="useUserPreferenceStore().user_settings !== undefined">
<b-form-group :label="$t('shopping_share')" :description="$t('shopping_share_desc')"> <b-form-group :label="$t('shopping_share')" :description="$t('shopping_share_desc')">
<generic-multiselect <generic-multiselect
@change="user_preferences.shopping_share = $event.val; updateSettings(false)" @change="useUserPreferenceStore().user_settings.shopping_share = $event.val; updateSettings(false)"
:model="Models.USER" :model="Models.USER"
:initial_selection="user_preferences.shopping_share" :initial_selection="useUserPreferenceStore().user_settings.shopping_share"
label="display_name" label="display_name"
:multiple="true" :multiple="true"
:placeholder="$t('User')" :placeholder="$t('User')"
@ -12,101 +12,95 @@
</b-form-group> </b-form-group>
<b-form-group :label="$t('shopping_auto_sync')" :description="$t('shopping_auto_sync_desc')"> <b-form-group :label="$t('shopping_auto_sync')" :description="$t('shopping_auto_sync_desc')">
<b-form-input type="range" :min="SHOPPING_MIN_AUTOSYNC_INTERVAL" max="60" step="1" v-model="user_preferences.shopping_auto_sync" <b-form-input type="range" :min="SHOPPING_MIN_AUTOSYNC_INTERVAL" max="60" step="1" v-model="useUserPreferenceStore().user_settings.shopping_auto_sync"
@change="updateSettings(false)"></b-form-input> @change="updateSettings(false)"></b-form-input>
<div class="text-center"> <div class="text-center">
<span v-if="user_preferences.shopping_auto_sync > 0"> <span v-if="useUserPreferenceStore().user_settings.shopping_auto_sync > 0">
{{ Math.round(user_preferences.shopping_auto_sync) }} {{ Math.round(useUserPreferenceStore().user_settings.shopping_auto_sync) }}
<span v-if="user_preferences.shopping_auto_sync === 1">{{ $t('Second') }}</span> <span v-if="useUserPreferenceStore().user_settings.shopping_auto_sync === 1">{{ $t('Second') }}</span>
<span v-else> {{ $t('Seconds') }}</span> <span v-else> {{ $t('Seconds') }}</span>
</span> </span>
<span v-if="user_preferences.shopping_auto_sync < 1">{{ $t('Disable') }}</span> <span v-if="useUserPreferenceStore().user_settings.shopping_auto_sync < 1">{{ $t('Disable') }}</span>
</div> </div>
<br/> <br/>
<b-button class="btn btn-sm" @click="user_preferences.shopping_auto_sync = 0; updateSettings(false)">{{ $t('Disabled') }}</b-button> <b-button class="btn btn-sm" @click="useUserPreferenceStore().user_settings.shopping_auto_sync = 0; updateSettings(false)">{{ $t('Disabled') }}</b-button>
</b-form-group> </b-form-group>
<b-form-group :description="$t('mealplan_autoadd_shopping_desc')"> <b-form-group :description="$t('mealplan_autoadd_shopping_desc')">
<b-form-checkbox v-model="user_preferences.mealplan_autoadd_shopping" <b-form-checkbox v-model="useUserPreferenceStore().user_settings.mealplan_autoadd_shopping"
@change="updateSettings(false)">{{ $t('mealplan_autoadd_shopping') }} @change="updateSettings(false)">{{ $t('mealplan_autoadd_shopping') }}
</b-form-checkbox> </b-form-checkbox>
</b-form-group> </b-form-group>
<b-form-group :description="$t('mealplan_autoexclude_onhand_desc')"> <b-form-group :description="$t('mealplan_autoexclude_onhand_desc')">
<b-form-checkbox v-model="user_preferences.mealplan_autoexclude_onhand" <b-form-checkbox v-model="useUserPreferenceStore().user_settings.mealplan_autoexclude_onhand"
@change="updateSettings(false)">{{ $t('mealplan_autoexclude_onhand') }} @change="updateSettings(false)">{{ $t('mealplan_autoexclude_onhand') }}
</b-form-checkbox> </b-form-checkbox>
</b-form-group> </b-form-group>
<b-form-group :description="$t('mealplan_autoinclude_related_desc')"> <b-form-group :description="$t('mealplan_autoinclude_related_desc')">
<b-form-checkbox v-model="user_preferences.mealplan_autoinclude_related" <b-form-checkbox v-model="useUserPreferenceStore().user_settings.mealplan_autoinclude_related"
@change="updateSettings(false)">{{ $t('mealplan_autoinclude_related') }} @change="updateSettings(false)">{{ $t('mealplan_autoinclude_related') }}
</b-form-checkbox> </b-form-checkbox>
</b-form-group> </b-form-group>
<b-form-group :description="$t('shopping_add_onhand_desc')"> <b-form-group :description="$t('shopping_add_onhand_desc')">
<b-form-checkbox v-model="user_preferences.shopping_add_onhand" <b-form-checkbox v-model="useUserPreferenceStore().user_settings.shopping_add_onhand"
@change="updateSettings(false)">{{ $t('shopping_add_onhand') }} @change="updateSettings(false)">{{ $t('shopping_add_onhand') }}
</b-form-checkbox> </b-form-checkbox>
</b-form-group> </b-form-group>
<b-form-group :label="$t('default_delay')" :description="$t('default_delay_desc')"> <b-form-group :label="$t('default_delay')" :description="$t('default_delay_desc')">
<b-form-input type="range" min="1" max="72" step="1" v-model="user_preferences.default_delay" <b-form-input type="range" min="1" max="72" step="1" v-model="useUserPreferenceStore().user_settings.default_delay"
@change="updateSettings(false)"></b-form-input> @change="updateSettings(false)"></b-form-input>
<div class="text-center"> <div class="text-center">
<span>{{ Math.round(user_preferences.default_delay) }} <span>{{ Math.round(useUserPreferenceStore().user_settings.default_delay) }}
<span v-if="user_preferences.default_delay === 1">{{ $t('Hour') }}</span> <span v-if="useUserPreferenceStore().user_settings.default_delay === 1">{{ $t('Hour') }}</span>
<span v-else> {{ $t('Hours') }}</span> <span v-else> {{ $t('Hours') }}</span>
</span> </span>
</div> </div>
</b-form-group> </b-form-group>
<b-form-group :description="$t('filter_to_supermarket_desc')"> <b-form-group :description="$t('filter_to_supermarket_desc')">
<b-form-checkbox v-model="user_preferences.filter_to_supermarket" <b-form-checkbox v-model="useUserPreferenceStore().user_settings.filter_to_supermarket"
@change="updateSettings(false)">{{ $t('filter_to_supermarket') }} @change="updateSettings(false)">{{ $t('filter_to_supermarket') }}
</b-form-checkbox> </b-form-checkbox>
</b-form-group> </b-form-group>
<b-form-group :label="$t('shopping_recent_days')" :description="$t('shopping_recent_days_desc')"> <b-form-group :label="$t('shopping_recent_days')" :description="$t('shopping_recent_days_desc')">
<b-form-input type="range" min="0" max="14" step="1" v-model="user_preferences.shopping_recent_days" <b-form-input type="range" min="0" max="14" step="1" v-model="useUserPreferenceStore().user_settings.shopping_recent_days"
@change="updateSettings(false)"></b-form-input> @change="updateSettings(false)"></b-form-input>
<div class="text-center"> <div class="text-center">
<span>{{ Math.round(user_preferences.shopping_recent_days) }} <span>{{ Math.round(useUserPreferenceStore().user_settings.shopping_recent_days) }}
<span v-if="user_preferences.shopping_recent_days === 1">{{ $t('Day') }}</span> <span v-if="useUserPreferenceStore().user_settings.shopping_recent_days === 1">{{ $t('Day') }}</span>
<span v-else> {{ $t('Days') }}</span> <span v-else> {{ $t('Days') }}</span>
</span> </span>
</div> </div>
</b-form-group> </b-form-group>
<b-form-group :label="$t('csv_delim_label')" :description="$t('csv_delim_help')"> <b-form-group :label="$t('csv_delim_label')" :description="$t('csv_delim_help')">
<b-form-input v-model="user_preferences.csv_delim" @change="updateSettings(false)"></b-form-input> <b-form-input v-model="useUserPreferenceStore().user_settings.csv_delim" @change="updateSettings(false)"></b-form-input>
</b-form-group> </b-form-group>
<b-form-group :label="$t('csv_prefix_label')" :description="$t('csv_prefix_help')"> <b-form-group :label="$t('csv_prefix_label')" :description="$t('csv_prefix_help')">
<b-form-input v-model="user_preferences.csv_prefix" @change="updateSettings(false)"></b-form-input> <b-form-input v-model="useUserPreferenceStore().user_settings.csv_prefix" @change="updateSettings(false)"></b-form-input>
</b-form-group> </b-form-group>
</div> </div>
</template> </template>
<script> <script>
import {ApiApiFactory} from "@/utils/openapi/api";
import {ApiMixin, StandardToasts} from "@/utils/utils"; import {ApiMixin, StandardToasts} from "@/utils/utils";
import axios from "axios";
import GenericMultiselect from "@/components/GenericMultiselect"; import GenericMultiselect from "@/components/GenericMultiselect";
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
axios.defaults.xsrfCookieName = 'csrftoken'
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN"
export default { export default {
name: "ShoppingSettingsComponent", name: "ShoppingSettingsComponent",
mixins: [ApiMixin], mixins: [ApiMixin],
components: {GenericMultiselect}, components: {GenericMultiselect},
props: { props: { },
user_id: Number,
},
data() { data() {
return { return {
user_preferences: undefined, user_preferences: undefined,
@ -115,30 +109,15 @@ export default {
} }
}, },
mounted() { mounted() {
this.user_preferences = this.preferences
this.languages = window.AVAILABLE_LANGUAGES this.languages = window.AVAILABLE_LANGUAGES
this.loadSettings()
useUserPreferenceStore().loadUserSettings(false)
}, },
methods: { methods: {
loadSettings: function () { useUserPreferenceStore,
let apiFactory = new ApiApiFactory()
apiFactory.retrieveUserPreference(this.user_id.toString()).then(result => {
this.user_preferences = result.data
}).catch(err => {
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err)
})
},
updateSettings: function (reload) { updateSettings: function (reload) {
let apiFactory = new ApiApiFactory()
this.$emit('updated', this.user_preferences) this.$emit('updated', this.user_preferences)
apiFactory.partialUpdateUserPreference(this.user_id.toString(), this.user_preferences).then(result => { useUserPreferenceStore().updateUserSettings()
StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_UPDATE)
if (reload) {
location.reload()
}
}).catch(err => {
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err)
})
}, },
} }
} }

View File

@ -191,6 +191,7 @@ export const useShoppingListStore = defineStore(_STORE_ID, {
*/ */
autosync() { autosync() {
if (!this.currently_updating && this.autosync_has_focus) { if (!this.currently_updating && this.autosync_has_focus) {
console.log('running autosync')
this.currently_updating = true this.currently_updating = true
@ -203,8 +204,6 @@ export const useShoppingListStore = defineStore(_STORE_ID, {
}).then((r) => { }).then((r) => {
r.data.forEach((e) => { r.data.forEach((e) => {
// dont update stale client data // dont update stale client data
console.log('new: ', !(Object.keys(this.entries).includes(e.id.toString())), ' updated at ', Date.parse(this.entries[e.id].updated_at) < Date.parse(e.updated_at))
console.log('client updated at ', this.entries[e.id].updated_at,Date.parse(this.entries[e.id].updated_at), ' server updated at ', e.updated_at,Date.parse(e.updated_at))
if (!(Object.keys(this.entries).includes(e.id.toString())) || Date.parse(this.entries[e.id].updated_at) < Date.parse(e.updated_at)) { if (!(Object.keys(this.entries).includes(e.id.toString())) || Date.parse(this.entries[e.id].updated_at) < Date.parse(e.updated_at)) {
console.log('auto sync updating entry ', e) console.log('auto sync updating entry ', e)
Vue.set(this.entries, e.id, e) Vue.set(this.entries, e.id, e)
@ -326,7 +325,6 @@ export const useShoppingListStore = defineStore(_STORE_ID, {
if (undo) { if (undo) {
this.registerChange((checked ? 'CHECKED' : 'UNCHECKED'), entries) this.registerChange((checked ? 'CHECKED' : 'UNCHECKED'), entries)
} }
console.log('entry changed at ', Date.now(), ' setting to ', moment().format())
let entry_id_list = [] let entry_id_list = []
for (let i in entries) { for (let i in entries) {

View File

@ -3,6 +3,7 @@ import {defineStore} from 'pinia'
import {ApiApiFactory, UserPreference} from "@/utils/openapi/api"; import {ApiApiFactory, UserPreference} from "@/utils/openapi/api";
import Vue from "vue"; import Vue from "vue";
import {StandardToasts} from "@/utils/utils";
const _STALE_TIME_IN_MS = 1000 * 30 const _STALE_TIME_IN_MS = 1000 * 30
const _STORE_ID = 'user_preference_store' const _STORE_ID = 'user_preference_store'
@ -87,7 +88,7 @@ export const useUserPreferenceStore = defineStore(_STORE_ID, {
localStorage.setItem(_LS_DEVICE_SETTINGS, JSON.stringify(this.device_settings)) localStorage.setItem(_LS_DEVICE_SETTINGS, JSON.stringify(this.device_settings))
}, },
// ---------------- new methods for user settings // ---------------- new methods for user settings
loadUserSettings: function () { loadUserSettings: function (allow_cached_results) {
let s = localStorage.getItem(_LS_USER_SETTINGS) let s = localStorage.getItem(_LS_USER_SETTINGS)
if (!(s === null || s === {})) { if (!(s === null || s === {})) {
let settings = JSON.parse(s) let settings = JSON.parse(s)
@ -96,7 +97,7 @@ export const useUserPreferenceStore = defineStore(_STORE_ID, {
} }
//console.log(`loaded local user settings age ${((new Date().getTime()) - this.user_settings.locally_updated_at) / 1000} `) //console.log(`loaded local user settings age ${((new Date().getTime()) - this.user_settings.locally_updated_at) / 1000} `)
} }
if (((new Date().getTime()) - this.user_settings.locally_updated_at) > _STALE_TIME_IN_MS) { if (((new Date().getTime()) - this.user_settings.locally_updated_at) > _STALE_TIME_IN_MS || !allow_cached_results) {
//console.log('refreshing user settings from API') //console.log('refreshing user settings from API')
let apiClient = new ApiApiFactory() let apiClient = new ApiApiFactory()
apiClient.retrieveUserPreference(localStorage.getItem('USER_ID')).then(r => { apiClient.retrieveUserPreference(localStorage.getItem('USER_ID')).then(r => {
@ -122,8 +123,10 @@ export const useUserPreferenceStore = defineStore(_STORE_ID, {
this.user_settings = r.data this.user_settings = r.data
Vue.set(this.user_settings, 'locally_updated_at', new Date().getTime()) Vue.set(this.user_settings, 'locally_updated_at', new Date().getTime())
localStorage.setItem(_LS_USER_SETTINGS, JSON.stringify(this.user_settings)) localStorage.setItem(_LS_USER_SETTINGS, JSON.stringify(this.user_settings))
StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_UPDATE)
}).catch(err => { }).catch(err => {
this.currently_updating = false this.currently_updating = false
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err)
}) })
}, },
// ---------------- // ----------------