basic tempate of web
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user