model editor stuff

This commit is contained in:
vabene1111
2024-10-02 22:28:59 +02:00
parent ddf977f665
commit 64c5fe3157
7 changed files with 156 additions and 9 deletions

View File

@@ -1,8 +1,10 @@
<template>
<v-dialog max-width="600" activator="parent" v-model="dialog">
<supermarket-category-editor :item="item" @create="createEvent" @save="saveEvent" @delete="deleteEvent" dialog @close="dialog = false" v-if="model == 'SupermarketCategory'"></supermarket-category-editor>
<unit-conversion-editor :item="item" @create="createEvent" @save="saveEvent" @delete="deleteEvent" dialog @close="dialog = false" v-if="model == 'UnitConversion'" :disabled-fields="disabledFields"></unit-conversion-editor>
<access-token-editor :item="item" @create="createEvent" @save="saveEvent" @delete="deleteEvent" dialog @close="dialog = false" v-if="model == 'AccessToken'"></access-token-editor>
<invite-link-editor :item="item" @create="createEvent" @save="saveEvent" @delete="deleteEvent" dialog @close="dialog = false" v-if="model == 'InviteLink'"></invite-link-editor>
<supermarket-editor :item="item" @create="createEvent" @save="saveEvent" @delete="deleteEvent" dialog @close="dialog = false" v-if="model == 'Supermarket'"></supermarket-editor>
<user-space-editor :item="item" @create="createEvent" @save="saveEvent" @delete="deleteEvent" dialog @close="dialog = false" v-if="model == 'UserSpace'"></user-space-editor>
<meal-type-editor :item="item" @create="createEvent" @save="saveEvent" @delete="deleteEvent" dialog @close="dialog = false" v-if="model == 'MealType'"></meal-type-editor>
<property-editor :item="item" @create="createEvent" @save="saveEvent" @delete="deleteEvent" dialog @close="dialog = false" v-if="model == 'Property'"></property-editor>
@@ -22,12 +24,14 @@ import MealTypeEditor from "@/components/model_editors/MealTypeEditor.vue";
import PropertyEditor from "@/components/model_editors/PropertyEditor.vue";
import UnitConversionEditor from "@/components/model_editors/UnitConversionEditor.vue";
import FoodEditor from "@/components/model_editors/FoodEditor.vue";
import SupermarketEditor from "@/components/model_editors/SupermarketEditor.vue";
import SupermarketCategoryEditor from "@/components/model_editors/SupermarketCategoryEditor.vue";
const emit = defineEmits(['create', 'save', 'delete'])
const props = defineProps({
model: {
type: String as PropType<'UnitConversion' | 'AccessToken'| 'InviteLink' | 'UserSpace' | 'MealType' | 'Property' | 'Food'>,
type: String as PropType<'UnitConversion' | 'AccessToken'| 'InviteLink' | 'UserSpace' | 'MealType' | 'Property' | 'Food' | 'Supermarket' | 'SupermarketCategory'>,
required: true,
},
item: {default: null},

View File

@@ -9,14 +9,13 @@
:model-class="modelClass"
:object-name="editingObjName()">
<v-tabs v-model="tab" :disabled="loading">
<v-tabs v-model="tab" :disabled="loading" grow>
<v-tab value="food">{{ $t('Food') }}</v-tab>
<v-tab value="properties">{{ $t('Properties') }}</v-tab>
<v-tab value="conversions">{{ $t('Conversion') }}</v-tab>
<v-tab value="misc">{{ $t('Miscellaneous') }}</v-tab>
</v-tabs>
<v-card-text>
<v-tabs-window v-model="tab">
<v-tabs-window-item value="food">

View File

@@ -0,0 +1,55 @@
<template>
<model-editor-base
:loading="loading"
:dialog="dialog"
@save="saveObject"
@delete="deleteObject"
@close="emit('close')"
:is-update="isUpdate()"
:model-class="modelClass"
:object-name="editingObjName()">
<v-card-text>
<v-form :disabled="loading">
<v-text-field :label="$t('Name')" v-model="editingObj.name"></v-text-field>
<v-textarea :label="$t('Description')" v-model="editingObj.description"></v-textarea>
</v-form>
</v-card-text>
</model-editor-base>
</template>
<script setup lang="ts">
import {onMounted, PropType} from "vue";
import {SupermarketCategory} from "@/openapi";
import ModelEditorBase from "@/components/model_editors/ModelEditorBase.vue";
import {useModelEditorFunctions} from "@/composables/useModelEditorFunctions";
import {useI18n} from "vue-i18n";
const {t} = useI18n()
const props = defineProps({
item: {type: {} as PropType<SupermarketCategory>, required: false, default: null},
itemId: {type: [Number, String], required: false, default: undefined},
dialog: {type: Boolean, default: false}
})
const emit = defineEmits(['create', 'save', 'delete', 'close'])
const {setupState, deleteObject, saveObject, isUpdate, editingObjName, loading, editingObj, modelClass} = useModelEditorFunctions<SupermarketCategory>('SupermarketCategory', emit)
// object specific data (for selects/display)
onMounted(() => {
if (!setupState(props.item, props.itemId)) {
// functions to populate defaults
}
})
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,68 @@
<template>
<model-editor-base
:loading="loading"
:dialog="dialog"
@save="saveObject"
@delete="deleteObject"
@close="emit('close')"
:is-update="isUpdate()"
:model-class="modelClass"
:object-name="editingObjName()">
<v-tabs v-model="tab" :disabled="loading" grow>
<v-tab value="supermarket">{{ $t('Supermarket') }}</v-tab>
<v-tab value="categories">{{ $t('Categories') }}</v-tab>
</v-tabs>
<v-card-text>
<v-tabs-window v-model="tab">
<v-tabs-window-item value="supermarket">
<v-form :disabled="loading">
<v-text-field :label="$t('Name')" v-model="editingObj.name"></v-text-field>
<v-textarea :label="$t('Description')" v-model="editingObj.description"></v-textarea>
<v-text-field :label="$t('Open_Data_Slug')" :hint="$t('open_data_help_text')" persistent-hint v-model="editingObj.openDataSlug" disabled></v-text-field>
</v-form>
</v-tabs-window-item>
<v-tabs-window-item value="supermarket">
</v-tabs-window-item>
</v-tabs-window>
</v-card-text>
</model-editor-base>
</template>
<script setup lang="ts">
import {onMounted, PropType, ref} from "vue";
import {Supermarket} from "@/openapi";
import ModelEditorBase from "@/components/model_editors/ModelEditorBase.vue";
import {useModelEditorFunctions} from "@/composables/useModelEditorFunctions";
const props = defineProps({
item: {type: {} as PropType<Supermarket>, required: false, default: null},
itemId: {type: [Number, String], required: false, default: undefined},
dialog: {type: Boolean, default: false}
})
const emit = defineEmits(['create', 'save', 'delete', 'close'])
const {setupState, deleteObject, saveObject, isUpdate, editingObjName, loading, editingObj, modelClass} = useModelEditorFunctions<Supermarket>('Supermarket', emit)
// object specific data (for selects/display)
const tab = ref("supermarket")
onMounted(() => {
if (!setupState(props.item, props.itemId)) {
// functions to populate defaults
}
})
</script>
<style scoped>
</style>

View File

@@ -14,6 +14,7 @@
<food-editor :item-id="id" v-if="model == 'Food'" @delete="router.go(-1)"></food-editor>
<unit-editor :item-id="id" v-if="model == 'Unit'" @delete="router.go(-1)"></unit-editor>
<keyword-editor :item-id="id" v-if="model == 'Keyword'" @delete="router.go(-1)"></keyword-editor>
<supermarket-editor :item-id="id" v-if="model == 'Supermarket'" @delete="router.go(-1)"></supermarket-editor>
</v-col>
</v-row>
</v-container>
@@ -27,6 +28,7 @@ import {ApiApi, Food} from "@/openapi";
import {useRouter} from "vue-router";
import UnitEditor from "@/components/model_editors/UnitEditor.vue";
import KeywordEditor from "@/components/model_editors/KeywordEditor.vue";
import SupermarketEditor from "@/components/model_editors/SupermarketEditor.vue";
const props = defineProps({
model: {type: String, default: 'Food'},

View File

@@ -18,8 +18,12 @@
</v-list>
</v-menu>
</v-btn>
<v-icon :icon="genericModel.model.icon"></v-icon>
<i :class="genericModel.model.icon"></i>
{{ $t(genericModel.model.localizationKey) }}</span>
<v-btn class="float-right" icon="$create" color="create" >
<i class="fa-solid fa-plus"></i>
<model-edit-dialog :close-after-create="false" :model="model" @create="loadItems({tablePage, tablePageSize})"></model-edit-dialog>
</v-btn>
</v-col>
</v-row>
<v-row>
@@ -34,6 +38,8 @@
:headers="genericModel.getTableHeaders()"
:items-per-page-options="itemsPerPageOptions"
:show-select="tableShowSelect"
:page="tablePage"
:items-per-page="tablePageSize"
>
<template v-slot:item.action="{ item }">
<v-btn color="edit" :to="{name: 'ModelEditPage', params: {model: model, id: item.id}}">
@@ -49,7 +55,7 @@
<script setup lang="ts">
import {onBeforeMount, onMounted, ref, watch} from "vue";
import {nextTick, onBeforeMount, onMounted, ref, watch} from "vue";
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
import {useI18n} from "vue-i18n";
import {
@@ -66,10 +72,12 @@ import {
TUserFile, TCookLog, TViewLog
} from "@/types/Models";
import {VDataTable} from "vuetify/components";
import {useUrlSearchParams} from "@vueuse/core";
import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue";
type VDataTableProps = InstanceType<typeof VDataTable>['$props']
const {t} = useI18n()
const params = useUrlSearchParams('history', {initialValue:{page:"1", pageSize: "10"}})
const props = defineProps({
model: {type: String, default: 'Food'},
@@ -88,6 +96,10 @@ const tableHeaders : VDataTableProps['headers'] = [
{title: t('Actions'), key: 'action', align: 'end'},
]
const tablePage = ref(1)
const tablePageInitialized = ref(false) // TODO workaround until vuetify bug is fixed
const tablePageSize = ref(params.pageSize)
const tableShowSelect = ref(true)
// data
@@ -103,14 +115,13 @@ const genericModel = ref({} as GenericModel)
watch(() => props.model, () => {
console.log('loading model ', props.model)
genericModel.value = getGenericModelFromString(props.model, t)
loadItems({page: 1, itemsPerPage: 10})
loadItems({page: tablePage, itemsPerPage: tablePageSize})
})
/**
* select model class before mount because template renders (and requests item load) before onMounted is called
*/
onBeforeMount(() => {
try {
genericModel.value = getGenericModelFromString(props.model, t)
} catch (Error) {
@@ -121,10 +132,18 @@ onBeforeMount(() => {
function loadItems({page, itemsPerPage, search, sortBy, groupBy}) {
loading.value = true
// TODO workaround for initial page bug see https://github.com/vuetifyjs/vuetify/issues/17966
if(page == 1 && Number(params.page) > 1 && !tablePageInitialized.value){
page = params.page
}
tablePageInitialized.value = true
params.page = page
params.pageSize = itemsPerPage
genericModel.value.list({page: page, pageSize: itemsPerPage, query: search}).then(r => {
items.value = r.results
itemCount.value = r.count
tablePage.value = page // TODO remove once page bug is fixed
}).catch((err: any) => {
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
}).finally(() => {

View File

@@ -64,7 +64,7 @@ export default createVuetify({
save: 'fa-solid fa-floppy-disk',
delete: 'fa-solid fa-trash-can',
edit: 'fa-solid fa-pencil',
create: 'fa-solid fa-circle-plus',
create: 'fa-solid fa-plus',
search: 'fa-solid fa-magnifying-glass',
copy: 'fa-solid fa-copy',
close: 'fa-solid fa-xmark',