sorting
This commit is contained in:
parent
0dacdcc72f
commit
0ce4d45eeb
@ -52,20 +52,19 @@
|
|||||||
</b-row>
|
</b-row>
|
||||||
|
|
||||||
<!-- shopping list table -->
|
<!-- shopping list table -->
|
||||||
|
|
||||||
<b-row v-for="c in shopping_list_store.get_entries_by_group" v-bind:key="c.id" class="pr-1 pl-1">
|
<b-row v-for="c in shopping_list_store.get_entries_by_group" v-bind:key="c.id" class="pr-1 pl-1">
|
||||||
<b-col cols="12">
|
<b-col cols="12">
|
||||||
<b-button-group class="w-100 mt-1">
|
<b-button-group class="w-100 mt-1">
|
||||||
<b-button variant="light" block class="btn btn-block text-left">
|
<b-button variant="light" block class="btn btn-block text-left">
|
||||||
<span v-if="c.name === -1">{{ $t('Undefined') }}</span>
|
<span v-if="c.name === shopping_list_store.UNDEFINED_CATEGORY">{{ $t('Undefined') }}</span>
|
||||||
<span v-else>{{ c.name }}</span>
|
<span v-else>{{ c.name }}</span>
|
||||||
</b-button>
|
</b-button>
|
||||||
<b-button variant="success"><i class="fas fa-check"></i></b-button> <!-- todo implement -->
|
<b-button variant="success"><i class="fas fa-check"></i></b-button> <!-- todo implement -->
|
||||||
</b-button-group>
|
</b-button-group>
|
||||||
|
|
||||||
<span v-for="f in c.foods" v-bind:key="f.id">
|
<span v-for="f in c.foods" v-bind:key="f.id">
|
||||||
<shopping-line-item :entries="f['entries']" class="mt-1"/>
|
<shopping-line-item :entries="f['entries']" class="mt-1"/>
|
||||||
</span>
|
</span>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
|
|
||||||
@ -371,8 +370,9 @@
|
|||||||
<b-form-select v-model="group_by" :options="group_by_choices" size="sm"></b-form-select>
|
<b-form-select v-model="group_by" :options="group_by_choices" size="sm"></b-form-select>
|
||||||
</b-form-group>
|
</b-form-group>
|
||||||
<b-form-group v-bind:label="$t('Supermarket')" label-for="popover-input-2" label-cols="6" class="mb-1">
|
<b-form-group v-bind:label="$t('Supermarket')" label-for="popover-input-2" label-cols="6" class="mb-1">
|
||||||
<b-form-select v-model="ui.selected_supermarket" :options="supermarkets" text-field="name"
|
<generic-multiselect :model="Models.SUPERMARKET" @change="shopping_list_store.selected_supermarket = $event.val" :multiple="false"></generic-multiselect>
|
||||||
value-field="id" size="sm"></b-form-select>
|
<!-- <b-form-select v-model="shopping_list_store.selected_supermarket" :options="shopping_list_store.supermarkets" text-field="name"-->
|
||||||
|
<!-- value-field="id" size="sm"></b-form-select>-->
|
||||||
</b-form-group>
|
</b-form-group>
|
||||||
<!-- TODO: shade filters red when they are actually filtering content -->
|
<!-- TODO: shade filters red when they are actually filtering content -->
|
||||||
<b-form-group v-bind:label="$t('ShowDelayed')" label-for="popover-input-3" content-cols="1"
|
<b-form-group v-bind:label="$t('ShowDelayed')" label-for="popover-input-3" content-cols="1"
|
||||||
@ -814,8 +814,7 @@ export default {
|
|||||||
})
|
})
|
||||||
this.$i18n.locale = window.CUSTOM_LOCALE
|
this.$i18n.locale = window.CUSTOM_LOCALE
|
||||||
|
|
||||||
let store = useShoppingListStore()
|
this.shopping_list_store.refreshFromAPI()
|
||||||
store.refreshFromAPI()
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
useShoppingListStore,
|
useShoppingListStore,
|
||||||
@ -951,32 +950,32 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
}
|
}
|
||||||
this.genericAPI(this.Models.SHOPPING_LIST, this.Actions.LIST, params).then((results) => {
|
// this.genericAPI(this.Models.SHOPPING_LIST, this.Actions.LIST, params).then((results) => {
|
||||||
if (!autosync) {
|
// if (!autosync) {
|
||||||
if (results.data?.length) {
|
// if (results.data?.length) {
|
||||||
this.items = results.data
|
// this.items = results.data
|
||||||
} else {
|
// } else {
|
||||||
console.log("no data returned")
|
// console.log("no data returned")
|
||||||
}
|
// }
|
||||||
this.loading = false
|
// this.loading = false
|
||||||
} else {
|
// } else {
|
||||||
if (!this.auto_sync_blocked) {
|
// if (!this.auto_sync_blocked) {
|
||||||
this.getSyncQueueLength().then((r) => {
|
// this.getSyncQueueLength().then((r) => {
|
||||||
if (r === 0) {
|
// if (r === 0) {
|
||||||
this.mergeShoppingList(results.data)
|
// this.mergeShoppingList(results.data)
|
||||||
} else {
|
// } else {
|
||||||
this.auto_sync_running = false
|
// this.auto_sync_running = false
|
||||||
this.replaySyncQueue()
|
// this.replaySyncQueue()
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.catch((err) => {
|
// .catch((err) => {
|
||||||
if (!autosync) {
|
// if (!autosync) {
|
||||||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err)
|
// StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err)
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
},
|
},
|
||||||
getSupermarkets: function () {
|
getSupermarkets: function () {
|
||||||
let api = new ApiApiFactory()
|
let api = new ApiApiFactory()
|
||||||
|
@ -31,7 +31,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #default>
|
<template #default>
|
||||||
<h6 class="mt-2">{{ $t('Quick actions') }}</h6>
|
<h5 class="mt-2">{{ $t('Quick actions') }}</h5>
|
||||||
|
{{ $t('Category')}}
|
||||||
<b-form-select
|
<b-form-select
|
||||||
class="form-control mb-2"
|
class="form-control mb-2"
|
||||||
:options="useShoppingListStore().supermarket_categories"
|
:options="useShoppingListStore().supermarket_categories"
|
||||||
@ -41,9 +42,10 @@
|
|||||||
@change="detail_modal_visible = false; updateFoodCategory(food)"
|
@change="detail_modal_visible = false; updateFoodCategory(food)"
|
||||||
></b-form-select>
|
></b-form-select>
|
||||||
|
|
||||||
<b-button variant="success" block @click="detail_modal_visible = false;"> {{ $t("Edit_Food") }}</b-button> <!-- TODO implement -->
|
<!-- TODO implement -->
|
||||||
|
<!-- <b-button variant="success" block @click="detail_modal_visible = false;"> {{ $t("Edit_Food") }}</b-button> -->
|
||||||
|
|
||||||
<b-button variant="info" block @click="detail_modal_visible = false;useShoppingListStore().delayEntries(entries)">{{ $t('Delay') }}</b-button>
|
<b-button variant="info" block @click="detail_modal_visible = false;useShoppingListStore().delayEntries(entries)">{{ $t('Shop_later') }}</b-button>
|
||||||
|
|
||||||
|
|
||||||
<h6 class="mt-2">{{ $t('Entries') }}</h6>
|
<h6 class="mt-2">{{ $t('Entries') }}</h6>
|
||||||
|
@ -67,6 +67,7 @@
|
|||||||
"Step_Type": "Step Type",
|
"Step_Type": "Step Type",
|
||||||
"Make_Header": "Make Header",
|
"Make_Header": "Make Header",
|
||||||
"Make_Ingredient": "Make Ingredient",
|
"Make_Ingredient": "Make Ingredient",
|
||||||
|
"Shop_later": "Shop later",
|
||||||
"Amount": "Amount",
|
"Amount": "Amount",
|
||||||
"Enable_Amount": "Enable Amount",
|
"Enable_Amount": "Enable Amount",
|
||||||
"Disable_Amount": "Disable Amount",
|
"Disable_Amount": "Disable Amount",
|
||||||
|
@ -12,32 +12,66 @@ const _LOCAL_STORAGE_KEY = "SHOPPING_LIST_CLIENT_SETTINGS"
|
|||||||
* */
|
* */
|
||||||
export const useShoppingListStore = defineStore(_STORE_ID, {
|
export const useShoppingListStore = defineStore(_STORE_ID, {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
|
// shopping data
|
||||||
entries: {},
|
entries: {},
|
||||||
|
|
||||||
category_food_entries: {},
|
|
||||||
supermarket_categories: [],
|
supermarket_categories: [],
|
||||||
|
supermarkets: [],
|
||||||
|
|
||||||
|
//settings
|
||||||
show_checked_entries: false, // TODO move to settings
|
show_checked_entries: false, // TODO move to settings
|
||||||
|
show_delayed_entries: false,
|
||||||
|
show_selected_supermarket_only: false,
|
||||||
|
selected_supermarket: null,
|
||||||
|
selected_group: 'food.supermarket_category.name',
|
||||||
|
|
||||||
|
// internal
|
||||||
currently_updating: false,
|
currently_updating: false,
|
||||||
settings: null,
|
settings: null,
|
||||||
|
|
||||||
|
// constants
|
||||||
GROUP_CATEGORY: 'food.supermarket_category.name',
|
GROUP_CATEGORY: 'food.supermarket_category.name',
|
||||||
GROUP_CREATED_BY: 'created_by.display_name',
|
GROUP_CREATED_BY: 'created_by.display_name',
|
||||||
GROUP_RECIPE: 'recipe_mealplan.recipe_name',
|
GROUP_RECIPE: 'recipe_mealplan.recipe_name',
|
||||||
GROUP_MEALPLAN: 'recipe_mealplan.mealplan', //TODO give this some name from the API
|
GROUP_MEALPLAN: 'recipe_mealplan.mealplan', //TODO give this some name from the API
|
||||||
|
UNDEFINED_CATEGORY: 'shopping_undefined_category'
|
||||||
selected_group: 'food.supermarket_category.name',
|
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
|
/**
|
||||||
|
* build a multi-level data structure ready for display from shopping list entries
|
||||||
|
* group by selected grouping key
|
||||||
|
* @return {{}}
|
||||||
|
*/
|
||||||
get_entries_by_group: function () {
|
get_entries_by_group: function () {
|
||||||
let structure = {}
|
let structure = {}
|
||||||
|
let ordered_structure = []
|
||||||
for (let i in this.entries) {
|
for (let i in this.entries) {
|
||||||
structure = this.updateEntryInStructure(structure, this.entries[i], this.selected_group)
|
structure = this.updateEntryInStructure(structure, this.entries[i], this.selected_group)
|
||||||
}
|
}
|
||||||
return structure
|
|
||||||
|
if (this.selected_group === this.GROUP_CATEGORY && this.selected_supermarket !== null) {
|
||||||
|
if (this.UNDEFINED_CATEGORY in structure) {
|
||||||
|
ordered_structure.push(structure[this.UNDEFINED_CATEGORY])
|
||||||
|
Vue.delete(structure, this.UNDEFINED_CATEGORY)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let c of this.selected_supermarket.category_to_supermarket) {
|
||||||
|
if (c.category.name in structure) {
|
||||||
|
ordered_structure.push(structure[c.category.name])
|
||||||
|
Vue.delete(structure, c.category.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!this.show_selected_supermarket_only) {
|
||||||
|
for (let i in structure) {
|
||||||
|
ordered_structure.push(structure[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i in structure) {
|
||||||
|
ordered_structure.push(structure[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ordered_structure
|
||||||
},
|
},
|
||||||
|
|
||||||
client_settings: function () {
|
client_settings: function () {
|
||||||
@ -52,8 +86,6 @@ export const useShoppingListStore = defineStore(_STORE_ID, {
|
|||||||
/**
|
/**
|
||||||
* Retrieves all shopping list entries from the API and parses them into a structured object category > food > entry
|
* Retrieves all shopping list entries from the API and parses them into a structured object category > food > entry
|
||||||
*/
|
*/
|
||||||
this.category_food_entries = {}
|
|
||||||
Vue.set(this.category_food_entries, -1, {'id': -1, 'name': '', foods: {}})
|
|
||||||
|
|
||||||
if (!this.currently_updating) {
|
if (!this.currently_updating) {
|
||||||
this.currently_updating = true
|
this.currently_updating = true
|
||||||
@ -72,6 +104,12 @@ export const useShoppingListStore = defineStore(_STORE_ID, {
|
|||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err)
|
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
apiClient.listSupermarkets().then(r => {
|
||||||
|
this.supermarkets = r.data
|
||||||
|
}).catch((err) => {
|
||||||
|
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_FETCH, err)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
createObject(object) {
|
createObject(object) {
|
||||||
@ -120,15 +158,6 @@ export const useShoppingListStore = defineStore(_STORE_ID, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// concenience methods
|
// concenience methods
|
||||||
getFoodCategory(food) {
|
|
||||||
/**
|
|
||||||
* Get category id from food or return -1 if food has no category
|
|
||||||
*/
|
|
||||||
if (food.supermarket_category !== null) {
|
|
||||||
return food.supermarket_category.id
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
},
|
|
||||||
/**
|
/**
|
||||||
* function to set entry to its proper place in the data structure to perform grouping
|
* function to set entry to its proper place in the data structure to perform grouping
|
||||||
* @param {{}} structure datastructure
|
* @param {{}} structure datastructure
|
||||||
@ -137,10 +166,10 @@ export const useShoppingListStore = defineStore(_STORE_ID, {
|
|||||||
* @returns updated datastructure including entry
|
* @returns updated datastructure including entry
|
||||||
*/
|
*/
|
||||||
updateEntryInStructure(structure, entry, group) {
|
updateEntryInStructure(structure, entry, group) {
|
||||||
let grouping_key = _.get(entry, group, -1)
|
let grouping_key = _.get(entry, group, this.UNDEFINED_CATEGORY)
|
||||||
// todo handele parent
|
// todo handele parent
|
||||||
if (grouping_key === undefined || grouping_key === null) {
|
if (grouping_key === undefined || grouping_key === null) {
|
||||||
grouping_key = -1
|
grouping_key = this.UNDEFINED_CATEGORY
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(grouping_key in structure)) {
|
if (!(grouping_key in structure)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user