197 lines
4.6 KiB
Vue
197 lines
4.6 KiB
Vue
<template>
|
|
<v-skeleton-loader
|
|
v-if="isNil(user)"
|
|
type="card"
|
|
/>
|
|
<HeaderActionsFormCard
|
|
v-else
|
|
ref="headerActionsFormCard"
|
|
title="User Details"
|
|
elevation="10"
|
|
@submit.prevent="saveWrapper"
|
|
>
|
|
<template #header-actions> </template>
|
|
<v-row>
|
|
<v-col
|
|
cols="12"
|
|
md="6"
|
|
>
|
|
<v-label class="mb-2">First name *</v-label>
|
|
<v-text-field
|
|
v-model="user.firstName"
|
|
hide-details="auto"
|
|
:rules="[required]"
|
|
required
|
|
/>
|
|
</v-col>
|
|
<v-col
|
|
cols="12"
|
|
md="6"
|
|
>
|
|
<v-label class="mb-2">Last name *</v-label>
|
|
<v-text-field
|
|
v-model="user.lastName"
|
|
hide-details="auto"
|
|
:rules="[required]"
|
|
required
|
|
/>
|
|
</v-col>
|
|
<v-col
|
|
cols="12"
|
|
md="6"
|
|
>
|
|
<v-label class="mb-2">Display name *</v-label>
|
|
<v-text-field
|
|
v-model="user.displayName"
|
|
hide-details="auto"
|
|
:rules="[required]"
|
|
required
|
|
/>
|
|
</v-col>
|
|
<v-col
|
|
cols="12"
|
|
md="6"
|
|
>
|
|
<v-label class="mb-2">Email</v-label>
|
|
<v-text-field
|
|
v-model="user.email"
|
|
type="email"
|
|
hide-details="auto"
|
|
:rules="[required, email]"
|
|
/>
|
|
</v-col>
|
|
<v-col
|
|
cols="12"
|
|
md="6"
|
|
>
|
|
<v-label class="mb-2">Roles</v-label>
|
|
<UserRoleSelect
|
|
v-model="user.roles"
|
|
hide-details="auto"
|
|
:rules="[required]"
|
|
/>
|
|
</v-col>
|
|
</v-row>
|
|
|
|
<template #actions>
|
|
<div class="d-flex mt-8">
|
|
<v-btn
|
|
:loading="isLoading"
|
|
color="primary"
|
|
type="submit"
|
|
>
|
|
Save User
|
|
</v-btn>
|
|
<v-spacer />
|
|
<v-btn
|
|
color="warning"
|
|
class="ml-4"
|
|
variant="outlined"
|
|
:loading="isLoading"
|
|
:to="{ name: 'administration/UsersPage' }"
|
|
>
|
|
Cancel
|
|
</v-btn>
|
|
<v-btn
|
|
v-if="canDelete"
|
|
color="error"
|
|
class="ml-4"
|
|
variant="outlined"
|
|
:loading="isDeleting"
|
|
@click="showDeleteDialog = true"
|
|
>
|
|
Delete
|
|
</v-btn>
|
|
</div>
|
|
</template>
|
|
</HeaderActionsFormCard>
|
|
|
|
<ConfirmDialog
|
|
v-model="showDeleteDialog"
|
|
title="Delete user?"
|
|
:message="`Permanently delete ${user?.displayName || user?.email}? This removes the user from all organizations and roles and cannot be undone.`"
|
|
confirm-text="Delete"
|
|
confirm-color="error"
|
|
@confirm="handleDelete"
|
|
/>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, ref, toRefs } from "vue"
|
|
import { RouteLocationRaw, useRouter } from "vue-router"
|
|
import { isNil } from "lodash"
|
|
|
|
import { email, required } from "@/utils/validators"
|
|
|
|
import usersApi from "@/api/users-api"
|
|
import useCurrentUser from "@/use/use-current-user"
|
|
import useSnack from "@/use/use-snack"
|
|
import useUser from "@/use/use-user"
|
|
|
|
import ConfirmDialog from "@/components/common/ConfirmDialog.vue"
|
|
import HeaderActionsFormCard from "@/components/common/HeaderActionsFormCard.vue"
|
|
import UserRoleSelect from "@/components/users/UserRoleSelect.vue"
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
userId: number
|
|
returnTo?: RouteLocationRaw
|
|
}>(),
|
|
{
|
|
returnTo: undefined,
|
|
}
|
|
)
|
|
|
|
const emit = defineEmits<{
|
|
saved: [userId: number]
|
|
}>()
|
|
|
|
const { userId } = toRefs(props)
|
|
const { user, policy, isLoading, save } = useUser(userId)
|
|
|
|
const { currentUser } = useCurrentUser()
|
|
const router = useRouter()
|
|
const headerActionsFormCard = ref<InstanceType<typeof HeaderActionsFormCard> | null>(null)
|
|
const snack = useSnack()
|
|
|
|
const showDeleteDialog = ref(false)
|
|
const isDeleting = ref(false)
|
|
|
|
const canDelete = computed(() => {
|
|
if (!policy.value?.destroy) return false
|
|
if (currentUser.value?.id === userId.value) return false
|
|
return true
|
|
})
|
|
|
|
async function handleDelete() {
|
|
if (isNil(user.value)) return
|
|
|
|
isDeleting.value = true
|
|
try {
|
|
await usersApi.delete(user.value.id)
|
|
snack.success("User deleted.")
|
|
await router.push({ name: "administration/UsersPage" })
|
|
} catch (error) {
|
|
snack.error(`Failed to delete user: ${error}`)
|
|
} finally {
|
|
isDeleting.value = false
|
|
}
|
|
}
|
|
|
|
async function saveWrapper() {
|
|
if (isNil(user.value)) return
|
|
if (headerActionsFormCard.value === null) return
|
|
|
|
const { valid } = await headerActionsFormCard.value.validate()
|
|
if (!valid) return
|
|
|
|
try {
|
|
await save()
|
|
snack.success("User saved!")
|
|
emit("saved", user.value.id)
|
|
} catch (error) {
|
|
snack.error(`Failed to save user: ${error}`)
|
|
}
|
|
}
|
|
</script>
|