mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-24 07:39:41 +02:00
feat: Migrate to Nuxt 3 framework (#5184)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com> Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>
This commit is contained in:
parent
89ab7fac25
commit
c24d532608
403 changed files with 23959 additions and 19557 deletions
|
@ -1,59 +1,77 @@
|
|||
<template>
|
||||
<div>
|
||||
<slot name="activator" v-bind="{ open }" />
|
||||
<slot
|
||||
name="activator"
|
||||
v-bind="{ open }"
|
||||
/>
|
||||
<v-dialog
|
||||
v-model="dialog"
|
||||
absolute
|
||||
:width="width"
|
||||
:max-width="maxWidth"
|
||||
:max-width="maxWidth ?? undefined"
|
||||
:content-class="top ? 'top-dialog' : undefined"
|
||||
:fullscreen="$vuetify.breakpoint.xsOnly"
|
||||
@keydown.enter="
|
||||
$emit('submit');
|
||||
dialog = false;
|
||||
"
|
||||
@click:outside="$emit('cancel')"
|
||||
@keydown.esc="$emit('cancel')"
|
||||
:fullscreen="$vuetify.display.xs"
|
||||
@keydown.enter="() => {
|
||||
emit('submit'); dialog = false;
|
||||
}"
|
||||
@click:outside="emit('cancel')"
|
||||
@keydown.esc="emit('cancel')"
|
||||
>
|
||||
<v-card height="100%">
|
||||
<v-app-bar dark dense :color="color" class="">
|
||||
<v-icon large left>
|
||||
<v-toolbar
|
||||
dark
|
||||
density="comfortable"
|
||||
:color="color"
|
||||
class="px-3 position-relative top-0 left-0 w-100"
|
||||
>
|
||||
<v-icon size="large">
|
||||
{{ icon }}
|
||||
</v-icon>
|
||||
<v-toolbar-title class="headline"> {{ title }} </v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
</v-app-bar>
|
||||
<v-progress-linear v-if="loading" class="mt-1" indeterminate color="primary"></v-progress-linear>
|
||||
<v-toolbar-title class="headline">
|
||||
{{ title }}
|
||||
</v-toolbar-title>
|
||||
<v-spacer />
|
||||
</v-toolbar>
|
||||
<v-progress-linear
|
||||
v-if="loading"
|
||||
class="mt-1"
|
||||
indeterminate
|
||||
color="primary"
|
||||
/>
|
||||
|
||||
<div>
|
||||
<slot v-bind="{ submitEvent }" />
|
||||
</div>
|
||||
|
||||
<v-divider class="mx-2"></v-divider>
|
||||
<v-divider class="mx-2" />
|
||||
|
||||
<v-card-actions>
|
||||
<slot name="card-actions">
|
||||
<v-btn
|
||||
text
|
||||
variant="text"
|
||||
color="grey"
|
||||
@click="
|
||||
dialog = false;
|
||||
$emit('cancel');
|
||||
emit('cancel');
|
||||
"
|
||||
>
|
||||
{{ $t("general.cancel") }}
|
||||
</v-btn>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
|
||||
<slot name="custom-card-action"></slot>
|
||||
<BaseButton v-if="$listeners.delete" delete secondary @click="deleteEvent" />
|
||||
<slot name="custom-card-action" />
|
||||
<BaseButton
|
||||
v-if="$listeners.confirm"
|
||||
v-if="canDelete"
|
||||
delete
|
||||
secondary
|
||||
@click="deleteEvent"
|
||||
/>
|
||||
<BaseButton
|
||||
v-if="canConfirm"
|
||||
:color="color"
|
||||
type="submit"
|
||||
:disabled="submitDisabled"
|
||||
@click="
|
||||
$emit('confirm');
|
||||
emit('confirm');
|
||||
dialog = false;
|
||||
"
|
||||
>
|
||||
|
@ -63,141 +81,127 @@
|
|||
{{ $t("general.confirm") }}
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
v-if="$listeners.submit"
|
||||
v-if="canSubmit"
|
||||
type="submit"
|
||||
:disabled="submitDisabled"
|
||||
@click="submitEvent"
|
||||
>
|
||||
{{ submitText }}
|
||||
<template v-if="submitIcon" #icon>
|
||||
<template
|
||||
v-if="submitIcon"
|
||||
#icon
|
||||
>
|
||||
{{ submitIcon }}
|
||||
</template>
|
||||
</BaseButton>
|
||||
</slot>
|
||||
</v-card-actions>
|
||||
|
||||
<div v-if="$slots['below-actions']" class="pb-4">
|
||||
<slot name="below-actions"> </slot>
|
||||
<div
|
||||
v-if="$slots['below-actions']"
|
||||
class="pb-4"
|
||||
>
|
||||
<slot name="below-actions" />
|
||||
</div>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed } from "@nuxtjs/composition-api";
|
||||
export default defineComponent({
|
||||
name: "BaseDialog",
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: "primary",
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "Modal Title",
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
width: {
|
||||
type: [Number, String],
|
||||
default: "500",
|
||||
},
|
||||
maxWidth: {
|
||||
type: [Number, String],
|
||||
default: null,
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
top: {
|
||||
default: null,
|
||||
type: Boolean,
|
||||
},
|
||||
submitIcon: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
submitText: {
|
||||
type: String,
|
||||
default: function () {
|
||||
return this.$t("general.create");
|
||||
},
|
||||
},
|
||||
submitDisabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
keepOpen: {
|
||||
default: false,
|
||||
type: Boolean,
|
||||
},
|
||||
},
|
||||
setup(props, context) {
|
||||
const dialog = computed<boolean>({
|
||||
get() {
|
||||
return props.value;
|
||||
},
|
||||
set(val) {
|
||||
context.emit("input", val);
|
||||
},
|
||||
});
|
||||
<script setup lang="ts">
|
||||
import { useNuxtApp } from "#app";
|
||||
|
||||
return {
|
||||
dialog,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
submitted: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
determineClose(): boolean {
|
||||
return this.submitted && !this.loading && !this.keepOpen;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
determineClose() {
|
||||
this.submitted = false;
|
||||
this.dialog = false;
|
||||
},
|
||||
dialog(val) {
|
||||
if (val) this.submitted = false;
|
||||
if (!val) this.$emit("close");
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
submitEvent() {
|
||||
this.$emit("submit");
|
||||
this.submitted = true;
|
||||
},
|
||||
deleteEvent() {
|
||||
this.$emit("delete");
|
||||
this.submitted = true;
|
||||
},
|
||||
open() {
|
||||
this.dialog = true;
|
||||
this.logDeprecatedProp("open");
|
||||
},
|
||||
close() {
|
||||
this.dialog = false;
|
||||
this.logDeprecatedProp("close");
|
||||
},
|
||||
logDeprecatedProp(val: string) {
|
||||
console.warn(
|
||||
`[BaseDialog] The method '${val}' is deprecated. Please use v-model="value" to manage state instead.`
|
||||
);
|
||||
},
|
||||
},
|
||||
interface DialogProps {
|
||||
modelValue: boolean;
|
||||
color?: string;
|
||||
title?: string;
|
||||
icon?: string | null;
|
||||
width?: number | string;
|
||||
maxWidth?: number | string | null;
|
||||
loading?: boolean;
|
||||
top?: boolean | null;
|
||||
submitIcon?: string | null;
|
||||
submitText?: string;
|
||||
submitDisabled?: boolean;
|
||||
keepOpen?: boolean;
|
||||
// actions
|
||||
canDelete?: boolean;
|
||||
canConfirm?: boolean;
|
||||
canSubmit?: boolean;
|
||||
}
|
||||
|
||||
interface DialogEmits {
|
||||
(e: "update:modelValue", value: boolean): void;
|
||||
(e: "submit" | "cancel" | "confirm" | "delete" | "close"): void;
|
||||
}
|
||||
|
||||
// Using TypeScript interface with withDefaults for props
|
||||
const props = withDefaults(defineProps<DialogProps>(), {
|
||||
color: "primary",
|
||||
title: "Modal Title",
|
||||
icon: null,
|
||||
width: "500",
|
||||
maxWidth: null,
|
||||
loading: false,
|
||||
top: null,
|
||||
submitIcon: null,
|
||||
submitText: () => useNuxtApp().$i18n.t("general.create"),
|
||||
submitDisabled: false,
|
||||
keepOpen: false,
|
||||
canDelete: false,
|
||||
canConfirm: false,
|
||||
canSubmit: false,
|
||||
});
|
||||
const emit = defineEmits<DialogEmits>();
|
||||
|
||||
const dialog = computed({
|
||||
get: () => props.modelValue,
|
||||
set: val => emit("update:modelValue", val),
|
||||
});
|
||||
|
||||
const submitted = ref(false);
|
||||
|
||||
const determineClose = computed(() => {
|
||||
return submitted.value && !props.loading && !props.keepOpen;
|
||||
});
|
||||
|
||||
watch(determineClose, (shouldClose) => {
|
||||
if (shouldClose) {
|
||||
submitted.value = false;
|
||||
dialog.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
watch(dialog, (val) => {
|
||||
if (val) submitted.value = false;
|
||||
if (!val) emit("close");
|
||||
});
|
||||
|
||||
function submitEvent() {
|
||||
emit("submit");
|
||||
submitted.value = true;
|
||||
}
|
||||
|
||||
function deleteEvent() {
|
||||
emit("delete");
|
||||
submitted.value = true;
|
||||
}
|
||||
|
||||
function open() {
|
||||
dialog.value = true;
|
||||
logDeprecatedProp("open");
|
||||
}
|
||||
|
||||
/* function close() {
|
||||
dialog.value = false;
|
||||
logDeprecatedProp("close");
|
||||
} */
|
||||
|
||||
function logDeprecatedProp(val: string) {
|
||||
console.warn(
|
||||
`[BaseDialog] The method '${val}' is deprecated. Please use v-model="value" to manage state instead.`,
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue