added multi day meal planning
This commit is contained in:
parent
65d670a995
commit
94f398a7f6
@ -277,7 +277,7 @@ admin.site.register(RecipeBookEntry, RecipeBookEntryAdmin)
|
|||||||
|
|
||||||
|
|
||||||
class MealPlanAdmin(admin.ModelAdmin):
|
class MealPlanAdmin(admin.ModelAdmin):
|
||||||
list_display = ('user', 'recipe', 'meal_type', 'date')
|
list_display = ('user', 'recipe', 'meal_type', 'from_date', 'to_date')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def user(obj):
|
def user(obj):
|
||||||
|
@ -326,49 +326,6 @@ class ImportRecipeForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
# TODO deprecate
|
# TODO deprecate
|
||||||
class MealPlanForm(forms.ModelForm):
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
space = kwargs.pop('space')
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.fields['recipe'].queryset = Recipe.objects.filter(space=space).all()
|
|
||||||
self.fields['meal_type'].queryset = MealType.objects.filter(space=space).all()
|
|
||||||
self.fields['shared'].queryset = User.objects.filter(userpreference__space=space).all()
|
|
||||||
|
|
||||||
def clean(self):
|
|
||||||
cleaned_data = super(MealPlanForm, self).clean()
|
|
||||||
|
|
||||||
if cleaned_data['title'] == '' and cleaned_data['recipe'] is None:
|
|
||||||
raise forms.ValidationError(
|
|
||||||
_('You must provide at least a recipe or a title.')
|
|
||||||
)
|
|
||||||
|
|
||||||
return cleaned_data
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = MealPlan
|
|
||||||
fields = (
|
|
||||||
'recipe', 'title', 'meal_type', 'note',
|
|
||||||
'servings', 'date', 'shared'
|
|
||||||
)
|
|
||||||
|
|
||||||
help_texts = {
|
|
||||||
'shared': _('You can list default users to share recipes with in the settings.'),
|
|
||||||
'note': _('You can use markdown to format this field. See the <a href="/docs/markdown/">docs here</a>')
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
widgets = {
|
|
||||||
'recipe': SelectWidget,
|
|
||||||
'date': DateWidget,
|
|
||||||
'shared': MultiSelectWidget
|
|
||||||
}
|
|
||||||
field_classes = {
|
|
||||||
'recipe': SafeModelChoiceField,
|
|
||||||
'meal_type': SafeModelChoiceField,
|
|
||||||
'shared': SafeModelMultipleChoiceField,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class InviteLinkForm(forms.ModelForm):
|
class InviteLinkForm(forms.ModelForm):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
user = kwargs.pop('user')
|
user = kwargs.pop('user')
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
# Generated by Django 4.1.10 on 2023-09-08 12:20
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
from django.db.models import F
|
||||||
|
from django_scopes import scopes_disabled
|
||||||
|
|
||||||
|
|
||||||
|
def apply_migration(apps, schema_editor):
|
||||||
|
with scopes_disabled():
|
||||||
|
MealPlan = apps.get_model('cookbook', 'MealPlan')
|
||||||
|
MealPlan.objects.update(to_date=F('from_date'))
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
('cookbook', '0200_alter_propertytype_options_remove_keyword_icon_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='mealplan',
|
||||||
|
old_name='date',
|
||||||
|
new_name='from_date',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mealplan',
|
||||||
|
name='to_date',
|
||||||
|
field=models.DateField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.RunPython(apply_migration),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='mealplan',
|
||||||
|
name='to_date',
|
||||||
|
field=models.DateField(),
|
||||||
|
),
|
||||||
|
]
|
@ -993,7 +993,8 @@ class MealPlan(ExportModelOperationsMixin('meal_plan'), models.Model, Permission
|
|||||||
shared = models.ManyToManyField(User, blank=True, related_name='plan_share')
|
shared = models.ManyToManyField(User, blank=True, related_name='plan_share')
|
||||||
meal_type = models.ForeignKey(MealType, on_delete=models.CASCADE)
|
meal_type = models.ForeignKey(MealType, on_delete=models.CASCADE)
|
||||||
note = models.TextField(blank=True)
|
note = models.TextField(blank=True)
|
||||||
date = models.DateField()
|
from_date = models.DateField()
|
||||||
|
to_date = models.DateField()
|
||||||
|
|
||||||
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
||||||
objects = ScopedManager(space='space')
|
objects = ScopedManager(space='space')
|
||||||
@ -1007,7 +1008,7 @@ class MealPlan(ExportModelOperationsMixin('meal_plan'), models.Model, Permission
|
|||||||
return self.meal_type.name
|
return self.meal_type.name
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f'{self.get_label()} - {self.date} - {self.meal_type.name}'
|
return f'{self.get_label()} - {self.from_date} - {self.meal_type.name}'
|
||||||
|
|
||||||
|
|
||||||
class ShoppingListRecipe(ExportModelOperationsMixin('shopping_list_recipe'), models.Model, PermissionModelMixin):
|
class ShoppingListRecipe(ExportModelOperationsMixin('shopping_list_recipe'), models.Model, PermissionModelMixin):
|
||||||
|
@ -449,7 +449,7 @@ class KeywordSerializer(UniqueFieldsMixin, ExtendedRecipeMixin):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = Keyword
|
model = Keyword
|
||||||
fields = (
|
fields = (
|
||||||
'id', 'name', 'label', 'description', 'image', 'parent', 'numchild', 'numrecipe', 'created_at',
|
'id', 'name', 'label', 'description', 'image', 'parent', 'numchild', 'numrecipe', 'created_at',
|
||||||
'updated_at', 'full_name')
|
'updated_at', 'full_name')
|
||||||
read_only_fields = ('id', 'label', 'numchild', 'parent', 'image')
|
read_only_fields = ('id', 'label', 'numchild', 'parent', 'image')
|
||||||
|
|
||||||
@ -528,7 +528,7 @@ class PropertyTypeSerializer(OpenDataModelMixin, WritableNestedModelSerializer,
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = PropertyType
|
model = PropertyType
|
||||||
fields = ('id', 'name', 'unit', 'description', 'order', 'open_data_slug')
|
fields = ('id', 'name', 'unit', 'description', 'order', 'open_data_slug')
|
||||||
|
|
||||||
|
|
||||||
class PropertySerializer(UniqueFieldsMixin, WritableNestedModelSerializer):
|
class PropertySerializer(UniqueFieldsMixin, WritableNestedModelSerializer):
|
||||||
@ -995,7 +995,7 @@ class MealPlanSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
|
|||||||
model = MealPlan
|
model = MealPlan
|
||||||
fields = (
|
fields = (
|
||||||
'id', 'title', 'recipe', 'servings', 'note', 'note_markdown',
|
'id', 'title', 'recipe', 'servings', 'note', 'note_markdown',
|
||||||
'date', 'meal_type', 'created_by', 'shared', 'recipe_name',
|
'from_date', 'to_date', 'meal_type', 'created_by', 'shared', 'recipe_name',
|
||||||
'meal_type_name', 'shopping'
|
'meal_type_name', 'shopping'
|
||||||
)
|
)
|
||||||
read_only_fields = ('created_by',)
|
read_only_fields = ('created_by',)
|
||||||
|
@ -166,7 +166,7 @@ urlpatterns = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
generic_models = (
|
generic_models = (
|
||||||
Recipe, RecipeImport, Storage, RecipeBook, MealPlan, SyncLog, Sync,
|
Recipe, RecipeImport, Storage, RecipeBook, SyncLog, Sync,
|
||||||
Comment, RecipeBookEntry, ShoppingList, InviteLink, UserSpace, Space
|
Comment, RecipeBookEntry, ShoppingList, InviteLink, UserSpace, Space
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -662,11 +662,11 @@ class MealPlanViewSet(viewsets.ModelViewSet):
|
|||||||
|
|
||||||
from_date = self.request.query_params.get('from_date', None)
|
from_date = self.request.query_params.get('from_date', None)
|
||||||
if from_date is not None:
|
if from_date is not None:
|
||||||
queryset = queryset.filter(date__gte=from_date)
|
queryset = queryset.filter(to_date__gte=from_date)
|
||||||
|
|
||||||
to_date = self.request.query_params.get('to_date', None)
|
to_date = self.request.query_params.get('to_date', None)
|
||||||
if to_date is not None:
|
if to_date is not None:
|
||||||
queryset = queryset.filter(date__lte=to_date)
|
queryset = queryset.filter(to_date__lte=to_date)
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
@ -1673,8 +1673,11 @@ def get_plan_ical(request, from_date, to_date):
|
|||||||
for p in queryset:
|
for p in queryset:
|
||||||
event = Event()
|
event = Event()
|
||||||
event['uid'] = p.id
|
event['uid'] = p.id
|
||||||
event.add('dtstart', p.date)
|
event.add('dtstart', p.from_date)
|
||||||
event.add('dtend', p.date)
|
if p.to_date:
|
||||||
|
event.add('dtend', p.to_date)
|
||||||
|
else:
|
||||||
|
event.add('dtend', p.from_date)
|
||||||
event['summary'] = f'{p.meal_type.name}: {p.get_label()}'
|
event['summary'] = f'{p.meal_type.name}: {p.get_label()}'
|
||||||
event['description'] = p.note
|
event['description'] = p.note
|
||||||
cal.add_component(event)
|
cal.add_component(event)
|
||||||
|
@ -8,7 +8,7 @@ from django.utils.translation import gettext as _
|
|||||||
from django.views.generic import UpdateView
|
from django.views.generic import UpdateView
|
||||||
from django.views.generic.edit import FormMixin
|
from django.views.generic.edit import FormMixin
|
||||||
|
|
||||||
from cookbook.forms import CommentForm, ExternalRecipeForm, MealPlanForm, StorageForm, SyncForm
|
from cookbook.forms import CommentForm, ExternalRecipeForm, StorageForm, SyncForm
|
||||||
from cookbook.helper.permission_helper import GroupRequiredMixin, OwnerRequiredMixin, group_required, above_space_limit
|
from cookbook.helper.permission_helper import GroupRequiredMixin, OwnerRequiredMixin, group_required, above_space_limit
|
||||||
from cookbook.models import (Comment, MealPlan, MealType, Recipe, RecipeImport, Storage, Sync,
|
from cookbook.models import (Comment, MealPlan, MealType, Recipe, RecipeImport, Storage, Sync,
|
||||||
UserPreference)
|
UserPreference)
|
||||||
@ -192,26 +192,6 @@ class ImportUpdate(GroupRequiredMixin, UpdateView):
|
|||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class MealPlanUpdate(OwnerRequiredMixin, UpdateView, SpaceFormMixing):
|
|
||||||
template_name = "generic/edit_template.html"
|
|
||||||
model = MealPlan
|
|
||||||
form_class = MealPlanForm
|
|
||||||
|
|
||||||
def get_success_url(self):
|
|
||||||
return reverse('view_plan_entry', kwargs={'pk': self.object.pk})
|
|
||||||
|
|
||||||
def get_form(self, form_class=None):
|
|
||||||
form = self.form_class(**self.get_form_kwargs())
|
|
||||||
form.fields['meal_type'].queryset = MealType.objects \
|
|
||||||
.filter(created_by=self.request.user).all()
|
|
||||||
return form
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = super(MealPlanUpdate, self).get_context_data(**kwargs)
|
|
||||||
context['title'] = _("Meal-Plan")
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView, SpaceFormMixing):
|
class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView, SpaceFormMixing):
|
||||||
groups_required = ['user']
|
groups_required = ['user']
|
||||||
model = Recipe
|
model = Recipe
|
||||||
|
@ -12,7 +12,7 @@ from django.urls import reverse, reverse_lazy
|
|||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django.views.generic import CreateView
|
from django.views.generic import CreateView
|
||||||
|
|
||||||
from cookbook.forms import ImportRecipeForm, InviteLinkForm, MealPlanForm, Storage, StorageForm
|
from cookbook.forms import ImportRecipeForm, InviteLinkForm, Storage, StorageForm
|
||||||
from cookbook.helper.permission_helper import GroupRequiredMixin, group_required, above_space_limit
|
from cookbook.helper.permission_helper import GroupRequiredMixin, group_required, above_space_limit
|
||||||
from cookbook.models import (InviteLink, MealPlan, MealType, Recipe, RecipeBook, RecipeImport,
|
from cookbook.models import (InviteLink, MealPlan, MealType, Recipe, RecipeBook, RecipeImport,
|
||||||
ShareLink, Step, UserPreference, UserSpace)
|
ShareLink, Step, UserPreference, UserSpace)
|
||||||
@ -135,55 +135,3 @@ def create_new_external_recipe(request, import_id):
|
|||||||
return render(request, 'forms/edit_import_recipe.html', {'form': form})
|
return render(request, 'forms/edit_import_recipe.html', {'form': form})
|
||||||
|
|
||||||
|
|
||||||
class MealPlanCreate(GroupRequiredMixin, CreateView, SpaceFormMixing):
|
|
||||||
groups_required = ['user']
|
|
||||||
template_name = "generic/new_template.html"
|
|
||||||
model = MealPlan
|
|
||||||
form_class = MealPlanForm
|
|
||||||
success_url = reverse_lazy('view_plan')
|
|
||||||
|
|
||||||
def get_form(self, form_class=None):
|
|
||||||
form = self.form_class(**self.get_form_kwargs())
|
|
||||||
form.fields['meal_type'].queryset = MealType.objects.filter(created_by=self.request.user,
|
|
||||||
space=self.request.space).all()
|
|
||||||
return form
|
|
||||||
|
|
||||||
def get_initial(self):
|
|
||||||
return dict(
|
|
||||||
meal_type=(
|
|
||||||
self.request.GET['meal']
|
|
||||||
if 'meal' in self.request.GET
|
|
||||||
else None
|
|
||||||
),
|
|
||||||
date=(
|
|
||||||
datetime.strptime(self.request.GET['date'], '%Y-%m-%d')
|
|
||||||
if 'date' in self.request.GET
|
|
||||||
else None
|
|
||||||
),
|
|
||||||
shared=(
|
|
||||||
self.request.user.userpreference.plan_share.all()
|
|
||||||
if self.request.user.userpreference.plan_share
|
|
||||||
else None
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def form_valid(self, form):
|
|
||||||
obj = form.save(commit=False)
|
|
||||||
obj.created_by = self.request.user
|
|
||||||
obj.space = self.request.space
|
|
||||||
obj.save()
|
|
||||||
return HttpResponseRedirect(reverse('view_plan'))
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = super(MealPlanCreate, self).get_context_data(**kwargs)
|
|
||||||
context['title'] = _("Meal-Plan")
|
|
||||||
|
|
||||||
recipe = self.request.GET.get('recipe')
|
|
||||||
if recipe:
|
|
||||||
if re.match(r'^([0-9])+$', recipe):
|
|
||||||
if Recipe.objects.filter(pk=int(recipe), space=self.request.space).exists():
|
|
||||||
context['default_recipe'] = Recipe.objects.get(pk=int(recipe), space=self.request.space)
|
|
||||||
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class=" d-none d-lg-block">
|
<div class="d-none d-lg-block">
|
||||||
<div class="row">
|
<div class="row ">
|
||||||
<div class="col col-2">
|
<div class="col col-2">
|
||||||
<h4>{{ $t('Meal_Types') }}</h4>
|
<h4>{{ $t('Meal_Types') }}</h4>
|
||||||
|
|
||||||
@ -79,9 +79,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row d-block d-lg-none">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="row d-block d-lg-none">
|
<div class="">
|
||||||
<div>
|
<div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="col-12 d-flex justify-content-center mt-2">
|
<div class="col-12 d-flex justify-content-center mt-2">
|
||||||
@ -370,7 +372,7 @@ export default {
|
|||||||
date: moment_date,
|
date: moment_date,
|
||||||
create_default_date: moment_date.format("YYYY-MM-DD"), // improve meal plan edit modal to do formatting itself and accept dates
|
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'),
|
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', '[]'))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -496,12 +498,16 @@ export default {
|
|||||||
moveEntry(null_object, target_date, drag_event) {
|
moveEntry(null_object, target_date, drag_event) {
|
||||||
useMealPlanStore().plan_list.forEach((entry) => {
|
useMealPlanStore().plan_list.forEach((entry) => {
|
||||||
if (entry.id === this.dragged_item.id) {
|
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) {
|
if (drag_event.ctrlKey) {
|
||||||
let new_entry = Object.assign({}, entry)
|
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)
|
this.createEntry(new_entry)
|
||||||
} else {
|
} else {
|
||||||
entry.date = target_date
|
entry.from_date = target_date
|
||||||
|
entry.to_date = moment(target_date).add(fromToDiff, 'd')
|
||||||
this.saveEntry(entry)
|
this.saveEntry(entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -510,7 +516,8 @@ export default {
|
|||||||
moveEntryLeft(data) {
|
moveEntryLeft(data) {
|
||||||
useMealPlanStore().plan_list.forEach((entry) => {
|
useMealPlanStore().plan_list.forEach((entry) => {
|
||||||
if (entry.id === data.id) {
|
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)
|
this.saveEntry(entry)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -518,7 +525,8 @@ export default {
|
|||||||
moveEntryRight(data) {
|
moveEntryRight(data) {
|
||||||
useMealPlanStore().plan_list.forEach((entry) => {
|
useMealPlanStore().plan_list.forEach((entry) => {
|
||||||
if (entry.id === data.id) {
|
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)
|
this.saveEntry(entry)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -536,7 +544,8 @@ export default {
|
|||||||
openEntryEdit(entry) {
|
openEntryEdit(entry) {
|
||||||
this.$bvModal.show(`id_meal_plan_edit_modal`)
|
this.$bvModal.show(`id_meal_plan_edit_modal`)
|
||||||
this.entryEditing = entry
|
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) {
|
if (this.entryEditing.recipe != null) {
|
||||||
this.entryEditing.title_placeholder = this.entryEditing.recipe.name
|
this.entryEditing.title_placeholder = this.entryEditing.recipe.name
|
||||||
}
|
}
|
||||||
@ -559,21 +568,32 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
saveEntry(entry) {
|
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) {
|
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)
|
useMealPlanStore().createObject(entry)
|
||||||
},
|
},
|
||||||
buildItem(plan_entry) {
|
buildItem(plan_entry) {
|
||||||
//dirty hack to order items within a day
|
//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 {
|
return {
|
||||||
id: plan_entry.id,
|
id: plan_entry.id,
|
||||||
startDate: date,
|
startDate: from_date,
|
||||||
endDate: date,
|
endDate: to_date,
|
||||||
entry: plan_entry,
|
entry: plan_entry,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1102,7 +1102,7 @@ export default {
|
|||||||
date: moment_date,
|
date: moment_date,
|
||||||
create_default_date: moment_date.format("YYYY-MM-DD"), // improve meal plan edit modal to do formatting itself and accept dates
|
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'),
|
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'))
|
plan_entries: this.meal_plan_store.plan_list.filter((m) => moment_date.isBetween(moment(m.from_date), moment(m.to_date), 'day', '[]'))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1358,22 +1358,6 @@ export default {
|
|||||||
this.meal_plan_store = useMealPlanStore()
|
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"))
|
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) {
|
genericSelectChanged: function (obj) {
|
||||||
if (obj.var.includes("::")) {
|
if (obj.var.includes("::")) {
|
||||||
|
@ -6,14 +6,13 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col col-md-12">
|
<div class="col col-md-12">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-6 col-lg-9">
|
<div class="col-12">
|
||||||
<b-input-group>
|
<b-input-group>
|
||||||
<b-form-input id="TitleInput" v-model="entryEditing.title"
|
<b-form-input id="TitleInput" v-model="entryEditing.title"
|
||||||
:placeholder="entryEditing.title_placeholder"
|
:placeholder="entryEditing.title_placeholder"
|
||||||
@change="missing_recipe = false"></b-form-input>
|
@change="missing_recipe = false"></b-form-input>
|
||||||
<b-input-group-append class="d-none d-lg-block">
|
<b-input-group-append class="d-none d-lg-block">
|
||||||
<b-button variant="primary" @click="entryEditing.title = ''"><i
|
<b-button variant="primary" @click="entryEditing.title = ''"><i class="fa fa-eraser"></i></b-button>
|
||||||
class="fa fa-eraser"></i></b-button>
|
|
||||||
</b-input-group-append>
|
</b-input-group-append>
|
||||||
</b-input-group>
|
</b-input-group>
|
||||||
<span class="text-danger" v-if="missing_recipe">{{
|
<span class="text-danger" v-if="missing_recipe">{{
|
||||||
@ -23,13 +22,30 @@
|
|||||||
$t("Title")
|
$t("Title")
|
||||||
}}</small>
|
}}</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 col-lg-3">
|
<div class="col-12 col-lg-6">
|
||||||
<input type="date" id="DateInput" class="form-control" v-model="entryEditing.date"/>
|
<b-input-group>
|
||||||
<small tabindex="-1" class="form-text text-muted">{{ $t("Date") }}</small>
|
<b-form-input type="date" v-model="entryEditing.from_date"></b-form-input>
|
||||||
|
<b-input-group-append>
|
||||||
|
<b-button variant="secondary" @click="entryEditing.from_date = changeDate(entryEditing.from_date, -1)"><i class="fas fa-minus"></i></b-button>
|
||||||
|
<b-button variant="primary" @click="entryEditing.from_date = changeDate(entryEditing.from_date, 1)"><i class="fas fa-plus"></i></b-button>
|
||||||
|
</b-input-group-append>
|
||||||
|
</b-input-group>
|
||||||
|
|
||||||
|
<small tabindex="-1" class="form-text text-muted">{{ $t("StartDate") }}</small>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-lg-6">
|
||||||
|
<b-input-group>
|
||||||
|
<b-form-input type="date" v-model="entryEditing.to_date"></b-form-input>
|
||||||
|
<b-input-group-append>
|
||||||
|
<b-button variant="secondary" @click="entryEditing.to_date = changeDate(entryEditing.to_date, -1)"><i class="fas fa-minus"></i></b-button>
|
||||||
|
<b-button variant="primary" @click="entryEditing.to_date = changeDate(entryEditing.to_date, 1)"><i class="fas fa-plus"></i></b-button>
|
||||||
|
</b-input-group-append>
|
||||||
|
</b-input-group>
|
||||||
|
<small tabindex="-1" class="form-text text-muted">{{ $t("EndDate") }}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-3">
|
<div class="row">
|
||||||
<div class="col-12 col-lg-6 col-xl-6">
|
<div class="col-12">
|
||||||
<b-form-group>
|
<b-form-group>
|
||||||
<generic-multiselect
|
<generic-multiselect
|
||||||
@change="selectRecipe"
|
@change="selectRecipe"
|
||||||
@ -43,7 +59,11 @@
|
|||||||
></generic-multiselect>
|
></generic-multiselect>
|
||||||
<small tabindex="-1" class="form-text text-muted">{{ $t("Recipe") }}</small>
|
<small tabindex="-1" class="form-text text-muted">{{ $t("Recipe") }}</small>
|
||||||
</b-form-group>
|
</b-form-group>
|
||||||
<b-form-group class="mt-3">
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-lg-6 col-xl-6">
|
||||||
|
<b-form-group class="">
|
||||||
<generic-multiselect
|
<generic-multiselect
|
||||||
required
|
required
|
||||||
@change="selectMealType"
|
@change="selectMealType"
|
||||||
@ -142,6 +162,7 @@ const {ApiApiFactory} = require("@/utils/openapi/api")
|
|||||||
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
|
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
|
||||||
import {useMealPlanStore} from "@/stores/MealPlanStore";
|
import {useMealPlanStore} from "@/stores/MealPlanStore";
|
||||||
import ShoppingModal from "@/components/Modals/ShoppingModal.vue";
|
import ShoppingModal from "@/components/Modals/ShoppingModal.vue";
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
Vue.use(BootstrapVue)
|
Vue.use(BootstrapVue)
|
||||||
Vue.use(VueCookies)
|
Vue.use(VueCookies)
|
||||||
@ -221,7 +242,8 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.create_date) {
|
if (this.create_date) {
|
||||||
this.entryEditing.date = this.create_date
|
this.entryEditing.from_date = this.create_date
|
||||||
|
this.entryEditing.to_date = this.create_date
|
||||||
}
|
}
|
||||||
|
|
||||||
useUserPreferenceStore().getData().then(userPreference => {
|
useUserPreferenceStore().getData().then(userPreference => {
|
||||||
@ -290,6 +312,9 @@ export default {
|
|||||||
this.entryEditing.servings = 1
|
this.entryEditing.servings = 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
changeDate(date, change){
|
||||||
|
return moment(date).add(change, 'd').format("YYYY-MM-DD")
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -184,7 +184,7 @@ export default {
|
|||||||
localStorage.setItem("pinned_recipes", JSON.stringify(pinnedRecipes))
|
localStorage.setItem("pinned_recipes", JSON.stringify(pinnedRecipes))
|
||||||
},
|
},
|
||||||
saveMealPlan: function (entry) {
|
saveMealPlan: function (entry) {
|
||||||
entry.date = moment(entry.date).format("YYYY-MM-DD")
|
entry.from_date = moment(entry.from_date).format("YYYY-MM-DD")
|
||||||
let reviewshopping = entry.addshopping && entry.reviewshopping
|
let reviewshopping = entry.addshopping && entry.reviewshopping
|
||||||
entry.addshopping = entry.addshopping && !entry.reviewshopping
|
entry.addshopping = entry.addshopping && !entry.reviewshopping
|
||||||
|
|
||||||
@ -208,7 +208,7 @@ export default {
|
|||||||
createMealPlan(data) {
|
createMealPlan(data) {
|
||||||
this.entryEditing = this.options.entryEditing
|
this.entryEditing = this.options.entryEditing
|
||||||
this.entryEditing.recipe = this.recipe
|
this.entryEditing.recipe = this.recipe
|
||||||
this.entryEditing.date = moment(new Date()).format("YYYY-MM-DD")
|
this.entryEditing.from_date = moment(new Date()).format("YYYY-MM-DD")
|
||||||
this.$nextTick(function () {
|
this.$nextTick(function () {
|
||||||
this.$bvModal.show(`modal-meal-plan_${this.modal_id}`)
|
this.$bvModal.show(`modal-meal-plan_${this.modal_id}`)
|
||||||
})
|
})
|
||||||
|
@ -101,6 +101,8 @@
|
|||||||
"Energy": "Energy",
|
"Energy": "Energy",
|
||||||
"Nutrition": "Nutrition",
|
"Nutrition": "Nutrition",
|
||||||
"Date": "Date",
|
"Date": "Date",
|
||||||
|
"StartDate": "Start Date",
|
||||||
|
"EndDate": "End Date",
|
||||||
"Share": "Share",
|
"Share": "Share",
|
||||||
"Automation": "Automation",
|
"Automation": "Automation",
|
||||||
"Parameter": "Parameter",
|
"Parameter": "Parameter",
|
||||||
|
@ -29,7 +29,8 @@ export const useMealPlanStore = defineStore(_STORE_ID, {
|
|||||||
},
|
},
|
||||||
empty_meal_plan: function () {
|
empty_meal_plan: function () {
|
||||||
return {
|
return {
|
||||||
date: null,
|
from_date: null,
|
||||||
|
to_date: null,
|
||||||
id: -1,
|
id: -1,
|
||||||
meal_type: null,
|
meal_type: null,
|
||||||
note: "",
|
note: "",
|
||||||
|
@ -1812,7 +1812,13 @@ export interface MealPlan {
|
|||||||
* @type {string}
|
* @type {string}
|
||||||
* @memberof MealPlan
|
* @memberof MealPlan
|
||||||
*/
|
*/
|
||||||
date: string;
|
from_date: string;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
* @memberof MealPlan
|
||||||
|
*/
|
||||||
|
to_date?: string | null;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {MealPlanMealType}
|
* @type {MealPlanMealType}
|
||||||
|
Loading…
Reference in New Issue
Block a user