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:
Hayden 2022-02-22 15:32:13 -09:00 committed by GitHub
parent 177a430d8c
commit 2211174636
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 43 additions and 20 deletions

View file

@ -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

View file

@ -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 "";

View file

@ -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: {

View file

@ -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;

View file

@ -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()

View file

@ -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):