Rewrite Recipe Editor Buttons Bar (#482)

* rewrite editor button row

* add context menu items to recipe page

Co-authored-by: hay-kot <hay-kot@pm.me>
This commit is contained in:
Hayden 2021-06-10 18:32:03 -08:00 committed by GitHub
parent c175c8e9a0
commit ead02737ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 221 additions and 116 deletions

View File

@ -8,15 +8,23 @@
ref="deleteRecipieConfirm"
v-on:confirm="deleteRecipe()"
/>
<v-menu offset-y top left>
<v-menu
offset-y
left
:bottom="!menuTop"
:nudge-bottom="!menuTop ? '5' : '0'"
:top="menuTop"
:nudge-top="menuTop ? '5' : '0'"
allow-overflow
>
<template v-slot:activator="{ on, attrs }">
<v-btn color="primary" icon dark v-bind="attrs" v-on="on" @click.prevent>
<v-btn :fab="fab" small="fab" :color="color" :icon="!fab" dark v-bind="attrs" v-on="on" @click.prevent>
<v-icon>{{ menuIcon }}</v-icon>
</v-btn>
</template>
<v-list dense>
<v-list-item
v-for="(item, index) in loggedIn ? userMenu : defaultMenu"
v-for="(item, index) in loggedIn && cardMenu ? userMenu : defaultMenu"
:key="index"
@click="menuAction(item.action)"
>
@ -39,6 +47,18 @@ export default {
ConfirmationDialog,
},
props: {
menuTop: {
type: Boolean,
default: true,
},
fab: {
type: Boolean,
default: false,
},
color: {
type: String,
default: "primary",
},
slug: {
type: String,
},
@ -48,6 +68,10 @@ export default {
name: {
type: String,
},
cardMenu: {
type: Boolean,
default: true,
},
},
computed: {
loggedIn() {
@ -118,7 +142,7 @@ export default {
url: this.recipeURL,
})
.then(() => console.log("Successful share"))
.catch(error => {
.catch((error) => {
console.log("WebShareAPI not supported", error);
this.updateClipboard();
});

View File

@ -1,97 +0,0 @@
<template>
<v-expand-transition>
<v-toolbar
class="card-btn pt-1"
flat
:height="isSticky ? null : '0'"
:extension-height="isSticky ? '20' : '0'"
color="rgb(255, 0, 0, 0.0)"
>
<ConfirmationDialog
:title="$t('recipe.delete-recipe')"
:message="$t('recipe.delete-confirmation')"
color="error"
icon="mdi-alert-circle"
ref="deleteRecipieConfirm"
v-on:confirm="deleteRecipe()"
/>
<template v-slot:extension>
<v-col></v-col>
<div v-if="open">
<v-btn class="mr-2" fab dark small color="error" @click="deleteRecipeConfrim">
<v-icon>{{ $globals.icons.delete }}</v-icon>
</v-btn>
<v-btn class="mr-2" fab dark small color="success" @click="save">
<v-icon>{{ $globals.icons.save }}</v-icon>
</v-btn>
<v-btn class="mr-5" fab dark small color="secondary" @click="json">
<v-icon>mdi-code-braces</v-icon>
</v-btn>
</div>
<v-btn color="accent" fab dark small @click="editor">
<v-icon>{{ $globals.icons.edit }}</v-icon>
</v-btn>
</template>
</v-toolbar>
</v-expand-transition>
</template>
<script>
import ConfirmationDialog from "@/components/UI/Dialogs/ConfirmationDialog.vue";
export default {
props: {
open: {
type: Boolean,
default: true,
},
},
components: {
ConfirmationDialog,
},
data() {
return {
stickyTop: 50,
scrollPosition: null,
};
},
mounted() {
window.addEventListener("scroll", this.updateScroll);
},
destroy() {
window.removeEventListener("scroll", this.updateScroll);
},
computed: {
isSticky() {
return this.scrollPosition >= 500;
},
},
methods: {
editor() {
this.$emit("editor");
},
save() {
this.$emit("save");
},
updateScroll() {
this.scrollPosition = window.scrollY;
},
deleteRecipeConfrim() {
this.$refs.deleteRecipieConfirm.open();
},
deleteRecipe() {
this.$emit("delete");
},
json() {
this.$emit("json");
},
},
};
</script>
<style></style>

View File

@ -0,0 +1,164 @@
<template>
<v-toolbar
rounded
height="0"
class="fixed-bar mt-0"
color="rgb(255, 0, 0, 0.0)"
flat
style="z-index: 2; position: sticky"
:class="{ 'fixed-bar-mobile': $vuetify.breakpoint.xs }"
>
<ConfirmationDialog
:title="$t('recipe.delete-recipe')"
:message="$t('recipe.delete-confirmation')"
color="error"
icon="mdi-alert-circle"
ref="deleteRecipieConfirm"
v-on:confirm="emitDelete()"
/>
<v-spacer></v-spacer>
<div v-if="!edit" class="custom-btn-group ma-1">
<v-btn
fab
small
class="mx-1"
color="info"
@click="
edit = true;
$emit('edit');
"
>
<v-icon> {{ $globals.icons.edit }} </v-icon>
</v-btn>
<ContextMenu
:menu-top="false"
:slug="slug"
:name="name"
menu-icon="mdi-dots-horizontal"
fab
color="info"
:card-menu="false"
/>
</div>
<div v-if="edit" class="custom-btn-group mb-">
<v-btn
v-for="(btn, index) in editorButtons"
:key="index"
:fab="$vuetify.breakpoint.xs"
:small="$vuetify.breakpoint.xs"
class="mx-1"
:color="btn.color"
@click="emitHandler(btn.event)"
>
<v-icon :left="!$vuetify.breakpoint.xs">{{ btn.icon }}</v-icon>
{{ $vuetify.breakpoint.xs ? "" : btn.text }}
</v-btn>
</div>
</v-toolbar>
</template>
<script>
import ConfirmationDialog from "@/components/UI/Dialogs/ConfirmationDialog.vue";
import ContextMenu from "@/components/Recipe/ContextMenu.vue";
const SAVE_EVENT = "save";
const DELETE_EVENT = "delete";
const CLOSE_EVENT = "close";
const JSON_EVENT = "json";
export default {
components: { ConfirmationDialog, ContextMenu },
props: {
slug: {
type: String,
},
name: {
type: String,
},
},
data() {
return {
edit: false,
editorButtons: [
{
text: "Delete",
icon: this.$globals.icons.delete,
event: DELETE_EVENT,
color: "error",
},
{
text: "JSON",
icon: "mdi-code-braces",
event: JSON_EVENT,
color: "accent",
},
{
text: "Close",
icon: "mdi-close",
event: CLOSE_EVENT,
color: undefined,
},
{
text: "Save",
icon: this.$globals.icons.save,
event: SAVE_EVENT,
color: "success",
},
],
};
},
methods: {
emitHandler(event) {
switch (event) {
case CLOSE_EVENT:
this.$emit(CLOSE_EVENT);
this.edit = false;
break;
case SAVE_EVENT:
this.$emit(SAVE_EVENT);
this.edit = false;
break;
case JSON_EVENT:
this.$emit(JSON_EVENT);
break;
case DELETE_EVENT:
this.$refs.deleteRecipieConfirm.open();
break;
default:
break;
}
},
emitDelete() {
this.$emit(DELETE_EVENT);
this.edit = false;
},
},
};
</script>
<style scoped>
.custom-btn-group {
flex: 0, 1, auto;
display: inline-flex;
}
.vertical {
flex-direction: column !important;
}
.sticky {
margin-left: auto;
position: fixed !important;
margin-top: 4.25rem;
}
.fixed-bar {
position: sticky;
position: -webkit-sticky; /* for Safari */
top: 4.5em;
z-index: 2;
}
.fixed-bar-mobile {
top: 1.5em !important;
}
</style>

View File

@ -10,7 +10,7 @@
</v-img>
<br v-else />
<EditorButtonRow @json="jsonEditor = true" @editor="jsonEditor = false" @save="createRecipe" />
<RecipePageActionMenu @json="jsonEditor = true" @edit="jsonEditor = false" @save="createRecipe" />
<div v-if="jsonEditor">
<!-- Probably not the best way, but it works! -->
@ -29,12 +29,12 @@ import { api } from "@/api";
import RecipeEditor from "@/components/Recipe/RecipeEditor";
import VJsoneditor from "v-jsoneditor";
import EditorButtonRow from "@/components/Recipe/EditorButtonRow";
import RecipePageActionMenu from "@/components/Recipe/RecipePageActionMenu";
export default {
components: {
VJsoneditor,
RecipeEditor,
EditorButtonRow,
RecipePageActionMenu,
},
data() {
return {

View File

@ -6,7 +6,7 @@
<NoRecipe v-else-if="loadFailed" />
<v-card v-else-if="!loadFailed" id="myRecipe" class="d-print-none">
<v-img
:height="hideImage ? '40' : imageHeight"
:height="hideImage ? '50' : imageHeight"
@error="hideImage = true"
:src="getImage(recipeDetails.slug)"
class="d-print-none"
@ -20,17 +20,20 @@
:performTime="recipeDetails.performTime"
/>
</v-img>
<EditorButtonRow
<RecipePageActionMenu
:slug="recipeDetails.slug"
:name="recipeDetails.name"
v-if="loggedIn"
:open="showIcons"
@json="jsonEditor = true"
@editor="
@close="form = false"
@json="jsonEditor = !jsonEditor"
@edit="
jsonEditor = false;
form = true;
"
@save="saveRecipe"
@delete="deleteRecipe"
class="sticky"
class="ml-auto"
/>
<RecipeViewer v-if="!form" :recipe="recipeDetails" />
@ -42,7 +45,13 @@
height="1500px"
:options="jsonEditorOptions"
/>
<RecipeEditor v-else v-model="recipeDetails" ref="recipeEditor" @upload="getImageFile" />
<RecipeEditor
v-else
v-model="recipeDetails"
:class="$vuetify.breakpoint.xs ? 'mt-5' : undefiend"
ref="recipeEditor"
@upload="getImageFile"
/>
</v-card>
<CommentsSection
class="mt-2 d-print-none"
@ -56,6 +65,7 @@
</template>
<script>
import RecipePageActionMenu from "@/components/Recipe/RecipePageActionMenu.vue";
import { api } from "@/api";
import FavoriteBadge from "@/components/Recipe/FavoriteBadge";
import VJsoneditor from "v-jsoneditor";
@ -63,7 +73,6 @@ import RecipeViewer from "@/components/Recipe/RecipeViewer";
import PrintView from "@/components/Recipe/PrintView";
import RecipeEditor from "@/components/Recipe/RecipeEditor";
import RecipeTimeCard from "@/components/Recipe/RecipeTimeCard.vue";
import EditorButtonRow from "@/components/Recipe/EditorButtonRow.vue";
import NoRecipe from "@/components/Fallbacks/NoRecipe";
import { user } from "@/mixins/user";
import { router } from "@/routes";
@ -74,8 +83,8 @@ export default {
VJsoneditor,
RecipeViewer,
RecipeEditor,
EditorButtonRow,
RecipeTimeCard,
RecipePageActionMenu,
PrintView,
NoRecipe,
FavoriteBadge,
@ -126,15 +135,13 @@ export default {
this.jsonEditor = false;
this.form = this.$route.query.edit === "true" && this.loggedIn;
if (this.$route.query.print) {
this.printPage();
this.$router.push(this.$route.path);
}
this.checkPrintRecipe();
},
watch: {
$route: function () {
this.getRecipeDetails();
this.checkPrintRecipe();
},
},
@ -166,6 +173,13 @@ export default {
},
},
methods: {
checkPrintRecipe() {
if (this.$route.query.print) {
this.printPage();
this.$router.push(this.$route.path);
this.$route.query.print = null;
}
},
getImageFile(fileObject) {
this.fileObject = fileObject;
this.saveImage();