Merge branch 'develop' of https://github.com/vabene1111/recipes into develop

# Conflicts:
#	vue/src/apps/ShoppingListView/ShoppingListView.vue
This commit is contained in:
Kaibu
2022-04-23 20:45:35 +02:00
12 changed files with 147 additions and 88 deletions

View File

@ -218,8 +218,7 @@
:href="resolveDjangoUrl('view_recipe',r.id)">{{
r.name
}}</a>
<span class="float-right">Imported</span>
<!-- TODO localize -->
<span class="float-right">{{ $t('Imported') }}</span>
</div>
</b-list-group-item>
@ -230,8 +229,7 @@
<div class="clearfix">
<a class="float-left" target="_blank"
rel="noreferrer nofollow" :href="u">{{ u }}</a>
<span class="float-right">Failed</span>
<!-- TODO localize -->
<span class="float-right">{{ $t('Failure') }}</span>
</div>
</b-list-group-item>
</b-list-group>

View File

@ -1,23 +1,37 @@
<template>
<div id="app">
<beta-warning></beta-warning>
<div class="row mt-2">
<div class="col col-md-6">
<generic-multiselect @change="food = $event.val; refreshList()" ref="food_multiselect"
:model="Models.FOOD"
:initial_single_selection="food"
:multiple="false"></generic-multiselect>
<b-button @click="generic_model = Models.FOOD; generic_action=Actions.DELETE" :disabled="food === null">
<i class="fas fa-trash-alt"></i>
</b-button>
<b-button @click="generic_model = Models.FOOD; generic_action=Actions.MERGE" :disabled="food === null">
<i class="fas fa-compress-arrows-alt"></i>
</b-button>
<b-input-group>
<generic-multiselect @change="food = $event.val; refreshList()" ref="food_multiselect"
:model="Models.FOOD"
:initial_single_selection="food"
:multiple="false"
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"></generic-multiselect>
<b-button @click="generic_model = Models.FOOD; generic_action=Actions.UPDATE" :disabled="food === null">
<i class="fas fa-edit"></i>
</b-button>
<b-input-group-append>
<b-dropdown no-caret right :disabled="food === null">
<template #button-content>
<i class="fas fa-ellipsis-v"></i>
</template>
<b-dropdown-item @click="generic_model = Models.FOOD; generic_action=Actions.UPDATE"
:disabled="food === null">
<i class="fas fa-edit fa-fw"></i> {{ $t('Edit') }}
</b-dropdown-item>
<b-dropdown-item @click="generic_model = Models.FOOD; generic_action=Actions.MERGE"
:disabled="food === null">
<i class="fas fa-compress-arrows-alt fa-fw"></i> {{ $t('Merge') }}
</b-dropdown-item>
<b-dropdown-item @click="generic_model = Models.FOOD; generic_action=Actions.DELETE"
:disabled="food === null">
<i class="fas fa-trash-alt fa-fw"></i> {{ $t('Delete') }}
</b-dropdown-item>
</b-dropdown>
</b-input-group-append>
</b-input-group>
<generic-modal-form :model="Models.FOOD" :action="generic_action" :show="generic_model === Models.FOOD"
:item1="food"
@ -25,36 +39,58 @@
</div>
<div class="col col-md-6">
<generic-multiselect
@change="unit = $event.val; refreshList()"
:model="Models.UNIT"
ref="unit_multiselect"
:initial_single_selection="unit"
:multiple="false"></generic-multiselect>
<b-input-group>
<generic-multiselect
@change="unit = $event.val; refreshList()"
:model="Models.UNIT"
ref="unit_multiselect"
:initial_single_selection="unit"
:multiple="false"
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"></generic-multiselect>
<b-input-group-append>
<b-dropdown no-caret right :disabled="unit === null">
<template #button-content>
<i class="fas fa-ellipsis-v"></i>
</template>
<b-dropdown-item @click="generic_model = Models.UNIT; generic_action=Actions.UPDATE"
:disabled="unit === null">
<i class="fas fa-edit fa-fw"></i> {{ $t('Edit') }}
</b-dropdown-item>
<b-dropdown-item @click="generic_model = Models.UNIT; generic_action=Actions.MERGE"
:disabled="unit === null">
<i class="fas fa-compress-arrows-alt fa-fw"></i> {{ $t('Merge') }}
</b-dropdown-item>
<b-dropdown-item @click="generic_model = Models.UNIT; generic_action=Actions.DELETE"
:disabled="unit === null">
<i class="fas fa-trash-alt fa-fw"></i> {{ $t('Delete') }}
</b-dropdown-item>
</b-dropdown>
</b-input-group-append>
</b-input-group>
<b-button @click="generic_model = Models.UNIT; generic_action=Actions.DELETE" :disabled="unit === null">
<i class="fas fa-trash-alt"></i>
</b-button>
<b-button @click="generic_model = Models.UNIT; generic_action=Actions.MERGE" :disabled="unit === null">
<i class="fas fa-compress-arrows-alt"></i>
</b-button>
<b-button @click="generic_model = Models.UNIT; generic_action=Actions.UPDATE" :disabled="unit === null">
<i class="fas fa-edit"></i>
</b-button>
<generic-modal-form :model="Models.UNIT" :action="generic_action" :show="generic_model === Models.UNIT"
:item1="unit"
@finish-action="finishGenericAction()"/>
</div>
</div>
<b-pagination pills v-model="current_page" :total-rows="total_object_count" :per-page="page_size"
@change="pageChange"></b-pagination>
<b-row class="mt-2">
<b-col cols="12">
<b-pagination align="center" pills v-model="current_page" :total-rows="total_object_count"
:per-page="page_size"
@change="pageChange"></b-pagination>
</b-col>
</b-row>
<div class="row mt-2">
<div class="col col-md-12">
<table class="table table-bordered">
<b-row class="mt-2">
<b-col>
<table class="table table-bordered table-sm">
<thead>
<tr>
<th>{{ $t('Amount') }}</th>
@ -62,7 +98,8 @@
<th>{{ $t('Food') }}</th>
<th>{{ $t('Note') }}</th>
<th>
<b-button variant="success" @click="updateIngredient()"><i class="fas fa-save"></i>
<b-button variant="success" class="btn btn-sm" @click="updateIngredient()"><i
class="fas fa-save"></i>
</b-button>
</th>
</tr>
@ -108,15 +145,17 @@
</td>
<td style="width: 5vw">
<b-button :disabled="i.changed !== true"
:variant="(i.changed !== true) ? 'primary' : 'success'"
@click="updateIngredient(i)">
<i class="fas fa-save"></i>
</b-button>
<b-button variant="danger"
@click="deleteIngredient(i)">
<i class="fas fa-trash"></i>
</b-button>
<b-button-group>
<b-button :disabled="i.changed !== true"
:variant="(i.changed !== true) ? 'primary' : 'success'"
@click="updateIngredient(i)">
<i class="fas fa-save"></i>
</b-button>
<b-button variant="danger"
@click="deleteIngredient(i)">
<i class="fas fa-trash"></i>
</b-button>
</b-button-group>
</td>
</tr>
@ -127,12 +166,17 @@
</table>
<b-pagination pills v-model="current_page" :total-rows="total_object_count" :per-page="page_size"
@change="pageChange"></b-pagination>
</div>
</div>
</b-col>
</b-row>
<b-row class="mt-2">
<b-col cols="12">
<b-pagination align="center" pills v-model="current_page" :total-rows="total_object_count"
:per-page="page_size"
@change="pageChange"></b-pagination>
</b-col>
</b-row>
</div>
</template>
@ -153,7 +197,7 @@ Vue.use(BootstrapVue)
export default {
name: "IngredientEditorView",
mixins: [ApiMixin, ResolveUrlMixin],
components: {BetaWarning, LoadingSpinner, GenericMultiselect, GenericModalForm},
components: {LoadingSpinner, GenericMultiselect, GenericModalForm},
data() {
return {
ingredients: [],
@ -202,7 +246,7 @@ export default {
if (this.unit !== null) {
params.query.unit = this.unit.id
}
apiClient.listIngredients(this.current_page, this.page_size,params).then(result => {
apiClient.listIngredients(this.current_page, this.page_size, params).then(result => {
this.ingredients = result.data.results
this.total_object_count = result.data.count
this.loading = false

View File

@ -112,21 +112,21 @@
</div>
<!-- shopping list table -->
<div v-if="items && items.length > 0">
<div v-for="(done, x) in Sections" :key="x">
<div v-if="x == 'true'"
<div v-for="(categories, checked_key) in Sections" :key="checked_key">
<div v-if="checked_key == 'true'"
class="bg-header w-100 text-center d-flex justify-content-center align-items-center">
<span class="h4 d-flex mt-1 mb-1">{{ $t("Completed") }}</span>
</div>
<div v-for="(s, i) in done" :key="i">
<div v-for="(foods_group, category_key) in categories" :key="category_key">
<div class="dropdown b-dropdown position-static inline-block"
data-html2canvas-ignore="true" v-if="Object.entries(s).length > 0">
data-html2canvas-ignore="true" v-if="Object.entries(foods_group).length > 0">
<button
aria-haspopup="true"
aria-expanded="false"
type="button"
class="btn dropdown-toggle btn-link text-decoration-none text-dark pr-2 dropdown-toggle-no-caret"
@click.stop="openContextMenu($event, s, true)"
@click.stop="openContextMenu($event, foods_group, true)"
>
<i class="fas fa-ellipsis-v"></i>
</button>
@ -135,20 +135,20 @@
class="btn btn-lg text-decoration-none text-dark px-1 py-0 border-0"
variant="link"
data-toggle="collapse"
:href="'#section-' + sectionID(x, i)"
:aria-expanded="'true' ? x == 'false' : 'true'"
:href="'#section-' + sectionID(checked_key, category_key)"
:aria-expanded="'true' ? checked_key == 'false' : 'true'"
>
<i class="fa fa-chevron-right rotate"/>
<span class="h6 ml-2 text-secondary">{{ i }}</span>
<span class="h6 ml-2 text-secondary">{{ category_key }}</span>
</b-button>
</div>
<div class="collapse" :id="'section-' + sectionID(x, i)" visible
role="tabpanel" :class="{ show: x == 'false' }">
<div class="collapse" :id="'section-' + sectionID(checked_key, category_key)" visible
role="tabpanel" :class="{ show: checked_key == 'false' }">
<!-- passing an array of values to the table grouped by Food -->
<transition-group name="slide-fade">
<div class="pl-4 pr-0" v-for="(entries, x) in Object.entries(s)"
:key="x">
<div class="pl-4 pr-0" v-for="(entries, index) in Object.entries(foods_group)"
:key="index">
<transition name="slide-fade" mode="out-in">
<shopping-line-item
:entries="entries[1]"
@ -846,6 +846,8 @@ export default {
},
computed: {
Sections() {
// Sections to display in list (checked/unchecked -> category -> food group -> entries)
// ordering/sorting is definied by the order in which categories are added to the sections array (even trough the dev console does not show it like this)
function getKey(item, group_by, x) {
switch (group_by) {
case "category":
@ -879,10 +881,12 @@ export default {
}
var groups = {false: {}, true: {}} // force unchecked to always be first
// TODO: make nulls_first a user setting
// add undefined group to both the checked and non checked
groups.false[this.$t("Undefined")] = {}
groups.true[this.$t("Undefined")] = {}
// category order is defined by order of insertion into groups variable
if (this.ui.selected_supermarket) {
// TODO: make nulls_first a user setting
groups.false[this.$t("Undefined")] = {}
groups.true[this.$t("Undefined")] = {}
let super_cats = this.supermarkets
.filter((x) => x.id === this.ui.selected_supermarket)
.map((x) => x.category_to_supermarket)
@ -978,7 +982,7 @@ export default {
watch: {
ui: {
handler() {
this.$cookies.set(SETTINGS_COOKIE_NAME, {ui: this.ui, settings: {entrymode: this.entrymode}})
this.$cookies.set(SETTINGS_COOKIE_NAME, {ui: this.ui, settings: {entrymode: this.entrymode}}, "100y")
if (this.entrymode) {
this.$nextTick(function () {
this.setFocus()
@ -989,7 +993,7 @@ export default {
},
entrymode: {
handler() {
this.$cookies.set(SETTINGS_COOKIE_NAME, {ui: this.ui, settings: {entrymode: this.entrymode}})
this.$cookies.set(SETTINGS_COOKIE_NAME, {ui: this.ui, settings: {entrymode: this.entrymode}}, "100y")
if (this.entrymode) {
document.getElementById('shoppinglist').scrollTop = 0
this.$nextTick(function () {
@ -1069,7 +1073,7 @@ export default {
if (this.new_item.ingredient !== "" && this.new_item.ingredient !== undefined) {
this.genericPostAPI("api_ingredient_from_string", {text: this.new_item.ingredient}).then((result) => {
let unit = null
if (result.data.unit !== "") {
if (result.data.unit !== null) {
unit = {name: result.data.unit}
}
@ -1129,9 +1133,10 @@ export default {
promises.push(this.saveThis({id: entry, delay_until: delay_date}, false))
})
Promise.all(promises).then(() => {
StandardToasts.makeStandardToast(this, StandardToasts.SUCCESS_UPDATE)
this.items = this.items.filter((x) => !entries.includes(x.id))
this.delay = this.defaultDelay
}).catch(err => {
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE, err)
})
},
deleteRecipe: function (e, recipe) {

View File

@ -368,6 +368,7 @@
"no_pinned_recipes": "You have no pinned recipes!",
"Planned": "Planned",
"Pinned": "Pinned",
"Imported": "Imported",
"Quick actions": "Quick actions",
"Ratings": "Ratings",
"Internal": "Internal",