mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-11-30 15:44:37 -05:00
feature/editor-improvements (#289)
* pin editor buttons on scroll * scaler scratch * fix langauge assignment 1st pass * set lang on navigate * refactor/breakup router * unify style for language selectro * refactor/code-cleanup * refactor/page specific components to page folder * Fix time card layout issue * fix timecard display * update mobile cards / fix overflow errors Co-authored-by: hay-kot <hay-kot@pm.me>
This commit is contained in:
99
frontend/src/pages/Admin/Settings/CreatePageDialog.vue
Normal file
99
frontend/src/pages/Admin/Settings/CreatePageDialog.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<v-dialog v-model="pageDialog" max-width="500">
|
||||
<v-card>
|
||||
<v-app-bar dark dense color="primary">
|
||||
<v-icon left>
|
||||
mdi-page-layout-body
|
||||
</v-icon>
|
||||
|
||||
<v-toolbar-title class="headline">
|
||||
{{ title }}
|
||||
</v-toolbar-title>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
</v-app-bar>
|
||||
<v-form ref="newGroup" @submit.prevent="submitForm">
|
||||
<v-card-text>
|
||||
<v-text-field
|
||||
autofocus
|
||||
v-model="page.name"
|
||||
:label="$t('settings.page-name')"
|
||||
></v-text-field>
|
||||
<CategoryTagSelector
|
||||
v-model="page.categories"
|
||||
ref="categoryFormSelector"
|
||||
@mounted="catMounted = true"
|
||||
:tag-selector="false"
|
||||
/>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="grey" text @click="pageDialog = false">
|
||||
{{ $t("general.cancel") }}
|
||||
</v-btn>
|
||||
<v-btn color="primary" type="submit">
|
||||
{{ buttonText }}
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-form>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const NEW_PAGE_EVENT = "refresh-page";
|
||||
import { api } from "@/api";
|
||||
import CategoryTagSelector from "@/components/FormHelpers/CategoryTagSelector";
|
||||
export default {
|
||||
components: {
|
||||
CategoryTagSelector,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
catMounted: false,
|
||||
title: "",
|
||||
buttonText: "",
|
||||
create: false,
|
||||
pageDialog: false,
|
||||
page: {
|
||||
name: "",
|
||||
position: 0,
|
||||
categories: [],
|
||||
},
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
catMounted(val) {
|
||||
if (val) this.pushSelected();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
open(parameters) {
|
||||
this.page = parameters.data;
|
||||
this.create = parameters.create;
|
||||
this.buttonText = parameters.buttonText;
|
||||
this.title = parameters.title;
|
||||
this.pageDialog = true;
|
||||
|
||||
if (this.catMounted) this.pushSelected();
|
||||
},
|
||||
pushSelected() {
|
||||
this.$refs.categoryFormSelector.setInit(this.page.categories);
|
||||
},
|
||||
async submitForm() {
|
||||
if (this.create) {
|
||||
await api.siteSettings.createPage(this.page);
|
||||
} else {
|
||||
await api.siteSettings.updatePage(this.page);
|
||||
}
|
||||
this.pageDialog = false;
|
||||
this.page.categories = [];
|
||||
this.$emit(NEW_PAGE_EVENT);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
129
frontend/src/pages/Admin/Settings/CustomPageCreator.vue
Normal file
129
frontend/src/pages/Admin/Settings/CustomPageCreator.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<v-card flat>
|
||||
<CreatePageDialog ref="createDialog" @refresh-page="getPages" />
|
||||
<v-card-text>
|
||||
<h2 class="mt-1 mb-1 ">
|
||||
{{$t('settings.custom-pages')}}
|
||||
<span>
|
||||
<v-btn color="success" @click="newPage" small class="ml-3">
|
||||
{{$t('general.create')}}
|
||||
</v-btn>
|
||||
</span>
|
||||
</h2>
|
||||
<draggable class="row mt-1" v-model="customPages">
|
||||
<v-col
|
||||
:sm="6"
|
||||
:md="6"
|
||||
:lg="4"
|
||||
:xl="3"
|
||||
v-for="(item, index) in customPages"
|
||||
:key="item + item.id"
|
||||
>
|
||||
<v-card>
|
||||
<v-card-text class="mb-0 pb-0">
|
||||
<h3>{{ item.name }}</h3>
|
||||
<v-divider></v-divider>
|
||||
</v-card-text>
|
||||
<v-card-text class="mt-0">
|
||||
<div>
|
||||
<v-chip
|
||||
v-for="cat in item.categories"
|
||||
:key="cat.slug + cat.id"
|
||||
class="my-2 mr-2"
|
||||
label
|
||||
small
|
||||
color="accent lighten-1"
|
||||
>
|
||||
{{ cat.name }}
|
||||
</v-chip>
|
||||
</div>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-actions>
|
||||
<v-btn text small color="error" @click="deletePage(item.id)">
|
||||
{{$t('general.delete')}}
|
||||
</v-btn>
|
||||
<v-spacer> </v-spacer>
|
||||
<v-btn small text color="success" @click="editPage(index)">
|
||||
{{$t('general.edit')}}
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</draggable>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="success" @click="savePages">
|
||||
{{$t('general.save')}}
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import draggable from "vuedraggable";
|
||||
import CreatePageDialog from "./CreatePageDialog";
|
||||
import { api } from "@/api";
|
||||
export default {
|
||||
components: {
|
||||
draggable,
|
||||
CreatePageDialog,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageDialog: false,
|
||||
customPages: [],
|
||||
newPageData: {
|
||||
create: true,
|
||||
title: this.$t('settings.new-page'),
|
||||
buttonText: this.$t('general.create'),
|
||||
data: {
|
||||
name: "",
|
||||
categories: [],
|
||||
position: 0,
|
||||
},
|
||||
},
|
||||
editPageData: {
|
||||
create: false,
|
||||
title: this.$t('settings.edit-page'),
|
||||
buttonText: this.$t('general.update'),
|
||||
data: {},
|
||||
},
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
this.getPages();
|
||||
},
|
||||
methods: {
|
||||
async getPages() {
|
||||
this.customPages = await api.siteSettings.getPages();
|
||||
this.customPages.sort((a, b) => a.position - b.position);
|
||||
},
|
||||
async deletePage(id) {
|
||||
await api.siteSettings.deletePage(id);
|
||||
this.getPages();
|
||||
},
|
||||
async savePages() {
|
||||
this.customPages.forEach((element, index) => {
|
||||
element.position = index;
|
||||
});
|
||||
|
||||
await api.siteSettings.updateAllPages(this.customPages);
|
||||
|
||||
this.getPages();
|
||||
},
|
||||
editPage(index) {
|
||||
this.editPageData.data = this.customPages[index];
|
||||
this.$refs.createDialog.open(this.editPageData);
|
||||
},
|
||||
newPage() {
|
||||
this.newPageData.position = this.customPages.length;
|
||||
this.$refs.createDialog.open(this.newPageData);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
235
frontend/src/pages/Admin/Settings/HomePageSettings.vue
Normal file
235
frontend/src/pages/Admin/Settings/HomePageSettings.vue
Normal file
@@ -0,0 +1,235 @@
|
||||
<template>
|
||||
<v-card flat>
|
||||
<v-card-text>
|
||||
<h2 class="mt-1 mb-1">{{ $t("settings.homepage.home-page") }}</h2>
|
||||
<v-row align="center" justify="center" dense class="mb-n7 pb-n5">
|
||||
<v-col cols="12" sm="3" md="2">
|
||||
<v-switch
|
||||
v-model="settings.showRecent"
|
||||
:label="$t('settings.homepage.show-recent')"
|
||||
></v-switch>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="5" md="5">
|
||||
<v-slider
|
||||
class="pt-sm-4"
|
||||
:label="$t('settings.homepage.card-per-section')"
|
||||
v-model="settings.cardsPerSection"
|
||||
max="30"
|
||||
dense
|
||||
color="primary"
|
||||
min="3"
|
||||
thumb-label
|
||||
>
|
||||
</v-slider>
|
||||
</v-col>
|
||||
<v-spacer></v-spacer>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-card outlined min-height="350px">
|
||||
<v-app-bar dark dense color="primary">
|
||||
<v-icon left>
|
||||
mdi-home
|
||||
</v-icon>
|
||||
|
||||
<v-toolbar-title class="headline">
|
||||
{{ $t("settings.homepage.home-page-sections") }}
|
||||
</v-toolbar-title>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
</v-app-bar>
|
||||
<v-list height="300" dense style="overflow:auto">
|
||||
<v-list-item-group>
|
||||
<draggable
|
||||
v-model="settings.categories"
|
||||
group="categories"
|
||||
:style="{
|
||||
minHeight: `150px`,
|
||||
}"
|
||||
>
|
||||
<v-list-item
|
||||
v-for="(item, index) in settings.categories"
|
||||
:key="`${item.name}-${index}`"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-menu</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-title v-text="item.name"></v-list-item-title>
|
||||
</v-list-item-content>
|
||||
<v-list-item-icon @click="deleteActiveCategory(index)">
|
||||
<v-icon>mdi-delete</v-icon>
|
||||
</v-list-item-icon>
|
||||
</v-list-item>
|
||||
</draggable>
|
||||
</v-list-item-group>
|
||||
</v-list>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-card outlined height="350px">
|
||||
<v-app-bar dark dense color="primary">
|
||||
<v-icon left>
|
||||
mdi-tag
|
||||
</v-icon>
|
||||
|
||||
<v-toolbar-title class="headline">
|
||||
{{ $t("settings.homepage.all-categories") }}
|
||||
</v-toolbar-title>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
<NewCategoryTagDialog :tag-dialog="false" />
|
||||
</v-app-bar>
|
||||
<v-list height="300" dense style="overflow:auto">
|
||||
<v-list-item-group>
|
||||
<draggable
|
||||
v-model="allCategories"
|
||||
group="categories"
|
||||
:style="{
|
||||
minHeight: `150px`,
|
||||
}"
|
||||
>
|
||||
<v-list-item
|
||||
v-for="(item, index) in allCategories"
|
||||
:key="`${item.name}-${index}`"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-menu</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-title v-text="item.name"></v-list-item-title>
|
||||
</v-list-item-content>
|
||||
<v-list-item-icon
|
||||
@click="deleteCategoryfromDatabase(item.slug)"
|
||||
>
|
||||
<v-icon>mdi-delete</v-icon>
|
||||
</v-list-item-icon>
|
||||
</v-list-item>
|
||||
</draggable>
|
||||
</v-list-item-group>
|
||||
</v-list>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
<h2 class="mt-1 mb-4">{{ $t("settings.locale-settings") }}</h2>
|
||||
<v-row>
|
||||
<v-col cols="12" md="3" sm="12">
|
||||
<LanguageSelector @select-lang="writeLang" :site-settings="true" />
|
||||
</v-col>
|
||||
<v-col cols="12" md="3" sm="12">
|
||||
<v-select
|
||||
dense
|
||||
prepend-icon="mdi-calendar-week-begin"
|
||||
v-model="settings.firstDayOfWeek"
|
||||
:items="allDays"
|
||||
item-text="name"
|
||||
item-value="value"
|
||||
:label="$t('settings.first-day-of-week')"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="success" @click="saveSettings" class="mr-2">
|
||||
<v-icon left> mdi-content-save </v-icon>
|
||||
{{ $t("general.save") }}
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { api } from "@/api";
|
||||
import LanguageSelector from "@/components/FormHelpers/LanguageSelector";
|
||||
import draggable from "vuedraggable";
|
||||
import NewCategoryTagDialog from "@/components/UI/Dialogs/NewCategoryTagDialog.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
draggable,
|
||||
LanguageSelector,
|
||||
NewCategoryTagDialog,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
settings: {
|
||||
language: "en",
|
||||
firstDayOfWeek: 0,
|
||||
showRecent: null,
|
||||
cardsPerSection: null,
|
||||
categories: [],
|
||||
},
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getOptions();
|
||||
},
|
||||
computed: {
|
||||
allCategories() {
|
||||
return this.$store.getters.getAllCategories;
|
||||
},
|
||||
allDays() {
|
||||
return [
|
||||
{
|
||||
name: this.$t("general.sunday"),
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: this.$t("general.monday"),
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: this.$t("general.tuesday"),
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
name: this.$t("general.wednesday"),
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
name: this.$t("general.thursday"),
|
||||
value: 4,
|
||||
},
|
||||
{
|
||||
name: this.$t("general.friday"),
|
||||
value: 5,
|
||||
},
|
||||
{
|
||||
name: this.$t("general.saturday"),
|
||||
value: 6,
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
writeLang(val) {
|
||||
this.settings.language = val;
|
||||
},
|
||||
deleteCategoryfromDatabase(category) {
|
||||
api.categories.delete(category);
|
||||
},
|
||||
async getOptions() {
|
||||
this.settings = await api.siteSettings.get();
|
||||
},
|
||||
deleteActiveCategory(index) {
|
||||
this.settings.categories.splice(index, 1);
|
||||
},
|
||||
async saveSettings() {
|
||||
const newSettings = await api.siteSettings.update(this.settings);
|
||||
console.log("New Settings", newSettings);
|
||||
this.getOptions();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -20,8 +20,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HomePageSettings from "@/components/Admin/General/HomePageSettings";
|
||||
import CustomPageCreator from "@/components/Admin/General/CustomPageCreator";
|
||||
import HomePageSettings from "./HomePageSettings";
|
||||
import CustomPageCreator from "./CustomPageCreator";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
||||
Reference in New Issue
Block a user