mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-23 06:45:22 -07:00
RecipeTimelineContextMenu script setup and no emit mutation
This commit is contained in:
parent
4ce1f5c926
commit
4a2d248c43
1 changed files with 102 additions and 143 deletions
|
@ -6,12 +6,12 @@
|
||||||
:icon="$globals.icons.edit"
|
:icon="$globals.icons.edit"
|
||||||
can-submit
|
can-submit
|
||||||
:submit-text="$t('general.save')"
|
:submit-text="$t('general.save')"
|
||||||
@submit="$emit('update')"
|
@submit="submitEdit"
|
||||||
>
|
>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-form ref="domMadeThisForm">
|
<v-form ref="domEditEventForm">
|
||||||
<v-text-field v-model="event.subject" :label="$t('general.subject')" />
|
<v-text-field v-model="localEvent.subject" :label="$t('general.subject')" />
|
||||||
<v-textarea v-model="event.eventMessage" :label="$t('general.message')" rows="4" />
|
<v-textarea v-model="localEvent.eventMessage" :label="$t('general.message')" rows="4" />
|
||||||
</v-form>
|
</v-form>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
|
@ -25,30 +25,30 @@
|
||||||
@confirm="$emit('delete')"
|
@confirm="$emit('delete')"
|
||||||
>
|
>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
{{ $t("events.event-delete-confirmation") }}
|
{{ $t('events.event-delete-confirmation') }}
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
|
|
||||||
<v-menu
|
<v-menu
|
||||||
offset-y
|
offset-y
|
||||||
start
|
start
|
||||||
:bottom="!menuTop"
|
:bottom="!props.menuTop"
|
||||||
:nudge-bottom="!menuTop ? '5' : '0'"
|
:nudge-bottom="!props.menuTop ? '5' : '0'"
|
||||||
:top="menuTop"
|
:top="props.menuTop"
|
||||||
:nudge-top="menuTop ? '5' : '0'"
|
:nudge-top="props.menuTop ? '5' : '0'"
|
||||||
allow-overflow
|
allow-overflow
|
||||||
close-delay="125"
|
close-delay="125"
|
||||||
:open-on-hover="!useMobileFormat"
|
:open-on-hover="!props.useMobileFormat"
|
||||||
content-class="d-print-none"
|
content-class="d-print-none"
|
||||||
>
|
>
|
||||||
<template #activator="{ props }">
|
<template #activator="{ props: btnProps }">
|
||||||
<v-btn
|
<v-btn
|
||||||
:class="{ 'rounded-circle': fab }"
|
:class="{ 'rounded-circle': props.fab }"
|
||||||
:x-small="fab"
|
:x-small="props.fab"
|
||||||
:elevation="elevation"
|
:elevation="props.elevation ?? undefined"
|
||||||
:color="color"
|
:color="props.color"
|
||||||
:icon="!fab"
|
:icon="!props.fab"
|
||||||
v-bind="props"
|
v-bind="btnProps"
|
||||||
@click.prevent
|
@click.prevent
|
||||||
>
|
>
|
||||||
<v-icon>{{ icon }}</v-icon>
|
<v-icon>{{ icon }}</v-icon>
|
||||||
|
@ -72,7 +72,8 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
|
import { useI18n, useNuxtApp } from "#imports";
|
||||||
import type { RecipeTimelineEventOut } from "~/lib/api/types/recipe";
|
import type { RecipeTimelineEventOut } from "~/lib/api/types/recipe";
|
||||||
|
|
||||||
export interface TimelineContextMenuIncludes {
|
export interface TimelineContextMenuIncludes {
|
||||||
|
@ -87,70 +88,29 @@ export interface ContextMenuItem {
|
||||||
event: string;
|
event: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineNuxtComponent({
|
const props = defineProps<{
|
||||||
props: {
|
useItems?: TimelineContextMenuIncludes;
|
||||||
useItems: {
|
appendItems?: ContextMenuItem[];
|
||||||
type: Object as () => TimelineContextMenuIncludes,
|
leadingItems?: ContextMenuItem[];
|
||||||
default: () => ({
|
menuTop?: boolean;
|
||||||
edit: true,
|
fab?: boolean;
|
||||||
delete: true,
|
elevation?: number | null;
|
||||||
}),
|
color?: string;
|
||||||
},
|
event: RecipeTimelineEventOut;
|
||||||
// Append items are added at the end of the useItems list
|
menuIcon?: string | null;
|
||||||
appendItems: {
|
useMobileFormat?: boolean;
|
||||||
type: Array as () => ContextMenuItem[],
|
}>();
|
||||||
default: () => [],
|
|
||||||
},
|
const emit = defineEmits(["delete", "update"]);
|
||||||
// Append items are added at the beginning of the useItems list
|
|
||||||
leadingItems: {
|
const domEditEventForm = ref();
|
||||||
type: Array as () => ContextMenuItem[],
|
const recipeEventEditDialog = ref(false);
|
||||||
default: () => [],
|
const recipeEventDeleteDialog = ref(false);
|
||||||
},
|
const loading = ref(false);
|
||||||
menuTop: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
fab: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
elevation: {
|
|
||||||
type: Number,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
color: {
|
|
||||||
type: String,
|
|
||||||
default: "primary",
|
|
||||||
},
|
|
||||||
event: {
|
|
||||||
type: Object as () => RecipeTimelineEventOut,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
menuIcon: {
|
|
||||||
type: String,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
useMobileFormat: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
emits: ["delete", "update"],
|
|
||||||
setup(props, context) {
|
|
||||||
const domEditEventForm = ref<VForm>();
|
|
||||||
const state = reactive({
|
|
||||||
recipeEventEditDialog: false,
|
|
||||||
recipeEventDeleteDialog: false,
|
|
||||||
loading: false,
|
|
||||||
menuItems: [] as ContextMenuItem[],
|
|
||||||
});
|
|
||||||
|
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const { $globals } = useNuxtApp();
|
const { $globals } = useNuxtApp();
|
||||||
|
|
||||||
// ===========================================================================
|
|
||||||
// Context Menu Setup
|
|
||||||
|
|
||||||
const defaultItems: { [key: string]: ContextMenuItem } = {
|
const defaultItems: { [key: string]: ContextMenuItem } = {
|
||||||
edit: {
|
edit: {
|
||||||
title: i18n.t("general.edit"),
|
title: i18n.t("general.edit"),
|
||||||
|
@ -166,53 +126,52 @@ export default defineNuxtComponent({
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get Default Menu Items Specified in Props
|
const menuItems = computed(() => {
|
||||||
for (const [key, value] of Object.entries(props.useItems)) {
|
const items: ContextMenuItem[] = [];
|
||||||
|
const useItems = props.useItems ?? { edit: true, delete: true };
|
||||||
|
for (const [key, value] of Object.entries(useItems)) {
|
||||||
if (value) {
|
if (value) {
|
||||||
const item = defaultItems[key];
|
const item = defaultItems[key];
|
||||||
if (item) {
|
if (item) items.push(item);
|
||||||
state.menuItems.push(item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return [
|
||||||
|
...items,
|
||||||
|
...(props.leadingItems ?? []),
|
||||||
|
...(props.appendItems ?? []),
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
const icon = computed(() => props.menuIcon || $globals.icons.dotsVertical);
|
||||||
|
|
||||||
|
const localEvent = ref({ ...props.event });
|
||||||
|
watch(() => props.event, (val) => {
|
||||||
|
localEvent.value = { ...val };
|
||||||
|
});
|
||||||
|
|
||||||
|
function openEditDialog() {
|
||||||
|
localEvent.value = { ...props.event };
|
||||||
|
recipeEventEditDialog.value = true;
|
||||||
|
}
|
||||||
|
function openDeleteDialog() {
|
||||||
|
recipeEventDeleteDialog.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add Leading and Appending Items
|
|
||||||
state.menuItems = [...state.menuItems, ...props.leadingItems, ...props.appendItems];
|
|
||||||
|
|
||||||
const icon = props.menuIcon || $globals.icons.dotsVertical;
|
|
||||||
|
|
||||||
// ===========================================================================
|
|
||||||
// Context Menu Event Handler
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
|
||||||
const eventHandlers: { [key: string]: () => void | Promise<any> } = {
|
|
||||||
edit: () => {
|
|
||||||
state.recipeEventEditDialog = true;
|
|
||||||
},
|
|
||||||
delete: () => {
|
|
||||||
state.recipeEventDeleteDialog = true;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
function contextMenuEventHandler(eventKey: string) {
|
function contextMenuEventHandler(eventKey: string) {
|
||||||
const handler = eventHandlers[eventKey];
|
if (eventKey === "edit") {
|
||||||
|
openEditDialog();
|
||||||
if (handler && typeof handler === "function") {
|
loading.value = false;
|
||||||
handler();
|
|
||||||
state.loading = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (eventKey === "delete") {
|
||||||
context.emit(eventKey);
|
openDeleteDialog();
|
||||||
state.loading = false;
|
loading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit(eventKey as "delete" | "update");
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
function submitEdit() {
|
||||||
|
emit("update", { ...localEvent.value });
|
||||||
|
recipeEventEditDialog.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
|
||||||
...toRefs(state),
|
|
||||||
contextMenuEventHandler,
|
|
||||||
domEditEventForm,
|
|
||||||
icon,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue