mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-06 14:48:02 -05:00
batch merge view
This commit is contained in:
@@ -13,17 +13,17 @@
|
||||
{{ $t('BatchDeleteConfirm') }}
|
||||
|
||||
<v-list>
|
||||
<v-list-item border v-for="i in itemsToDelete">
|
||||
{{ genericModel.getLabel(i) }}
|
||||
<v-list-item border v-for="item in itemsToDelete">
|
||||
{{ genericModel.getLabel(item) }}
|
||||
<template #append>
|
||||
<v-chip prepend-icon="fa-solid fa-xmark" color="error" v-if="deletedErrored.includes(i)">{{$t('Error')}}</v-chip>
|
||||
<v-chip prepend-icon="fa-solid fa-check" color="success" v-else-if="deletedItems.includes(i)">{{$t('Deleted')}}</v-chip>
|
||||
<v-chip prepend-icon="fa-solid fa-circle-notch fa-spin" color="info" v-else-if="loading">{{$t('Waiting')}}</v-chip>
|
||||
<v-icon icon="fa-solid fa-xmark" color="error" variant="tonal" v-if="failedItems.includes(item)"></v-icon>
|
||||
<v-icon icon="fa-solid fa-check" color="success" variant="tonal" v-else-if="updatedItems.includes(item)"></v-icon>
|
||||
<v-icon icon="fa-solid fa-circle-notch fa-spin" variant="tonal" color="info" v-else-if="loading"></v-icon>
|
||||
|
||||
<v-btn icon="fa-solid fa-up-right-from-square" :to="{name: 'IngredientEditorPage', query: {food_id: i.id}}"
|
||||
v-if="genericModel.model.name == 'Food' && deletedErrored.includes(i)" size="small"></v-btn>
|
||||
<v-btn icon="fa-solid fa-up-right-from-square" :to="{name: 'IngredientEditorPage', query: {unit_id: i.id}}"
|
||||
v-if="genericModel.model.name == 'Unit' && deletedErrored.includes(i)" size="small"></v-btn>
|
||||
<v-btn icon="fa-solid fa-up-right-from-square" :to="{name: 'IngredientEditorPage', query: {food_id: item.id}}"
|
||||
v-if="genericModel.model.name == 'Food' && failedItems.includes(item)" size="small"></v-btn>
|
||||
<v-btn icon="fa-solid fa-up-right-from-square" :to="{name: 'IngredientEditorPage', query: {unit_id: item.id}}"
|
||||
v-if="genericModel.model.name == 'Unit' && failedItems.includes(item)" size="small"></v-btn>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
@@ -48,7 +48,7 @@ const emit = defineEmits(['change'])
|
||||
|
||||
const props = defineProps({
|
||||
model: {type: String as PropType<EditorSupportedModels>, required: true},
|
||||
items: {type: [] as PropType<Array<EditorSupportedTypes>>, required: true},
|
||||
items: {type: Array as PropType<Array<EditorSupportedTypes>>, required: true},
|
||||
activator: {type: String, default: 'parent'},
|
||||
})
|
||||
|
||||
@@ -60,8 +60,8 @@ const loading = ref(false)
|
||||
const genericModel = getGenericModelFromString(props.model, t)
|
||||
|
||||
const itemsToDelete = ref<EditorSupportedTypes[]>([])
|
||||
const deletedItems = ref<EditorSupportedTypes[]>([])
|
||||
const deletedErrored = ref<EditorSupportedTypes[]>([])
|
||||
const failedItems = ref<EditorSupportedTypes[]>([])
|
||||
const updatedItems = ref<EditorSupportedTypes[]>([])
|
||||
|
||||
watch(dialog, (newValue, oldValue) => {
|
||||
if(!oldValue && newValue){
|
||||
@@ -78,9 +78,9 @@ function deleteAll() {
|
||||
|
||||
itemsToDelete.value.forEach(item => {
|
||||
promises.push(genericModel.destroy(item.id!).then((r: any) => {
|
||||
deletedItems.value.push(item)
|
||||
updatedItems.value.push(item)
|
||||
}).catch((err: any) => {
|
||||
deletedErrored.value.push(item)
|
||||
failedItems.value.push(item)
|
||||
}))
|
||||
})
|
||||
|
||||
|
||||
@@ -3,26 +3,38 @@
|
||||
<v-card :loading="loading">
|
||||
<v-closable-card-title
|
||||
:title="$t('merge_title', {type: $t(genericModel.model.localizationKey)})"
|
||||
:sub-title="genericModel.getLabel(props.source)"
|
||||
:sub-title="sourceNames"
|
||||
:icon="genericModel.model.icon"
|
||||
v-model="dialog"
|
||||
></v-closable-card-title>
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-card-text>
|
||||
{{ $t('merge_selection', {source: genericModel.getLabel(props.source), type: $t(genericModel.model.localizationKey)}) }}
|
||||
{{ $t('merge_selection', {source: sourceNames, type: $t(genericModel.model.localizationKey)}) }}
|
||||
<model-select :model="props.model" v-model="target" allow-create></model-select>
|
||||
|
||||
<v-row>
|
||||
<v-col class="text-center">
|
||||
<v-card color="warning" variant="tonal">
|
||||
<v-card-title>{{ genericModel.getLabel(props.source) }}</v-card-title>
|
||||
</v-card>
|
||||
<v-icon icon="fa-solid fa-arrow-down" class="mt-4 mb-4"></v-icon>
|
||||
<v-card color="success" variant="tonal">
|
||||
<v-card-title v-if="!target">?</v-card-title>
|
||||
<v-card-title v-else>{{ genericModel.getLabel(target) }}</v-card-title>
|
||||
</v-card>
|
||||
<v-col>
|
||||
<v-list>
|
||||
<v-list-item border v-for="item in sourceItems">
|
||||
{{ genericModel.getLabel(item) }}
|
||||
|
||||
<template #append>
|
||||
<v-icon icon="fa-solid fa-xmark" color="error" variant="tonal" v-if="failedItems.includes(item)"></v-icon>
|
||||
<v-icon icon="fa-solid fa-check" color="success" variant="tonal" v-else-if="updatedItems.includes(item)"></v-icon>
|
||||
<v-icon icon="fa-solid fa-circle-notch fa-spin" variant="tonal" color="info" v-else-if="loading"></v-icon>
|
||||
</template>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item class="text-center">
|
||||
<v-icon icon="fa-solid fa-arrow-down" class="mt-4 mb-4"></v-icon>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item class="text-center" border>
|
||||
<span v-if="!target">?</span>
|
||||
<span v-else>{{ genericModel.getLabel(target) }}</span>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
@@ -40,7 +52,7 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import ModelSelect from "@/components/inputs/ModelSelect.vue";
|
||||
import {PropType, ref} from "vue";
|
||||
import {computed, PropType, ref, watch} from "vue";
|
||||
import {EditorSupportedModels, EditorSupportedTypes, getGenericModelFromString} from "@/types/Models";
|
||||
import {ErrorMessageType, PreparedMessage, useMessageStore} from "@/stores/MessageStore";
|
||||
import {useI18n} from "vue-i18n";
|
||||
@@ -51,7 +63,7 @@ const emit = defineEmits(['change'])
|
||||
|
||||
const props = defineProps({
|
||||
model: {type: String as PropType<EditorSupportedModels>, required: true},
|
||||
source: {type: {} as PropType<EditorSupportedTypes>, required: true},
|
||||
source: {type: Array as PropType<Array<EditorSupportedTypes>>, required: true},
|
||||
activator: {type: String, default: 'parent'},
|
||||
})
|
||||
|
||||
@@ -64,41 +76,62 @@ const automate = ref(false)
|
||||
const genericModel = getGenericModelFromString(props.model, t)
|
||||
const target = ref<null | EditorSupportedTypes>(null)
|
||||
|
||||
const sourceItems = ref<EditorSupportedTypes[]>([])
|
||||
const failedItems = ref<EditorSupportedTypes[]>([])
|
||||
const updatedItems = ref<EditorSupportedTypes[]>([])
|
||||
|
||||
watch(dialog, (newValue, oldValue) => {
|
||||
if (!oldValue && newValue) {
|
||||
sourceItems.value = JSON.parse(JSON.stringify(props.source))
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* generate comma seperated list of item names that act as the source
|
||||
*/
|
||||
const sourceNames = computed(() => {
|
||||
if (sourceItems.value) {
|
||||
return sourceItems.value.map(i => genericModel.getLabel(i)).join(', ')
|
||||
}
|
||||
return ''
|
||||
})
|
||||
|
||||
/**
|
||||
* merge source into selected target
|
||||
*/
|
||||
function mergeModel() {
|
||||
let api = new ApiApi()
|
||||
let promises: Promise<any>[] = []
|
||||
|
||||
if (target.value != null) {
|
||||
loading.value = true
|
||||
|
||||
genericModel.merge(props.source, target.value).then(r => {
|
||||
useMessageStore().addPreparedMessage(PreparedMessage.UPDATE_SUCCESS)
|
||||
emit('change', target.value)
|
||||
sourceItems.value.forEach(sourceItem => {
|
||||
promises.push(genericModel.merge(sourceItem, target.value).then(r => {
|
||||
|
||||
if (automate.value && target.value != null && Object.hasOwn(props.source, 'name') && Object.hasOwn(target.value, 'name')) {
|
||||
let automation = {
|
||||
name: `${t('Merge') } ${props.source.name} -> ${target.value.name}`.substring(0,128),
|
||||
param1: props.source.name,
|
||||
param2: target.value.name,
|
||||
type: genericModel.model.mergeAutomation
|
||||
} as Automation
|
||||
api.apiAutomationCreate({automation: automation}).catch(err => {
|
||||
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
dialog.value = false
|
||||
})
|
||||
}
|
||||
}).catch(err => {
|
||||
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
|
||||
}).finally(() => {
|
||||
if (!automate.value) {
|
||||
loading.value = false
|
||||
dialog.value = false
|
||||
}
|
||||
updatedItems.value.push(sourceItem)
|
||||
|
||||
if (automate.value && target.value != null && Object.hasOwn(sourceItem, 'name') && Object.hasOwn(sourceItem, 'name')) {
|
||||
let automation = {
|
||||
name: `${t('Merge')} ${sourceItem.name} -> ${target.value.name}`.substring(0, 128),
|
||||
param1: sourceItem.name,
|
||||
param2: target.value.name,
|
||||
type: genericModel.model.mergeAutomation
|
||||
} as Automation
|
||||
promises.push(api.apiAutomationCreate({automation: automation}).catch(err => {
|
||||
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
|
||||
}))
|
||||
}
|
||||
}).catch(err => {
|
||||
updatedItems.value.push(sourceItem)
|
||||
}))
|
||||
})
|
||||
|
||||
Promise.allSettled(promises).then(() => {
|
||||
loading.value = false
|
||||
emit('change')
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -153,6 +153,7 @@
|
||||
"Meal_Type_Required": "",
|
||||
"Meal_Types": "",
|
||||
"Merge": "",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "",
|
||||
"Message": "",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
"Meal_Type_Required": "Изисква се вид хранене",
|
||||
"Meal_Types": "Видове хранене",
|
||||
"Merge": "Обединяване",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Обединяване на ключова дума",
|
||||
"MissingProperties": "",
|
||||
"Month": "Месец",
|
||||
|
||||
@@ -204,6 +204,7 @@
|
||||
"Meal_Type_Required": "El tipus és obligatori",
|
||||
"Meal_Types": "Tipus de menjars",
|
||||
"Merge": "Unificar",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Fusioneu paraula clau",
|
||||
"Message": "Missatge",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -202,6 +202,7 @@
|
||||
"Meal_Type_Required": "Druh jídla je povinný",
|
||||
"Meal_Types": "Druhy jídel",
|
||||
"Merge": "Spojit",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Sloučit štítek",
|
||||
"Message": "Zpráva",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -204,6 +204,7 @@
|
||||
"Meal_Type_Required": "Måltidstype påkrævet",
|
||||
"Meal_Types": "Måltidstyper",
|
||||
"Merge": "Sammenflet",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Sammenflet nøgleord",
|
||||
"Message": "Besked",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -288,7 +288,7 @@
|
||||
"Meal_Type_Required": "Mahlzeitentyp ist erforderlich",
|
||||
"Meal_Types": "Mahlzeiten",
|
||||
"Merge": "Zusammenführen",
|
||||
"MergeAutomateHelp": "Erstelle eine Automatisierung ,die auch zukünftig erstellte Objekte mit diesem Namen durch das gewählte Objekt ersetzt.",
|
||||
"MergeAutomateHelp": "Erstelle eine Automatisierung, die auch zukünftig erstellte Objekte mit diesem Namen durch das gewählte Objekt ersetzt.",
|
||||
"Merge_Keyword": "Schlagworte zusammenführen",
|
||||
"Message": "Nachricht",
|
||||
"Messages": "Nachrichten",
|
||||
|
||||
@@ -204,6 +204,7 @@
|
||||
"Meal_Type_Required": "Το είδος του γεύματος είναι απαραίτητο",
|
||||
"Meal_Types": "Είδη γευμάτων",
|
||||
"Merge": "Συγχώνευση",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Συγχώνευση λέξης-κλειδί",
|
||||
"Message": "Μήνυμα",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -198,6 +198,7 @@
|
||||
"Meal_Type_Required": "Ateriatyyppi pakollinen",
|
||||
"Meal_Types": "Ateriatyypit",
|
||||
"Merge": "Yhdistä",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Yhdistä Avainsana",
|
||||
"Message": "Viesti",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -204,6 +204,7 @@
|
||||
"Meal_Type_Required": "סוג אוכל נדרש",
|
||||
"Meal_Types": "סוגי אוכל",
|
||||
"Merge": "איחוד",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "איחוד מילת מפתח",
|
||||
"Message": "הודעה",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -204,6 +204,7 @@
|
||||
"Meal_Type_Required": "Potreban je tip obroka",
|
||||
"Meal_Types": "Tipovi obroka",
|
||||
"Merge": "Spoji",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Spoji ključnu riječ",
|
||||
"Message": "Poruka",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -185,6 +185,7 @@
|
||||
"Meal_Type_Required": "Étkezés megadása kötelező",
|
||||
"Meal_Types": "Étkezések",
|
||||
"Merge": "Összefűzés",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Kulcsszó összevonása",
|
||||
"Message": "Üzenet",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
"Manage_Books": "Կարգավորել Գրքերը",
|
||||
"Meal_Plan": "Ճաշացուցակ",
|
||||
"Merge": "Միացնել",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Միացնել բանալի բառը",
|
||||
"MissingProperties": "",
|
||||
"Move": "Տեղափոխել",
|
||||
|
||||
@@ -170,6 +170,7 @@
|
||||
"Meal_Type_Required": "",
|
||||
"Meal_Types": "",
|
||||
"Merge": "Menggabungkan",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Gabungkan Kata Kunci",
|
||||
"Message": "",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -203,6 +203,7 @@
|
||||
"Meal_Type_Required": "",
|
||||
"Meal_Types": "",
|
||||
"Merge": "",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "",
|
||||
"Message": "",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -187,6 +187,7 @@
|
||||
"Meal_Type_Required": "",
|
||||
"Meal_Types": "",
|
||||
"Merge": "",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Sujungti raktažodį",
|
||||
"Message": "",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -204,6 +204,7 @@
|
||||
"Meal_Type_Required": "",
|
||||
"Meal_Types": "",
|
||||
"Merge": "",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "",
|
||||
"Message": "",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -194,6 +194,7 @@
|
||||
"Meal_Type_Required": "Måltidstype er nødvendig",
|
||||
"Meal_Types": "Måltidstyper",
|
||||
"Merge": "Slå sammen",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Slå sammen nøkkelord",
|
||||
"Message": "Melding",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -230,6 +230,7 @@
|
||||
"Meal_Type_Required": "Rodzaj posiłku jest wymagany",
|
||||
"Meal_Types": "Rodzaje posiłków",
|
||||
"Merge": "Scal",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Scal słowa kluczowe",
|
||||
"Message": "Wiadomość",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -160,6 +160,7 @@
|
||||
"Meal_Type_Required": "Tipo de refeição é necessário",
|
||||
"Meal_Types": "Tipos de refeições",
|
||||
"Merge": "Juntar",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Unir palavra-chave",
|
||||
"MissingProperties": "",
|
||||
"Month": "Mês",
|
||||
|
||||
@@ -285,6 +285,7 @@
|
||||
"Meal_Type_Required": "Tipo de comida é obrigatório",
|
||||
"Meal_Types": "Tipos de Comida",
|
||||
"Merge": "Mesclar",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Mesclar palavra-chave",
|
||||
"Message": "Mensagem",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -179,6 +179,7 @@
|
||||
"Meal_Type_Required": "Tipul mesei este necesar",
|
||||
"Meal_Types": "Tipuri de mese",
|
||||
"Merge": "Unire",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Unește cuvânt cheie",
|
||||
"Message": "Mesaj",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -241,6 +241,7 @@
|
||||
"Meal_Type_Required": "Måltidstyp är obligatorisk",
|
||||
"Meal_Types": "Måltidstyper",
|
||||
"Merge": "Slå samman",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Slå samman nyckelord",
|
||||
"Message": "Meddelande",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -204,6 +204,7 @@
|
||||
"Meal_Type_Required": "Yemek türü gereklidir",
|
||||
"Meal_Types": "Yemek türleri",
|
||||
"Merge": "Birleştir",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Anahtar Kelimeyi Birleştir",
|
||||
"Message": "Mesaj",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
"Meal_Type_Required": "Тип страви є обов'язковим",
|
||||
"Meal_Types": "Типи страви",
|
||||
"Merge": "Об'єднати",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "Об'єднати Ключове слово",
|
||||
"MissingProperties": "",
|
||||
"Month": "Місяць",
|
||||
|
||||
@@ -204,6 +204,7 @@
|
||||
"Meal_Type_Required": "用餐类型是必需的",
|
||||
"Meal_Types": "用餐类型",
|
||||
"Merge": "合并",
|
||||
"MergeAutomateHelp": "",
|
||||
"Merge_Keyword": "合并关键词",
|
||||
"Message": "信息",
|
||||
"MissingProperties": "",
|
||||
|
||||
@@ -57,7 +57,10 @@
|
||||
<v-icon icon="fa-solid fa-ellipsis-v"></v-icon>
|
||||
<v-menu activator="parent" close-on-content-click>
|
||||
<v-list density="compact" class="pt-1 pb-1" activatable>
|
||||
<v-list-item prepend-icon="$delete" @click="batchDeleteDialog = true">
|
||||
<v-list-item prepend-icon="fa-solid fa-arrows-to-dot" @click="batchMergeDialog = true" v-if="genericModel.model.isMerge">
|
||||
{{ $t('Merge') }}
|
||||
</v-list-item>
|
||||
<v-list-item prepend-icon="$delete" @click="batchDeleteDialog = true" v-if="!genericModel.model.disableDelete">
|
||||
{{ $t('Delete_All') }}
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
@@ -75,7 +78,7 @@
|
||||
</v-list-item>
|
||||
<v-list-item prepend-icon="fa-solid fa-arrows-to-dot" v-if="genericModel.model.isMerge" link>
|
||||
{{ $t('Merge') }}
|
||||
<model-merge-dialog :model="model" :source="item"
|
||||
<model-merge-dialog :model="model" :source="[item]"
|
||||
@change="loadItems({page: tablePage, itemsPerPage: useUserPreferenceStore().deviceSettings.general_tableItemsPerPage, search: searchQuery})"></model-merge-dialog>
|
||||
</v-list-item>
|
||||
<v-list-item prepend-icon="fa-solid fa-table-list" :to="{name: 'IngredientEditorPage', query: {food_id: item.id}}"
|
||||
@@ -103,6 +106,10 @@
|
||||
|
||||
<batch-delete-dialog :items="selectedItems" :model="props.model" v-model="batchDeleteDialog" activator="model"
|
||||
@change="loadItems({page: tablePage, itemsPerPage: useUserPreferenceStore().deviceSettings.general_tableItemsPerPage, search: searchQuery})"></batch-delete-dialog>
|
||||
|
||||
<model-merge-dialog :model="model" :source="selectedItems" v-model="batchMergeDialog" activator="model"
|
||||
@change="loadItems({page: tablePage, itemsPerPage: useUserPreferenceStore().deviceSettings.general_tableItemsPerPage, search: searchQuery})"></model-merge-dialog>
|
||||
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
@@ -149,6 +156,7 @@ const tablePage = ref(1)
|
||||
const selectedItems = ref([] as EditorSupportedTypes[])
|
||||
|
||||
const batchDeleteDialog = ref(false)
|
||||
const batchMergeDialog = ref(false)
|
||||
|
||||
// data
|
||||
const loading = ref(false);
|
||||
|
||||
Reference in New Issue
Block a user