Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: admin crud #44

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/@layouts/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { OffsetOptions } from '@floating-ui/dom'
import type { RouteLocationRaw } from 'vue-router'
import type { AppContentLayoutNav, ContentWidth, FooterType, HorizontalNavType, NavbarType } from '@base/@layouts/enums'
import type { Component } from 'vue'
import type { Actions } from '~/stores/casl'
import type { Actions } from '@base/stores/casl'

export interface LayoutConfig {
app: {
Expand Down
21 changes: 20 additions & 1 deletion app/assets/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,24 @@
"Users": "Users",
"Are you sure you want to delete this shortcut?": "Are you sure you want to delete this shortcut?",
"Account settings updated successfully": "Account settings updated successfully",
"Stripe customer self-service portal is not currently available!": "Stripe customer self-service portal is not currently available!"
"Stripe customer self-service portal is not currently available!": "Stripe customer self-service portal is not currently available!",
"Edit Permission": "Edit Permission",
"Create Permission": "Create Permission",
"Be careful!": "Be careful!",
"By modifying permission, you might break the system permissions functionality. Please ensure you\\'re absolutely certain before proceeding.": "By modifying permission, you might break the system permissions functionality. Please ensure you\\'re absolutely certain before proceeding.",
"Select Permission": "Select Permission",
"Create": "Create",
"Read": "Read",
"Update": "Update",
"Delete": "Delete",
"Manage": "Manage",
"Fill Module Name": "Fill Module Name",
"Select Scope": "Select Scope",
"All": "All",
"Creator": "Creator",
"Custom": "Custom",
"Fill Scope Value": "Fill Scope Value",
"Submit": "Submit",
"Total {number} permissions": "Total {number} permissions",
"Edit Role": "Edit Role"
}
21 changes: 20 additions & 1 deletion app/assets/locale/vi.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,24 @@
"Users": "Người dùng",
"Are you sure you want to delete this shortcut?": "Bạn có chắc chắn muốn xóa phím tắt này không?",
"Account settings updated successfully": "Thông tin tài khoản đã được cập nhật thành công",
"Stripe customer self-service portal is not currently available!": "Cổng tự phục vụ của thanh toán điện tử Stripe hiện không khả dụng!"
"Stripe customer self-service portal is not currently available!": "Cổng tự phục vụ của thanh toán điện tử Stripe hiện không khả dụng!",
"Edit Permission": "Chỉnh sửa quyền",
"Create Permission": "Tạo quyền",
"Be careful!": "Hãy cẩn thận!",
"By modifying permission, you might break the system permissions functionality. Please ensure you\\'re absolutely certain before proceeding.": "Bằng cách chỉnh sửa quyền, bạn có thể làm hỏng chức năng quyền của hệ thống. Vui lòng đảm bảo bạn hoàn toàn chắc chắn trước khi tiếp tục.",
"Select Permission": "Chọn quyền",
"Create": "Tạo",
"Read": "Đọc",
"Update": "Cập nhật",
"Delete": "Xóa",
"Manage": "Quản lý",
"Fill Module Name": "Điền tên mô-đun",
"Select Scope": "Chọn phạm vi",
"All": "Tất cả",
"Creator": "Người tạo",
"Custom": "Tùy chỉnh",
"Fill Scope Value": "Điền giá trị phạm vi",
"Submit": "Gửi",
"Total {number} permissions": "Tổng cộng {number} quyền",
"Edit Role": "Chỉnh sửa vai trò"
}
4 changes: 2 additions & 2 deletions app/components/organizations/OrganizationDrawer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { cloneDeep } from 'lodash-es'
import { PerfectScrollbar } from 'vue3-perfect-scrollbar'

import type { VForm } from 'vuetify/components/VForm'
import type { Organization } from '~/stores/admin/organization'
import type { DialogConfig, DrawerConfig } from '~/utils/types'
import type { Organization } from '@base/stores/admin/organization'
import type { DialogConfig, DrawerConfig } from '@base/utils/types'

interface Emit {
(e: 'update:isDrawerOpen', value: boolean): void
Expand Down
211 changes: 106 additions & 105 deletions app/components/permissions/AddEditPermissionDialog.vue
Original file line number Diff line number Diff line change
@@ -1,186 +1,187 @@
<script setup lang="ts">
import { on } from 'node:events'
import type { VForm } from 'vuetify/components/VForm'
import type { Permission } from '~/stores/admin/permission'
import { useRoleStore } from '~/stores/admin/role'

interface Props {
isDialogVisible: boolean
permissionData?: Partial<Permission>
}
interface Emit {
(e: 'update:isDialogVisible', value: boolean): void
(e: 'update:permissionData', value: Partial<Permission>): void
}

const props = defineProps<Props>()
const emit = defineEmits<Emit>()

const roleStore = useRoleStore()
const { roleList } = storeToRefs(roleStore)
const { fetchRoles } = roleStore

const isFormValid = ref(false)
const refForm = ref<VForm>()

const isPermissionDataEmpty = computed(() => {
const data = props.permissionData
return !data || Object.values(data).every(value => value === '')
import type { sysPermissionTable } from '@base/server/db/schemas/sys_permissions.schema'
import type { InferSelectModel } from 'drizzle-orm'
import { PermissionAction, PermissionScope } from '@base/server/db/schemas'
import { cloneDeep } from 'lodash-es'
import { requiredValidator } from '#imports'

type Permission = InferSelectModel<typeof sysPermissionTable>

const props = defineProps<{
permission?: Permission | null
}>()

const emit = defineEmits<{
(e: 'edit', payload: Permission): void
(e: 'create', payload: Permission): void
(e: 'cancel'): void
}>()

const modelValue = defineModel<boolean>({
default: false,
})

const localPermissionData = ref<Partial<Permission>>({
id: '',
role_id: '',
action: '',
subject: '',
})

function onReset() {
emit('update:isDialogVisible', false)
const formTemplate = useTemplateRef('formRef')

localPermissionData.value = {
function getDefaultFormData(): Permission {
return {
id: '',
role_id: '',
action: '',
action: PermissionAction.READ,
subject: '',
scope: PermissionScope.ALL,
scope_value: '',
}
}

function onSubmit() {
refForm.value?.validate().then(({ valid }) => {
if (valid) {
emit('update:permissionData', props.permissionData
? localPermissionData.value
: {
role_id: localPermissionData.value.role_id,
action: localPermissionData.value.action,
subject: localPermissionData.value.subject,
})

onReset()
}
})
}
const formData = ref(getDefaultFormData())

watch(() => props.permissionData, (newPermissionData) => {
if (newPermissionData) {
localPermissionData.value = { ...newPermissionData }
watch(modelValue, (value) => {
if (!value) {
formData.value = getDefaultFormData()
}
}, { immediate: true })
})

syncRef(computed(() => props.permission), formData, {
direction: 'ltr',
transform: {
ltr(left) {
if (left)
return cloneDeep(left)

onMounted(async () => {
await fetchRoles()
return getDefaultFormData()
},
},
})

async function handleSubmit() {
try {
if (formTemplate.value) {
const { valid } = await formTemplate.value.validate()

if (valid) {
if (formData.value.id)
emit('edit', formData.value)
else
emit('create', formData.value)
}
}
}
catch {}
}
</script>

<template>
<VDialog
v-model="modelValue"
:width="$vuetify.display.smAndDown ? 'auto' : 600"
:model-value="props.isDialogVisible"
@update:model-value="onReset"
>
<VCard class="pa-sm-8 pa-5">
<!-- 👉 dialog close btn -->
<DialogCloseBtn
variant="text"
size="default"
@click="onReset"
@click="modelValue = false"
/>

<VCardText class="mt-5">
<!-- 👉 Title -->
<div class="text-center mb-6">
<h4 class="text-h4 mb-2">
{{ isPermissionDataEmpty ? 'Add' : 'Edit' }} Permission
{{ permission ? $t('Edit Permission') : $t('Create Permission') }}
</h4>

<p class="text-body-1">
{{ isPermissionDataEmpty ? 'Add' : 'Edit' }} permission as per your requirements.
</p>
</div>

<!-- 👉 Form -->
<VForm
ref="refForm"
v-model="isFormValid"
@submit.prevent="onSubmit"
ref="formRef"
@submit.prevent="handleSubmit"
>
<VAlert
type="warning"
title="Warning!"
:title="$t('Be careful!')"
variant="tonal"
class="mb-6"
>
By {{ isPermissionDataEmpty ? 'editing' : 'adding' }} the permission name, you might break the system permissions functionality. Please ensure you're absolutely certain before proceeding.
{{
$t('By modifying permission, you might break the system permissions functionality. Please ensure you\'re absolutely certain before proceeding.')
}}
</VAlert>

<!-- 👉 Role action -->
<div class="mb-4">
<div class="d-flex flex-column gap-4 mb-4">
<VSelect
v-model="localPermissionData.action"
v-model="formData.action"
density="compact"
:label="$t('Select Permission')"
:placeholder="$t('Select Permission')"
:rules="[requiredValidator]"
label="Select Action"
placeholder="Select Action"
:items="[
{
title: 'Create',
value: 'create',
title: $t('Create'),
value: PermissionAction.CREATE,
},
{
title: 'Read',
value: 'read',
title: $t('Read'),
value: PermissionAction.READ,
},
{
title: 'Update',
value: 'update',
title: $t('Update'),
value: PermissionAction.UPDATE,
},
{
title: 'Delete',
value: 'delete',
title: $t('Delete'),
value: PermissionAction.DELETE,
},
{
title: 'Manage',
value: 'manage',
title: $t('Manage'),
value: PermissionAction.MANAGE,
},
]"
/>

<VSelect
v-model="localPermissionData.role_id"
density="compact"
label="Select Role"
<VTextField
v-model="formData.subject"
placeholder="Post, Category, User, etc."
:label="$t('Fill Module Name')"
:rules="[requiredValidator]"
:items="roleList"
item-title="name"
item-value="id"
/>

<VSelect
v-model="localPermissionData.subject"
v-model="formData.scope"
density="compact"
:label="$t('Select Scope')"
:placeholder="$t('Select Scope')"
:rules="[requiredValidator]"
label="Select Subject"
:items="[
{
title: 'Category',
value: 'category',
title: $t('All'),
value: PermissionScope.ALL,
},
{
title: $t('Organization'),
value: PermissionScope.ORGANIZATION,
},
{
title: 'Project',
value: 'project',
title: $t('Creator'),
value: PermissionScope.SELF,
},
{
title: 'All',
value: 'all',
title: $t('Custom'),
value: PermissionScope.CUSTOM,
},
]"
/>

<VTextField
v-if="formData.scope === PermissionScope.CUSTOM"
v-model="formData.scope_value"
placeholder="Post, Category, User, etc."
:label="$t('Fill Scope Value')"
:rules="[requiredValidator]"
/>
</div>

<VBtn @click="onSubmit">
{{ isPermissionDataEmpty ? 'Add' : 'Edit' }}
<VBtn type="submit">
{{ permission ? $t('Update') : $t('Submit') }}
</VBtn>
</div>
</VForm>
Expand Down
Loading