updated model editors to composable and base template

This commit is contained in:
vabene1111
2024-09-28 13:07:46 +02:00
parent 67fff17f06
commit 143eafa24a
43 changed files with 531 additions and 522 deletions

View File

@@ -4,7 +4,8 @@
<v-card>
<v-card-title>{{ $t('Delete') }}</v-card-title>
<v-card-text>
{{ $t('DeleteConfirmQuestion')}}
{{ $t('DeleteConfirmQuestion')}} <br/>
<b>{{ modelName }}</b><br/>
<b>{{ objectName }}</b>
</v-card-text>
<v-card-actions>
@@ -25,7 +26,8 @@ import {ref} from "vue";
const emit = defineEmits(['delete'])
const props = defineProps({
objectName: {type: String, default: ''}
objectName: {type: String, default: ''},
modelName: {type: String, default: ''},
})
const dialog = ref(false)

View File

@@ -1,9 +1,13 @@
<template>
<v-card :loading="loading">
<v-card-title>
{{ $t(modelClass.model.localizationKey) }}
<v-btn class="float-right" icon="$close" variant="plain" @click="emit('close')" v-if="dialog"></v-btn>
</v-card-title>
<model-editor-base
:loading="loading"
:dialog="dialog"
@save="saveObject"
@delete="deleteObject"
@close="emit('close')"
:is-update="isUpdate()"
:model-name="$t(modelClass.model.localizationKey)"
:object-name="editingObjName()">
<v-card-text>
<v-form :disabled="loading">
<v-row>
@@ -19,65 +23,33 @@
<v-date-input :label="$t('Valid Until')" v-model="editingObj.expires"></v-date-input>
</v-form>
</v-card-text>
<v-card-actions>
<v-btn color="delete" prepend-icon="$delete" v-if="isUpdate">{{ $t('Delete') }}
<delete-confirm-dialog :object-name="objectName" @delete="deleteObject"></delete-confirm-dialog>
</v-btn>
<v-btn color="save" prepend-icon="$save" @click="saveObject(modelClass, editingObj)">{{ isUpdate ? $t('Save') : $t('Create') }}</v-btn>
</v-card-actions>
</v-card>
</model-editor-base>
</template>
<script setup lang="ts">
import {VDateInput} from 'vuetify/labs/VDateInput' //TODO remove once component is out of labs
import {computed, onBeforeMount, onMounted, PropType, ref} from "vue";
import {onMounted, PropType} from "vue";
import {AccessToken} from "@/openapi";
import DeleteConfirmDialog from "@/components/dialogs/DeleteConfirmDialog.vue";
import {useI18n} from "vue-i18n";
import {ErrorMessageType, PreparedMessage, useMessageStore} from "@/stores/MessageStore";
import {DateTime} from "luxon";
import BtnCopy from "@/components/buttons/BtnCopy.vue";
import {GenericModel, getGenericModelFromString} from "@/types/Models";
import {useModelEditorFunctions} from "@/composables/useModelEditorFunctions";
const {t} = useI18n()
const emit = defineEmits(['create', 'save', 'delete', 'close'])
import ModelEditorBase from "@/components/model_editors/ModelEditorBase.vue";
const props = defineProps({
item: {type: {} as PropType<AccessToken>, required: false},
item: {type: {} as PropType<AccessToken>, required: false, default: null},
itemId: {type: Number, required: false, default: undefined},
dialog: {type: Boolean, default: false}
})
//const editingObj = ref({} as AccessToken)
const modelClass = ref({} as GenericModel)
const emit = defineEmits(['create', 'save', 'delete', 'close'])
const {setupState, deleteObject, saveObject, isUpdate, editingObjName, loading, editingObj, modelClass} = useModelEditorFunctions<AccessToken>('AccessToken', emit)
const {deleteObject, saveObject, loading, editingObj} = useModelEditorFunctions<AccessToken>(emit)
/**
* checks if given object has ID property to determine if it needs to be updated or created
*/
const isUpdate = computed(() => {
return editingObj.value.id !== undefined
})
/**
* display name for object in headers/delete dialog/...
*/
const objectName = computed(() => {
return isUpdate ? `${t(modelClass.value.model.localizationKey)} ${editingObj.value.token}` : `${t(modelClass.value.model.localizationKey)} (${t('New')})`
})
onBeforeMount(() => {
modelClass.value = getGenericModelFromString('AccessToken', t)
})
onMounted(() => {
if (props.item != null) {
editingObj.value = props.item
} else {
if (!setupState(props.item, props.itemId)) {
// functions to populate defaults
editingObj.value.expires = DateTime.now().plus({year: 1}).toJSDate()
editingObj.value.scope = 'read write'

View File

@@ -1,129 +1,65 @@
<template>
<v-card>
<v-card-title>
{{ $t(OBJ_LOCALIZATION_KEY) }}
<v-btn class="float-right" icon="$close" variant="plain" @click="emit('close')" v-if="dialog"></v-btn>
</v-card-title>
<model-editor-base
:loading="loading"
:dialog="dialog"
@save="saveObject"
@delete="deleteObject"
@close="emit('close')"
:is-update="isUpdate()"
:model-name="$t(modelClass.model.localizationKey)"
:object-name="editingObjName()">
<v-card-text>
<v-form>
<v-form :disabled="loading">
<v-text-field :label="$t('Email')" v-model="editingObj.email"></v-text-field>
<v-select :label="$t('Role')" :items="groups" item-value="id" item-title="name" return-object v-model="editingObj.group"></v-select>
<v-date-input :label="$t('Valid Until')" v-model="editingObj.validUntil"></v-date-input>
<v-textarea :label="$t('Note')" v-model="editingObj.internalNote"></v-textarea>
<v-checkbox :label="$t('Reusable')" v-model="editingObj.reusable"></v-checkbox>
</v-form>
</v-card-text>
<v-card-actions>
<v-btn color="delete" prepend-icon="$delete" v-if="isUpdate">{{ $t('Delete') }}
<delete-confirm-dialog :object-name="objectName" @delete="deleteObject"></delete-confirm-dialog>
</v-btn>
<v-btn color="save" prepend-icon="$save" @click="saveObject">{{ isUpdate ? $t('Save') : $t('Create') }}</v-btn>
</v-card-actions>
</v-card>
</model-editor-base>
</template>
<script setup lang="ts">
import {VDateInput} from 'vuetify/labs/VDateInput' //TODO remove once component is out of labs
import {computed, onMounted, ref} from "vue";
import {AccessToken, ApiApi, Group, InviteLink} from "@/openapi";
import DeleteConfirmDialog from "@/components/dialogs/DeleteConfirmDialog.vue";
import {useI18n} from "vue-i18n";
import {ErrorMessageType, PreparedMessage, useMessageStore} from "@/stores/MessageStore";
import { onMounted, PropType, ref} from "vue";
import {ApiApi, Group, InviteLink} from "@/openapi";
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
import {DateTime} from "luxon";
import {useClipboard} from "@vueuse/core";
import ModelEditorBase from "@/components/model_editors/ModelEditorBase.vue";
import {useModelEditorFunctions} from "@/composables/useModelEditorFunctions";
const {t} = useI18n()
const {copy} = useClipboard()
const emit = defineEmits(['create', 'save', 'delete', 'close'])
const props = defineProps({
item: {type: {} as InviteLink, required: false},
item: {type: {} as PropType<InviteLink>, required: false, default: null},
itemId: {type: Number, required: false, default: undefined},
dialog: {type: Boolean, default: false}
})
const OBJ_LOCALIZATION_KEY = 'Invite_Link'
const editingObj = ref({} as InviteLink)
const loading = ref(false)
const emit = defineEmits(['create', 'save', 'delete', 'close'])
const {setupState, deleteObject, saveObject, isUpdate, editingObjName, loading, editingObj, modelClass} = useModelEditorFunctions<InviteLink>('InviteLink', emit)
// object specific data (for selects/display)
const groups = ref([] as Group[])
/**
* checks if given object has ID property to determine if it needs to be updated or created
*/
const isUpdate = computed(() => {
return editingObj.value.id !== undefined
})
/**
* display name for object in headers/delete dialog/...
*/
const objectName = computed(() => {
return isUpdate ? `${t(OBJ_LOCALIZATION_KEY)} ${editingObj.value.token}` : `${t(OBJ_LOCALIZATION_KEY)} (${t('New')})`
})
onMounted(() => {
const api = new ApiApi()
api.apiGroupList().then(r => {
groups.value = r
if (props.item != null) {
editingObj.value = props.item
} else {
if (!setupState(props.item, props.itemId)) {
// functions to populate defaults
editingObj.value.validUntil = DateTime.now().plus({month: 1}).toJSDate()
editingObj.value.group = groups.value[0]
}
}).catch(err => {
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
})
})
/**
* saves the edited object in the database
*/
async function saveObject() {
let api = new ApiApi()
if (isUpdate.value) {
api.apiInviteLinkUpdate({id: editingObj.value.id, inviteLink: editingObj.value}).then(r => {
editingObj.value = r
emit('save', r)
useMessageStore().addPreparedMessage(PreparedMessage.UPDATE_SUCCESS)
}).catch(err => {
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
})
} else {
api.apiInviteLinkCreate({inviteLink: editingObj.value}).then(r => {
editingObj.value = r
emit('create', r)
useMessageStore().addPreparedMessage(PreparedMessage.CREATE_SUCCESS)
}).catch(err => {
useMessageStore().addError(ErrorMessageType.CREATE_ERROR, err)
})
}
}
/**
* deletes the editing object from the database
*/
async function deleteObject() {
let api = new ApiApi()
api.apiInviteLinkDestroy({id: editingObj.value.id}).then(r => {
editingObj.value = {} as InviteLink
emit('delete')
}).catch(err => {
useMessageStore().addError(ErrorMessageType.DELETE_ERROR, err)
})
}
</script>
<style scoped>

View File

@@ -1,11 +1,15 @@
<template>
<v-card>
<v-card-title>
{{ $t(OBJ_LOCALIZATION_KEY) }}
<v-btn class="float-right" icon="$close" variant="plain" @click="emit('close')" v-if="dialog"></v-btn>
</v-card-title>
<model-editor-base
:loading="loading"
:dialog="dialog"
@save="saveObject"
@delete="deleteObject"
@close="emit('close')"
:is-update="isUpdate()"
:model-name="$t(modelClass.model.localizationKey)"
:object-name="editingObjName()">
<v-card-text>
<v-form>
<v-form :disabled="loading">
<v-text-field v-model="editingObj.name" :label="$t('Name')"></v-text-field>
<v-text-field
@@ -17,117 +21,49 @@
prepend-icon="fa-solid fa-clock"
readonly>
<v-menu
v-model="timePickerMenu"
:close-on-content-click="false"
activator="parent"
transition="scale-transition">
<v-time-picker v-if="timePickerMenu" format="24hr" v-model="editingObj.time"></v-time-picker>
</v-menu>
v-model="timePickerMenu"
:close-on-content-click="false"
activator="parent"
transition="scale-transition">
<v-time-picker v-if="timePickerMenu" format="24hr" v-model="editingObj.time"></v-time-picker>
</v-menu>
</v-text-field>
<v-color-picker v-model="editingObj.color" mode="hex" :modes="['hex']" show-swatches
:swatches="[['#ddbf86'],['#b98766'],['#b55e4f'],['#82aa8b'],['#385f84']]"></v-color-picker>
</v-form>
</v-card-text>
<v-card-actions>
<v-btn color="delete" prepend-icon="$delete" v-if="isUpdate">{{ $t('Delete') }}
<delete-confirm-dialog :object-name="objectName" @delete="deleteObject"></delete-confirm-dialog>
</v-btn>
<v-btn color="save" prepend-icon="$save" @click="saveObject">{{ isUpdate ? $t('Save') : $t('Create') }}</v-btn>
</v-card-actions>
</v-card>
</model-editor-base>
</template>
<script setup lang="ts">
import {computed, onMounted, ref} from "vue";
import {ApiApi, MealType} from "@/openapi";
import DeleteConfirmDialog from "@/components/dialogs/DeleteConfirmDialog.vue";
import {useI18n} from "vue-i18n";
import {ErrorMessageType, PreparedMessage, useMessageStore} from "@/stores/MessageStore";
import {useClipboard} from "@vueuse/core";
import {VTimePicker} from 'vuetify/labs/VTimePicker'
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore"; // TODO remove once out of labs
import {onMounted, PropType, ref} from "vue";
import {MealType} from "@/openapi";
import {VTimePicker} from 'vuetify/labs/VTimePicker'; // TODO remove once out of labs
import ModelEditorBase from "@/components/model_editors/ModelEditorBase.vue";
import {useModelEditorFunctions} from "@/composables/useModelEditorFunctions";
const {t} = useI18n()
const {copy} = useClipboard()
const emit = defineEmits(['create', 'save', 'delete', 'close'])
const props = defineProps({
item: {type: {} as MealType, required: true},
item: {type: {} as PropType<MealType>, required: false, default: null},
itemId: {type: Number, required: false, default: undefined},
dialog: {type: Boolean, default: false}
})
const OBJ_LOCALIZATION_KEY = 'Meal_Type'
const editingObj = ref({} as MealType)
const loading = ref(false)
const emit = defineEmits(['create', 'save', 'delete', 'close'])
const {setupState, deleteObject, saveObject, isUpdate, editingObjName, loading, editingObj, modelClass} = useModelEditorFunctions<MealType>('MealType', emit)
// object specific data (for selects/display)
const timePickerMenu = ref(false)
/**
* checks if given object has ID property to determine if it needs to be updated or created
*/
const isUpdate = computed(() => {
return editingObj.value.id !== undefined
})
/**
* display name for object in headers/delete dialog/...
*/
const objectName = computed(() => {
return isUpdate ? `${t(OBJ_LOCALIZATION_KEY)} ${editingObj.value.token}` : `${t(OBJ_LOCALIZATION_KEY)} (${t('New')})`
})
onMounted(() => {
if (props.item != null) {
editingObj.value = props.item
} else {
if (!setupState(props.item, props.itemId)) {
// functions to populate defaults
}
})
/**
* saves the edited object in the database
*/
async function saveObject() {
let api = new ApiApi()
if (isUpdate.value) {
api.apiMealTypeUpdate({id: editingObj.value.id, mealType: editingObj.value}).then(r => {
editingObj.value = r
emit('save', r)
useMessageStore().addPreparedMessage(PreparedMessage.UPDATE_SUCCESS)
}).catch(err => {
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
})
} else {
api.apiMealTypeCreate({mealType: editingObj.value}).then(r => {
editingObj.value = r
emit('create', r)
useMessageStore().addPreparedMessage(PreparedMessage.UPDATE_SUCCESS)
}).catch(err => {
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
})
}
}
/**
* deletes the editing object from the database
*/
async function deleteObject() {
let api = new ApiApi()
api.apiMealTypeDestroy({id: editingObj.value.id}).then(r => {
editingObj.value = {} as MealType
emit('delete', editingObj.value)
}).catch(err => {
useMessageStore().addError(ErrorMessageType.DELETE_ERROR, err)
})
}
</script>
<style scoped>

View File

@@ -0,0 +1,41 @@
<template>
<v-card :loading="loading">
<v-card-title>
{{ modelName }}
<v-btn class="float-right" icon="$close" variant="plain" @click="emit('close')" v-if="dialog"></v-btn>
<v-card-subtitle class="pa-0">{{ objectName }}</v-card-subtitle>
</v-card-title>
<v-divider></v-divider>
<slot name="default">
</slot>
<v-divider></v-divider>
<v-card-actions>
<v-btn color="delete" prepend-icon="$delete" v-if="isUpdate">{{ $t('Delete') }}
<delete-confirm-dialog :object-name="objectName" :model-name="modelName" @delete="emit('delete')"></delete-confirm-dialog>
</v-btn>
<v-btn color="save" prepend-icon="$save" @click="emit('save')">{{ isUpdate ? $t('Save') : $t('Create') }}</v-btn>
</v-card-actions>
</v-card>
</template>
<script setup lang="ts">
import DeleteConfirmDialog from "@/components/dialogs/DeleteConfirmDialog.vue";
const emit = defineEmits(['save', 'delete', 'close'])
const props = defineProps({
loading: {type: Boolean, default: false},
dialog: {type: Boolean, default: false},
objectName: {type: String, default: ''},
modelName: {type: String, default: ''},
isUpdate: {type: Boolean, default: false}
})
</script>
<style scoped>
</style>

View File

@@ -1,10 +1,13 @@
<template>
<v-card>
<v-card-title>
{{ $t(OBJ_LOCALIZATION_KEY) }}
<v-btn class="float-right" icon="$close" variant="plain" @click="emit('close')" v-if="dialog"></v-btn>
</v-card-title>
<model-editor-base
:loading="loading"
:dialog="dialog"
@save="saveObject"
@delete="deleteObject"
@close="emit('close')"
:is-update="isUpdate()"
:model-name="$t(modelClass.model.localizationKey)"
:object-name="editingObjName()">
<v-card-text>
<v-form>
<v-number-input :step="10" v-model="editingObj.propertyAmount" control-variant="stacked">
@@ -15,116 +18,38 @@
<model-select :label="$t('Property')" v-model="editingObj.propertyType" model="PropertyType"></model-select>
</v-form>
</v-card-text>
<v-card-actions>
<v-btn color="delete" prepend-icon="$delete" v-if="isUpdate">{{ $t('Delete') }}
<delete-confirm-dialog :object-name="objectName" @delete="deleteObject"></delete-confirm-dialog>
</v-btn>
<v-btn color="save" prepend-icon="$save" @click="saveObject">{{ isUpdate ? $t('Save') : $t('Create') }}</v-btn>
</v-card-actions>
</v-card>
</model-editor-base>
</template>
<script setup lang="ts">
import {computed, onMounted, ref} from "vue";
import {ApiApi, Property} from "@/openapi";
import DeleteConfirmDialog from "@/components/dialogs/DeleteConfirmDialog.vue";
import {useI18n} from "vue-i18n";
import {ErrorMessageType, PreparedMessage, useMessageStore} from "@/stores/MessageStore";
import {onMounted, PropType} from "vue";
import {Property} from "@/openapi";
import ModelSelect from "@/components/inputs/ModelSelect.vue";
import {VNumberInput} from 'vuetify/labs/VNumberInput' //TODO remove once component is out of labs
const {t} = useI18n()
import ModelEditorBase from "@/components/model_editors/ModelEditorBase.vue";
import {useModelEditorFunctions} from "@/composables/useModelEditorFunctions";
const emit = defineEmits(['create', 'save', 'delete', 'close'])
const props = defineProps({
item: {type: {} as Property, required: false},
itemId: {type: String, required: false},
item: {type: {} as PropType<Property>, required: false, default: null},
itemId: {type: Number, required: false, default: undefined},
dialog: {type: Boolean, default: false}
})
const OBJ_LOCALIZATION_KEY = 'Food'
const editingObj = ref({} as Property)
const loading = ref(false)
const emit = defineEmits(['create', 'save', 'delete', 'close'])
const {setupState, deleteObject, saveObject, isUpdate, editingObjName, loading, editingObj, modelClass} = useModelEditorFunctions<Property>('Property', emit)
// object specific data (for selects/display)
/**
* checks if given object has ID property to determine if it needs to be updated or created
*/
const isUpdate = computed(() => {
return Object.keys(editingObj.value).length > 0
})
/**
* display name for object in headers/delete dialog/...
*/
const objectName = computed(() => {
return isUpdate ? `${t(OBJ_LOCALIZATION_KEY)} ${editingObj.value.token}` : `${t(OBJ_LOCALIZATION_KEY)} (${t('New')})`
})
onMounted(() => {
if (props.item != null) {
editingObj.value = props.item
} else if (props.itemId != null) {
const api = new ApiApi()
api.apiPropertyRetrieve({id: props.itemId}).then(r => {
editingObj.value = r
}).catch(err => {
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
})
} else {
// functions to populate defaults for new item
if (!setupState(props.item, props.itemId)) {
// functions to populate defaults
}
})
/**
* saves the edited object in the database
*/
async function saveObject() {
let api = new ApiApi()
if (isUpdate.value) {
api.apiPropertyUpdate({id: editingObj.value.id, property: editingObj.value}).then(r => {
editingObj.value = r
emit('save', r)
useMessageStore().addPreparedMessage(PreparedMessage.UPDATE_SUCCESS)
}).catch(err => {
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
})
} else {
api.apiPropertyCreate({property: editingObj.value}).then(r => {
editingObj.value = r
emit('create', r)
useMessageStore().addPreparedMessage(PreparedMessage.CREATE_SUCCESS)
}).catch(err => {
useMessageStore().addError(ErrorMessageType.CREATE_ERROR, err)
})
}
}
/**
* deletes the editing object from the database
*/
async function deleteObject() {
if (editingObj.value.id !== undefined) {
let api = new ApiApi()
api.apiPropertyDestroy({id: editingObj.value.id}).then(r => {
editingObj.value = {} as Property
emit('delete', editingObj.value)
}).catch(err => {
useMessageStore().addError(ErrorMessageType.DELETE_ERROR, err)
})
} else {
editingObj.value = {} as Property
emit('delete', editingObj.value)
}
}
// ------------------------------------------------------
// object specific functions
// ------------------------------------------------------
</script>

View File

@@ -1,15 +1,18 @@
<template>
<v-card>
<v-card-title>
{{ $t(OBJ_LOCALIZATION_KEY) }}
<v-btn class="float-right" icon="$close" variant="plain" @click="emit('close')" v-if="dialog"></v-btn>
</v-card-title>
<model-editor-base
:loading="loading"
:dialog="dialog"
@save="saveObject"
@delete="deleteObject"
@close="emit('close')"
:is-update="isUpdate()"
:model-name="$t(modelClass.model.localizationKey)"
:object-name="editingObjName()">
<v-card-text>
<v-form>
<v-row>
<v-col>
<model-select model="Food" v-model="editingObj.food" :label="$t('Food')" :disabled="disabledFields.includes('food')"></model-select>
<model-select model="Food" v-model="editingObj.food" :label="$t('Food')"></model-select>
</v-col>
</v-row>
<v-row>
@@ -37,119 +40,36 @@
</v-row>
</v-form>
</v-card-text>
<v-card-actions>
<v-btn color="delete" prepend-icon="$delete" v-if="isUpdate">{{ $t('Delete') }}
<delete-confirm-dialog :object-name="objectName" @delete="deleteObject"></delete-confirm-dialog>
</v-btn>
<v-btn color="save" prepend-icon="$save" @click="saveObject">{{ isUpdate ? $t('Save') : $t('Create') }}</v-btn>
</v-card-actions>
</v-card>
</model-editor-base>
</template>
<script setup lang="ts">
import {computed, onMounted, ref} from "vue";
import {ApiApi, Property, UnitConversion} from "@/openapi";
import DeleteConfirmDialog from "@/components/dialogs/DeleteConfirmDialog.vue";
import {useI18n} from "vue-i18n";
import {ErrorMessageType, PreparedMessage, useMessageStore} from "@/stores/MessageStore";
import {onMounted, PropType} from "vue";
import {UnitConversion} from "@/openapi";
import ModelSelect from "@/components/inputs/ModelSelect.vue";
import {VNumberInput} from 'vuetify/labs/VNumberInput' //TODO remove once component is out of labs
const {t} = useI18n()
const emit = defineEmits(['create', 'save', 'delete', 'close'])
import {useModelEditorFunctions} from "@/composables/useModelEditorFunctions";
import ModelEditorBase from "@/components/model_editors/ModelEditorBase.vue";
const props = defineProps({
item: {type: {} as UnitConversion, required: false},
itemId: {type: String, required: false},
dialog: {type: Boolean, default: false},
disabledFields: {default: []},
item: {type: {} as PropType<UnitConversion>, required: false, default: null},
itemId: {type: Number, required: false, default: undefined},
dialog: {type: Boolean, default: false}
})
const OBJ_LOCALIZATION_KEY = 'Conversion'
const editingObj = ref({} as UnitConversion)
const loading = ref(false)
const emit = defineEmits(['create', 'save', 'delete', 'close'])
const {setupState, deleteObject, saveObject, isUpdate, editingObjName, loading, editingObj, modelClass} = useModelEditorFunctions<UnitConversion>('UnitConversion', emit)
// object specific data (for selects/display)
/**
* checks if given object has ID property to determine if it needs to be updated or created
*/
const isUpdate = computed(() => {
return Object.keys(editingObj.value).length > 0
})
/**
* display name for object in headers/delete dialog/...
*/
const objectName = computed(() => {
return isUpdate ? `${t(OBJ_LOCALIZATION_KEY)} ${editingObj.value.token}` : `${t(OBJ_LOCALIZATION_KEY)} (${t('New')})`
})
onMounted(() => {
if (props.item != null) {
editingObj.value = props.item
} else if (props.itemId != null) {
const api = new ApiApi()
api.apiUnitConversionRetrieve({id: props.itemId}).then(r => {
editingObj.value = r
}).catch(err => {
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
})
} else {
// functions to populate defaults for new item
if (!setupState(props.item, props.itemId)) {
// functions to populate defaults
}
})
/**
* saves the edited object in the database
*/
async function saveObject() {
let api = new ApiApi()
if (editingObj.value.id) {
api.apiUnitConversionUpdate({id: editingObj.value.id, unitConversion: editingObj.value}).then(r => {
editingObj.value = r
emit('save', r)
useMessageStore().addPreparedMessage(PreparedMessage.UPDATE_SUCCESS)
}).catch(err => {
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
})
} else {
api.apiUnitConversionCreate({unitConversion: editingObj.value}).then(r => {
editingObj.value = r
emit('create', r)
useMessageStore().addPreparedMessage(PreparedMessage.CREATE_SUCCESS)
}).catch(err => {
useMessageStore().addError(ErrorMessageType.CREATE_ERROR, err)
})
}
}
/**
* deletes the editing object from the database
*/
async function deleteObject() {
if (editingObj.value.id !== undefined) {
let api = new ApiApi()
api.apiUnitConversionDestroy({id: editingObj.value.id}).then(r => {
editingObj.value = {} as UnitConversion
emit('delete', editingObj.value)
}).catch(err => {
useMessageStore().addError(ErrorMessageType.DELETE_ERROR, err)
})
} else {
editingObj.value = {} as UnitConversion
emit('delete', editingObj.value)
}
}
// ------------------------------------------------------
// object specific functions
// ------------------------------------------------------
</script>
<style scoped>

View File

@@ -1,66 +1,45 @@
<template>
<v-card>
<v-card-title>
{{ $t(OBJ_LOCALIZATION_KEY) }}
<v-btn class="float-right" icon="$close" variant="plain" @click="emit('close')" v-if="dialog"></v-btn>
</v-card-title>
<model-editor-base
:loading="loading"
:dialog="dialog"
@save="saveObject"
@delete="deleteObject"
@close="emit('close')"
:is-update="isUpdate()"
:model-name="$t(modelClass.model.localizationKey)"
:object-name="editingObjName()">
<v-card-text>
<v-form>
<v-select :label="$t('Role')" :items="groups" item-value="id" item-title="name" return-object multiple v-model="editingObj.groups"></v-select>
</v-form>
</v-card-text>
<v-card-actions>
<v-btn color="delete" prepend-icon="$delete" v-if="isUpdate">{{ $t('Delete') }}
<delete-confirm-dialog :object-name="objectName" @delete="deleteObject"></delete-confirm-dialog>
</v-btn>
<v-btn color="save" prepend-icon="$save" @click="saveObject">{{ isUpdate ? $t('Save') : $t('Create') }}</v-btn>
</v-card-actions>
</v-card>
</model-editor-base>
</template>
<script setup lang="ts">
import {computed, onMounted, ref} from "vue";
import {AccessToken, ApiApi, Group, InviteLink, UserSpace} from "@/openapi";
import DeleteConfirmDialog from "@/components/dialogs/DeleteConfirmDialog.vue";
import {useI18n} from "vue-i18n";
import {ErrorMessageType, PreparedMessage, useMessageStore} from "@/stores/MessageStore";
import {DateTime} from "luxon";
import {useClipboard} from "@vueuse/core";
import {tr} from "vuetify/locale";
import {onMounted, PropType, ref} from "vue";
import {ApiApi, Group, UserSpace} from "@/openapi";
const {t} = useI18n()
const {copy} = useClipboard()
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
const emit = defineEmits(['create', 'save', 'delete', 'close'])
import ModelEditorBase from "@/components/model_editors/ModelEditorBase.vue";
import {useModelEditorFunctions} from "@/composables/useModelEditorFunctions";
const props = defineProps({
item: {type: {} as UserSpace, required: true},
item: {type: {} as PropType<UserSpace>, required: false, default: null},
itemId: {type: Number, required: false, default: undefined},
dialog: {type: Boolean, default: false}
})
const OBJ_LOCALIZATION_KEY = 'Invite_Link'
const editingObj = ref({} as UserSpace)
const loading = ref(false)
const emit = defineEmits(['create', 'save', 'delete', 'close'])
const {setupState, deleteObject, saveObject, isUpdate, editingObjName, loading, editingObj, modelClass} = useModelEditorFunctions<UserSpace>('UserSpace', emit)
// object specific data (for selects/display)
const groups = ref([] as Group[])
/**
* checks if given object has ID property to determine if it needs to be updated or created
*/
const isUpdate = computed(() => {
return editingObj.value.id !== undefined
})
/**
* display name for object in headers/delete dialog/...
*/
const objectName = computed(() => {
return isUpdate ? `${t(OBJ_LOCALIZATION_KEY)} ${editingObj.value.token}` : `${t(OBJ_LOCALIZATION_KEY)} (${t('New')})`
})
onMounted(() => {
const api = new ApiApi()
api.apiGroupList().then(r => {
@@ -69,41 +48,11 @@ onMounted(() => {
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
})
if (props.item != null) {
editingObj.value = props.item
} else {
console.error('UserSpaceEditor cannot create items')
if (!setupState(props.item, props.itemId)) {
// functions to populate defaults
}
})
/**
* saves the edited object in the database
*/
async function saveObject() {
let api = new ApiApi()
if (isUpdate.value) {
api.apiUserSpacePartialUpdate({id: editingObj.value.id, patchedUserSpace: editingObj.value}).then(r => {
editingObj.value = r
emit('save', r)
useMessageStore().addPreparedMessage(PreparedMessage.UPDATE_SUCCESS)
}).catch(err => {
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
})
}
}
/**
* deletes the editing object from the database
*/
async function deleteObject() {
let api = new ApiApi()
api.apiUserSpaceDestroy({id: editingObj.value.id}).then(r => {
editingObj.value = {} as UserSpace
emit('delete', editingObj.value)
}).catch(err => {
useMessageStore().addError(ErrorMessageType.DELETE_ERROR, err)
})
}
</script>