Feature/UI updates (#990)
* titleCase utility * update rules ui * order by date_added * fix error on page refresh * fix health checks * fix cookbook return values
This commit is contained in:
parent
177a430d8c
commit
2211174636
6 changed files with 43 additions and 20 deletions
|
@ -131,7 +131,7 @@ ENV APP_PORT=9000
|
|||
|
||||
EXPOSE ${APP_PORT}
|
||||
|
||||
HEALTHCHECK CMD curl -f http://localhost:${APP_PORT} || exit 1
|
||||
HEALTHCHECK CMD curl -f http://localhost:${APP_PORT}/docs || exit 1
|
||||
|
||||
RUN chmod +x $MEALIE_HOME/mealie/run.sh
|
||||
ENTRYPOINT $MEALIE_HOME/mealie/run.sh
|
||||
|
|
|
@ -4,6 +4,13 @@ export const useAsyncKey = function () {
|
|||
return String(Date.now());
|
||||
};
|
||||
|
||||
export const titleCase = function (str: string) {
|
||||
return str
|
||||
.split(" ")
|
||||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(" ");
|
||||
};
|
||||
|
||||
export function detectServerBaseUrl(req?: IncomingMessage | null) {
|
||||
if (!req || req === undefined) {
|
||||
return "";
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<v-img max-height="100" max-width="100" :src="require('~/static/svgs/manage-cookbooks.svg')"></v-img>
|
||||
</template>
|
||||
<template #title> Meal Plan Rules </template>
|
||||
Here you can set rules for auto selecting recipes for you meal plans. These rules are used by the server to
|
||||
You can create rules for auto selecting recipes for you meal plans. These rules are used by the server to
|
||||
determine the random pool of recipes to select from when creating meal plans. Note that if rules have the same
|
||||
day/type constraints then the categories of the rules will be merged. In practice, it's unnecessary to create
|
||||
duplicate rules, but it's possible to do so.
|
||||
|
@ -36,9 +36,10 @@
|
|||
<BaseCardSectionTitle class="mt-10" title="Recipe Rules" />
|
||||
<div>
|
||||
<div v-for="(rule, idx) in allRules" :key="rule.id">
|
||||
<v-card class="my-2">
|
||||
<v-card-title>
|
||||
{{ rule.day }} - {{ rule.entryType }}
|
||||
<v-card class="my-2 left-border">
|
||||
<v-card-title class="headline pb-1">
|
||||
{{ rule.day === "unset" ? "Applies to all days" : `Applies on ${rule.day}s` }}
|
||||
{{ rule.entryType === "unset" ? "for all meal types" : ` for ${rule.entryType} meal types` }}
|
||||
<span class="ml-auto">
|
||||
<BaseButtonGroup
|
||||
:buttons="[
|
||||
|
@ -60,8 +61,15 @@
|
|||
</v-card-title>
|
||||
<v-card-text>
|
||||
<template v-if="!editState[rule.id]">
|
||||
<div>Categories: {{ rule.categories.map((c) => c.name).join(", ") }}</div>
|
||||
<div>Tags: {{ rule.tags.map((t) => t.name).join(", ") }}</div>
|
||||
<div v-if="rule.categories">
|
||||
<h4 class="py-1">{{ $t("category.categories") }}:</h4>
|
||||
<RecipeChips :items="rule.categories" is-category small />
|
||||
</div>
|
||||
|
||||
<div v-if="rule.tags">
|
||||
<h4 class="py-1">{{ $t("tag.tags") }}:</h4>
|
||||
<RecipeChips :items="rule.tags" :is-category="false" small />
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<GroupMealPlanRuleForm
|
||||
|
@ -88,10 +96,12 @@ import { useUserApi } from "~/composables/api";
|
|||
import { PlanRulesCreate, PlanRulesOut } from "~/types/api-types/meal-plan";
|
||||
import GroupMealPlanRuleForm from "~/components/Domain/Group/GroupMealPlanRuleForm.vue";
|
||||
import { useAsyncKey } from "~/composables/use-utils";
|
||||
import RecipeChips from "~/components/Domain/Recipe/RecipeChips.vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
GroupMealPlanRuleForm,
|
||||
RecipeChips,
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
|
|
|
@ -217,7 +217,7 @@
|
|||
<!-- Debug Extras -->
|
||||
<section v-if="debugData && tab === 'debug'">
|
||||
<v-checkbox v-model="debugTreeView" label="Tree View"></v-checkbox>
|
||||
<VJsoneditor
|
||||
<LazyRecipeJsonEditor
|
||||
v-model="debugData"
|
||||
class="primary"
|
||||
:options="{
|
||||
|
@ -322,11 +322,9 @@ import {
|
|||
useRouter,
|
||||
useContext,
|
||||
computed,
|
||||
useRoute
|
||||
useRoute,
|
||||
} from "@nuxtjs/composition-api";
|
||||
import { AxiosResponse } from "axios";
|
||||
// @ts-ignore No Types for v-jsoneditor
|
||||
import VJsoneditor from "v-jsoneditor";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import RecipeCategoryTagSelector from "~/components/Domain/Recipe/RecipeCategoryTagSelector.vue";
|
||||
import { validators } from "~/composables/use-validators";
|
||||
|
@ -336,7 +334,7 @@ import { VForm } from "~/types/vuetify";
|
|||
import { MenuItem } from "~/components/global/BaseOverflowButton.vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: { VJsoneditor, RecipeCategoryTagSelector },
|
||||
components: { RecipeCategoryTagSelector },
|
||||
setup() {
|
||||
const state = reactive({
|
||||
error: false,
|
||||
|
@ -397,7 +395,7 @@ export default defineComponent({
|
|||
|
||||
const recipeUrl = computed({
|
||||
set(recipe_import_url: string) {
|
||||
recipe_import_url = recipe_import_url.trim()
|
||||
recipe_import_url = recipe_import_url.trim();
|
||||
router.replace({ query: { ...route.value.query, recipe_import_url } });
|
||||
},
|
||||
get() {
|
||||
|
@ -516,7 +514,6 @@ export default defineComponent({
|
|||
});
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
.force-white > a {
|
||||
color: white !important;
|
||||
|
|
|
@ -84,6 +84,7 @@ class RepositoryRecipes(RepositoryGeneric[Recipe, RecipeModel]):
|
|||
self.session.query(RecipeModel)
|
||||
.options(*args)
|
||||
.filter(RecipeModel.group_id == group_id)
|
||||
.order_by(RecipeModel.date_added.desc())
|
||||
.offset(start)
|
||||
.limit(limit)
|
||||
.all()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from functools import cached_property
|
||||
from typing import Type
|
||||
|
||||
from fastapi import APIRouter
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.core.exceptions import mealie_registered_exceptions
|
||||
|
@ -9,10 +9,15 @@ from mealie.routes._base import BaseUserController, controller
|
|||
from mealie.routes._base.mixins import CrudMixins
|
||||
from mealie.schema import mapper
|
||||
from mealie.schema.cookbook import CreateCookBook, ReadCookBook, RecipeCookBook, SaveCookBook, UpdateCookBook
|
||||
from mealie.schema.recipe.recipe_category import RecipeCategoryResponse
|
||||
|
||||
router = APIRouter(prefix="/groups/cookbooks", tags=["Groups: Cookbooks"])
|
||||
|
||||
|
||||
class CookBookRecipeResponse(RecipeCookBook):
|
||||
categories: list[RecipeCategoryResponse]
|
||||
|
||||
|
||||
@controller(router)
|
||||
class GroupCookbookController(BaseUserController):
|
||||
@cached_property
|
||||
|
@ -54,12 +59,15 @@ class GroupCookbookController(BaseUserController):
|
|||
|
||||
return updated
|
||||
|
||||
@router.get("/{item_id}", response_model=RecipeCookBook)
|
||||
@router.get("/{item_id}", response_model=CookBookRecipeResponse)
|
||||
def get_one(self, item_id: UUID4 | str):
|
||||
if isinstance(item_id, str):
|
||||
self.mixins.get_one(item_id, key="slug")
|
||||
else:
|
||||
return self.mixins.get_one(item_id)
|
||||
match_attr = "slug" if isinstance(item_id, str) else "id"
|
||||
book = self.repo.get_one(item_id, match_attr, override_schema=CookBookRecipeResponse)
|
||||
|
||||
if book is None:
|
||||
raise HTTPException(status_code=404)
|
||||
|
||||
return book
|
||||
|
||||
@router.put("/{item_id}", response_model=RecipeCookBook)
|
||||
def update_one(self, item_id: str, data: CreateCookBook):
|
||||
|
|
Loading…
Reference in a new issue