mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-03 05:11:31 -05:00
fixed some things but page param still broken
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-dialog max-width="70vw" min-height="80vh" activator="parent">
|
<v-dialog max-width="70vw" min-height="80vh" :activator="activator">
|
||||||
<template v-slot:default="{ isActive }">
|
<template v-slot:default="{ isActive }">
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-card-title>
|
<v-card-title>
|
||||||
Nachrichten
|
{{ $t('Messages')}}
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
|
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
@@ -27,20 +27,20 @@
|
|||||||
divided
|
divided
|
||||||
multiple>
|
multiple>
|
||||||
<v-btn :value="MessageType.SUCCESS">
|
<v-btn :value="MessageType.SUCCESS">
|
||||||
<v-icon icon="fa-regular fa-eye" color="success"></v-icon>
|
<v-icon icon="fa-regular fa-eye" color="success" class="me-2"></v-icon>
|
||||||
Success
|
{{$t('Success')}}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn :value="MessageType.INFO">
|
<v-btn :value="MessageType.INFO">
|
||||||
<v-icon icon="fa-regular fa-eye" color="info"></v-icon>
|
<v-icon icon="fa-regular fa-eye" color="info" class="me-2"></v-icon>
|
||||||
Info
|
{{$t('Information')}}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn :value="MessageType.WARNING">
|
<v-btn :value="MessageType.WARNING">
|
||||||
<v-icon icon="fa-regular fa-eye" color="warning"></v-icon>
|
<v-icon icon="fa-regular fa-eye" color="warning" class="me-2"></v-icon>
|
||||||
Warning
|
{{$t('Warning')}}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn :value="MessageType.ERROR">
|
<v-btn :value="MessageType.ERROR">
|
||||||
<v-icon icon="fa-regular fa-eye" color="error"></v-icon>
|
<v-icon icon="fa-regular fa-eye" color="error" class="me-2"></v-icon>
|
||||||
Error
|
{{$t('Error')}}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-btn-toggle>
|
</v-btn-toggle>
|
||||||
|
|
||||||
@@ -61,9 +61,15 @@
|
|||||||
</v-chip>
|
</v-chip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template v-slot:item.msg="{ value }">
|
||||||
|
<b v-if="value.title">{{ value.title }}<br/></b>
|
||||||
|
{{ value.text }}
|
||||||
|
</template>
|
||||||
|
|
||||||
<template v-slot:item.actions="{ item }">
|
<template v-slot:item.actions="{ item }">
|
||||||
<v-icon icon="$search" @click="showDetailDialog = true; detailItem = item"></v-icon>
|
<v-icon icon="$search" @click="showDetailDialog = true; detailItem = item"></v-icon>
|
||||||
<v-icon class="ms-1" icon="mdi-content-copy" @click="copy(JSON.stringify({'type': item.type, 'createdAt': item.createdAt, 'msg': item.msg, 'data': item.data}));"></v-icon>
|
<v-icon class="ms-1" icon="$copy"
|
||||||
|
@click="copy(JSON.stringify({'type': item.type, 'createdAt': item.createdAt, 'msg': item.msg, 'data': item.data}));"></v-icon>
|
||||||
</template>
|
</template>
|
||||||
</v-data-table>
|
</v-data-table>
|
||||||
|
|
||||||
@@ -72,9 +78,9 @@
|
|||||||
|
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn @click="useMessageStore().deleteAllMessages()" color="error">Alle Löschen</v-btn>
|
<v-btn @click="useMessageStore().deleteAllMessages()" color="error">{{$t('Delete_All')}}</v-btn>
|
||||||
<v-btn @click="addTestMessage()" color="warning">Test Nachricht</v-btn>
|
<v-btn @click="addTestMessage()" color="warning">{{$t('Add')}}</v-btn>
|
||||||
<v-btn @click="isActive.value = false">Close</v-btn>
|
<v-btn @click="isActive.value = false">{{ $t('Close')}}</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
@@ -84,19 +90,21 @@
|
|||||||
<v-dialog v-model="showDetailDialog" max-width="50vw">
|
<v-dialog v-model="showDetailDialog" max-width="50vw">
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-card-title>
|
<v-card-title>
|
||||||
Nachricht Details <small>{{ DateTime.fromSeconds(detailItem.createdAt).toLocaleString(DateTime.DATETIME_MED) }}</small>
|
{{$t('Created')}} <small>{{ DateTime.fromSeconds(detailItem.createdAt).toLocaleString(DateTime.DATETIME_MED) }}</small>
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
<v-divider></v-divider>
|
<v-divider></v-divider>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-label>Typ</v-label>
|
<v-label>{{ $t('Type')}}</v-label>
|
||||||
<br/>
|
<br/>
|
||||||
<v-chip :color="detailItem.type">{{ detailItem.type }}</v-chip>
|
<v-chip :color="detailItem.type">{{ detailItem.type }}</v-chip>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<v-label class="mt-2">Nachricht</v-label>
|
<v-label class="mt-2">{{$t('Messages')}}</v-label>
|
||||||
<p>{{ detailItem.msg }}</p>
|
<br/>
|
||||||
|
<b v-if="detailItem.msg.title">{{ detailItem.msg.title }}<br/></b>
|
||||||
|
<span class="text-pre">{{ detailItem.msg.text }}</span>
|
||||||
|
|
||||||
<v-label class="mt-2">Data</v-label>
|
<v-label class="mt-2">{{ $t('Information')}}</v-label>
|
||||||
<pre style="white-space: pre-wrap;" v-if="detailItem.data != null">{{ detailItem.data }}</pre>
|
<pre style="white-space: pre-wrap;" v-if="detailItem.data != null">{{ detailItem.data }}</pre>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
|
||||||
@@ -118,8 +126,14 @@ import {computed, ref} from 'vue'
|
|||||||
import {Message, MessageType, useMessageStore} from "@/stores/MessageStore";
|
import {Message, MessageType, useMessageStore} from "@/stores/MessageStore";
|
||||||
import {DateTime} from "luxon";
|
import {DateTime} from "luxon";
|
||||||
import {useClipboard} from "@vueuse/core";
|
import {useClipboard} from "@vueuse/core";
|
||||||
|
import {useI18n} from "vue-i18n";
|
||||||
|
|
||||||
const {copy} = useClipboard()
|
const {copy} = useClipboard()
|
||||||
|
const {t} = useI18n()
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
activator: {default: 'parent'}
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* loads messages from store and filters them according to selected message types
|
* loads messages from store and filters them according to selected message types
|
||||||
@@ -137,10 +151,10 @@ const displayItems = computed(() => {
|
|||||||
const sortBy = ref([{key: 'createdAt', order: 'desc'}])
|
const sortBy = ref([{key: 'createdAt', order: 'desc'}])
|
||||||
const search = ref('')
|
const search = ref('')
|
||||||
const tableHeaders = ref([
|
const tableHeaders = ref([
|
||||||
{title: 'Typ', key: 'type'},
|
{title: t('Type'), key: 'type'},
|
||||||
{title: 'Erstellt', key: 'createdAt'},
|
{title: t('Created'), key: 'createdAt'},
|
||||||
{title: 'Nachricht', key: 'msg'},
|
{title: t('Message'), key: 'msg'},
|
||||||
{title: 'Actions', key: 'actions', align: 'end'},
|
{title: t('Actions'), key: 'actions', align: 'end'},
|
||||||
])
|
])
|
||||||
const typeFilter = ref([MessageType.SUCCESS, MessageType.INFO, MessageType.WARNING, MessageType.ERROR])
|
const typeFilter = ref([MessageType.SUCCESS, MessageType.INFO, MessageType.WARNING, MessageType.ERROR])
|
||||||
const detailItem = ref({} as Message)
|
const detailItem = ref({} as Message)
|
||||||
@@ -151,7 +165,7 @@ const showDetailDialog = ref(false)
|
|||||||
*/
|
*/
|
||||||
function addTestMessage() {
|
function addTestMessage() {
|
||||||
let types = [MessageType.SUCCESS, MessageType.ERROR, MessageType.INFO, MessageType.WARNING]
|
let types = [MessageType.SUCCESS, MessageType.ERROR, MessageType.INFO, MessageType.WARNING]
|
||||||
useMessageStore().addMessage(types[Math.floor(Math.random() * types.length)], `Lorem Ipsum ${Math.random() * 1000}`, 5000, {json: "data", 'msg': 'whatever', data: 1})
|
useMessageStore().addMessage(types[Math.floor(Math.random() * types.length)], {title: 'Test', text: `Lorem Ipsum ${Math.random() * 1000}`}, 5000, {json: "data", 'msg': 'whatever', data: 1})
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -30,12 +30,13 @@ import SupermarketEditor from "@/components/model_editors/SupermarketEditor.vue"
|
|||||||
import SupermarketCategoryEditor from "@/components/model_editors/SupermarketCategoryEditor.vue";
|
import SupermarketCategoryEditor from "@/components/model_editors/SupermarketCategoryEditor.vue";
|
||||||
import PropertyTypeEditor from "@/components/model_editors/PropertyTypeEditor.vue";
|
import PropertyTypeEditor from "@/components/model_editors/PropertyTypeEditor.vue";
|
||||||
import AutomationEditor from "@/components/model_editors/AutomationEditor.vue";
|
import AutomationEditor from "@/components/model_editors/AutomationEditor.vue";
|
||||||
|
import {EditorSupportedModels} from "@/types/Models";
|
||||||
|
|
||||||
const emit = defineEmits(['create', 'save', 'delete'])
|
const emit = defineEmits(['create', 'save', 'delete'])
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
model: {
|
model: {
|
||||||
type: String as PropType<'UnitConversion' | 'AccessToken'| 'InviteLink' | 'UserSpace' | 'MealType' | 'Property' | 'Food' | 'Supermarket' | 'SupermarketCategory' | 'PropertyType' | 'Automation'>,
|
type: String as PropType<EditorSupportedModels>,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
item: {default: null},
|
item: {default: null},
|
||||||
|
|||||||
@@ -1,29 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-snackbar
|
<div>
|
||||||
v-model="showSnackbar"
|
<v-snackbar
|
||||||
:timer="true"
|
v-model="showSnackbar"
|
||||||
:timeout="visibleMessage.showTimeout"
|
:timer="true"
|
||||||
:color="visibleMessage.type"
|
:timeout="visibleMessage.showTimeout"
|
||||||
:vertical="vertical"
|
:color="visibleMessage.type"
|
||||||
:location="location"
|
:vertical="props.vertical"
|
||||||
multi-line
|
:location="props.location"
|
||||||
>
|
multi-line
|
||||||
<small>{{ DateTime.fromSeconds(visibleMessage.createdAt).toLocaleString(DateTime.DATETIME_MED) }}</small> <br/>
|
>
|
||||||
{{ visibleMessage.msg }}
|
<small>{{ DateTime.fromSeconds(visibleMessage.createdAt).toLocaleString(DateTime.DATETIME_MED) }}</small> <br/>
|
||||||
|
<h3 v-if="visibleMessage.msg.title">{{ visibleMessage.msg.title }}</h3>
|
||||||
|
<span class="text-pre">{{ visibleMessage.msg.text }}</span>
|
||||||
|
|
||||||
<template v-slot:actions>
|
<template v-slot:actions>
|
||||||
|
|
||||||
|
<v-btn ref="ref_btn_view">View</v-btn>
|
||||||
|
<v-btn variant="text" @click="removeItem()">
|
||||||
|
<span v-if="useMessageStore().snackbarQueue.length > 1">Next ({{ useMessageStore().snackbarQueue.length - 1 }})</span>
|
||||||
|
<span v-else>Close</span>
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
</v-snackbar>
|
||||||
|
|
||||||
|
<message-list-dialog :activator="viewMessageDialogBtn"></message-list-dialog>
|
||||||
|
</div>
|
||||||
|
|
||||||
<v-btn variant="text">View <message-list-dialog></message-list-dialog> </v-btn>
|
|
||||||
<v-btn variant="text" @click="removeItem()">
|
|
||||||
<span v-if="useMessageStore().snackbarQueue.length > 1">Next ({{ useMessageStore().snackbarQueue.length - 1 }})</span>
|
|
||||||
<span v-else>Close</span>
|
|
||||||
</v-btn>
|
|
||||||
</template>
|
|
||||||
</v-snackbar>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref} from 'vue'
|
import {ref, useTemplateRef} from 'vue'
|
||||||
import {Message, useMessageStore} from "@/stores/MessageStore";
|
import {Message, useMessageStore} from "@/stores/MessageStore";
|
||||||
import {DateTime} from "luxon";
|
import {DateTime} from "luxon";
|
||||||
import MessageListDialog from "@/components/dialogs/MessageListDialog.vue";
|
import MessageListDialog from "@/components/dialogs/MessageListDialog.vue";
|
||||||
@@ -49,6 +55,8 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// ref to open message list dialog
|
||||||
|
const viewMessageDialogBtn = useTemplateRef('ref_btn_view')
|
||||||
// ID of message timeout currently running
|
// ID of message timeout currently running
|
||||||
const timeoutId = ref(-1)
|
const timeoutId = ref(-1)
|
||||||
// currently visible message
|
// currently visible message
|
||||||
|
|||||||
@@ -68,6 +68,7 @@
|
|||||||
"DeleteShoppingConfirm": "",
|
"DeleteShoppingConfirm": "",
|
||||||
"Delete_Food": "",
|
"Delete_Food": "",
|
||||||
"Delete_Keyword": "",
|
"Delete_Keyword": "",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "",
|
"Description": "",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
"DeviceSettingsHelp": "",
|
"DeviceSettingsHelp": "",
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
"DeleteShoppingConfirm": "Сигурни ли сте, че искате да премахнете цялата {food} от списъка за пазаруване?",
|
"DeleteShoppingConfirm": "Сигурни ли сте, че искате да премахнете цялата {food} от списъка за пазаруване?",
|
||||||
"Delete_Food": "Изтриване на храна",
|
"Delete_Food": "Изтриване на храна",
|
||||||
"Delete_Keyword": "Изтриване на ключова дума",
|
"Delete_Keyword": "Изтриване на ключова дума",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Описание",
|
"Description": "Описание",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
"DeviceSettingsHelp": "",
|
"DeviceSettingsHelp": "",
|
||||||
|
|||||||
@@ -97,6 +97,7 @@
|
|||||||
"Delete_All": "",
|
"Delete_All": "",
|
||||||
"Delete_Food": "",
|
"Delete_Food": "",
|
||||||
"Delete_Keyword": "Esborreu paraula clau",
|
"Delete_Keyword": "Esborreu paraula clau",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "",
|
"Description": "",
|
||||||
"Description_Replace": "Substituïu descripció",
|
"Description_Replace": "Substituïu descripció",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -97,6 +97,7 @@
|
|||||||
"Delete_All": "Smazat vše",
|
"Delete_All": "Smazat vše",
|
||||||
"Delete_Food": "Smazat potravinu",
|
"Delete_Food": "Smazat potravinu",
|
||||||
"Delete_Keyword": "Smazat štítek",
|
"Delete_Keyword": "Smazat štítek",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Popis",
|
"Description": "Popis",
|
||||||
"Description_Replace": "Nahraď popis",
|
"Description_Replace": "Nahraď popis",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -88,6 +88,7 @@
|
|||||||
"DeleteShoppingConfirm": "Er du sikker på at du vil fjerne {food} fra indkøbsliste?",
|
"DeleteShoppingConfirm": "Er du sikker på at du vil fjerne {food} fra indkøbsliste?",
|
||||||
"Delete_Food": "Slet mad",
|
"Delete_Food": "Slet mad",
|
||||||
"Delete_Keyword": "Slet nøgleord",
|
"Delete_Keyword": "Slet nøgleord",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Beskrivelse",
|
"Description": "Beskrivelse",
|
||||||
"Description_Replace": "Erstat beskrivelse",
|
"Description_Replace": "Erstat beskrivelse",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -99,6 +99,7 @@
|
|||||||
"Delete_All": "Alles löschen",
|
"Delete_All": "Alles löschen",
|
||||||
"Delete_Food": "Lebensmittel löschen",
|
"Delete_Food": "Lebensmittel löschen",
|
||||||
"Delete_Keyword": "Schlagwort löschen",
|
"Delete_Keyword": "Schlagwort löschen",
|
||||||
|
"Deleted": "Gelöscht",
|
||||||
"Description": "Beschreibung",
|
"Description": "Beschreibung",
|
||||||
"Description_Replace": "Beschreibung ersetzen",
|
"Description_Replace": "Beschreibung ersetzen",
|
||||||
"DeviceSettings": "Geräte Einstellungen",
|
"DeviceSettings": "Geräte Einstellungen",
|
||||||
|
|||||||
@@ -87,6 +87,7 @@
|
|||||||
"DeleteShoppingConfirm": "Θέλετε σίγουρα να αφαιρέσετε τα {food} από τη λίστα αγορών;",
|
"DeleteShoppingConfirm": "Θέλετε σίγουρα να αφαιρέσετε τα {food} από τη λίστα αγορών;",
|
||||||
"Delete_Food": "Διαγραφή φαγητού",
|
"Delete_Food": "Διαγραφή φαγητού",
|
||||||
"Delete_Keyword": "Διαγραφή λέξης-κλειδί",
|
"Delete_Keyword": "Διαγραφή λέξης-κλειδί",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Περιγραφή",
|
"Description": "Περιγραφή",
|
||||||
"Description_Replace": "Αλλαγή περιγραφής",
|
"Description_Replace": "Αλλαγή περιγραφής",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -98,6 +98,7 @@
|
|||||||
"Delete_All": "Delete all",
|
"Delete_All": "Delete all",
|
||||||
"Delete_Food": "Delete Food",
|
"Delete_Food": "Delete Food",
|
||||||
"Delete_Keyword": "Delete Keyword",
|
"Delete_Keyword": "Delete Keyword",
|
||||||
|
"Deleted": "Deleted",
|
||||||
"Description": "Description",
|
"Description": "Description",
|
||||||
"Description_Replace": "Description Replace",
|
"Description_Replace": "Description Replace",
|
||||||
"DeviceSettings": "Device Settings",
|
"DeviceSettings": "Device Settings",
|
||||||
|
|||||||
@@ -98,6 +98,7 @@
|
|||||||
"Delete_All": "Borrar todo",
|
"Delete_All": "Borrar todo",
|
||||||
"Delete_Food": "Eliminar Ingrediente",
|
"Delete_Food": "Eliminar Ingrediente",
|
||||||
"Delete_Keyword": "Eliminar palabra clave",
|
"Delete_Keyword": "Eliminar palabra clave",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Descripción",
|
"Description": "Descripción",
|
||||||
"Description_Replace": "Reemplazar Descripción",
|
"Description_Replace": "Reemplazar Descripción",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
"DeleteConfirmQuestion": "",
|
"DeleteConfirmQuestion": "",
|
||||||
"Delete_Food": "Poista ruoka",
|
"Delete_Food": "Poista ruoka",
|
||||||
"Delete_Keyword": "Poista avainsana",
|
"Delete_Keyword": "Poista avainsana",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Kuvaus",
|
"Description": "Kuvaus",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
"DeviceSettingsHelp": "",
|
"DeviceSettingsHelp": "",
|
||||||
|
|||||||
@@ -97,6 +97,7 @@
|
|||||||
"Delete_All": "Supprimer tout",
|
"Delete_All": "Supprimer tout",
|
||||||
"Delete_Food": "Supprimer l’aliment",
|
"Delete_Food": "Supprimer l’aliment",
|
||||||
"Delete_Keyword": "Supprimer le mot-clé",
|
"Delete_Keyword": "Supprimer le mot-clé",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Description",
|
"Description": "Description",
|
||||||
"Description_Replace": "Remplacer la Description",
|
"Description_Replace": "Remplacer la Description",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -98,6 +98,7 @@
|
|||||||
"Delete_All": "מחק הכל",
|
"Delete_All": "מחק הכל",
|
||||||
"Delete_Food": "מחק אוכל",
|
"Delete_Food": "מחק אוכל",
|
||||||
"Delete_Keyword": "מחר מילת מפתח",
|
"Delete_Keyword": "מחר מילת מפתח",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "תיאור",
|
"Description": "תיאור",
|
||||||
"Description_Replace": "החלפת תיאור",
|
"Description_Replace": "החלפת תיאור",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -86,6 +86,7 @@
|
|||||||
"DeleteShoppingConfirm": "Biztos, hogy az összes {food}-t el akarja távolítani a bevásárlólistáról?",
|
"DeleteShoppingConfirm": "Biztos, hogy az összes {food}-t el akarja távolítani a bevásárlólistáról?",
|
||||||
"Delete_Food": "Alapanyag törlése",
|
"Delete_Food": "Alapanyag törlése",
|
||||||
"Delete_Keyword": "Kulcsszó törlése",
|
"Delete_Keyword": "Kulcsszó törlése",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Megnevezés",
|
"Description": "Megnevezés",
|
||||||
"Description_Replace": "Megnevezés csere",
|
"Description_Replace": "Megnevezés csere",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
"DeleteConfirmQuestion": "",
|
"DeleteConfirmQuestion": "",
|
||||||
"Delete_Food": "Ջնջել սննդամթերքը",
|
"Delete_Food": "Ջնջել սննդամթերքը",
|
||||||
"Delete_Keyword": "Ջնջել բանալի բառը",
|
"Delete_Keyword": "Ջնջել բանալի բառը",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Նկարագրություն",
|
"Description": "Նկարագրություն",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
"DeviceSettingsHelp": "",
|
"DeviceSettingsHelp": "",
|
||||||
|
|||||||
@@ -77,6 +77,7 @@
|
|||||||
"DeleteShoppingConfirm": "",
|
"DeleteShoppingConfirm": "",
|
||||||
"Delete_Food": "",
|
"Delete_Food": "",
|
||||||
"Delete_Keyword": "Hapus Kata Kunci",
|
"Delete_Keyword": "Hapus Kata Kunci",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "",
|
"Description": "",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
"DeviceSettingsHelp": "",
|
"DeviceSettingsHelp": "",
|
||||||
|
|||||||
@@ -97,6 +97,7 @@
|
|||||||
"Delete_All": "",
|
"Delete_All": "",
|
||||||
"Delete_Food": "",
|
"Delete_Food": "",
|
||||||
"Delete_Keyword": "",
|
"Delete_Keyword": "",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "",
|
"Description": "",
|
||||||
"Description_Replace": "",
|
"Description_Replace": "",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -81,6 +81,7 @@
|
|||||||
"DeleteShoppingConfirm": "Sei sicuro di voler rimuovere tutto {food} dalla lista della spesa?",
|
"DeleteShoppingConfirm": "Sei sicuro di voler rimuovere tutto {food} dalla lista della spesa?",
|
||||||
"Delete_Food": "Elimina alimento",
|
"Delete_Food": "Elimina alimento",
|
||||||
"Delete_Keyword": "Elimina parola chiave",
|
"Delete_Keyword": "Elimina parola chiave",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Descrizione",
|
"Description": "Descrizione",
|
||||||
"Description_Replace": "Sostituisci descrizione",
|
"Description_Replace": "Sostituisci descrizione",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -88,6 +88,7 @@
|
|||||||
"DeleteShoppingConfirm": "",
|
"DeleteShoppingConfirm": "",
|
||||||
"Delete_Food": "",
|
"Delete_Food": "",
|
||||||
"Delete_Keyword": "Ištrinti raktažodį",
|
"Delete_Keyword": "Ištrinti raktažodį",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "",
|
"Description": "",
|
||||||
"Description_Replace": "Pakeisti aprašymą",
|
"Description_Replace": "Pakeisti aprašymą",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -85,6 +85,7 @@
|
|||||||
"DeleteShoppingConfirm": "Er du sikker på at du fjerne alle {food} fra handlelisten?",
|
"DeleteShoppingConfirm": "Er du sikker på at du fjerne alle {food} fra handlelisten?",
|
||||||
"Delete_Food": "Slett Matrett",
|
"Delete_Food": "Slett Matrett",
|
||||||
"Delete_Keyword": "Slett nøkkelord",
|
"Delete_Keyword": "Slett nøkkelord",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Beskrivelse",
|
"Description": "Beskrivelse",
|
||||||
"Description_Replace": "Erstatt beskrivelse",
|
"Description_Replace": "Erstatt beskrivelse",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -89,6 +89,7 @@
|
|||||||
"DeleteShoppingConfirm": "Weet je zeker dat je {food} van de boodschappenlijst wil verwijderen?",
|
"DeleteShoppingConfirm": "Weet je zeker dat je {food} van de boodschappenlijst wil verwijderen?",
|
||||||
"Delete_Food": "Verwijder Eten",
|
"Delete_Food": "Verwijder Eten",
|
||||||
"Delete_Keyword": "Verwijder Etiket",
|
"Delete_Keyword": "Verwijder Etiket",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Beschrijving",
|
"Description": "Beschrijving",
|
||||||
"Description_Replace": "Vervang beschrijving",
|
"Description_Replace": "Vervang beschrijving",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -99,6 +99,7 @@
|
|||||||
"Delete_All": "Usuń wszystko",
|
"Delete_All": "Usuń wszystko",
|
||||||
"Delete_Food": "Usuń żywność",
|
"Delete_Food": "Usuń żywność",
|
||||||
"Delete_Keyword": "Usuń słowo kluczowe",
|
"Delete_Keyword": "Usuń słowo kluczowe",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Opis",
|
"Description": "Opis",
|
||||||
"Description_Replace": "Zmień opis",
|
"Description_Replace": "Zmień opis",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -69,6 +69,7 @@
|
|||||||
"DeleteShoppingConfirm": "Tem a certeza que pretende remover toda {food} da sua lista de compras?",
|
"DeleteShoppingConfirm": "Tem a certeza que pretende remover toda {food} da sua lista de compras?",
|
||||||
"Delete_Food": "Eliminar comida",
|
"Delete_Food": "Eliminar comida",
|
||||||
"Delete_Keyword": "Eliminar Palavra Chave",
|
"Delete_Keyword": "Eliminar Palavra Chave",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Descrição",
|
"Description": "Descrição",
|
||||||
"Description_Replace": "Substituir descrição",
|
"Description_Replace": "Substituir descrição",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -95,6 +95,7 @@
|
|||||||
"Delete_All": "Excluir tudo",
|
"Delete_All": "Excluir tudo",
|
||||||
"Delete_Food": "Deletar Comida",
|
"Delete_Food": "Deletar Comida",
|
||||||
"Delete_Keyword": "Deletar palavra-chave",
|
"Delete_Keyword": "Deletar palavra-chave",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Descrição",
|
"Description": "Descrição",
|
||||||
"Description_Replace": "Substituir Descrição",
|
"Description_Replace": "Substituir Descrição",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -83,6 +83,7 @@
|
|||||||
"DeleteShoppingConfirm": "Sunteți sigur că doriți să eliminați toate {food} din lista de cumpărături?",
|
"DeleteShoppingConfirm": "Sunteți sigur că doriți să eliminați toate {food} din lista de cumpărături?",
|
||||||
"Delete_Food": "Ștergere mâncare",
|
"Delete_Food": "Ștergere mâncare",
|
||||||
"Delete_Keyword": "Ștergere cuvânt cheie",
|
"Delete_Keyword": "Ștergere cuvânt cheie",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Descriere",
|
"Description": "Descriere",
|
||||||
"Description_Replace": "Înlocuire descripție",
|
"Description_Replace": "Înlocuire descripție",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
"DeleteShoppingConfirm": "Вы уверены, что хотите удалить все {food} из вашего списка покупок?",
|
"DeleteShoppingConfirm": "Вы уверены, что хотите удалить все {food} из вашего списка покупок?",
|
||||||
"Delete_Food": "Удалить элемент",
|
"Delete_Food": "Удалить элемент",
|
||||||
"Delete_Keyword": "Удалить ключевое слово",
|
"Delete_Keyword": "Удалить ключевое слово",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Описание",
|
"Description": "Описание",
|
||||||
"Description_Replace": "Изменить описание",
|
"Description_Replace": "Изменить описание",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -59,6 +59,7 @@
|
|||||||
"DeleteShoppingConfirm": "Si prepričan/a, da želiš odstraniti VSO {food} iz nakupovalnega listka?",
|
"DeleteShoppingConfirm": "Si prepričan/a, da želiš odstraniti VSO {food} iz nakupovalnega listka?",
|
||||||
"Delete_Food": "Izbriši hrano",
|
"Delete_Food": "Izbriši hrano",
|
||||||
"Delete_Keyword": "Izbriši ključno besedo",
|
"Delete_Keyword": "Izbriši ključno besedo",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Opis",
|
"Description": "Opis",
|
||||||
"Description_Replace": "Zamenjaj Opis",
|
"Description_Replace": "Zamenjaj Opis",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -99,6 +99,7 @@
|
|||||||
"Delete_All": "Radera alla",
|
"Delete_All": "Radera alla",
|
||||||
"Delete_Food": "Ta bort livsmedel",
|
"Delete_Food": "Ta bort livsmedel",
|
||||||
"Delete_Keyword": "Ta bort nyckelord",
|
"Delete_Keyword": "Ta bort nyckelord",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Beskrivning",
|
"Description": "Beskrivning",
|
||||||
"Description_Replace": "Ersätt beskrivning",
|
"Description_Replace": "Ersätt beskrivning",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -98,6 +98,7 @@
|
|||||||
"Delete_All": "Tümünü sil",
|
"Delete_All": "Tümünü sil",
|
||||||
"Delete_Food": "Yiyeceği Sil",
|
"Delete_Food": "Yiyeceği Sil",
|
||||||
"Delete_Keyword": "Anahtar Kelimeyi Sil",
|
"Delete_Keyword": "Anahtar Kelimeyi Sil",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Açıklama",
|
"Description": "Açıklama",
|
||||||
"Description_Replace": "Açıklama Değiştir",
|
"Description_Replace": "Açıklama Değiştir",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -73,6 +73,7 @@
|
|||||||
"DeleteShoppingConfirm": "Ви впевнені, що хочете видалити {food} з вашого списку покупок?",
|
"DeleteShoppingConfirm": "Ви впевнені, що хочете видалити {food} з вашого списку покупок?",
|
||||||
"Delete_Food": "Видалити Їжу",
|
"Delete_Food": "Видалити Їжу",
|
||||||
"Delete_Keyword": "Видалити Ключове слово",
|
"Delete_Keyword": "Видалити Ключове слово",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "Опис",
|
"Description": "Опис",
|
||||||
"Description_Replace": "Замінити Опис",
|
"Description_Replace": "Замінити Опис",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -95,6 +95,7 @@
|
|||||||
"Delete_All": "全部删除",
|
"Delete_All": "全部删除",
|
||||||
"Delete_Food": "删除食物",
|
"Delete_Food": "删除食物",
|
||||||
"Delete_Keyword": "删除关键词",
|
"Delete_Keyword": "删除关键词",
|
||||||
|
"Deleted": "",
|
||||||
"Description": "描述",
|
"Description": "描述",
|
||||||
"Description_Replace": "替换描述",
|
"Description_Replace": "替换描述",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
"Date": "",
|
"Date": "",
|
||||||
"Delete": "",
|
"Delete": "",
|
||||||
"DeleteConfirmQuestion": "",
|
"DeleteConfirmQuestion": "",
|
||||||
|
"Deleted": "",
|
||||||
"DeviceSettings": "",
|
"DeviceSettings": "",
|
||||||
"DeviceSettingsHelp": "",
|
"DeviceSettingsHelp": "",
|
||||||
"Download": "",
|
"Download": "",
|
||||||
|
|||||||
@@ -9,21 +9,22 @@
|
|||||||
<v-list>
|
<v-list>
|
||||||
|
|
||||||
<v-list-item
|
<v-list-item
|
||||||
v-for="model in [TFood, TUnit, TKeyword,TSupermarket, TSupermarketCategory, TPropertyType, TUnitConversion, TAutomation, TUserFile, TCookLog, TViewLog]"
|
v-for="m in [TFood, TUnit, TKeyword,TSupermarket, TSupermarketCategory, TPropertyType, TUnitConversion, TAutomation, TUserFile, TCookLog, TViewLog]"
|
||||||
:to="{name: 'ModelListPage', params: {model: model.name}}"
|
@click="changeModel(m)"
|
||||||
|
:active="m.name == genericModel.model.name"
|
||||||
>
|
>
|
||||||
<template #prepend><v-icon :icon="model.icon"></v-icon> </template>
|
<template #prepend><v-icon :icon="m.icon"></v-icon> </template>
|
||||||
{{ $t(model.localizationKey) }}
|
{{ $t(m.localizationKey) }}
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-menu>
|
</v-menu>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<i :class="genericModel.model.icon"></i>
|
<i :class="genericModel.model.icon"></i>
|
||||||
{{ $t(genericModel.model.localizationKey) }}</span>
|
{{ $t(genericModel.model.localizationKey) }}</span>
|
||||||
<v-btn class="float-right" icon="$create" color="create" >
|
<v-btn class="float-right" icon="$create" color="create">
|
||||||
<i class="fa-solid fa-plus"></i>
|
<i class="fa-solid fa-plus"></i>
|
||||||
<model-edit-dialog :close-after-create="false" :model="model" @create="loadItems({tablePage, tablePageSize})"></model-edit-dialog>
|
<model-edit-dialog :close-after-create="false" :model="model" @create="loadItems({tablePage, tablePageSize})"></model-edit-dialog>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
<v-row>
|
<v-row>
|
||||||
@@ -55,7 +56,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
|
||||||
import {nextTick, onBeforeMount, onMounted, ref, watch} from "vue";
|
import {nextTick, onBeforeMount, onMounted, PropType, ref, watch} from "vue";
|
||||||
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
|
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
|
||||||
import {useI18n} from "vue-i18n";
|
import {useI18n} from "vue-i18n";
|
||||||
import {
|
import {
|
||||||
@@ -69,18 +70,25 @@ import {
|
|||||||
TSupermarket,
|
TSupermarket,
|
||||||
TUnitConversion,
|
TUnitConversion,
|
||||||
TAutomation,
|
TAutomation,
|
||||||
TUserFile, TCookLog, TViewLog
|
TUserFile, TCookLog, TViewLog, Model, EditorSupportedModels
|
||||||
} from "@/types/Models";
|
} from "@/types/Models";
|
||||||
import {VDataTable} from "vuetify/components";
|
import {VDataTable} from "vuetify/components";
|
||||||
import {useUrlSearchParams} from "@vueuse/core";
|
import {useUrlSearchParams} from "@vueuse/core";
|
||||||
import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue";
|
import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue";
|
||||||
|
import {useRouter} from "vue-router";
|
||||||
|
|
||||||
type VDataTableProps = InstanceType<typeof VDataTable>['$props']
|
type VDataTableProps = InstanceType<typeof VDataTable>['$props']
|
||||||
|
|
||||||
const {t} = useI18n()
|
const {t} = useI18n()
|
||||||
const params = useUrlSearchParams('history', {initialValue:{page:"1", pageSize: "10"}})
|
const router = useRouter()
|
||||||
|
|
||||||
|
const params = useUrlSearchParams('history', {initialValue: {page: "1", pageSize: "10"}})
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
model: {type: String, default: 'Food'},
|
model: {
|
||||||
|
type: String as PropType<EditorSupportedModels>,
|
||||||
|
default: 'Food'
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// table config
|
// table config
|
||||||
@@ -90,7 +98,7 @@ const itemsPerPageOptions = [
|
|||||||
{value: 50, title: '50'},
|
{value: 50, title: '50'},
|
||||||
]
|
]
|
||||||
|
|
||||||
const tableHeaders : VDataTableProps['headers'] = [
|
const tableHeaders: VDataTableProps['headers'] = [
|
||||||
{title: t('Name'), key: 'name'},
|
{title: t('Name'), key: 'name'},
|
||||||
{title: t('Category'), key: 'supermarketCategory.name'},
|
{title: t('Category'), key: 'supermarketCategory.name'},
|
||||||
{title: t('Actions'), key: 'action', align: 'end'},
|
{title: t('Actions'), key: 'action', align: 'end'},
|
||||||
@@ -98,7 +106,7 @@ const tableHeaders : VDataTableProps['headers'] = [
|
|||||||
|
|
||||||
const tablePage = ref(1)
|
const tablePage = ref(1)
|
||||||
const tablePageInitialized = ref(false) // TODO workaround until vuetify bug is fixed
|
const tablePageInitialized = ref(false) // TODO workaround until vuetify bug is fixed
|
||||||
const tablePageSize = ref(params.pageSize)
|
const tablePageSize = ref(10)
|
||||||
|
|
||||||
const tableShowSelect = ref(true)
|
const tableShowSelect = ref(true)
|
||||||
|
|
||||||
@@ -111,17 +119,21 @@ const searchQuery = ref('')
|
|||||||
const genericModel = ref({} as GenericModel)
|
const genericModel = ref({} as GenericModel)
|
||||||
|
|
||||||
|
|
||||||
// watch for changes to the prop in case its changed
|
// when navigating to ModelListPage from ModelListPage with a different model lifecycle hooks are not called so watch for change here
|
||||||
watch(() => props.model, () => {
|
watch(() => props.model, () => {
|
||||||
console.log('loading model ', props.model)
|
console.log('PAGE SIZE in watch params is ', params.pageSize)
|
||||||
genericModel.value = getGenericModelFromString(props.model, t)
|
genericModel.value = getGenericModelFromString(props.model, t)
|
||||||
loadItems({page: tablePage, itemsPerPage: tablePageSize})
|
loadItems({page: 1, itemsPerPage: Number(params.pageSize)})
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* select model class before mount because template renders (and requests item load) before onMounted is called
|
* select model class before mount because template renders (and requests item load) before onMounted is called
|
||||||
*/
|
*/
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
|
// TODO this whole params thing is strange, properly review the code once vuetify fixes their table (see below)
|
||||||
|
if (Number(params.pageSize) != tablePageSize.value) {
|
||||||
|
tablePageSize.value = Number(params.pageSize)
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
genericModel.value = getGenericModelFromString(props.model, t)
|
genericModel.value = getGenericModelFromString(props.model, t)
|
||||||
} catch (Error) {
|
} catch (Error) {
|
||||||
@@ -130,27 +142,48 @@ onBeforeMount(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load items from API whenever the table calls for it
|
||||||
|
* parameters defined by vuetify
|
||||||
|
* @param page
|
||||||
|
* @param itemsPerPage
|
||||||
|
* @param search
|
||||||
|
* @param sortBy
|
||||||
|
* @param groupBy
|
||||||
|
*/
|
||||||
function loadItems({page, itemsPerPage, search, sortBy, groupBy}) {
|
function loadItems({page, itemsPerPage, search, sortBy, groupBy}) {
|
||||||
|
console.log('load items called', page, params.page, itemsPerPage, params.pageSize)
|
||||||
loading.value = true
|
loading.value = true
|
||||||
// TODO workaround for initial page bug see https://github.com/vuetifyjs/vuetify/issues/17966
|
// TODO workaround for initial page bug see https://github.com/vuetifyjs/vuetify/issues/17966
|
||||||
if(page == 1 && Number(params.page) > 1 && !tablePageInitialized.value){
|
if (page == 1 && Number(params.page) > 1 && !tablePageInitialized.value) {
|
||||||
page = params.page
|
page = Number(params.page)
|
||||||
}
|
}
|
||||||
tablePageInitialized.value = true
|
tablePageInitialized.value = true
|
||||||
|
|
||||||
params.page = page
|
genericModel.value.list({page: page, pageSize: itemsPerPage, query: search}).then((r: any) => {
|
||||||
params.pageSize = itemsPerPage
|
|
||||||
genericModel.value.list({page: page, pageSize: itemsPerPage, query: search}).then(r => {
|
|
||||||
items.value = r.results
|
items.value = r.results
|
||||||
itemCount.value = r.count
|
itemCount.value = r.count
|
||||||
tablePage.value = page // TODO remove once page bug is fixed
|
|
||||||
}).catch((err: any) => {
|
}).catch((err: any) => {
|
||||||
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
|
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
|
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
console.log('setting parameters to ', page.toString(), itemsPerPage.toString())
|
||||||
|
params.page = page.toString()
|
||||||
|
params.pageSize = itemsPerPage.toString()
|
||||||
|
})
|
||||||
|
|
||||||
|
tablePage.value = page // TODO remove once page bug is fixed
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeModel(m: Model) {
|
||||||
|
tablePage.value = 1
|
||||||
|
router.push({name: 'ModelListPage', params: {model: m.name}})
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import {acceptHMRUpdate, defineStore} from 'pinia'
|
|||||||
import {ref} from "vue";
|
import {ref} from "vue";
|
||||||
import {useStorage} from "@vueuse/core";
|
import {useStorage} from "@vueuse/core";
|
||||||
import {DateTime} from "luxon";
|
import {DateTime} from "luxon";
|
||||||
|
import {ResponseError} from "@/openapi";
|
||||||
|
import {useI18n} from "vue-i18n";
|
||||||
|
|
||||||
/** @enum {string} different message types */
|
/** @enum {string} different message types */
|
||||||
export enum MessageType {
|
export enum MessageType {
|
||||||
@@ -13,10 +15,10 @@ export enum MessageType {
|
|||||||
|
|
||||||
/** @enum {string} pre defined error messages */
|
/** @enum {string} pre defined error messages */
|
||||||
export enum ErrorMessageType {
|
export enum ErrorMessageType {
|
||||||
FETCH_ERROR = 'Fetch Error',
|
FETCH_ERROR = 'Fehler beim Laden',
|
||||||
UPDATE_ERROR = 'Update Error',
|
UPDATE_ERROR = 'Fehler beim Aktualisieren',
|
||||||
CREATE_ERROR = 'Update Error',
|
DELETE_ERROR = 'Fehler beim Löschen',
|
||||||
DELETE_ERROR = 'Update Error',
|
CREATE_ERROR = 'Fehler beim Erstellen',
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @enum {MessageType} prepared messages */
|
/** @enum {MessageType} prepared messages */
|
||||||
@@ -26,6 +28,14 @@ export enum PreparedMessage {
|
|||||||
DELETE_SUCCESS = 'DELETE_SUCCESS',
|
DELETE_SUCCESS = 'DELETE_SUCCESS',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* structured message type
|
||||||
|
*/
|
||||||
|
export interface StructuredMessage {
|
||||||
|
title: string
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type Message holding all required contents of a message
|
* Type Message holding all required contents of a message
|
||||||
*/
|
*/
|
||||||
@@ -33,17 +43,20 @@ export class Message {
|
|||||||
type = {} as MessageType
|
type = {} as MessageType
|
||||||
createdAt = -1
|
createdAt = -1
|
||||||
showTimeout = 0
|
showTimeout = 0
|
||||||
msg = ""
|
msg = {} as StructuredMessage
|
||||||
data = {} as any
|
data = {} as any
|
||||||
code = ''
|
code = ''
|
||||||
|
|
||||||
constructor(type: MessageType, msg: string, showTimeout?: number, data?: any) {
|
constructor(type: MessageType, msg: string | StructuredMessage, showTimeout?: number, data?: any) {
|
||||||
if (typeof showTimeout === 'undefined') {
|
if (typeof showTimeout === 'undefined') {
|
||||||
showTimeout = 0
|
showTimeout = 0
|
||||||
}
|
}
|
||||||
if (typeof data === 'undefined') {
|
if (typeof data === 'undefined') {
|
||||||
data = {}
|
data = {}
|
||||||
}
|
}
|
||||||
|
if (typeof msg === 'string') {
|
||||||
|
msg = {title: '', text: msg} as StructuredMessage
|
||||||
|
}
|
||||||
|
|
||||||
this.type = type
|
this.type = type
|
||||||
this.msg = msg
|
this.msg = msg
|
||||||
@@ -61,14 +74,19 @@ export const useMessageStore = defineStore('message_store', () => {
|
|||||||
let messages = useStorage('LOCAL_MESSAGES', [] as Message[])
|
let messages = useStorage('LOCAL_MESSAGES', [] as Message[])
|
||||||
let snackbarQueue = ref([] as Message[])
|
let snackbarQueue = ref([] as Message[])
|
||||||
|
|
||||||
|
const {t} = useI18n()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a message to the message store. If showTimeout is greater than 0 it is also added to the display queue.
|
* Add a message to the message store. If showTimeout is greater than 0 it is also added to the display queue.
|
||||||
* @param {MessageType} type type of message
|
* @param {MessageType} type type of message
|
||||||
* @param {String} msg message text
|
* @param {String|StructuredMessage} msg message text or structured message
|
||||||
* @param {number} showTimeout optional number of ms to show message to user, set to 0 or leave undefined for silent message
|
* @param {number} showTimeout optional number of ms to show message to user, set to 0 or leave undefined for silent message
|
||||||
* @param {string} data optional additional data only shown in log
|
* @param {string} data optional additional data only shown in log
|
||||||
*/
|
*/
|
||||||
function addMessage(type: MessageType, msg: string, showTimeout?: number, data?: any) {
|
function addMessage(type: MessageType, msg: string | StructuredMessage, showTimeout?: number, data?: any) {
|
||||||
|
if (typeof msg == 'string') {
|
||||||
|
msg = {title: '', text: msg} as StructuredMessage
|
||||||
|
}
|
||||||
let message = new Message(type, msg, showTimeout, data)
|
let message = new Message(type, msg, showTimeout, data)
|
||||||
|
|
||||||
messages.value.push(message)
|
messages.value.push(message)
|
||||||
@@ -79,27 +97,67 @@ export const useMessageStore = defineStore('message_store', () => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* shorthand function to quickly add an error message
|
* shorthand function to quickly add an error message
|
||||||
|
* automatically show additional information when given supported error types (e.g. ResponseError)
|
||||||
* @param errorType pre defined error type
|
* @param errorType pre defined error type
|
||||||
* @param data optional error data
|
* @param data optional error data
|
||||||
*/
|
*/
|
||||||
function addError(errorType: ErrorMessageType | string, data?: any) {
|
function addError(errorType: ErrorMessageType | string, data?: any) {
|
||||||
addMessage(MessageType.ERROR, errorType, 7000, data)
|
if (data instanceof ResponseError) {
|
||||||
|
let messageText = ""
|
||||||
|
messageText += `URL: ${data.response.url} \n\nErrors:\n`
|
||||||
|
try {
|
||||||
|
data.response.json().then(responseJson => {
|
||||||
|
let flatResponseJson = flattenObject(responseJson)
|
||||||
|
for (let key in flatResponseJson) {
|
||||||
|
messageText += ` - ${key}: ${flatResponseJson[key]}\n`
|
||||||
|
}
|
||||||
|
addMessage(MessageType.ERROR, {
|
||||||
|
title: `${errorType} - ${data.response.statusText} (${data.response.status})`,
|
||||||
|
text: messageText
|
||||||
|
} as StructuredMessage, 5000 + Object.keys(responseJson).length * 1500, responseJson)
|
||||||
|
}).catch(() => {
|
||||||
|
// if response does not contain parsable JSON or parsing fails for some other reason show generic error
|
||||||
|
addMessage(MessageType.ERROR, {title: errorType, text: ''} as StructuredMessage, 7000, data)
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
addMessage(MessageType.ERROR, {title: errorType, text: ''} as StructuredMessage, 7000, data)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addMessage(MessageType.ERROR, {title: errorType, text: ''} as StructuredMessage, 7000, data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shorthand function to quickly add a message
|
* shorthand function to quickly add a message
|
||||||
* @param preparedMessage pre defined message
|
* @param preparedMessage pre defined message
|
||||||
|
* @param data optional data to log along with the message
|
||||||
*/
|
*/
|
||||||
function addPreparedMessage(preparedMessage: PreparedMessage) {
|
function addPreparedMessage(preparedMessage: PreparedMessage, data?: any) {
|
||||||
if (preparedMessage == PreparedMessage.UPDATE_SUCCESS) {
|
if (preparedMessage == PreparedMessage.UPDATE_SUCCESS) {
|
||||||
addMessage(MessageType.SUCCESS, 'Updated Successfully', 7000, {}) // TODO localize and make more useful ?
|
addMessage(MessageType.SUCCESS, {title: t('Updated'), text: ''} as StructuredMessage, 6000, data)
|
||||||
}
|
|
||||||
if (preparedMessage == PreparedMessage.CREATE_SUCCESS) {
|
|
||||||
addMessage(MessageType.SUCCESS, 'Created Successfully', 7000, {})
|
|
||||||
}
|
}
|
||||||
if (preparedMessage == PreparedMessage.DELETE_SUCCESS) {
|
if (preparedMessage == PreparedMessage.DELETE_SUCCESS) {
|
||||||
addMessage(MessageType.SUCCESS, 'Deleted Successfully', 7000, {})
|
addMessage(MessageType.SUCCESS, {title: t('Deleted'), text: ''} as StructuredMessage, 6000, data)
|
||||||
}
|
}
|
||||||
|
if (preparedMessage == PreparedMessage.CREATE_SUCCESS) {
|
||||||
|
addMessage(MessageType.SUCCESS, {title: t('Created'), text: ''} as StructuredMessage, 6000, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* recursively flatten any multi level object to a flat object with previously nested keys seperated by dots
|
||||||
|
* @param obj object to flatten
|
||||||
|
* @param keyPrefix key prefix for recursive calls to build structure
|
||||||
|
*/
|
||||||
|
function flattenObject(obj: any, keyPrefix = '') {
|
||||||
|
return Object.keys(obj).reduce((acc, key) => {
|
||||||
|
if (typeof obj[key] === 'object') {
|
||||||
|
Object.assign(acc, flattenObject(obj[key], (keyPrefix.length ? keyPrefix + '.' : '') + key))
|
||||||
|
} else {
|
||||||
|
acc[keyPrefix] = obj[key]
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,18 +1,5 @@
|
|||||||
import {
|
import { ApiApi } from "@/openapi";
|
||||||
ApiApi,
|
|
||||||
Keyword as IKeyword,
|
|
||||||
Food as IFood,
|
|
||||||
RecipeOverview as IRecipeOverview,
|
|
||||||
Recipe as IRecipe,
|
|
||||||
Unit as IUnit,
|
|
||||||
MealType as IMealType,
|
|
||||||
User as IUser,
|
|
||||||
FoodInheritField as IFoodInheritField,
|
|
||||||
SupermarketCategory as ISupermarketCategory,
|
|
||||||
PropertyType as IPropertyType, ApiFoodListRequest, ApiUnitListRequest,
|
|
||||||
} from "@/openapi";
|
|
||||||
import {VDataTable} from "vuetify/components";
|
import {VDataTable} from "vuetify/components";
|
||||||
import {useI18n} from "vue-i18n";
|
|
||||||
|
|
||||||
type VDataTableProps = InstanceType<typeof VDataTable>['$props']
|
type VDataTableProps = InstanceType<typeof VDataTable>['$props']
|
||||||
|
|
||||||
@@ -57,7 +44,7 @@ type ModelTableHeaders = {
|
|||||||
/**
|
/**
|
||||||
* custom type containing all attributes needed by the generic model system to properly handle all functions
|
* custom type containing all attributes needed by the generic model system to properly handle all functions
|
||||||
*/
|
*/
|
||||||
type Model = {
|
export type Model = {
|
||||||
name: string,
|
name: string,
|
||||||
localizationKey: string,
|
localizationKey: string,
|
||||||
icon: string,
|
icon: string,
|
||||||
@@ -75,6 +62,8 @@ type Model = {
|
|||||||
}
|
}
|
||||||
export let SUPPORTED_MODELS = new Map<string, Model>()
|
export let SUPPORTED_MODELS = new Map<string, Model>()
|
||||||
|
|
||||||
|
export type EditorSupportedModels = 'UnitConversion' | 'AccessToken' | 'InviteLink' | 'UserSpace' | 'MealType' | 'Property' | 'Food' | 'Supermarket' | 'SupermarketCategory' | 'PropertyType' | 'Automation'
|
||||||
|
|
||||||
export const TFood = {
|
export const TFood = {
|
||||||
name: 'Food',
|
name: 'Food',
|
||||||
localizationKey: 'Food',
|
localizationKey: 'Food',
|
||||||
|
|||||||
Reference in New Issue
Block a user