mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-02-28 10:43:17 -05:00
feature/recipe-patch-improvements (#382)
* automated docs update * recipe rating component * recipe partial updates - closes #25 * use Vue.delete to update store * format * arrow functions * fix tests * format * initial context menu * localize * add confirmation dialog * context menu * fix bare exception * update line length * format all file with prettier * update changelog * download as json * update python dependencies * update javascript dependencies Co-authored-by: hay-kot <hay-kot@pm.me>
This commit is contained in:
@@ -47,5 +47,4 @@ export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
<template>
|
||||
<v-form ref="file">
|
||||
<input ref="uploader" class="d-none" type="file" @change="onFileChanged" />
|
||||
<v-btn
|
||||
:loading="isSelecting"
|
||||
@click="onButtonClick"
|
||||
color="accent"
|
||||
:text="textBtn"
|
||||
>
|
||||
<v-btn :loading="isSelecting" @click="onButtonClick" color="accent" :text="textBtn">
|
||||
<v-icon left> {{ icon }}</v-icon>
|
||||
{{ text ? text : defaultText }}
|
||||
</v-btn>
|
||||
@@ -55,7 +50,7 @@ export default {
|
||||
let formData = new FormData();
|
||||
formData.append(this.fileName, this.file);
|
||||
|
||||
if(await api.utils.uploadFile(this.url, formData)) {
|
||||
if (await api.utils.uploadFile(this.url, formData)) {
|
||||
this.$emit(UPLOAD_EVENT);
|
||||
}
|
||||
this.isSelecting = false;
|
||||
@@ -81,5 +76,4 @@ export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
<style></style>
|
||||
|
||||
@@ -22,14 +22,10 @@
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item @click="$emit('sort-recent')">
|
||||
<v-list-item-title>{{
|
||||
$t("general.recent")
|
||||
}}</v-list-item-title>
|
||||
<v-list-item-title>{{ $t("general.recent") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="$emit('sort')">
|
||||
<v-list-item-title>{{
|
||||
$t("general.sort-alphabetically")
|
||||
}}</v-list-item-title>
|
||||
<v-list-item-title>{{ $t("general.sort-alphabetically") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
@@ -39,14 +35,7 @@
|
||||
</v-card>
|
||||
<div v-if="recipes">
|
||||
<v-row v-if="!viewScale">
|
||||
<v-col
|
||||
:sm="6"
|
||||
:md="6"
|
||||
:lg="4"
|
||||
:xl="3"
|
||||
v-for="recipe in recipes.slice(0, cardLimit)"
|
||||
:key="recipe.name"
|
||||
>
|
||||
<v-col :sm="6" :md="6" :lg="4" :xl="3" v-for="recipe in recipes.slice(0, cardLimit)" :key="recipe.name">
|
||||
<RecipeCard
|
||||
:name="recipe.name"
|
||||
:description="recipe.description"
|
||||
@@ -148,10 +137,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
bumpList() {
|
||||
const newCardLimit = Math.min(
|
||||
this.cardLimit + 20,
|
||||
this.effectiveHardLimit
|
||||
);
|
||||
const newCardLimit = Math.min(this.cardLimit + 20, this.effectiveHardLimit);
|
||||
|
||||
if (this.loading === false && newCardLimit > this.cardLimit) {
|
||||
this.setLoader();
|
||||
@@ -172,4 +158,4 @@ export default {
|
||||
.transparent {
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<slot name="open" v-bind="{ open }"> </slot>
|
||||
<v-dialog
|
||||
v-model="dialog"
|
||||
:width="modalWidth + 'px'"
|
||||
:content-class="top ? 'top-dialog' : undefined"
|
||||
>
|
||||
<v-dialog v-model="dialog" :width="modalWidth + 'px'" :content-class="top ? 'top-dialog' : undefined">
|
||||
<v-card class="pb-10" height="100%">
|
||||
<v-app-bar dark :color="color" class="mt-n1 mb-2">
|
||||
<v-icon large left>
|
||||
@@ -14,20 +10,16 @@
|
||||
<v-toolbar-title class="headline"> {{ title }} </v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
</v-app-bar>
|
||||
<v-progress-linear
|
||||
v-if="loading"
|
||||
indeterminate
|
||||
color="primary"
|
||||
></v-progress-linear>
|
||||
<v-progress-linear v-if="loading" indeterminate color="primary"></v-progress-linear>
|
||||
<slot> </slot>
|
||||
<v-card-actions>
|
||||
<slot name="card-actions">
|
||||
<v-btn text color="grey" @click="dialog = false">
|
||||
{{$t('general.cancel')}}
|
||||
{{ $t("general.cancel") }}
|
||||
</v-btn>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="success" @click="submitEvent">
|
||||
{{$t('general.submit')}}
|
||||
{{ $t("general.submit") }}
|
||||
</v-btn>
|
||||
</slot>
|
||||
</v-card-actions>
|
||||
@@ -84,4 +76,4 @@ export default {
|
||||
.top-dialog {
|
||||
align-self: flex-start;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
<template>
|
||||
<v-dialog
|
||||
v-model="dialog"
|
||||
@@ -7,17 +6,16 @@
|
||||
@click:outside="cancel"
|
||||
@keydown.esc="cancel"
|
||||
>
|
||||
<template v-slot:activator="{}">
|
||||
<slot v-bind="{ open }"> </slot>
|
||||
</template>
|
||||
<v-card>
|
||||
<v-app-bar v-if="Boolean(title)" :color="color" dense dark>
|
||||
<v-app-bar v-if="Boolean(title)" :color="color" dense dark>
|
||||
<v-icon v-if="Boolean(icon)" left> {{ icon }}</v-icon>
|
||||
<v-toolbar-title v-text="title" />
|
||||
</v-app-bar>
|
||||
|
||||
<v-card-text
|
||||
v-show="!!message"
|
||||
class="pa-4 text--primary"
|
||||
v-html="message"
|
||||
/>
|
||||
<v-card-text v-show="!!message" class="pa-4 text--primary" v-html="message" />
|
||||
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
@@ -35,6 +33,7 @@
|
||||
<script>
|
||||
const CLOSE_EVENT = "close";
|
||||
const OPEN_EVENT = "open";
|
||||
const CONFIRM_EVENT = "confirm";
|
||||
/**
|
||||
* ConfirmationDialog Component used to add a second validaion step to an action.
|
||||
* @version 1.0.1
|
||||
@@ -96,13 +95,9 @@ export default {
|
||||
dialog: false,
|
||||
}),
|
||||
methods: {
|
||||
/**
|
||||
* Sets the modal to be visiable.
|
||||
*/
|
||||
open() {
|
||||
this.dialog = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Cancel button handler.
|
||||
*/
|
||||
@@ -129,7 +124,7 @@ export default {
|
||||
* @event confirm
|
||||
* @property {string} content content of the first prop passed to the event
|
||||
*/
|
||||
this.$emit("confirm");
|
||||
this.$emit(CONFIRM_EVENT);
|
||||
|
||||
//Hide Modal
|
||||
this.dialog = false;
|
||||
@@ -138,5 +133,4 @@ export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
<style></style>
|
||||
|
||||
@@ -21,12 +21,7 @@
|
||||
<v-card-title> </v-card-title>
|
||||
<v-form @submit.prevent="select">
|
||||
<v-card-text>
|
||||
<v-text-field
|
||||
dense
|
||||
:label="inputLabel"
|
||||
v-model="itemName"
|
||||
:rules="[rules.required]"
|
||||
></v-text-field>
|
||||
<v-text-field dense :label="inputLabel" v-model="itemName" :rules="[rules.required]"></v-text-field>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
@@ -103,5 +98,4 @@ export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
<style></style>
|
||||
|
||||
@@ -61,9 +61,7 @@ export default {
|
||||
try {
|
||||
this.results = this.fuse.search(this.search.trim());
|
||||
} catch {
|
||||
this.results = this.rawData
|
||||
.map(x => ({ item: x }))
|
||||
.sort((a, b) => (a.name > b.name ? 1 : -1));
|
||||
this.results = this.rawData.map(x => ({ item: x })).sort((a, b) => (a.name > b.name ? 1 : -1));
|
||||
}
|
||||
this.$emit(RESULTS_EVENT, this.results);
|
||||
|
||||
@@ -75,5 +73,4 @@ export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
<template>
|
||||
<v-menu
|
||||
v-model="menuModel"
|
||||
readonly
|
||||
offset-y
|
||||
offset-overflow
|
||||
max-height="75vh"
|
||||
>
|
||||
<v-menu v-model="menuModel" readonly offset-y offset-overflow max-height="75vh">
|
||||
<template #activator="{ attrs }">
|
||||
<v-text-field
|
||||
ref="searchInput"
|
||||
@@ -33,12 +27,7 @@
|
||||
</template>
|
||||
</v-text-field>
|
||||
</template>
|
||||
<v-card
|
||||
v-if="showResults"
|
||||
max-height="75vh"
|
||||
:max-width="maxWidth"
|
||||
scrollable
|
||||
>
|
||||
<v-card v-if="showResults" max-height="75vh" :max-width="maxWidth" scrollable>
|
||||
<v-card-text class="flex row mx-auto ">
|
||||
<div class="mr-auto">
|
||||
Results
|
||||
@@ -56,22 +45,10 @@
|
||||
<v-list-item-avatar>
|
||||
<v-img :src="getImage(item.item.slug)"></v-img>
|
||||
</v-list-item-avatar>
|
||||
<v-list-item-content
|
||||
@click="
|
||||
showResults ? null : selected(item.item.slug, item.item.name)
|
||||
"
|
||||
>
|
||||
<v-list-item-title v-html="highlight(item.item.name)">
|
||||
</v-list-item-title>
|
||||
<v-rating
|
||||
dense
|
||||
v-if="item.item.rating"
|
||||
:value="item.item.rating"
|
||||
size="12"
|
||||
>
|
||||
</v-rating>
|
||||
<v-list-item-subtitle v-html="highlight(item.item.description)">
|
||||
</v-list-item-subtitle>
|
||||
<v-list-item-content @click="showResults ? null : selected(item.item.slug, item.item.name)">
|
||||
<v-list-item-title v-html="highlight(item.item.name)"> </v-list-item-title>
|
||||
<v-rating dense v-if="item.item.rating" :value="item.item.rating" size="12"> </v-rating>
|
||||
<v-list-item-subtitle v-html="highlight(item.item.description)"> </v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
@@ -153,9 +130,7 @@ export default {
|
||||
try {
|
||||
this.result = this.fuse.search(this.search.trim());
|
||||
} catch {
|
||||
this.result = this.data
|
||||
.map(x => ({ item: x }))
|
||||
.sort((a, b) => (a.name > b.name ? 1 : -1));
|
||||
this.result = this.data.map(x => ({ item: x })).sort((a, b) => (a.name > b.name ? 1 : -1));
|
||||
}
|
||||
this.$emit("results", this.result);
|
||||
|
||||
@@ -173,10 +148,7 @@ export default {
|
||||
if (!this.search) {
|
||||
return string;
|
||||
}
|
||||
return string.replace(
|
||||
new RegExp(this.search, "gi"),
|
||||
match => `<mark>${match}</mark>`
|
||||
);
|
||||
return string.replace(new RegExp(this.search, "gi"), match => `<mark>${match}</mark>`);
|
||||
},
|
||||
getImage(image) {
|
||||
return api.recipes.recipeTinyImage(image);
|
||||
@@ -221,4 +193,4 @@ export default {
|
||||
&, & > *
|
||||
display: flex
|
||||
flex-direction: column
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<template>
|
||||
<div class="text-center ">
|
||||
<v-dialog
|
||||
v-model="dialog"
|
||||
width="600px"
|
||||
height="0"
|
||||
:fullscreen="isMobile"
|
||||
content-class="top-dialog"
|
||||
>
|
||||
<v-dialog v-model="dialog" width="600px" height="0" :fullscreen="isMobile" content-class="top-dialog">
|
||||
<v-card>
|
||||
<v-app-bar dark color="primary lighten-1" rounded="0">
|
||||
<SearchBar
|
||||
@@ -103,4 +97,4 @@ export default {
|
||||
.top-dialog {
|
||||
align-self: flex-start;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<TheSidebar ref="theSidebar" />
|
||||
<v-app-bar
|
||||
clipped-left
|
||||
dense
|
||||
app
|
||||
color="primary"
|
||||
dark
|
||||
class="d-print-none"
|
||||
:bottom="isMobile"
|
||||
>
|
||||
<v-app-bar clipped-left dense app color="primary" dark class="d-print-none" :bottom="isMobile">
|
||||
<v-btn icon @click="openSidebar">
|
||||
<v-icon> mdi-menu </v-icon>
|
||||
</v-btn>
|
||||
@@ -36,7 +28,7 @@
|
||||
<v-btn icon @click="$refs.recipeSearch.open()">
|
||||
<v-icon> mdi-magnify </v-icon>
|
||||
</v-btn>
|
||||
<SearchDialog ref="recipeSearch"/>
|
||||
<SearchDialog ref="recipeSearch" />
|
||||
</div>
|
||||
|
||||
<TheSiteMenu />
|
||||
@@ -90,5 +82,4 @@ export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
||||
@@ -6,14 +6,7 @@
|
||||
<v-icon large left v-if="!processing">
|
||||
mdi-link
|
||||
</v-icon>
|
||||
<v-progress-circular
|
||||
v-else
|
||||
indeterminate
|
||||
color="white"
|
||||
large
|
||||
class="mr-2"
|
||||
>
|
||||
</v-progress-circular>
|
||||
<v-progress-circular v-else indeterminate color="white" large class="mr-2"> </v-progress-circular>
|
||||
|
||||
<v-toolbar-title class="headline">
|
||||
{{ $t("new-recipe.from-url") }}
|
||||
@@ -54,21 +47,9 @@
|
||||
</v-form>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
<v-speed-dial
|
||||
v-model="fab"
|
||||
:open-on-hover="absolute"
|
||||
:fixed="absolute"
|
||||
:bottom="absolute"
|
||||
:right="absolute"
|
||||
>
|
||||
<v-speed-dial v-model="fab" :open-on-hover="absolute" :fixed="absolute" :bottom="absolute" :right="absolute">
|
||||
<template v-slot:activator>
|
||||
<v-btn
|
||||
v-model="fab"
|
||||
:color="absolute ? 'accent' : 'white'"
|
||||
dark
|
||||
:icon="!absolute"
|
||||
:fab="absolute"
|
||||
>
|
||||
<v-btn v-model="fab" :color="absolute ? 'accent' : 'white'" dark :icon="!absolute" :fab="absolute">
|
||||
<v-icon> mdi-plus </v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
@@ -132,5 +113,4 @@ export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
<style></style>
|
||||
|
||||
@@ -4,11 +4,7 @@
|
||||
<template v-slot:prepend>
|
||||
<v-list-item two-line v-if="isLoggedIn">
|
||||
<v-list-item-avatar color="accent" class="white--text">
|
||||
<img
|
||||
:src="userProfileImage"
|
||||
v-if="!hideImage"
|
||||
@error="hideImage = true"
|
||||
/>
|
||||
<img :src="userProfileImage" v-if="!hideImage" @error="hideImage = true" />
|
||||
<div v-else>
|
||||
{{ initials }}
|
||||
</div>
|
||||
@@ -16,21 +12,14 @@
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-title> {{ user.fullName }}</v-list-item-title>
|
||||
<v-list-item-subtitle>
|
||||
{{ user.admin ? "Admin" : "User" }}</v-list-item-subtitle
|
||||
>
|
||||
<v-list-item-subtitle> {{ user.admin ? "Admin" : "User" }}</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</template>
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-list nav dense>
|
||||
<v-list-item
|
||||
v-for="nav in effectiveMenu"
|
||||
:key="nav.title"
|
||||
link
|
||||
:to="nav.to"
|
||||
>
|
||||
<v-list-item v-for="nav in effectiveMenu" :key="nav.title" link :to="nav.to">
|
||||
<v-list-item-icon>
|
||||
<v-icon>{{ nav.icon }}</v-icon>
|
||||
</v-list-item-icon>
|
||||
@@ -228,15 +217,12 @@ export default {
|
||||
this.showSidebar = false;
|
||||
},
|
||||
async getVersion() {
|
||||
let response = await axios.get(
|
||||
"https://api.github.com/repos/hay-kot/mealie/releases/latest",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
Authorization: null,
|
||||
},
|
||||
}
|
||||
);
|
||||
let response = await axios.get("https://api.github.com/repos/hay-kot/mealie/releases/latest", {
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
Authorization: null,
|
||||
},
|
||||
});
|
||||
|
||||
this.latestVersion = response.data.tag_name;
|
||||
},
|
||||
@@ -250,4 +236,4 @@ export default {
|
||||
bottom: 0 !important;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
<template>
|
||||
<div class="text-center">
|
||||
<LoginDialog ref="loginDialog" />
|
||||
<v-menu
|
||||
transition="slide-x-transition"
|
||||
bottom
|
||||
right
|
||||
offset-y
|
||||
offset-overflow
|
||||
open-on-hover
|
||||
close-delay="200"
|
||||
>
|
||||
<v-menu transition="slide-x-transition" bottom right offset-y offset-overflow open-on-hover close-delay="200">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-btn v-bind="attrs" v-on="on" icon>
|
||||
<v-icon>mdi-account</v-icon>
|
||||
@@ -49,7 +41,7 @@ export default {
|
||||
return [
|
||||
{
|
||||
icon: "mdi-account",
|
||||
title: this.$t('user.login'),
|
||||
title: this.$t("user.login"),
|
||||
restricted: false,
|
||||
login: true,
|
||||
},
|
||||
@@ -83,7 +75,7 @@ export default {
|
||||
nav: "/admin",
|
||||
restricted: true,
|
||||
},
|
||||
]
|
||||
];
|
||||
},
|
||||
filteredItems() {
|
||||
if (this.loggedIn) {
|
||||
@@ -108,4 +100,4 @@ export default {
|
||||
.menu-text {
|
||||
text-align: left !important;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user