mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 06:23:34 -07:00
Upload component (#113)
* unified upload button + download backups * javascript toolings * fix vuetur config * fixed type check error * refactor: clean up bag javascript * UI updates + name validation * docs: changelog + sp * fixed route links * changelog Co-authored-by: Hayden <hay-kot@pm.me>
This commit is contained in:
parent
f35e9c20d6
commit
41e079d423
19 changed files with 204 additions and 139 deletions
|
@ -72,7 +72,6 @@ Mealie also provides a secure API for interactions from 3rd party applications.
|
||||||
* [Vue.js](https://vuejs.org/)
|
* [Vue.js](https://vuejs.org/)
|
||||||
* [Vuetify](https://vuetifyjs.com/en/)
|
* [Vuetify](https://vuetifyjs.com/en/)
|
||||||
* [FastAPI](https://fastapi.tiangolo.com/)
|
* [FastAPI](https://fastapi.tiangolo.com/)
|
||||||
* [MongoDB](https://www.mongodb.com/)
|
|
||||||
* [Docker](https://www.docker.com/)
|
* [Docker](https://www.docker.com/)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ Frontend
|
||||||
- [ ] Search Bar redesign
|
- [ ] Search Bar redesign
|
||||||
- [x] Initial
|
- [x] Initial
|
||||||
- [ ] Results redesign
|
- [ ] Results redesign
|
||||||
- [ ] Replace Backups card with something like Home Assistant
|
- [x] Replace Backups card with something like Home Assistant
|
||||||
- [x] Replace import card with something like Home Assistant
|
- [x] Replace import card with something like Home Assistant
|
||||||
- [x] Select which imports to do
|
- [x] Select which imports to do
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,37 @@
|
||||||
# Release Notes
|
# Release Notes
|
||||||
|
|
||||||
|
## V0.2.0 - Now with Test!
|
||||||
|
### Bug Fixes
|
||||||
|
- Remove ability to save recipe with no name
|
||||||
|
- Fixed data validation error on missing parameters
|
||||||
|
- Fixed failed database initialization at startup
|
||||||
|
- Fixed misaligned text on various cards
|
||||||
|
- Fixed bug that blocked opening links in new tabs
|
||||||
|
|
||||||
|
### Features and Improvements
|
||||||
|
- Meal Planner
|
||||||
|
- Improved Search (Fuzzy Search)
|
||||||
|
- New Scheduled card support
|
||||||
|
- Upload/Download backups
|
||||||
|
- Dockerfile now 1/5 of the size!
|
||||||
|
- **Minor**
|
||||||
|
- Continued work on button/style unification
|
||||||
|
- Adding icons to buttons
|
||||||
|
|
||||||
|
### Development
|
||||||
|
- Fixed Vetur config file. Autocomplete in VSCode works!
|
||||||
|
- Added Prettier config
|
||||||
|
- Fixed incorrect layout code
|
||||||
|
- FastAPI Route tests for major operations
|
||||||
|
|
||||||
|
### Breaking Changes
|
||||||
|
- Officially Dropped MongoDB Support
|
||||||
|
- Mounting volume moved to different internal location due to development issues. New volume should be mounted as `mealie/data:/app_data/`
|
||||||
|
|
||||||
## v0.1.0 - Initial Beta
|
## v0.1.0 - Initial Beta
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
- Fixed Can't delete recipe after changing name - Closes Issue #67
|
- Fixed Can't delete recipe after changing name - Closes Issue #67
|
||||||
- Fixed No image when added by URL, and can;t add an image - Closes Issue #66
|
- Fixed No image when added by URL, and can't add an image - Closes Issue #66
|
||||||
- Fixed Images saved with no way to delete when add recipe via URL fails - Closes Issue #43
|
- Fixed Images saved with no way to delete when add recipe via URL fails - Closes Issue #43
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
@ -23,7 +51,7 @@
|
||||||
- Major code refactoring to support new database layer
|
- Major code refactoring to support new database layer
|
||||||
- Global variable refactor
|
- Global variable refactor
|
||||||
|
|
||||||
### Break Changes
|
### Breaking Changes
|
||||||
|
|
||||||
- Internal docker port is now 80 instead of 9000. You MUST remap the internal port to connect to the UI.
|
- Internal docker port is now 80 instead of 9000. You MUST remap the internal port to connect to the UI.
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,6 @@ Mealie also provides an API for interactions from 3rd party applications. **Why
|
||||||
* [Vue.js](https://vuejs.org/)
|
* [Vue.js](https://vuejs.org/)
|
||||||
* [Vuetify](https://vuetifyjs.com/en/)
|
* [Vuetify](https://vuetifyjs.com/en/)
|
||||||
* [FastAPI](https://fastapi.tiangolo.com/)
|
* [FastAPI](https://fastapi.tiangolo.com/)
|
||||||
* [MongoDB](https://www.mongodb.com/)
|
|
||||||
* [Docker](https://www.docker.com/)
|
* [Docker](https://www.docker.com/)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,12 +34,12 @@ Feature placement is not set in stone. This is much more of a guideline than any
|
||||||
- [ ] Category Filter
|
- [ ] Category Filter
|
||||||
- [ ] Tag Filter
|
- [ ] Tag Filter
|
||||||
- [x] Fuzzy Search
|
- [x] Fuzzy Search
|
||||||
- [ ] Backup card redesign
|
- [x] Backup card redesign
|
||||||
- [ ] Additional Backup / Import Features
|
- [ ] Additional Backup / Import Features
|
||||||
- [ ] Import Recipes Force/Rebase options
|
- [ ] Import Recipes Force/Rebase options
|
||||||
- [ ] Upload .zip file
|
- [x] Upload .zip file
|
||||||
- [ ] Improved Color Picker
|
- [ ] Improved Color Picker
|
||||||
- [ ] Meal Plan redesign
|
- [x] Meal Plan redesign
|
||||||
### Backend
|
### Backend
|
||||||
- [ ] PostgreSQL Support
|
- [ ] PostgreSQL Support
|
||||||
- [ ] Setup SQL Migrations
|
- [ ] Setup SQL Migrations
|
||||||
|
@ -48,4 +48,4 @@ Feature placement is not set in stone. This is much more of a guideline than any
|
||||||
- MongoDB support dropped
|
- MongoDB support dropped
|
||||||
## Code Chores
|
## Code Chores
|
||||||
- [x] Remove MongoDB Interface Code
|
- [x] Remove MongoDB Interface Code
|
||||||
- [ ] Dockerfile Trim
|
- [x] Dockerfile Trim
|
||||||
|
|
|
@ -151,11 +151,13 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
get_random(list) {
|
get_random(list) {
|
||||||
const object = list[Math.floor(Math.random() * list.length)];
|
const object = list[Math.floor(Math.random() * list.length)];
|
||||||
return object.slug;
|
return object;
|
||||||
},
|
},
|
||||||
random() {
|
random() {
|
||||||
this.meals.forEach((element, index) => {
|
this.meals.forEach((element, index) => {
|
||||||
this.meals[index]["slug"] = this.get_random(this.items);
|
let recipe = this.get_random(this.items);
|
||||||
|
this.meals[index]["slug"] = recipe.slug;
|
||||||
|
this.meals[index]["name"] = recipe.name;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
processTime(index) {
|
processTime(index) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<v-form ref="form">
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-row dense>
|
<v-row dense>
|
||||||
<v-col cols="3"></v-col>
|
<v-col cols="3"></v-col>
|
||||||
|
@ -33,14 +33,26 @@
|
||||||
></v-col>
|
></v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-row>
|
</v-row>
|
||||||
<v-text-field class="my-3" :label="$t('recipe.recipe-name')" v-model="value.name">
|
<v-text-field
|
||||||
|
class="my-3"
|
||||||
|
:label="$t('recipe.recipe-name')"
|
||||||
|
v-model="value.name"
|
||||||
|
:rules="[rules.required, rules.whiteSpace]"
|
||||||
|
>
|
||||||
</v-text-field>
|
</v-text-field>
|
||||||
<v-textarea height="100" :label="$t('recipe.description')" v-model="value.description">
|
<v-textarea
|
||||||
|
height="100"
|
||||||
|
:label="$t('recipe.description')"
|
||||||
|
v-model="value.description"
|
||||||
|
>
|
||||||
</v-textarea>
|
</v-textarea>
|
||||||
<div class="my-2"></div>
|
<div class="my-2"></div>
|
||||||
<v-row dense disabled>
|
<v-row dense disabled>
|
||||||
<v-col sm="5">
|
<v-col sm="5">
|
||||||
<v-text-field :label="$t('recipe.servings')" v-model="value.recipeYield">
|
<v-text-field
|
||||||
|
:label="$t('recipe.servings')"
|
||||||
|
v-model="value.recipeYield"
|
||||||
|
>
|
||||||
</v-text-field>
|
</v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col></v-col>
|
<v-col></v-col>
|
||||||
|
@ -54,7 +66,7 @@
|
||||||
</v-row>
|
</v-row>
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" sm="12" md="4" lg="4">
|
<v-col cols="12" sm="12" md="4" lg="4">
|
||||||
<h2 class="mb-4">{{$t('recipe.ingredients')}}</h2>
|
<h2 class="mb-4">{{ $t("recipe.ingredients") }}</h2>
|
||||||
<div
|
<div
|
||||||
v-for="(ingredient, index) in value.recipeIngredient"
|
v-for="(ingredient, index) in value.recipeIngredient"
|
||||||
:key="generateKey('ingredient', index)"
|
:key="generateKey('ingredient', index)"
|
||||||
|
@ -81,7 +93,7 @@
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<BulkAdd @bulk-data="appendIngredients" />
|
<BulkAdd @bulk-data="appendIngredients" />
|
||||||
|
|
||||||
<h2 class="mt-6">{{$t('recipe.categories')}}</h2>
|
<h2 class="mt-6">{{ $t("recipe.categories") }}</h2>
|
||||||
<v-combobox
|
<v-combobox
|
||||||
dense
|
dense
|
||||||
multiple
|
multiple
|
||||||
|
@ -103,7 +115,7 @@
|
||||||
</template>
|
</template>
|
||||||
</v-combobox>
|
</v-combobox>
|
||||||
|
|
||||||
<h2 class="mt-4">{{$t('recipe.tags')}}</h2>
|
<h2 class="mt-4">{{ $t("recipe.tags") }}</h2>
|
||||||
<v-combobox dense multiple chips deletable-chips v-model="value.tags">
|
<v-combobox dense multiple chips deletable-chips v-model="value.tags">
|
||||||
<template v-slot:selection="data">
|
<template v-slot:selection="data">
|
||||||
<v-chip
|
<v-chip
|
||||||
|
@ -118,7 +130,7 @@
|
||||||
</template>
|
</template>
|
||||||
</v-combobox>
|
</v-combobox>
|
||||||
|
|
||||||
<h2 class="my-4">{{$t('recipe.notes')}}</h2>
|
<h2 class="my-4">{{ $t("recipe.notes") }}</h2>
|
||||||
<v-card
|
<v-card
|
||||||
class="mt-1"
|
class="mt-1"
|
||||||
v-for="(note, index) in value.notes"
|
v-for="(note, index) in value.notes"
|
||||||
|
@ -142,7 +154,10 @@
|
||||||
></v-text-field>
|
></v-text-field>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
<v-textarea :label="$t('recipe.note')" v-model="value.notes[index]['text']">
|
<v-textarea
|
||||||
|
:label="$t('recipe.note')"
|
||||||
|
v-model="value.notes[index]['text']"
|
||||||
|
>
|
||||||
</v-textarea>
|
</v-textarea>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
@ -155,7 +170,7 @@
|
||||||
<v-divider class="my-divider" :vertical="true"></v-divider>
|
<v-divider class="my-divider" :vertical="true"></v-divider>
|
||||||
|
|
||||||
<v-col cols="12" sm="12" md="8" lg="8">
|
<v-col cols="12" sm="12" md="8" lg="8">
|
||||||
<h2 class="mb-4">{{$t('recipe.instructions')}}</h2>
|
<h2 class="mb-4">{{ $t("recipe.instructions") }}</h2>
|
||||||
<div v-for="(step, index) in value.recipeInstructions" :key="index">
|
<div v-for="(step, index) in value.recipeInstructions" :key="index">
|
||||||
<v-hover v-slot="{ hover }">
|
<v-hover v-slot="{ hover }">
|
||||||
<v-card
|
<v-card
|
||||||
|
@ -173,7 +188,9 @@
|
||||||
@click="removeStep(index)"
|
@click="removeStep(index)"
|
||||||
>
|
>
|
||||||
<v-icon color="error">mdi-delete</v-icon> </v-btn
|
<v-icon color="error">mdi-delete</v-icon> </v-btn
|
||||||
>{{ $t('recipe.step-index', {step: index + 1}) }}</v-card-title
|
>{{
|
||||||
|
$t("recipe.step-index", { step: index + 1 })
|
||||||
|
}}</v-card-title
|
||||||
>
|
>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-textarea
|
<v-textarea
|
||||||
|
@ -192,7 +209,7 @@
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</div>
|
</v-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -211,6 +228,11 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
fileObject: null,
|
fileObject: null,
|
||||||
|
rules: {
|
||||||
|
required: v => !!v || "Key Name Required",
|
||||||
|
whiteSpace: v =>
|
||||||
|
!v || v.split(" ").length <= 1 || "No White Space Allowed",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -259,7 +281,7 @@ export default {
|
||||||
|
|
||||||
appendSteps(steps) {
|
appendSteps(steps) {
|
||||||
let processSteps = [];
|
let processSteps = [];
|
||||||
steps.forEach((element) => {
|
steps.forEach(element => {
|
||||||
processSteps.push({ text: element });
|
processSteps.push({ text: element });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -289,6 +311,13 @@ export default {
|
||||||
saveExtras(extras) {
|
saveExtras(extras) {
|
||||||
this.value.extras = extras;
|
this.value.extras = extras;
|
||||||
},
|
},
|
||||||
|
validateRecipe() {
|
||||||
|
if (this.$refs.form.validate()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -65,14 +65,14 @@
|
||||||
<v-divider></v-divider>
|
<v-divider></v-divider>
|
||||||
|
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-btn color="success" text :href="`/api/backups/${name}/download/`">
|
<v-btn color="accent" text :href="`/api/backups/${name}/download/`">
|
||||||
{{ $t("general.download") }}
|
{{ $t("general.download") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn color="error" text @click="raiseEvent('delete')">
|
<v-btn color="error" text @click="raiseEvent('delete')">
|
||||||
{{ $t("general.delete") }}
|
{{ $t("general.delete") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn color="success" text @click="raiseEvent('import')">
|
<v-btn color="success" outlined @click="raiseEvent('import')">
|
||||||
{{ $t("general.import") }}
|
{{ $t("general.import") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
<v-divider class="my-3"></v-divider>
|
<v-divider class="my-3"></v-divider>
|
||||||
<v-card-title class="mt-n6">
|
<v-card-title class="mt-n6">
|
||||||
Available Backups
|
Available Backups
|
||||||
<v-spacer></v-spacer>
|
|
||||||
<span>
|
<span>
|
||||||
<UploadBtn
|
<UploadBtn
|
||||||
class="mt-1"
|
class="mt-1"
|
||||||
|
@ -27,6 +26,7 @@
|
||||||
@uploaded="getAvailableBackups"
|
@uploaded="getAvailableBackups"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
<AvailableBackupCard
|
<AvailableBackupCard
|
||||||
@loading="backupLoading = true"
|
@loading="backupLoading = true"
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<p>
|
<p>
|
||||||
{{$t('migration.currently-chowdown-via-public-repo-url-is-the-only-supported-type-of-migration')}}
|
{{
|
||||||
|
$t(
|
||||||
|
"migration.currently-chowdown-via-public-repo-url-is-the-only-supported-type-of-migration"
|
||||||
|
)
|
||||||
|
}}
|
||||||
</p>
|
</p>
|
||||||
<v-form ref="form">
|
<v-form ref="form">
|
||||||
<v-row dense align="center">
|
<v-row dense align="center">
|
||||||
|
@ -14,12 +18,15 @@
|
||||||
</v-text-field>
|
</v-text-field>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" md="4" sm="5">
|
<v-col cols="12" md="4" sm="5">
|
||||||
<v-btn text color="info" @click="importRepo"> {{$t('migration.migrate')}} </v-btn>
|
<v-btn text color="info" @click="importRepo">
|
||||||
|
<v-icon left> mdi-import </v-icon>
|
||||||
|
{{ $t("migration.migrate") }}
|
||||||
|
</v-btn>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-form>
|
</v-form>
|
||||||
<v-alert v-if="failedRecipes[1]" outlined dense type="error">
|
<v-alert v-if="failedRecipes[1]" outlined dense type="error">
|
||||||
<h4>{{$t('migration.failed-recipes')}}</h4>
|
<h4>{{ $t("migration.failed-recipes") }}</h4>
|
||||||
<v-list dense>
|
<v-list dense>
|
||||||
<v-list-item v-for="fail in this.failedRecipes" :key="fail">
|
<v-list-item v-for="fail in this.failedRecipes" :key="fail">
|
||||||
{{ fail }}
|
{{ fail }}
|
||||||
|
@ -27,7 +34,7 @@
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-alert>
|
</v-alert>
|
||||||
<v-alert v-if="failedImages[1]" outlined dense type="error">
|
<v-alert v-if="failedImages[1]" outlined dense type="error">
|
||||||
<h4>{{$t('migration.failed-images')}}</h4>
|
<h4>{{ $t("migration.failed-images") }}</h4>
|
||||||
<v-list dense>
|
<v-list dense>
|
||||||
<v-list-item v-for="fail in this.failedImages" :key="fail">
|
<v-list-item v-for="fail in this.failedImages" :key="fail">
|
||||||
{{ fail }}
|
{{ fail }}
|
||||||
|
@ -49,7 +56,7 @@ export default {
|
||||||
failedRecipes: [],
|
failedRecipes: [],
|
||||||
repo: "",
|
repo: "",
|
||||||
rules: {
|
rules: {
|
||||||
required: (v) => !!v || "Selection Required",
|
required: v => !!v || "Selection Required",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -20,9 +20,11 @@
|
||||||
<v-col md="1" sm="12">
|
<v-col md="1" sm="12">
|
||||||
<v-btn-toggle group>
|
<v-btn-toggle group>
|
||||||
<v-btn text color="info" @click="importRecipes">
|
<v-btn text color="info" @click="importRecipes">
|
||||||
|
<v-icon left> mdi-import </v-icon>
|
||||||
{{ $t("migration.migrate") }}
|
{{ $t("migration.migrate") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn text color="error" @click="deleteImportValidation">
|
<v-btn text color="error" @click="deleteImportValidation">
|
||||||
|
<v-icon left> mdi-delete </v-icon>
|
||||||
{{ $t("general.delete") }}
|
{{ $t("general.delete") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<UploadBtn
|
<UploadBtn
|
||||||
|
|
|
@ -126,6 +126,7 @@
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn color="success" @click="saveThemes" class="mr-2">
|
<v-btn color="success" @click="saveThemes" class="mr-2">
|
||||||
|
<v-icon left> mdi-content-save </v-icon>
|
||||||
{{ $t("general.save") }}
|
{{ $t("general.save") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
|
|
|
@ -15,18 +15,14 @@
|
||||||
|
|
||||||
<v-row dense align="center">
|
<v-row dense align="center">
|
||||||
<v-col cols="12" md="2" sm="5">
|
<v-col cols="12" md="2" sm="5">
|
||||||
<v-switch
|
<v-switch v-model="enabled" :label="$t('general.enabled')"></v-switch>
|
||||||
v-model="enabled"
|
|
||||||
inset
|
|
||||||
:label="$t('general.enabled')"
|
|
||||||
class="my-n3"
|
|
||||||
></v-switch>
|
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" md="3" sm="5">
|
<v-col cols="12" md="3" sm="5">
|
||||||
<TimePickerDialog @save-time="saveTime" />
|
<TimePickerDialog @save-time="saveTime" />
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" md="4" sm="5">
|
<v-col cols="12" md="4" sm="5">
|
||||||
<v-btn text color="info" @click="testWebhooks">
|
<v-btn text color="info" @click="testWebhooks">
|
||||||
|
<v-icon left> mdi-webhook </v-icon>
|
||||||
{{ $t("settings.webhooks.test-webhooks") }}
|
{{ $t("settings.webhooks.test-webhooks") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
@ -47,19 +43,14 @@
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-row>
|
|
||||||
<v-col>
|
|
||||||
<v-btn icon color="success" @click="addWebhook">
|
<v-btn icon color="success" @click="addWebhook">
|
||||||
<v-icon>mdi-plus</v-icon>
|
<v-icon>mdi-plus</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-col>
|
<v-spacer></v-spacer>
|
||||||
<v-col> </v-col>
|
|
||||||
<v-col align="end">
|
|
||||||
<v-btn color="success" @click="saveWebhooks" class="mr-2 mb-1">
|
<v-btn color="success" @click="saveWebhooks" class="mr-2 mb-1">
|
||||||
{{ $t("settings.webhooks.save-webhooks") }}
|
<v-icon left> mdi-content-save </v-icon>
|
||||||
|
{{ $t("general.save") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
<v-card
|
<v-card
|
||||||
:class="{ 'on-hover': hover }"
|
:class="{ 'on-hover': hover }"
|
||||||
:elevation="hover ? 12 : 2"
|
:elevation="hover ? 12 : 2"
|
||||||
@click="moreInfo(slug)"
|
:to="route ? `/recipe/${slug}` : ''"
|
||||||
|
@click="$emit('click')"
|
||||||
>
|
>
|
||||||
<v-img height="200" :src="getImage(image)"></v-img>
|
<v-img height="200" :src="getImage(image)"></v-img>
|
||||||
<v-card-title class="my-n3 mb-n6">{{ name | truncate(30) }}</v-card-title>
|
<v-card-title class="my-n3 mb-n6">{{ name | truncate(30) }}</v-card-title>
|
||||||
|
@ -52,11 +53,6 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
moreInfo(recipeSlug) {
|
|
||||||
if (this.route) {
|
|
||||||
this.$router.push(`/recipe/${recipeSlug}`);
|
|
||||||
} else this.$emit("click");
|
|
||||||
},
|
|
||||||
getImage(image) {
|
getImage(image) {
|
||||||
return utils.getImageURL(image);
|
return utils.getImageURL(image);
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,13 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<v-form ref="file">
|
<v-form ref="file">
|
||||||
<input ref="uploader" class="d-none" type="file" @change="onFileChanged" />
|
<input ref="uploader" class="d-none" type="file" @change="onFileChanged" />
|
||||||
<v-btn
|
<v-btn :loading="isSelecting" @click="onButtonClick" color="accent" text>
|
||||||
:loading="isSelecting"
|
<v-icon left> mdi-cloud-upload </v-icon>
|
||||||
@click="onButtonClick"
|
|
||||||
color="success"
|
|
||||||
text
|
|
||||||
>
|
|
||||||
<v-icon left > mdi-cloud-upload </v-icon>
|
|
||||||
Upload
|
Upload
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-form>
|
</v-form>
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
{{ $t("meal-plan.meal-plans") }}
|
{{ $t("meal-plan.meal-plans") }}
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
<v-divider></v-divider>
|
<v-divider></v-divider>
|
||||||
|
</v-card>
|
||||||
<v-row no-gutters>
|
<v-row dense>
|
||||||
<v-col
|
<v-col
|
||||||
:sm="6"
|
:sm="6"
|
||||||
:md="6"
|
:md="6"
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
v-for="(mealplan, i) in plannedMeals"
|
v-for="(mealplan, i) in plannedMeals"
|
||||||
:key="i"
|
:key="i"
|
||||||
>
|
>
|
||||||
<v-card class="ml-2 mt-2 mr-0">
|
<v-card class="mt-1">
|
||||||
<v-card-title>
|
<v-card-title>
|
||||||
{{ formatDate(mealplan.startDate) }} -
|
{{ formatDate(mealplan.startDate) }} -
|
||||||
{{ formatDate(mealplan.endDate) }}
|
{{ formatDate(mealplan.endDate) }}
|
||||||
|
@ -70,7 +70,6 @@
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-card>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -23,14 +23,16 @@
|
||||||
<v-card-text> {{ meal.description }} </v-card-text>
|
<v-card-text> {{ meal.description }} </v-card-text>
|
||||||
|
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
<v-btn
|
<v-btn
|
||||||
align="center"
|
align="center"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
text
|
text
|
||||||
@click="$router.push(`/recipe/${meal.slug}`)"
|
@click="$router.push(`/recipe/${meal.slug}`)"
|
||||||
>
|
>
|
||||||
{{$t('recipe.view-recipe')}}
|
{{ $t("recipe.view-recipe") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
|
@ -29,7 +29,12 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<RecipeEditor v-else v-model="recipeDetails" @upload="getImage" />
|
<RecipeEditor
|
||||||
|
ref="recipeEditor"
|
||||||
|
v-else
|
||||||
|
v-model="recipeDetails"
|
||||||
|
@upload="getImage"
|
||||||
|
/>
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -85,6 +90,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
async createRecipe() {
|
async createRecipe() {
|
||||||
|
if (this.$refs.recipeEditor.validateRecipe()) {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
|
||||||
if (this.fileObject) {
|
if (this.fileObject) {
|
||||||
|
@ -99,6 +105,7 @@ export default {
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
|
|
||||||
this.$router.push(`/recipe/${slug}`);
|
this.$router.push(`/recipe/${slug}`);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,7 +45,12 @@
|
||||||
height="1500px"
|
height="1500px"
|
||||||
:options="jsonEditorOptions"
|
:options="jsonEditorOptions"
|
||||||
/>
|
/>
|
||||||
<RecipeEditor v-else v-model="recipeDetails" @upload="getImageFile" />
|
<RecipeEditor
|
||||||
|
v-else
|
||||||
|
v-model="recipeDetails"
|
||||||
|
ref="recipeEditor"
|
||||||
|
@upload="getImageFile"
|
||||||
|
/>
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -101,7 +106,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
$route: function () {
|
$route: function() {
|
||||||
this.getRecipeDetails();
|
this.getRecipeDetails();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -138,6 +143,9 @@ export default {
|
||||||
api.recipes.delete(this.recipeDetails.slug);
|
api.recipes.delete(this.recipeDetails.slug);
|
||||||
},
|
},
|
||||||
async saveRecipe() {
|
async saveRecipe() {
|
||||||
|
if (this.$refs.recipeEditor.validateRecipe()) {
|
||||||
|
console.log("Thank you")
|
||||||
|
}
|
||||||
let slug = await api.recipes.update(this.recipeDetails);
|
let slug = await api.recipes.update(this.recipeDetails);
|
||||||
|
|
||||||
if (this.fileObject) {
|
if (this.fileObject) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue