Skip to content

Commit 9cb46a6

Browse files
committed
feat: permissions crud
1 parent 900886d commit 9cb46a6

17 files changed

+289
-458
lines changed

app/components/permissions/AddEditPermissionDialog.vue

+106-100
Original file line numberDiff line numberDiff line change
@@ -1,187 +1,193 @@
11
<script setup lang="ts">
22
import type { VForm } from 'vuetify/components/VForm'
3-
import type { Permission } from '~/stores/admin/permission'
4-
import { useRoleStore } from '~/stores/admin/role'
3+
import { useRoleStore } from '@base/stores/admin/role'
54
6-
interface Props {
7-
isDialogVisible: boolean
8-
permissionData?: Partial<Permission>
9-
}
10-
interface Emit {
11-
(e: 'update:isDialogVisible', value: boolean): void
12-
(e: 'update:permissionData', value: Partial<Permission>): void
13-
}
14-
15-
const props = defineProps<Props>()
16-
const emit = defineEmits<Emit>()
5+
import type { sysPermissionTable } from '@base/server/db/schemas/sys_permissions.schema'
6+
import type { InferSelectModel } from 'drizzle-orm'
7+
import { usePermissionStore } from '@base/stores/admin/permission'
8+
import { cloneDeep } from 'lodash-es'
9+
import { PermissionAction, PermissionScope } from '@base/server/db/schemas'
10+
import { requiredValidator } from '#imports'
1711
18-
const roleStore = useRoleStore()
19-
const { roleList } = storeToRefs(roleStore)
20-
const { fetchRoles } = roleStore
12+
type Permission = InferSelectModel<typeof sysPermissionTable>
2113
22-
const isFormValid = ref(false)
23-
const refForm = ref<VForm>()
14+
const props = defineProps<{
15+
permission?: Permission | null
16+
}>()
2417
25-
const isPermissionDataEmpty = computed(() => {
26-
const data = props.permissionData
27-
return !data || Object.values(data).every(value => value === '')
28-
})
18+
const emit = defineEmits<{
19+
(e: 'edit', payload: Permission): void
20+
(e: 'create', payload: Permission): void
21+
(e: 'cancel'): void
22+
}>()
2923
30-
const localPermissionData = ref<Partial<Permission>>({
31-
id: '',
32-
role_id: '',
33-
action: '',
34-
subject: '',
24+
const modelValue = defineModel<boolean>({
25+
default: false,
3526
})
3627
37-
function onReset() {
38-
emit('update:isDialogVisible', false)
39-
40-
refForm.value?.reset()
28+
const formTemplate = useTemplateRef('formRef')
4129
42-
localPermissionData.value = {
30+
function getDefaultFormData(): Permission {
31+
return {
4332
id: '',
44-
role_id: '',
45-
action: '',
33+
action: PermissionAction.READ,
4634
subject: '',
35+
scope: PermissionScope.ALL,
36+
scope_value: '',
4737
}
4838
}
4939
50-
function onSubmit() {
51-
refForm.value?.validate().then(({ valid }) => {
52-
if (valid) {
53-
emit('update:permissionData', props.permissionData
54-
? localPermissionData.value
55-
: {
56-
role_id: localPermissionData.value.role_id,
57-
action: localPermissionData.value.action,
58-
subject: localPermissionData.value.subject,
59-
})
60-
61-
onReset()
62-
}
63-
})
64-
}
40+
const formData = ref(getDefaultFormData())
6541
66-
watch(() => props.permissionData, (newPermissionData) => {
67-
if (newPermissionData) {
68-
localPermissionData.value = { ...newPermissionData }
42+
watch(modelValue, (value) => {
43+
if (!value) {
44+
formData.value = getDefaultFormData()
6945
}
70-
}, { immediate: true })
46+
})
47+
48+
syncRef(computed(() => props.permission), formData, {
49+
direction: 'ltr',
50+
transform: {
51+
ltr(left) {
52+
if (left)
53+
return cloneDeep(left)
7154
72-
onMounted(async () => {
73-
await fetchRoles()
55+
return getDefaultFormData()
56+
},
57+
},
7458
})
59+
60+
async function handleSubmit() {
61+
try {
62+
if (formTemplate.value) {
63+
const { valid } = await formTemplate.value.validate()
64+
65+
if (valid) {
66+
if (formData.value.id) {
67+
emit('edit', formData.value)
68+
}
69+
else {
70+
emit('create', formData.value)
71+
}
72+
}
73+
}
74+
}
75+
catch {}
76+
}
7577
</script>
7678

7779
<template>
7880
<VDialog
81+
v-model="modelValue"
7982
:width="$vuetify.display.smAndDown ? 'auto' : 600"
80-
:model-value="props.isDialogVisible"
81-
@update:model-value="onReset"
8283
>
8384
<VCard class="pa-sm-8 pa-5">
8485
<!-- 👉 dialog close btn -->
8586
<DialogCloseBtn
8687
variant="text"
8788
size="default"
88-
@click="onReset"
89+
@click="modelValue = false"
8990
/>
9091

9192
<VCardText class="mt-5">
92-
<!-- 👉 Title -->
9393
<div class="text-center mb-6">
9494
<h4 class="text-h4 mb-2">
95-
{{ isPermissionDataEmpty ? 'Add' : 'Edit' }} Permission
95+
{{ permission ? $t('Edit Permission') : $t('Create Permission') }}
9696
</h4>
97-
98-
<p class="text-body-1">
99-
{{ isPermissionDataEmpty ? 'Add' : 'Edit' }} permission as per your requirements.
100-
</p>
10197
</div>
10298

103-
<!-- 👉 Form -->
10499
<VForm
105-
ref="refForm"
106-
v-model="isFormValid"
107-
@submit.prevent="onSubmit"
100+
ref="formRef"
101+
@submit.prevent="handleSubmit"
108102
>
109103
<VAlert
110104
type="warning"
111-
title="Warning!"
105+
:title="$t('Be careful!')"
112106
variant="tonal"
113107
class="mb-6"
114108
>
115-
By {{ isPermissionDataEmpty ? 'editing' : 'adding' }} the permission name, you might break the system permissions functionality. Please ensure you're absolutely certain before proceeding.
109+
{{
110+
$t('By modifying permission, you might break the system permissions functionality. Please ensure you\'re absolutely certain before proceeding.')
111+
}}
116112
</VAlert>
117113

118114
<!-- 👉 Role action -->
119115
<div class="mb-4">
120116
<div class="d-flex flex-column gap-4 mb-4">
121117
<VSelect
122-
v-model="localPermissionData.action"
118+
v-model="formData.action"
123119
density="compact"
120+
:label="$t('Select Permission')"
121+
:placeholder="$t('Select Permission')"
124122
:rules="[requiredValidator]"
125-
label="Select Action"
126-
placeholder="Select Action"
127123
:items="[
128124
{
129-
title: 'Create',
130-
value: 'create',
125+
title: $t('Create'),
126+
value: PermissionAction.CREATE,
131127
},
132128
{
133-
title: 'Read',
134-
value: 'read',
129+
title: $t('Read'),
130+
value: PermissionAction.READ,
135131
},
136132
{
137-
title: 'Update',
138-
value: 'update',
133+
title: $t('Update'),
134+
value: PermissionAction.UPDATE,
139135
},
140136
{
141-
title: 'Delete',
142-
value: 'delete',
137+
title: $t('Delete'),
138+
value: PermissionAction.DELETE,
143139
},
144140
{
145-
title: 'Manage',
146-
value: 'manage',
141+
title: $t('Manage'),
142+
value: PermissionAction.MANAGE,
147143
},
148144
]"
149145
/>
150146

151-
<VSelect
152-
v-model="localPermissionData.role_id"
153-
density="compact"
154-
label="Select Role"
147+
<VTextField
148+
v-model="formData.subject"
149+
placeholder="Post, Category, User, etc."
150+
:label="$t('Fill Module Name')"
155151
:rules="[requiredValidator]"
156-
:items="roleList"
157-
item-title="name"
158-
item-value="id"
159152
/>
160153

161154
<VSelect
162-
v-model="localPermissionData.subject"
155+
v-model="formData.scope"
163156
density="compact"
157+
:label="$t('Select Scope')"
158+
:placeholder="$t('Select Scope')"
164159
:rules="[requiredValidator]"
165-
label="Select Subject"
166160
:items="[
167161
{
168-
title: 'Category',
169-
value: 'category',
162+
title: $t('All'),
163+
value: PermissionScope.ALL,
170164
},
171165
{
172-
title: 'Project',
173-
value: 'project',
166+
title: $t('Organization'),
167+
value: PermissionScope.ORGANIZATION,
174168
},
175169
{
176-
title: 'All',
177-
value: 'all',
170+
title: $t('Creator'),
171+
value: PermissionScope.SELF,
172+
},
173+
{
174+
title: $t('Custom'),
175+
value: PermissionScope.CUSTOM,
178176
},
179177
]"
180178
/>
179+
180+
<VTextField
181+
v-if="formData.scope === PermissionScope.CUSTOM"
182+
v-model="formData.scope_value"
183+
placeholder="Post, Category, User, etc."
184+
:label="$t('Fill Scope Value')"
185+
:rules="[requiredValidator]"
186+
/>
181187
</div>
182188

183-
<VBtn @click="onSubmit">
184-
{{ isPermissionDataEmpty ? 'Add' : 'Edit' }}
189+
<VBtn type="submit">
190+
{{ permission ? $t('Update') : $t('Submit') }}
185191
</VBtn>
186192
</div>
187193
</VForm>

app/pages/admin.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script setup lang="ts">
22
definePageMeta({
3-
action: 'manage',
4-
subject: 'user',
3+
// action: 'manage',
4+
// subject: 'user',
55
sidebar: {
66
title: 'Users & Permissions',
77
icon: { icon: 'ri-admin-line' },

0 commit comments

Comments
 (0)