1
0
Fork 0
mirror of https://github.com/mealie-recipes/mealie.git synced 2025-07-23 15:19: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:
Hoa (Kyle) Trinh 2025-06-20 00:09:12 +07:00 committed by GitHub
parent 89ab7fac25
commit c24d532608
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
403 changed files with 23959 additions and 19557 deletions

View file

@ -1,9 +1,19 @@
<template>
<div>
<v-card-actions>
<v-menu v-if="tableConfig.hideColumns" offset-y bottom nudge-bottom="6" :close-on-content-click="false">
<template #activator="{ on, attrs }">
<v-btn color="accent" class="mr-2" dark v-bind="attrs" v-on="on">
<v-menu
v-if="tableConfig.hideColumns"
offset-y
bottom
nudge-bottom="6"
:close-on-content-click="false"
>
<template #activator="{ props }">
<v-btn
color="accent"
variant="elevated"
v-bind="props"
>
<v-icon>
{{ $globals.icons.cog }}
</v-icon>
@ -16,12 +26,12 @@
:key="itemValue.text + itemValue.show"
v-model="filteredHeaders"
:value="itemValue.value"
dense
density="compact"
flat
inset
:label="itemValue.text"
hide-details
></v-checkbox>
/>
</v-card-text>
</v-card>
</v-menu>
@ -30,41 +40,52 @@
:disabled="selected.length < 1"
mode="event"
color="info"
variant="elevated"
:items="bulkActions"
v-on="bulkActionListener"
>
</BaseOverflowButton>
<slot name="button-row"> </slot>
v-bind="bulkActionListener"
/>
<slot name="button-row" />
</v-card-actions>
<div class="mx-2 clip-width">
<v-text-field v-model="search" :label="$t('search.search')"></v-text-field>
<v-text-field
v-model="search"
variant="underlined"
:label="$t('search.search')"
/>
</div>
<v-data-table
v-model="selected"
item-key="id"
:show-select="bulkActions.length > 0"
:headers="activeHeaders"
:sort-by="initialSort"
:sort-desc="initialSortDesc"
:show-select="bulkActions.length > 0"
:sort-by="sortBy"
:items="data || []"
:items-per-page="15"
:search="search"
class="elevation-2"
>
<template v-for="header in activeHeaders" #[`item.${header.value}`]="{ item }">
<slot :name="'item.' + header.value" v-bind="{ item }"> {{ item[header.value] }}</slot>
<template
v-for="header in headersWithoutActions"
#[`item.${header.value}`]="{ item }"
>
<slot
:name="'item.' + header.value"
v-bind="{ item }"
>
{{ item[header.value] }}
</slot>
</template>
<template #item.actions="{ item }">
<template #[`item.actions`]="{ item }">
<BaseButtonGroup
:buttons="[
{
icon: $globals.icons.edit,
text: $tc('general.edit'),
text: $t('general.edit'),
event: 'edit',
},
{
icon: $globals.icons.delete,
text: $tc('general.delete'),
text: $t('general.delete'),
event: 'delete',
},
]"
@ -74,8 +95,11 @@
</template>
</v-data-table>
<v-card-actions class="justify-end">
<slot name="button-bottom"> </slot>
<BaseButton color="info" @click="downloadAsJson(data, 'export.json')">
<slot name="button-bottom" />
<BaseButton
color="info"
@click="downloadAsJson(data, 'export.json')"
>
<template #icon>
{{ $globals.icons.download }}
</template>
@ -86,7 +110,6 @@
</template>
<script lang="ts">
import { computed, defineComponent, ref } from "@nuxtjs/composition-api";
import { downloadAsJson } from "~/composables/use-utils";
export interface TableConfig {
@ -109,7 +132,7 @@ export interface BulkAction {
event: string;
}
export default defineComponent({
export default defineNuxtComponent({
props: {
tableConfig: {
type: Object as () => TableConfig,
@ -139,28 +162,34 @@ export default defineComponent({
default: false,
},
},
emits: ["delete-one", "edit-one"],
setup(props, context) {
const i18n = useI18n();
const sortBy = computed(() => [{
key: props.initialSort,
order: props.initialSortDesc ? "desc" : "asc",
}]);
// ===========================================================
// Reactive Headers
const filteredHeaders = ref<string[]>([]);
// Set default filtered
filteredHeaders.value = (() => {
const filtered: string[] = [];
props.headers.forEach((element) => {
if (element.show) {
filtered.push(element.value);
}
});
return filtered;
})();
const activeHeaders = computed(() => {
const filtered = props.headers.filter((header) => filteredHeaders.value.includes(header.value));
filtered.push({ text: "", value: "actions", show: true, align: "right" });
return filtered;
const filteredHeaders = computed<string[]>(() => {
return props.headers.filter(header => header.show).map(header => header.value);
});
const headersWithoutActions = computed(() =>
props.headers
.filter(header => filteredHeaders.value.includes(header.value))
.map(header => ({
...header,
title: i18n.t(header.text),
})),
);
const activeHeaders = computed(() => [
...headersWithoutActions.value,
{ title: "", value: "actions", show: true, align: "end" },
]);
const selected = ref<any[]>([]);
// ===========================================================
@ -183,8 +212,10 @@ export default defineComponent({
const search = ref("");
return {
sortBy,
selected,
filteredHeaders,
headersWithoutActions,
activeHeaders,
bulkActionListener,
search,
@ -198,4 +229,7 @@ export default defineComponent({
.clip-width {
max-width: 400px;
}
.v-btn--disabled {
opacity: 0.5 !important;
}
</style>