Merge remote-tracking branch 'upstream/dev' into locale-settings

This commit is contained in:
Florian Dupret 2021-04-17 09:22:34 +02:00
commit dbe510df72
15 changed files with 159 additions and 55 deletions

View file

@ -17,7 +17,7 @@
<v-text-field <v-text-field
autofocus autofocus
v-model="page.name" v-model="page.name"
label="Page Name" :label="$t('settings.page-name')"
></v-text-field> ></v-text-field>
<CategoryTagSelector <CategoryTagSelector
v-model="page.categories" v-model="page.categories"

View file

@ -3,10 +3,10 @@
<CreatePageDialog ref="createDialog" @refresh-page="getPages" /> <CreatePageDialog ref="createDialog" @refresh-page="getPages" />
<v-card-text> <v-card-text>
<h2 class="mt-1 mb-1 "> <h2 class="mt-1 mb-1 ">
Custom Pages {{$t('settings.custom-pages')}}
<span> <span>
<v-btn color="success" @click="newPage" small class="ml-3"> <v-btn color="success" @click="newPage" small class="ml-3">
Create {{$t('general.create')}}
</v-btn> </v-btn>
</span> </span>
</h2> </h2>
@ -41,11 +41,11 @@
<v-card-actions> <v-card-actions>
<v-btn text small color="error" @click="deletePage(item.id)"> <v-btn text small color="error" @click="deletePage(item.id)">
Delete {{$t('general.delete')}}
</v-btn> </v-btn>
<v-spacer> </v-spacer> <v-spacer> </v-spacer>
<v-btn small text color="success" @click="editPage(index)"> <v-btn small text color="success" @click="editPage(index)">
Edit {{$t('general.edit')}}
</v-btn> </v-btn>
</v-card-actions> </v-card-actions>
</v-card> </v-card>
@ -55,7 +55,7 @@
<v-card-actions> <v-card-actions>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-btn color="success" @click="savePages"> <v-btn color="success" @click="savePages">
Save {{$t('general.save')}}
</v-btn> </v-btn>
</v-card-actions> </v-card-actions>
</v-card> </v-card>
@ -76,8 +76,8 @@ export default {
customPages: [], customPages: [],
newPageData: { newPageData: {
create: true, create: true,
title: "New Page", title: this.$t('settings.new-page'),
buttonText: "Create", buttonText: this.$t('general.create'),
data: { data: {
name: "", name: "",
categories: [], categories: [],
@ -86,8 +86,8 @@ export default {
}, },
editPageData: { editPageData: {
create: false, create: false,
title: "Edit Page", title: this.$t('settings.edit-page'),
buttonText: "Update", buttonText: this.$t('general.update'),
data: {}, data: {},
}, },
}; };

View file

@ -90,7 +90,7 @@ export default {
computed: { computed: {
inputLabel() { inputLabel() {
if (!this.showLabel) return null; if (!this.showLabel) return null;
return this.tagSelector ? "Tags" : "Categories"; return this.tagSelector ? this.$t('recipe.tags') : this.$t('recipe.categories');
}, },
activeItems() { activeItems() {
let ItemObjects = []; let ItemObjects = [];

View file

@ -12,6 +12,7 @@
v-model="ingredient.checked" v-model="ingredient.checked"
class="pt-0 my-auto py-auto" class="pt-0 my-auto py-auto"
color="secondary" color="secondary"
:readonly="true"
> >
</v-checkbox> </v-checkbox>

View file

@ -5,7 +5,7 @@
<v-row v-if="title != null"> <v-row v-if="title != null">
<v-col> <v-col>
<v-btn-toggle group> <v-btn-toggle group>
<v-btn text :to="`/recipes/${title.toLowerCase()}`"> <v-btn text>
{{ title.toUpperCase() }} {{ title.toUpperCase() }}
</v-btn> </v-btn>
</v-btn-toggle> </v-btn-toggle>

View file

@ -54,22 +54,11 @@ export default {
{ {
icon: "mdi-magnify", icon: "mdi-magnify",
to: "/search", to: "/search",
title: "search", title: this.$t('search.search'),
}, },
], ],
}; };
}, },
computed: {
allCategories() {
return this.$store.getters.getCategories;
},
},
watch: {
allCategories() {
this.buildSidebar();
},
showSidebar() {},
},
mounted() { mounted() {
this.buildSidebar(); this.buildSidebar();
this.mobile = this.viewScale(); this.mobile = this.viewScale();
@ -81,14 +70,27 @@ export default {
this.links = []; this.links = [];
this.links.push(...this.baseLinks); this.links.push(...this.baseLinks);
const pages = await api.siteSettings.getPages(); const pages = await api.siteSettings.getPages();
pages.sort((a, b) => a.position - b.position); if(pages.length > 0) {
pages.forEach(async element => { pages.sort((a, b) => a.position - b.position);
this.links.push({ pages.forEach(async element => {
title: element.name, this.links.push({
to: `/pages/${element.slug}`, title: element.name,
icon: "mdi-tag", to: `/pages/${element.slug}`,
icon: "mdi-tag",
});
}); });
}); }
else {
const categories = await api.categories.getAll();
categories.forEach(async element => {
this.links.push({
title: element.name,
to: `/recipes/category/${element.slug}`,
icon: "mdi-tag",
});
});
}
}, },
viewScale() { viewScale() {
switch (this.$vuetify.breakpoint.name) { switch (this.$vuetify.breakpoint.name) {

View file

@ -93,7 +93,7 @@
"groups": "Gruppen", "groups": "Gruppen",
"could-not-validate-credentials": "Anmeldeinformationen konnten nicht validiert werden", "could-not-validate-credentials": "Anmeldeinformationen konnten nicht validiert werden",
"login": "Anmeldung", "login": "Anmeldung",
"groups-can-only-be-set-by-administrators": "Groups can only be set by administrators", "groups-can-only-be-set-by-administrators": "Gruppen können nur durch einen Administrator gesetzt werden",
"upload-photo": "Foto hochladen", "upload-photo": "Foto hochladen",
"reset-password": "Passwort zurücksetzen", "reset-password": "Passwort zurücksetzen",
"current-password": "Aktuelles Passwort", "current-password": "Aktuelles Passwort",

View file

@ -55,7 +55,8 @@
"wednesday": "Wednesday", "wednesday": "Wednesday",
"thursday": "Thursday", "thursday": "Thursday",
"friday": "Friday", "friday": "Friday",
"saturday": "Saturday" "saturday": "Saturday",
"about": "About"
}, },
"page": { "page": {
"home-page": "Home Page", "home-page": "Home Page",
@ -152,7 +153,16 @@
"delete-confirmation": "Are you sure you want to delete this recipe?" "delete-confirmation": "Are you sure you want to delete this recipe?"
}, },
"search": { "search": {
"search-mealie": "Search Mealie" "search-mealie": "Search Mealie",
"search-placeholder": "Search...",
"max-results": "Max Results",
"category-filter": "Category Filter",
"tag-filter": "Tag Filter",
"include": "Include",
"exclude": "Exclude",
"and": "And",
"or": "Or",
"search": "Search"
}, },
"settings": { "settings": {
"general-settings": "General Settings", "general-settings": "General Settings",
@ -224,7 +234,11 @@
"migrations": "Migrations", "migrations": "Migrations",
"profile": "Profile", "profile": "Profile",
"locale-settings": "Locale settings", "locale-settings": "Locale settings",
"first-day-of-week": "First day of the week" "first-day-of-week": "First day of the week",
"custom-pages": "Custom Pages",
"new-page": "New Page",
"edit-page": "Edit Page",
"page-name": "Page Name"
}, },
"migration": { "migration": {
"recipe-migration": "Recipe Migration", "recipe-migration": "Recipe Migration",

View file

@ -53,7 +53,10 @@
"sunday": "Dimanche", "sunday": "Dimanche",
"thursday": "Jeudi", "thursday": "Jeudi",
"tuesday": "Mardi", "tuesday": "Mardi",
"wednesday": "Mercredi" "wednesday": "Mercredi",
"groups": "Groupes",
"users": "Utilisateurs",
"about": "À propos"
}, },
"page": { "page": {
"home-page": "Accueil", "home-page": "Accueil",
@ -127,7 +130,7 @@
"categories": "Catégories", "categories": "Catégories",
"tags": "Tags", "tags": "Tags",
"instructions": "Instructions", "instructions": "Instructions",
"step-index": "Etape: {step}", "step-index": "Étape : {step}",
"recipe-name": "Nom de la recette", "recipe-name": "Nom de la recette",
"servings": "Portions", "servings": "Portions",
"ingredient": "Ingrédient", "ingredient": "Ingrédient",
@ -150,7 +153,16 @@
"delete-confirmation": "Êtes-vous sûr(e) de vouloir supprimer cette recette ?" "delete-confirmation": "Êtes-vous sûr(e) de vouloir supprimer cette recette ?"
}, },
"search": { "search": {
"search-mealie": "Rechercher dans Mealie" "search-mealie": "Rechercher dans Mealie",
"search-placeholder": "Rechercher...",
"and": "Et",
"category-filter": "Filtre par catégories",
"exclude": "Exclure",
"include": "Inclure",
"max-results": "Résultats max",
"or": "Ou",
"tag-filter": "Filtre par tags",
"search": "Rechercher"
}, },
"settings": { "settings": {
"general-settings": "Paramètres généraux", "general-settings": "Paramètres généraux",
@ -192,7 +204,7 @@
}, },
"webhooks": { "webhooks": {
"meal-planner-webhooks": "Webhooks du planificateur de repas", "meal-planner-webhooks": "Webhooks du planificateur de repas",
"the-urls-listed-below-will-recieve-webhooks-containing-the-recipe-data-for-the-meal-plan-on-its-scheduled-day-currently-webhooks-will-execute-at": "Les liens dans cette liste recevront les webhooks contenant les recettes pour le plan de menu du jour défini. Actuellement, les webhooks s'executeront à <strong>{ time }</strong>", "the-urls-listed-below-will-recieve-webhooks-containing-the-recipe-data-for-the-meal-plan-on-its-scheduled-day-currently-webhooks-will-execute-at": "Les liens dans cette liste recevront les webhooks contenant les recettes pour le plan de menu du jour défini. Actuellement, les webhooks s'exécuteront à",
"test-webhooks": "Tester les webhooks", "test-webhooks": "Tester les webhooks",
"webhook-url": "Lien du webhook" "webhook-url": "Lien du webhook"
}, },
@ -222,7 +234,11 @@
"profile": "Profil", "profile": "Profil",
"site-settings": "Paramètres site", "site-settings": "Paramètres site",
"locale-settings": "Paramètres de langue", "locale-settings": "Paramètres de langue",
"first-day-of-week": "Premier jour de la semaine" "first-day-of-week": "Premier jour de la semaine",
"custom-pages": "Pages personnalisées",
"edit-page": "Modifier la page",
"new-page": "Nouvelle page",
"page-name": "Nom de la page"
}, },
"migration": { "migration": {
"recipe-migration": "Migrer les recettes", "recipe-migration": "Migrer les recettes",

View file

@ -18,6 +18,20 @@ const router = new VueRouter({
mode: process.env.NODE_ENV === "production" ? "history" : "hash", mode: process.env.NODE_ENV === "production" ? "history" : "hash",
}); });
const DEFAULT_TITLE = 'Mealie';
const TITLE_SEPARATOR = '🍴';
const TITLE_SUFFIX = " " + TITLE_SEPARATOR + " " + DEFAULT_TITLE;
router.afterEach( (to) => {
Vue.nextTick( async () => {
if(typeof to.meta.title === 'function' ) {
const title = await to.meta.title(to);
document.title = title + TITLE_SUFFIX;
} else {
document.title = to.meta.title ? to.meta.title + TITLE_SUFFIX : DEFAULT_TITLE;
}
});
});
const vueApp = new Vue({ const vueApp = new Vue({
vuetify, vuetify,
store, store,

View file

@ -10,11 +10,11 @@
mandatory mandatory
> >
<v-btn :value="false"> <v-btn :value="false">
Include {{$t('search.include')}}
</v-btn> </v-btn>
<v-btn :value="true"> <v-btn :value="true">
Exclude {{$t('search.exclude')}}
</v-btn> </v-btn>
</v-btn-toggle> </v-btn-toggle>
<v-spacer></v-spacer> <v-spacer></v-spacer>
@ -28,10 +28,10 @@
mandatory mandatory
> >
<v-btn :value="false"> <v-btn :value="false">
And {{$t('search.and')}}
</v-btn> </v-btn>
<v-btn :value="true"> <v-btn :value="true">
Or {{$t('search.or')}}
</v-btn> </v-btn>
</v-btn-toggle> </v-btn-toggle>
</v-toolbar> </v-toolbar>

View file

@ -8,7 +8,7 @@
v-model="searchString" v-model="searchString"
outlined outlined
color="primary accent-3" color="primary accent-3"
placeholder="Placeholder" :placeholder="$t('search.search-placeholder')"
append-icon="mdi-magnify" append-icon="mdi-magnify"
> >
</v-text-field> </v-text-field>
@ -16,7 +16,7 @@
<v-col cols="12" md="2" sm="12"> <v-col cols="12" md="2" sm="12">
<v-text-field <v-text-field
class="mt-0 pt-0" class="mt-0 pt-0"
label="Max Results" :label="$t('search.max-results')"
v-model="maxResults" v-model="maxResults"
type="number" type="number"
outlined outlined
@ -26,7 +26,7 @@
<v-row dense class="mt-0 flex-row align-center justify-space-around"> <v-row dense class="mt-0 flex-row align-center justify-space-around">
<v-col> <v-col>
<h3 class="pl-2 text-center headline">Category Filter</h3> <h3 class="pl-2 text-center headline">{{$t('search.category-filter')}}</h3>
<FilterSelector class="mb-1" @update="updateCatParams" /> <FilterSelector class="mb-1" @update="updateCatParams" />
<CategoryTagSelector <CategoryTagSelector
:solo="true" :solo="true"
@ -36,7 +36,7 @@
/> />
</v-col> </v-col>
<v-col> <v-col>
<h3 class="pl-2 text-center headline">Tag Filter</h3> <h3 class="pl-2 text-center headline">{{$t('search.tag-filter')}}</h3>
<FilterSelector class="mb-1" @update="updateTagParams" /> <FilterSelector class="mb-1" @update="updateTagParams" />
<CategoryTagSelector <CategoryTagSelector

View file

@ -8,6 +8,7 @@ import ManageUsers from "@/pages/Admin/ManageUsers";
import Settings from "@/pages/Admin/Settings"; import Settings from "@/pages/Admin/Settings";
import About from "@/pages/Admin/About"; import About from "@/pages/Admin/About";
import { store } from "../store"; import { store } from "../store";
import i18n from '@/i18n.js';
export default { export default {
path: "/admin", path: "/admin",
@ -25,35 +26,59 @@ export default {
{ {
path: "profile", path: "profile",
component: Profile, component: Profile,
meta: {
title: i18n.t('settings.profile'),
},
}, },
{ {
path: "backups", path: "backups",
component: Backup, component: Backup,
meta: {
title: i18n.t('settings.backup-and-exports'),
},
}, },
{ {
path: "themes", path: "themes",
component: Theme, component: Theme,
meta: {
title: i18n.t('general.themes'),
},
}, },
{ {
path: "meal-planner", path: "meal-planner",
component: MealPlanner, component: MealPlanner,
meta: {
title: i18n.t('meal-plan.meal-planner'),
},
}, },
{ {
path: "migrations", path: "migrations",
component: Migration, component: Migration,
meta: {
title: i18n.t('settings.migrations'),
},
}, },
{ {
path: "manage-users", path: "manage-users",
component: ManageUsers, component: ManageUsers,
meta: {
title: i18n.t('settings.manage-users'),
},
}, },
{ {
path: "settings", path: "settings",
component: Settings, component: Settings,
meta: {
title: i18n.t('settings.site-settings'),
},
}, },
{ {
path: "about", path: "about",
component: About, component: About,
meta: {
title: i18n.t('general.about'),
},
}, },
], ],
}; };

View file

@ -15,6 +15,7 @@ import ThisWeek from "@/pages/MealPlan/ThisWeek";
import { api } from "@/api"; import { api } from "@/api";
import Admin from "./admin"; import Admin from "./admin";
import { store } from "../store"; import { store } from "../store";
import i18n from '@/i18n.js';
export const routes = [ export const routes = [
{ path: "/", name: "home", component: HomePage }, { path: "/", name: "home", component: HomePage },
@ -31,15 +32,43 @@ export const routes = [
{ path: "/sign-up", redirect: "/" }, { path: "/sign-up", redirect: "/" },
{ path: "/sign-up/:token", component: SignUpPage }, { path: "/sign-up/:token", component: SignUpPage },
{ path: "/debug", component: Debug }, { path: "/debug", component: Debug },
{ path: "/search", component: SearchPage }, {
path: "/search",
component: SearchPage,
meta: {
title: i18n.t('search.search'),
},
},
{ path: "/recipes/all", component: AllRecipes }, { path: "/recipes/all", component: AllRecipes },
{ path: "/pages/:customPage", component: CustomPage }, { path: "/pages/:customPage", component: CustomPage },
{ path: "/recipes/tag/:tag", component: TagPage }, { path: "/recipes/tag/:tag", component: TagPage },
{ path: "/recipes/category/:category", component: CategoryPage }, { path: "/recipes/category/:category", component: CategoryPage },
{ path: "/recipe/:recipe", component: ViewRecipe }, {
path: "/recipe/:recipe",
component: ViewRecipe,
meta: {
title: async route => {
const recipe = await api.recipes.requestDetails(route.params.recipe);
return recipe.name;
},
}
},
{ path: "/new/", component: NewRecipe }, { path: "/new/", component: NewRecipe },
{ path: "/meal-plan/planner", component: Planner }, {
{ path: "/meal-plan/this-week", component: ThisWeek }, path: "/meal-plan/planner",
component: Planner,
meta: {
title: i18n.t('meal-plan.meal-planner'),
}
},
{
path: "/meal-plan/this-week",
component: ThisWeek,
meta: {
title: i18n.t('meal-plan.dinner-this-week'),
}
},
Admin, Admin,
{ {
path: "/meal-plan/today", path: "/meal-plan/today",

View file

@ -26,9 +26,9 @@ class Cleaner:
recipe_data["description"] = Cleaner.html(recipe_data.get("description", "")) recipe_data["description"] = Cleaner.html(recipe_data.get("description", ""))
# Times # Times
recipe_data["prepTime"] = Cleaner.time(recipe_data.get("prepTime", None)) recipe_data["prepTime"] = Cleaner.time(recipe_data.get("prepTime"))
recipe_data["performTime"] = Cleaner.time(recipe_data.get("performTime", None)) recipe_data["performTime"] = Cleaner.time(recipe_data.get("performTime"))
recipe_data["totalTime"] = Cleaner.time(recipe_data.get("totalTime", None)) recipe_data["totalTime"] = Cleaner.time(recipe_data.get("totalTime"))
recipe_data["recipeCategory"] = Cleaner.category(recipe_data.get("recipeCategory", [])) recipe_data["recipeCategory"] = Cleaner.category(recipe_data.get("recipeCategory", []))
recipe_data["recipeYield"] = Cleaner.yield_amount(recipe_data.get("recipeYield")) recipe_data["recipeYield"] = Cleaner.yield_amount(recipe_data.get("recipeYield"))
@ -70,6 +70,9 @@ class Cleaner:
if not instructions: if not instructions:
return [] return []
if isinstance(instructions[0], list):
instructions = instructions[0]
# One long string split by (possibly multiple) new lines # One long string split by (possibly multiple) new lines
if isinstance(instructions, str): if isinstance(instructions, str):
return [{"text": Cleaner._instruction(line)} for line in instructions.splitlines() if line] return [{"text": Cleaner._instruction(line)} for line in instructions.splitlines() if line]