mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-01 20:28:46 -05:00
settings and model dialogs
This commit is contained in:
44
vue3/src/components/buttons/BtnCopy.vue
Normal file
44
vue3/src/components/buttons/BtnCopy.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
|
||||
<v-btn ref="copyBtn" :color="color" :size="size" :density="density" @click="clickCopy()">
|
||||
<v-icon icon="$copy"></v-icon>
|
||||
<v-tooltip v-model="showToolip" :target="btn" location="top">
|
||||
<v-icon icon="$copy"></v-icon>
|
||||
Copied!
|
||||
</v-tooltip>
|
||||
</v-btn>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
import {useClipboard} from "@vueuse/core";
|
||||
import {ref, useTemplateRef} from "vue";
|
||||
|
||||
const {copy} = useClipboard()
|
||||
|
||||
const props = defineProps({
|
||||
copyValue: {type: String, default: ''},
|
||||
color: {type: String, default: 'success'},
|
||||
size: {type: String, default: 'default'},
|
||||
density: {type: String, default: 'default'},
|
||||
|
||||
})
|
||||
|
||||
const btn = useTemplateRef('copyBtn')
|
||||
const showToolip = ref(false)
|
||||
|
||||
function clickCopy() {
|
||||
copy(props.copyValue)
|
||||
showToolip.value = true
|
||||
setTimeout(() => {
|
||||
showToolip.value = false
|
||||
}, 3000)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,6 +1,8 @@
|
||||
<template>
|
||||
<v-dialog max-width="600" activator="parent" v-model="dialog">
|
||||
<access-token-editor :item="item" @create="createEvent" @save="saveEvent" @delete="deleteEvent" dialog @close="dialog = false" v-if="model == SupportedModels.AccessToken"></access-token-editor>
|
||||
<invite-link-editor :item="item" @create="createEvent" @save="saveEvent" @delete="deleteEvent" dialog @close="dialog = false" v-if="model == SupportedModels.InviteLink"></invite-link-editor>
|
||||
<user-space-editor :item="item" @create="createEvent" @save="saveEvent" @delete="deleteEvent" dialog @close="dialog = false" v-if="model == SupportedModels.UserSpace"></user-space-editor>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
@@ -10,9 +12,13 @@
|
||||
import {PropType, ref} from "vue";
|
||||
import AccessTokenEditor from "@/components/model_editors/AccessTokenEditor.vue";
|
||||
import {AccessToken, Food} from "@/openapi";
|
||||
import InviteLinkEditor from "@/components/model_editors/InviteLinkEditor.vue";
|
||||
import UserSpaceEditor from "@/components/model_editors/UserSpaceEditor.vue";
|
||||
|
||||
enum SupportedModels {
|
||||
AccessToken = 'AccessToken'
|
||||
AccessToken = 'AccessToken',
|
||||
InviteLink = 'InviteLink',
|
||||
UserSpace = 'UserSpace',
|
||||
}
|
||||
|
||||
const emit = defineEmits(['create', 'save', 'delete'])
|
||||
@@ -21,7 +27,6 @@ const props = defineProps({
|
||||
model: {
|
||||
type: String,
|
||||
required: true,
|
||||
validator: (val) => ['AccessToken'].includes(val)
|
||||
},
|
||||
item: {default: null},
|
||||
closeAfterCreate: {default: true},
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
<v-col cols="10">
|
||||
<v-text-field label="Token" v-model="editingObj.token" disabled></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="2">
|
||||
<v-btn color="info" variant="tonal" icon="$copy" @click="copy(editingObj.token)"></v-btn>
|
||||
<v-col cols="2" >
|
||||
<btn-copy :copy-value="editingObj.token" class="me-1"></btn-copy>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn color="save" prepend-icon="$save" @click="saveObject">{{ isUpdate ? $t('Save') : $t('Create') }}</v-btn>
|
||||
<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>
|
||||
</template>
|
||||
@@ -38,6 +38,7 @@ import {useI18n} from "vue-i18n";
|
||||
import {ErrorMessageType, PreparedMessage, useMessageStore} from "@/stores/MessageStore";
|
||||
import {DateTime} from "luxon";
|
||||
import {useClipboard} from "@vueuse/core";
|
||||
import BtnCopy from "@/components/buttons/BtnCopy.vue";
|
||||
|
||||
const {t} = useI18n()
|
||||
const {copy} = useClipboard()
|
||||
@@ -108,7 +109,7 @@ async function deleteObject() {
|
||||
let api = new ApiApi()
|
||||
api.apiAccessTokenDestroy({id: editingObj.value.id}).then(r => {
|
||||
editingObj.value = {} as AccessToken
|
||||
emit('delete')
|
||||
emit('delete', editingObj.value)
|
||||
}).catch(err => {
|
||||
useMessageStore().addError(ErrorMessageType.DELETE_ERROR, err)
|
||||
})
|
||||
|
||||
131
vue3/src/components/model_editors/InviteLinkEditor.vue
Normal file
131
vue3/src/components/model_editors/InviteLinkEditor.vue
Normal file
@@ -0,0 +1,131 @@
|
||||
<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>
|
||||
<v-card-text>
|
||||
<v-form>
|
||||
|
||||
<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>
|
||||
</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 {DateTime} from "luxon";
|
||||
import {useClipboard} from "@vueuse/core";
|
||||
|
||||
const {t} = useI18n()
|
||||
const {copy} = useClipboard()
|
||||
|
||||
const emit = defineEmits(['create', 'save', 'delete', 'close'])
|
||||
|
||||
const props = defineProps({
|
||||
item: {type: {} as InviteLink, required: false},
|
||||
dialog: {type: Boolean, default: false}
|
||||
})
|
||||
|
||||
const OBJ_LOCALIZATION_KEY = 'Invite_Link'
|
||||
const editingObj = ref({} as InviteLink)
|
||||
const loading = ref(false)
|
||||
|
||||
// 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 {
|
||||
// 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>
|
||||
|
||||
</style>
|
||||
112
vue3/src/components/model_editors/UserSpaceEditor.vue
Normal file
112
vue3/src/components/model_editors/UserSpaceEditor.vue
Normal file
@@ -0,0 +1,112 @@
|
||||
<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>
|
||||
<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>
|
||||
</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";
|
||||
|
||||
const {t} = useI18n()
|
||||
const {copy} = useClipboard()
|
||||
|
||||
const emit = defineEmits(['create', 'save', 'delete', 'close'])
|
||||
|
||||
const props = defineProps({
|
||||
item: {type: {} as UserSpace, required: true},
|
||||
dialog: {type: Boolean, default: false}
|
||||
})
|
||||
|
||||
const OBJ_LOCALIZATION_KEY = 'Invite_Link'
|
||||
const editingObj = ref({} as UserSpace)
|
||||
const loading = ref(false)
|
||||
|
||||
// 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
|
||||
}).catch(err => {
|
||||
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
|
||||
})
|
||||
|
||||
if (props.item != null) {
|
||||
editingObj.value = props.item
|
||||
} else {
|
||||
console.error('UserSpaceEditor cannot create items')
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 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>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,75 +1,40 @@
|
||||
<template>
|
||||
<v-form>
|
||||
<p class="text-h6">{{ $t('SpaceMembers') }}</p>
|
||||
<v-divider class="mb-3"></v-divider>
|
||||
<v-divider></v-divider>
|
||||
<p class="text-subtitle-2">{{$t('SpaceMemberHelp')}}</p>
|
||||
|
||||
<v-data-table :items="spaceUserSpaces" :headers="userTableHeaders" density="compact" :hide-default-footer="spaceUserSpaces.length < 10">
|
||||
<v-data-table :items="spaceUserSpaces" :headers="userTableHeaders" density="compact" :hide-default-footer="spaceUserSpaces.length < 10" class="mt-3">
|
||||
<template #item.groups="{item}">
|
||||
<span v-for="g in item.groups">{{ g.name }} </span>
|
||||
</template>
|
||||
|
||||
<template #item.edit="{item}">
|
||||
<v-btn icon="$edit" color="edit" size="small" variant="tonal" @click="spaceUserEditDialogUserSpace = Object.assign({}, item); spaceUserEditDialogState = true"></v-btn>
|
||||
<v-btn color="edit" size="small" v-if="item.user.id != useUserPreferenceStore().activeSpace.createdBy.id">
|
||||
<v-icon icon="$edit"></v-icon>
|
||||
<model-editor-dialog model="UserSpace" :item="item" @delete="deleteUserSpace(item)" class="mt-2"></model-editor-dialog>
|
||||
</v-btn>
|
||||
<v-chip color="edit" v-else>{{$t('Owner')}}</v-chip>
|
||||
</template>
|
||||
</v-data-table>
|
||||
|
||||
<v-dialog v-model="spaceUserEditDialogState" max-width="400px">
|
||||
<v-card>
|
||||
<v-card-title>{{ $t('User') }}: {{ spaceUserEditDialogUserSpace.user.displayName }}</v-card-title>
|
||||
<v-card-subtitle>{{ $t('Created') }} {{ DateTime.fromJSDate(spaceUserEditDialogUserSpace.createdAt).toLocaleString(DateTime.DATETIME_MED) }}</v-card-subtitle>
|
||||
<v-card-text>
|
||||
<v-form>
|
||||
<v-select :items="groups" item-value="id" item-title="name" v-model="spaceUserEditDialogUserSpace.groups" multiple return-object></v-select>
|
||||
</v-form>
|
||||
<div v-if="spaceUserEditDialogUserSpace.internalNote">
|
||||
<p>{{ $t('Note') }}</p>
|
||||
<span>{{ spaceUserEditDialogUserSpace.internalNote }}</span>
|
||||
</div>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn color="cancel" @click="spaceUserEditDialogState = false">{{ $t('Cancel') }}</v-btn>
|
||||
<v-btn color="save" prepend-icon="$save" @click="updateUserSpace(spaceUserEditDialogUserSpace)">{{ $t('Save') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<p class="text-h6 mt-3">{{ $t('Invites') }}
|
||||
<v-btn size="small" class="float-right" prepend-icon="$create" color="create" @click="inviteLinkDialogObject = {} as InviteLink;inviteLinkDialogState = true">{{ $t('New') }}</v-btn>
|
||||
<v-btn size="small" class="float-right" prepend-icon="$create" color="create">
|
||||
{{ $t('New') }}
|
||||
<model-editor-dialog model="InviteLink" @delete="deleteInviteLink" @create="item => spaceInviteLinks.push(item)" class="mt-2"></model-editor-dialog>
|
||||
</v-btn>
|
||||
</p>
|
||||
<v-divider class="mb-3"></v-divider>
|
||||
|
||||
<v-data-table :items="spaceInviteLinks" :headers="inviteTableHeaders" density="compact" :hide-default-footer="spaceInviteLinks.length < 10">
|
||||
<template #item.edit="{item}">
|
||||
<v-btn icon="$copy" color="success" size="small" variant="tonal" @click="copyInviteLink(item)"></v-btn>
|
||||
<v-btn icon="$edit" color="edit" size="small" variant="tonal" @click="inviteLinkDialogObject = Object.assign({}, item); inviteLinkDialogState = true"></v-btn>
|
||||
<btn-copy size="small" :copy-value="inviteLinkUrl(item)" class="me-1"></btn-copy>
|
||||
<v-btn color="edit" size="small">
|
||||
<v-icon icon="$edit"></v-icon>
|
||||
<model-editor-dialog model="InviteLink" :item="item" @delete="deleteInviteLink(item)" class="mt-2"></model-editor-dialog>
|
||||
</v-btn>
|
||||
</template>
|
||||
|
||||
</v-data-table>
|
||||
|
||||
<v-dialog v-model="inviteLinkDialogState" max-width="400px">
|
||||
<v-card>
|
||||
<v-card-title>{{ $t('Invites') }}</v-card-title>
|
||||
<v-card-text>
|
||||
<v-form>
|
||||
<v-text-field :label="$t('Email')" v-model="inviteLinkDialogObject.email"></v-text-field>
|
||||
<v-select :label="$t('Role')" :items="groups" item-value="id" item-title="name" return-object v-model="inviteLinkDialogObject.group"></v-select>
|
||||
<v-date-input :label="$t('Valid Until')" v-model="inviteLinkDialogObject.validUntil"></v-date-input>
|
||||
<v-textarea :label="$t('Note')" v-model="inviteLinkDialogObject.internalNote"></v-textarea>
|
||||
<v-checkbox :label="$t('Reusable')" v-model="inviteLinkDialogObject.reusable"></v-checkbox>
|
||||
</v-form>
|
||||
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn color="cancel" @click="inviteLinkDialogState = false">{{ $t('Cancel') }}</v-btn>
|
||||
<v-btn color="save" prepend-icon="$save" @click="saveInviteLink(inviteLinkDialogObject)" :loading="inviteLinkDialogLoading">
|
||||
<span v-if="inviteLinkDialogObject.id == undefined">{{ $t('Create') }}</span>
|
||||
<span v-if="inviteLinkDialogObject.id != undefined">{{ $t('Update') }}</span>
|
||||
</v-btn>
|
||||
<v-btn color="delete" prepend-icon="$delete" @click="deleteInviteLink(inviteLinkDialogObject)" v-if="inviteLinkDialogObject.id != undefined">{{ $t('Delete') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
</v-form>
|
||||
</template>
|
||||
|
||||
@@ -82,21 +47,15 @@ import {ApiApi, Group, InviteLink, UserSpace} from "@/openapi";
|
||||
import {ErrorMessageType, PreparedMessage, useMessageStore} from "@/stores/MessageStore";
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {DateTime} from "luxon";
|
||||
import {VDateInput} from 'vuetify/labs/VDateInput' //TODO remove once component is out of labs
|
||||
import {useClipboard} from "@vueuse/core"; //TODO remove once component is out of labs
|
||||
import {useClipboard} from "@vueuse/core";
|
||||
import ModelEditorDialog from "@/components/dialogs/ModelEditorDialog.vue";
|
||||
import BtnCopy from "@/components/buttons/BtnCopy.vue";
|
||||
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
|
||||
|
||||
const {t} = useI18n()
|
||||
|
||||
const spaceUserSpaces = ref([] as UserSpace[])
|
||||
const spaceInviteLinks = ref([] as InviteLink[])
|
||||
const groups = ref([] as Group[])
|
||||
|
||||
const spaceUserEditDialogState = ref(false)
|
||||
const spaceUserEditDialogUserSpace = ref({} as UserSpace)
|
||||
|
||||
const inviteLinkDialogState = ref(false)
|
||||
const inviteLinkDialogObject = ref({} as InviteLink)
|
||||
const inviteLinkDialogLoading = ref(false)
|
||||
|
||||
const userTableHeaders = [
|
||||
{title: t('Username'), key: 'user.username'},
|
||||
@@ -114,12 +73,6 @@ const inviteTableHeaders = [
|
||||
onMounted(() => {
|
||||
const api = new ApiApi()
|
||||
|
||||
api.apiGroupList().then(r => {
|
||||
groups.value = r
|
||||
}).catch(err => {
|
||||
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
|
||||
})
|
||||
|
||||
api.apiUserSpaceList().then(r => {
|
||||
spaceUserSpaces.value = r.results
|
||||
}).catch(err => {
|
||||
@@ -134,75 +87,27 @@ onMounted(() => {
|
||||
})
|
||||
|
||||
/**
|
||||
* update user space in DB and list on client
|
||||
* @param userSpace UserSpace object to update
|
||||
* delete userspace from client list (database handled by editor)
|
||||
* @param userSpace UserSpace object that was deleted
|
||||
*/
|
||||
function updateUserSpace(userSpace: UserSpace) {
|
||||
const api = new ApiApi()
|
||||
|
||||
api.apiUserSpacePartialUpdate({id: userSpace.id!, patchedUserSpace: userSpace}).then(r => {
|
||||
spaceUserSpaces.value.splice(spaceUserSpaces.value.indexOf(userSpace), 1, r)
|
||||
useMessageStore().addPreparedMessage(PreparedMessage.UPDATE_SUCCESS)
|
||||
}).catch(err => {
|
||||
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
|
||||
})
|
||||
function deleteUserSpace(userSpace: UserSpace) {
|
||||
spaceUserSpaces.value.splice(spaceUserSpaces.value.indexOf(userSpace) - 1, 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* create or update the invite link, refresh invite link list on client
|
||||
* @param inviteLink InviteLink object to update
|
||||
*/
|
||||
function saveInviteLink(inviteLink: InviteLink) {
|
||||
const api = new ApiApi()
|
||||
|
||||
inviteLinkDialogLoading.value = true
|
||||
|
||||
if (inviteLink.id == undefined) {
|
||||
api.apiInviteLinkCreate({inviteLink: inviteLink}).then(r => {
|
||||
inviteLinkDialogState.value = false
|
||||
spaceInviteLinks.value.push(r)
|
||||
useMessageStore().addPreparedMessage(PreparedMessage.CREATE_SUCCESS)
|
||||
}).catch(err => {
|
||||
useMessageStore().addError(ErrorMessageType.CREATE_ERROR, err)
|
||||
}).finally(() => {
|
||||
inviteLinkDialogLoading.value = false
|
||||
})
|
||||
} else {
|
||||
api.apiInviteLinkUpdate({inviteLink: inviteLink, id: inviteLink.id}).then(r => {
|
||||
inviteLinkDialogState.value = false
|
||||
spaceInviteLinks.value.splice(spaceInviteLinks.value.indexOf(inviteLink), 1, r)
|
||||
useMessageStore().addPreparedMessage(PreparedMessage.UPDATE_SUCCESS)
|
||||
}).catch(err => {
|
||||
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
|
||||
}).finally(() => {
|
||||
inviteLinkDialogLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* delete invite link from database and client
|
||||
* @param inviteLink InviteLink object to delete
|
||||
* delete invite link from client list (database handled by editor)
|
||||
* @param inviteLink InviteLink object that was deleted
|
||||
*/
|
||||
function deleteInviteLink(inviteLink: InviteLink) {
|
||||
const api = new ApiApi()
|
||||
api.apiInviteLinkDestroy({id: inviteLink.id}).then(r => {
|
||||
inviteLinkDialogState.value = false
|
||||
spaceInviteLinks.value.splice(spaceInviteLinks.value.indexOf(inviteLink) - 1, 1)
|
||||
useMessageStore().addPreparedMessage(PreparedMessage.DELETE_SUCCESS)
|
||||
}).catch(err => {
|
||||
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
|
||||
})
|
||||
spaceInviteLinks.value.splice(spaceInviteLinks.value.indexOf(inviteLink) - 1, 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* copy invite link with url to clipboard
|
||||
* @param inviteLink InviteLink object to copy
|
||||
* returns url for invite link
|
||||
* @param inviteLink InviteLink object to create url for
|
||||
*/
|
||||
function copyInviteLink(inviteLink: InviteLink) {
|
||||
const {copy} = useClipboard()
|
||||
copy(`${location.protocol}//${location.host}/invite/${inviteLink.uuid}`)
|
||||
function inviteLinkUrl(inviteLink: InviteLink) {
|
||||
return `${location.protocol}//${location.host}/invite/${inviteLink.uuid}`
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user