Merge branch 'develop' into remove_facets

This commit is contained in:
vabene1111
2023-09-12 15:36:14 +02:00
committed by GitHub
23 changed files with 437 additions and 478 deletions

View File

@@ -1,219 +1,165 @@
<template>
<div>
<b-tabs content-class="mt-3" v-model="current_tab">
<b-tab :title="$t('Planner')" active>
<div class=" d-none d-lg-block">
<div class="row">
<div class="col col-2">
<h4>{{ $t('Meal_Types') }}</h4>
<div class="d-none d-lg-block">
<div class="row ">
<div class="col col-2">
<h4>{{ $t('Meal_Types') }}</h4>
<b-form-checkbox :button-variant="danger" v-model="mt.checked" size="lg" v-for="mt in meal_types" v-bind:key="mt.id">
<b-badge variant="primary" :style="{'background-color':mt.color}">{{ mt.name }}</b-badge>
</b-form-checkbox>
<hr/>
<button class="btn btn-success shadow-none mt-1 btn-block" @click="createEntryClick(new Date())"><i
class="fas fa-calendar-plus"></i> {{ $t("Create") }}
</button>
<button class="btn btn-primary shadow-none mt-1 btn-block" @click="createAutoPlan(new Date())"><i
class="fas fa-calendar-plus"></i> {{ $t("Auto_Planner") }}
</button>
<a class="btn btn-primary shadow-none mt-1 btn-blockmt-1 btn-block" :href="iCalUrl"><i class="fas fa-download"></i>
{{ $t("Export_To_ICal") }}
</a>
</div>
<div class="col col-10">
<div class="row calender-row ">
<div class="col-12 calender-parent">
<calendar-view
:show-date="showDate"
:enable-date-selection="true"
class="theme-default"
:items="plan_items"
:display-period-uom="settings.displayPeriodUom"
:period-changed-callback="periodChangedCallback"
:enable-drag-drop="true"
:item-content-height="item_height"
@click-date="createEntryClick"
@drop-on-date="moveEntry"
:display-period-count="settings.displayPeriodCount"
:starting-day-of-week="settings.startingDayOfWeek"
:display-week-numbers="settings.displayWeekNumbers"
>
<template #item="{ value, weekStartDate, top }">
<meal-plan-card
:value="value"
:week-start-date="weekStartDate"
:top="top"
:detailed="detailed_items"
:item_height="item_height"
@dragstart="dragged_item = value"
@click-item="entryClick"
@open-context-menu="openContextMenu"
/>
</template>
<template #header="{ headerProps }">
<meal-plan-calender-header
ref="header"
:header-props="headerProps"
@input="setShowDate"
@delete-dragged="deleteEntry(dragged_item)"
@create-new="createEntryClick(new Date())"
@set-starting-day-back="setStartingDay(-1)"
@set-starting-day-forward="setStartingDay(1)"
:i-cal-url="iCalUrl"
:options="options"
:settings_prop="settings"
/>
</template>
</calendar-view>
</div>
<div class="d-flex flex-row align-items-center border" v-for="mt in meal_types" v-bind:key="mt.id">
<div class="flex-column" style="width: 2.5rem; height: 2.5rem;" :style="{'background-color': mt.color}"></div>
<div class="flex-column flex-grow-1 align-middle justify-content-center">
<div class="card-body p-2 align-middle">
{{ mt.name }}
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row d-block d-lg-none">
<div>
<div class="col-12">
<div class="col-12 d-flex justify-content-center mt-2">
<b-button-toolbar key-nav aria-label="Toolbar with button groups">
<b-button-group class="mx-1">
<b-button v-html="'<<'" class="p-2 pr-3 pl-3"
@click="setShowDate($refs.header.headerProps.previousPeriod)"></b-button>
</b-button-group>
<b-button-group class="mx-1">
<b-button @click="setShowDate($refs.header.headerProps.currentPeriod)"><i
class="fas fa-home"></i></b-button>
<b-form-datepicker right button-only button-variant="secondary" @context="datePickerChanged"></b-form-datepicker>
</b-button-group>
<b-button-group class="mx-1">
<b-button v-html="'>>'" class="p-2 pr-3 pl-3"
@click="setShowDate($refs.header.headerProps.nextPeriod)"></b-button>
</b-button-group>
</b-button-toolbar>
</div>
</div>
<div class="col-12 mt-2" style="padding-bottom: 60px">
<div v-for="day in mobileSimpleGrid" v-bind:key="day.day">
<b-list-group>
<b-list-group-item>
<div class="d-flex flex-row align-middle">
<h6 class="mb-0 mt-1 align-middle">{{ day.date_label }}</h6>
<div class="flex-grow-1 text-right">
<b-button class="btn-sm btn-outline-primary" @click="showMealPlanEditModal(null, day.create_default_date)"><i
class="fa fa-plus"></i></b-button>
</div>
</div>
<hr/>
<button class="btn btn-success shadow-none mt-1 btn-block" @click="createEntryClick(new Date())"><i
class="fas fa-calendar-plus"></i> {{ $t("Create") }}
</button>
<button class="btn btn-warning shadow-none mt-1 btn-block" @click="createAutoPlan(new Date())"><i
class="fas fa-calendar-plus"></i> {{ $t("Auto_Planner") }}
</button>
<a class="btn btn-primary shadow-none mt-1 btn-blockmt-1 btn-block" :href="iCalUrl"><i class="fas fa-download"></i>
{{ $t("Export_To_ICal") }}
</a>
</b-list-group-item>
<b-list-group-item v-for="plan in day.plan_entries" v-bind:key="plan.entry.id">
<div class="d-flex flex-row align-items-center">
<div>
<b-img style="height: 50px; width: 50px; object-fit: cover"
:src="plan.entry.recipe.image" rounded="circle" v-if="plan.entry.recipe?.image"></b-img>
<b-img style="height: 50px; width: 50px; object-fit: cover"
:src="image_placeholder" rounded="circle" v-else></b-img>
</div>
<div class="flex-grow-1 ml-2"
style="text-overflow: ellipsis; overflow-wrap: anywhere;">
<a class="btn btn-info shadow-none mt-1 btn-block" :href="resolveDjangoUrl('view_settings')">
<i class="fas fa-cogs"></i> {{ $t("Settings") }}
</a>
</div>
<div class="col col-10">
<div class="row calender-row ">
<div class="col-12 calender-parent">
<calendar-view
:show-date="showDate"
:enable-date-selection="true"
class="theme-default"
:items="plan_items"
:display-period-uom="settings.displayPeriodUom"
:period-changed-callback="periodChangedCallback"
:enable-drag-drop="true"
:item-content-height="item_height"
@click-date="createEntryClick"
@drop-on-date="moveEntry"
:display-period-count="settings.displayPeriodCount"
:starting-day-of-week="settings.startingDayOfWeek"
:display-week-numbers="settings.displayWeekNumbers"
>
<template #item="{ value, weekStartDate, top }">
<meal-plan-card
:value="value"
:week-start-date="weekStartDate"
:top="top"
:detailed="detailed_items"
:item_height="item_height"
@dragstart="dragged_item = value"
@click-item="entryClick"
@open-context-menu="openContextMenu"
/>
</template>
<template #header="{ headerProps }">
<meal-plan-calender-header
ref="header"
:header-props="headerProps"
@input="setShowDate"
@delete-dragged="deleteEntry(dragged_item)"
@create-new="createEntryClick(new Date())"
@set-starting-day-back="setStartingDay(-1)"
@set-starting-day-forward="setStartingDay(1)"
:i-cal-url="iCalUrl"
:options="options"
:settings_prop="settings"
/>
</template>
</calendar-view>
</div>
</div>
</div>
</div>
</div>
<div class="row d-block d-lg-none">
<div class="row">
<div class="col">
<div class="">
<div>
<div class="col-12">
<div class="col-12 d-flex justify-content-center mt-2">
<b-button-toolbar key-nav aria-label="Toolbar with button groups">
<b-button-group class="mx-1">
<b-button v-html="'<<'" class="p-2 pr-3 pl-3"
@click="setShowDate($refs.header.headerProps.previousPeriod)"></b-button>
</b-button-group>
<b-button-group class="mx-1">
<b-button @click="setShowDate($refs.header.headerProps.currentPeriod)"><i
class="fas fa-home"></i></b-button>
<b-form-datepicker right button-only button-variant="secondary" @context="datePickerChanged"></b-form-datepicker>
</b-button-group>
<b-button-group class="mx-1">
<b-button v-html="'>>'" class="p-2 pr-3 pl-3"
@click="setShowDate($refs.header.headerProps.nextPeriod)"></b-button>
</b-button-group>
</b-button-toolbar>
</div>
</div>
<div class="col-12 mt-2" style="padding-bottom: 60px">
<div v-for="day in mobileSimpleGrid" v-bind:key="day.day">
<b-list-group>
<b-list-group-item>
<div class="d-flex flex-row align-middle">
<h6 class="mb-0 mt-1 align-middle">{{ day.date_label }}</h6>
<div class="flex-grow-1 text-right">
<b-button class="btn-sm btn-outline-primary" @click="showMealPlanEditModal(null, day.create_default_date)"><i
class="fa fa-plus"></i></b-button>
</div>
</div>
</b-list-group-item>
<b-list-group-item v-for="plan in day.plan_entries" v-bind:key="plan.entry.id">
<div class="d-flex flex-row align-items-center">
<div>
<b-img style="height: 50px; width: 50px; object-fit: cover"
:src="plan.entry.recipe.image" rounded="circle" v-if="plan.entry.recipe?.image"></b-img>
<b-img style="height: 50px; width: 50px; object-fit: cover"
:src="image_placeholder" rounded="circle" v-else></b-img>
</div>
<div class="flex-grow-1 ml-2"
style="text-overflow: ellipsis; overflow-wrap: anywhere;">
<span class="two-row-text">
<a :href="resolveDjangoUrl('view_recipe', plan.entry.recipe.id)" v-if="plan.entry.recipe">{{ plan.entry.recipe.name }}</a>
<span v-else>{{ plan.entry.title }}</span> <br/>
</span>
<span v-if="plan.entry.note" class="two-row-text">
<span v-if="plan.entry.note" class="two-row-text">
<small>{{ plan.entry.note }}</small> <br/>
</span>
<small class="text-muted">
<span v-if="plan.entry.shopping" class="font-light"><i class="fas fa-shopping-cart fa-xs "/></span>
{{ plan.entry.meal_type_name }}
<span v-if="plan.entry.recipe">
<small class="text-muted">
<span v-if="plan.entry.shopping" class="font-light"><i class="fas fa-shopping-cart fa-xs "/></span>
{{ plan.entry.meal_type_name }}
<span v-if="plan.entry.recipe">
- <i class="fa fa-clock"></i> {{ plan.entry.recipe.working_time + plan.entry.recipe.waiting_time }} {{ $t('min') }}
</span>
</small>
</div>
<div class="hover-button">
<a class="pr-2" @click.stop="openContextMenu($event, {originalItem: plan})"><i class="fas fa-ellipsis-v"></i></a>
</div>
</div>
</b-list-group-item>
</b-list-group>
</div>
</div>
</small>
</div>
<div class="hover-button">
<a class="pr-2" @click.stop="openContextMenu($event, {originalItem: plan})"><i class="fas fa-ellipsis-v"></i></a>
</div>
</div>
</b-list-group-item>
</b-list-group>
</div>
</div>
</div>
</div>
</div>
</b-tab>
<b-tab :title="$t('Settings')">
<div class="row mt-3">
<div class="col-12 col-md-9 col-lg-6">
<h5>{{ $t("Meal_Types") }}</h5>
<div>
<draggable :list="meal_types" group="meal_types" :empty-insert-threshold="10"
@sort="sortMealTypes()" ghost-class="ghost">
<b-card no-body class="mt-1 list-group-item p-2" style="cursor: move"
v-for="(meal_type, index) in meal_types" v-hover :key="meal_type.id">
<b-card-header class="p-2 border-0">
<div class="row">
<div class="col-2">
<button type="button" class="btn btn-lg shadow-none"><i
class="fas fa-arrows-alt-v"></i></button>
</div>
<div class="col-10">
<h5 class="mt-1 mb-1">
{{ meal_type.name }}<span class="float-right text-primary" style="cursor: pointer"
><i class="fa"
v-bind:class="{ 'fa-pen': !meal_type.editing, 'fa-save': meal_type.editing }"
@click="editOrSaveMealType(index)" aria-hidden="true"></i
></span>
</h5>
</div>
</div>
</b-card-header>
<b-card-body class="p-4" v-if="meal_type.editing">
<div class="form-group">
<label>{{ $t("Name") }}</label>
<input class="form-control" :placeholder="$t('Name')"
v-model="meal_type.name"/>
</div>
<div class="form-group">
<label>{{ $t("Color") }}</label>
<input class="form-control" type="color" name="Name"
:value="meal_type.color"
@change="meal_type.color = $event.target.value"/>
</div>
<b-form-checkbox id="checkbox-1" v-model="meal_type.default"
name="default_checkbox" class="mb-2">
{{ $t("Default") }}
</b-form-checkbox>
<button class="btn btn-danger" @click="deleteMealType(index)">{{
$t("Delete")
}}
</button>
<button class="btn btn-primary float-right" @click="editOrSaveMealType(index)">
{{ $t("Save") }}
</button>
</b-card-body>
</b-card>
</draggable>
<button class="btn btn-success float-right mt-1" @click="newMealType">
<i class="fas fa-plus"></i>
{{ $t("New_Meal_Type") }}
</button>
</div>
</div>
</div>
</b-tab>
</b-tabs>
</div>
</div>
<ContextMenu ref="menu">
<template #menu="{ contextData }">
<ContextMenuItem
@@ -336,7 +282,6 @@ export default {
ContextMenu,
ContextMenuItem,
MealPlanCalenderHeader,
draggable,
BottomNavigationBar,
},
mixins: [CalendarMathMixin, ApiMixin, ResolveUrlMixin],
@@ -362,7 +307,6 @@ export default {
displayWeekNumbers: true,
},
dragged_item: null,
current_tab: 0,
meal_types: [],
current_context_menu_item: null,
options: {
@@ -404,7 +348,7 @@ export default {
},
item_height: function () {
if (this.settings.displayPeriodUom === "week") {
return "10rem"
return "3rem"
} else {
return "1.6rem"
}
@@ -428,7 +372,7 @@ export default {
date: moment_date,
create_default_date: moment_date.format("YYYY-MM-DD"), // improve meal plan edit modal to do formatting itself and accept dates
date_label: moment_date.format('ddd DD.MM'),
plan_entries: this.plan_items.filter((m) => moment(m.startDate).isSame(moment_date, 'day'))
plan_entries: this.plan_items.filter((m) => moment_date.isBetween(moment(m.startDate), moment(m.endDate), 'day', '[]'))
})
}
}
@@ -436,18 +380,14 @@ export default {
}
},
mounted() {
this.$nextTick(function () {
if (this.$cookies.isKey(SETTINGS_COOKIE_NAME)) {
this.settings = Object.assign({}, this.settings, this.$cookies.get(SETTINGS_COOKIE_NAME))
}
})
this.settings = useMealPlanStore().client_settings
this.$i18n.locale = window.CUSTOM_LOCALE
moment.locale(window.CUSTOM_LOCALE)
},
watch: {
settings: {
handler() {
this.$cookies.set(SETTINGS_COOKIE_NAME, this.settings, "360d")
useMealPlanStore().updateClientSettings(this.settings)
},
deep: true,
},
@@ -554,12 +494,16 @@ export default {
moveEntry(null_object, target_date, drag_event) {
useMealPlanStore().plan_list.forEach((entry) => {
if (entry.id === this.dragged_item.id) {
let fromToDiff = Math.abs(moment(entry.to_date).diff(moment(entry.from_date), 'days'))
if (drag_event.ctrlKey) {
let new_entry = Object.assign({}, entry)
new_entry.date = target_date
new_entry.from_date = target_date
new_entry.to_date = moment(target_date).add(fromToDiff, 'd')
this.createEntry(new_entry)
} else {
entry.date = target_date
entry.from_date = target_date
entry.to_date = moment(target_date).add(fromToDiff, 'd')
this.saveEntry(entry)
}
}
@@ -568,7 +512,8 @@ export default {
moveEntryLeft(data) {
useMealPlanStore().plan_list.forEach((entry) => {
if (entry.id === data.id) {
entry.date = moment(entry.date).subtract(1, "d")
entry.from_date = moment(entry.from_date).subtract(1, "d")
entry.to_date = moment(entry.to_date).subtract(1, "d")
this.saveEntry(entry)
}
})
@@ -576,7 +521,8 @@ export default {
moveEntryRight(data) {
useMealPlanStore().plan_list.forEach((entry) => {
if (entry.id === data.id) {
entry.date = moment(entry.date).add(1, "d")
entry.from_date = moment(entry.from_date).add(1, "d")
entry.to_date = moment(entry.to_date).add(1, "d")
this.saveEntry(entry)
}
})
@@ -594,7 +540,8 @@ export default {
openEntryEdit(entry) {
this.$bvModal.show(`id_meal_plan_edit_modal`)
this.entryEditing = entry
this.entryEditing.date = moment(entry.date).format("YYYY-MM-DD")
this.entryEditing.from_date = moment(entry.from_date).format("YYYY-MM-DD")
this.entryEditing.to_date = moment(entry.to_date).format("YYYY-MM-DD")
if (this.entryEditing.recipe != null) {
this.entryEditing.title_placeholder = this.entryEditing.recipe.name
}
@@ -617,21 +564,32 @@ export default {
})
},
saveEntry(entry) {
entry.date = moment(entry.date).format("YYYY-MM-DD")
entry.from_date = moment(entry.from_date).format("YYYY-MM-DD")
entry.to_date = moment(entry.to_date).format("YYYY-MM-DD")
if (entry.from_date > entry.to_date) {
StandardToasts.makeStandardToast(this, StandardToasts.FAIL_UPDATE)
entry.to_date = entry.from_date
} else {
useMealPlanStore().updateObject(entry)
}
useMealPlanStore().updateObject(entry)
},
createEntry(entry) {
entry.date = moment(entry.date).format("YYYY-MM-DD")
entry.from_date = moment(entry.from_date).format("YYYY-MM-DD")
entry.to_date = moment(entry.to_date).format("YYYY-MM-DD")
useMealPlanStore().createObject(entry)
},
buildItem(plan_entry) {
//dirty hack to order items within a day
let date = moment(plan_entry.date).add(plan_entry.meal_type.order, "m")
let from_date = moment(plan_entry.from_date).add(plan_entry.meal_type.order, "m")
let to_date = moment(plan_entry.to_date).add(plan_entry.meal_type.order, "m")
return {
id: plan_entry.id,
startDate: date,
endDate: date,
startDate: from_date,
endDate: to_date,
entry: plan_entry,
}
},
@@ -684,7 +642,7 @@ export default {
}
.calender-row {
height: calc(100vh - 240px);
height: calc(100vh - 140px);
}
.calender-parent {

View File

@@ -723,9 +723,9 @@
<div class="row">
<div class="col col-md-12">
<div
style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); column-gap: 0.5rem; row-gap: 0.5rem; grid-auto-rows: max-content"
>
<div v-for="day in meal_plan_grid" v-bind:key="day.day" :class="{ 'd-none d-sm-block': day.plan_entries.length === 0 }">
style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); column-gap: 0.5rem;row-gap: 0.5rem; grid-auto-rows: max-content; ">
<div v-for="day in meal_plan_grid" v-bind:key="day.day" :class="{'d-none d-sm-block': day.plan_entries.length === 0}">
<b-list-group>
<b-list-group-item class="hover-div pb-0">
<div class="d-flex flex-row align-items-center">
@@ -739,16 +739,13 @@
</div>
</div>
</b-list-group-item>
<b-list-group-item v-for="plan in day.plan_entries" v-bind:key="plan.id" class="hover-div">
<b-list-group-item v-for="plan in day.plan_entries" v-bind:key="plan.id" class="hover-div p-0 pr-2">
<div class="d-flex flex-row align-items-center">
<div>
<b-img
style="height: 50px; width: 50px; object-fit: cover"
:src="plan.recipe.image"
rounded="circle"
v-if="plan.recipe?.image"
></b-img>
<b-img style="height: 50px; width: 50px; object-fit: cover" :src="image_placeholder" rounded="circle" v-else></b-img>
<img style="height: 50px; width: 50px; object-fit: cover" :src="plan.recipe.image" v-if="plan.recipe?.image"/>
<img style="height: 50px; width: 50px; object-fit: cover" :src="image_placeholder" v-else/>
</div>
<div class="flex-grow-1 ml-2" style="text-overflow: ellipsis; overflow-wrap: anywhere">
<span class="two-row-text">
@@ -986,8 +983,8 @@ export default {
grid.push({
date: moment_date,
create_default_date: moment_date.format("YYYY-MM-DD"), // improve meal plan edit modal to do formatting itself and accept dates
date_label: moment_date.format("ddd DD.MM"),
plan_entries: this.meal_plan_store.plan_list.filter((m) => moment(m.date).isSame(moment_date, "day")),
date_label: moment_date.format('ddd DD.MM'),
plan_entries: this.meal_plan_store.plan_list.filter((m) => moment_date.isBetween(moment(m.from_date), moment(m.to_date), 'day', '[]'))
})
}
}
@@ -1204,22 +1201,6 @@ export default {
console.log("loadMealpLan")
this.meal_plan_store = useMealPlanStore()
this.meal_plan_store.refreshFromAPI(moment().format("YYYY-MM-DD"), moment().add(this.ui.meal_plan_days, "days").format("YYYY-MM-DD"))
// if (this.ui.show_meal_plan) {
// let params = {
// options: {
// query: {
// from_date: moment().format("YYYY-MM-DD"),
// to_date: moment().add(this.ui.meal_plan_days, "days").format("YYYY-MM-DD"),
// },
// },
// }
// this.genericAPI(this.Models.MEAL_PLAN, this.Actions.LIST, params).then((result) => {
// this.meal_plans = result.data
// })
// } else {
// this.meal_plans = []
// }
},
genericSelectChanged: function (obj) {
if (obj.var.includes("::")) {