Merge branch 'dev' into integrasi_sso
This commit is contained in:
No files matched your search
@@ -2,7 +2,6 @@ import type { DataTableLoader } from '~/components/pub/my-ui/data-table/type'
|
||||
import type { PaginationMeta } from '~/components/pub/my-ui/pagination/pagination.type'
|
||||
import { refDebounced, useUrlSearchParams } from '@vueuse/core'
|
||||
import * as z from 'zod'
|
||||
import { is } from "date-fns/locale"
|
||||
|
||||
// Default query schema yang bisa digunakan semua list
|
||||
export const defaultQuerySchema = z.object({
|
||||
@@ -38,10 +37,23 @@ interface UsePaginatedListOptions<T = any> {
|
||||
}>
|
||||
// Nama endpoint untuk logging error
|
||||
entityName: string
|
||||
/**
|
||||
* Apakah state harus disinkronkan ke URL Browser?
|
||||
* Set `false` jika digunakan di dalam Modal, Drawer, atau Nested Component
|
||||
* agar tidak menimpa URL halaman induk.
|
||||
* @default true
|
||||
*/
|
||||
syncToUrl?: boolean
|
||||
}
|
||||
|
||||
export function usePaginatedList<T = any>(options: UsePaginatedListOptions<T>) {
|
||||
const { querySchema = defaultQuerySchema, defaultQuery = defaultQueryParams, fetchFn, entityName } = options
|
||||
const {
|
||||
querySchema = defaultQuerySchema,
|
||||
defaultQuery = defaultQueryParams,
|
||||
fetchFn,
|
||||
entityName,
|
||||
syncToUrl = true, // Default true agar behavior lama tetap jalan
|
||||
} = options
|
||||
|
||||
// State management
|
||||
const data = ref<T[]>([])
|
||||
@@ -49,11 +61,19 @@ export function usePaginatedList<T = any>(options: UsePaginatedListOptions<T>) {
|
||||
isTableLoading: false,
|
||||
})
|
||||
|
||||
// URL state management
|
||||
const queryParams = useUrlSearchParams('history', {
|
||||
initialValue: defaultQuery,
|
||||
removeFalsyValues: true,
|
||||
})
|
||||
let queryParams: any
|
||||
|
||||
if (syncToUrl) {
|
||||
// Mode Halaman Utama: Sync ke URL
|
||||
queryParams = useUrlSearchParams('history', {
|
||||
initialValue: defaultQuery,
|
||||
removeFalsyValues: true,
|
||||
write: false,
|
||||
})
|
||||
} else {
|
||||
// Mode Nested/Modal: Local Reactive State
|
||||
queryParams = reactive({ ...defaultQuery })
|
||||
}
|
||||
|
||||
const params = computed(() => {
|
||||
const result = querySchema.safeParse(queryParams)
|
||||
@@ -168,7 +188,7 @@ export function usePaginatedList<T = any>(options: UsePaginatedListOptions<T>) {
|
||||
}
|
||||
}
|
||||
|
||||
export function transform(endpoint: string ,params: any): string {
|
||||
export function transform(endpoint: string, params: any): string {
|
||||
const urlParams = new URLSearchParams()
|
||||
|
||||
Object.entries(params).forEach(([key, value]) => {
|
||||
|
||||
@@ -1,12 +1,71 @@
|
||||
import { computed } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
export function useQueryCRUD(modeKey: string = 'mode', recordIdKey: string = 'record-id') {
|
||||
type params = {
|
||||
mode: string
|
||||
recordId: any
|
||||
}
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const crudQueryParams = computed<params>({
|
||||
get: () => {
|
||||
return {
|
||||
mode: route.query[modeKey] && route.query[modeKey] === 'entry' ? 'entry' : 'list',
|
||||
recordId: route.query[recordIdKey],
|
||||
}
|
||||
},
|
||||
set: (val) => {
|
||||
router.push({
|
||||
path: route.path,
|
||||
query: {
|
||||
...route.query,
|
||||
[modeKey]: val.mode,
|
||||
[recordIdKey]: val.recordId,
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
const goToEntry = (myRecord_id?: any) => {
|
||||
if (myRecord_id) {
|
||||
crudQueryParams.value.mode = 'entry'
|
||||
crudQueryParams.value.recordId = myRecord_id
|
||||
} else {
|
||||
crudQueryParams.value.mode = 'entry'
|
||||
crudQueryParams.value.recordId = undefined
|
||||
}
|
||||
}
|
||||
|
||||
const backToList = () => {
|
||||
delete route.query[recordIdKey]
|
||||
router.push({
|
||||
path: route.path,
|
||||
query: {
|
||||
...route.query,
|
||||
mode: 'list',
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return { crudQueryParams, goToEntry, backToList }
|
||||
}
|
||||
|
||||
export function useQueryCRUDMode(key: string = 'mode') {
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const mode = computed<'list' | 'entry'>({
|
||||
get: () => (route.query[key] && route.query[key] === 'entry' ? 'entry' : 'list'),
|
||||
const mode = computed<'list' | 'entry' | 'view'>({
|
||||
get: () => {
|
||||
const q = route.query[key]
|
||||
|
||||
if (q === 'entry') return 'entry'
|
||||
if (q === 'view') return 'view'
|
||||
|
||||
return 'list'
|
||||
},
|
||||
set: (val) => {
|
||||
router.push({
|
||||
path: route.path,
|
||||
@@ -18,20 +77,58 @@ export function useQueryCRUDMode(key: string = 'mode') {
|
||||
},
|
||||
})
|
||||
|
||||
const goToEntry = () => (mode.value = 'entry')
|
||||
const fromView = computed(() => route.query['from'] === 'view')
|
||||
|
||||
const goToEntry = (options?: { fromView?: boolean }) => {
|
||||
router.push({
|
||||
path: route.path,
|
||||
query: {
|
||||
...route.query,
|
||||
[key]: 'entry',
|
||||
from: options?.fromView ? 'view' : undefined,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const goToView = (myRecord_id?: any) => {
|
||||
mode.value = 'view'
|
||||
if (myRecord_id) {
|
||||
myRecord_id.value = myRecord_id
|
||||
}
|
||||
}
|
||||
|
||||
const backToList = () => {
|
||||
router.push({
|
||||
path: route.path,
|
||||
query: {
|
||||
...route.query,
|
||||
mode: 'list',
|
||||
// HAPUS record-id
|
||||
'record-id': undefined,
|
||||
recordIdKey: undefined,
|
||||
from: undefined,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return { mode, goToEntry, backToList }
|
||||
const backToView = () => {
|
||||
router.push({
|
||||
path: route.path,
|
||||
query: {
|
||||
...route.query,
|
||||
mode: 'view',
|
||||
from: undefined,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const goBack = () => {
|
||||
if (fromView.value) {
|
||||
backToView()
|
||||
} else {
|
||||
backToList()
|
||||
}
|
||||
}
|
||||
|
||||
return { mode, fromView, goToEntry, goToView, backToList, backToView, goBack }
|
||||
}
|
||||
|
||||
export function useQueryCRUDRecordId(key: string = 'record-id') {
|
||||
|
||||
+24
-16
@@ -1,4 +1,5 @@
|
||||
import type { Permission, RoleAccess } from '~/models/role'
|
||||
import type { Permission, RoleAccesses } from '~/models/role'
|
||||
import { systemCode } from '~/const/common/role'
|
||||
|
||||
export interface PageOperationPermission {
|
||||
canRead: boolean
|
||||
@@ -7,7 +8,6 @@ export interface PageOperationPermission {
|
||||
canDelete: boolean
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if user has access to a page
|
||||
*/
|
||||
@@ -15,19 +15,27 @@ export function useRBAC() {
|
||||
// NOTE: this roles was dummy for testing only, it should taken from the user store
|
||||
const authStore = useUserStore()
|
||||
|
||||
const checkRole = (roleAccess: RoleAccess, _userRoles?: string[]): boolean => {
|
||||
const roles = authStore.userRole
|
||||
return roles.some((role: string) => (role in roleAccess) || role === 'system') // system by-passes this check
|
||||
const checkRole = (roleAccesses: RoleAccesses, _userRoles?: string[]): boolean => {
|
||||
const activeRole = authStore.getActiveRole() || ''
|
||||
if (activeRole === systemCode) {
|
||||
return true
|
||||
}
|
||||
return (activeRole in roleAccesses);
|
||||
}
|
||||
|
||||
const checkPermission = (roleAccess: RoleAccess, permission: Permission, _userRoles?: string[]): boolean => {
|
||||
const roles = authStore.userRole
|
||||
return roles.some((role: string) => roleAccess[role]?.includes(permission) || role === 'system') // system by-passes this check
|
||||
const checkPermission = (roleAccesses: RoleAccesses, permission: Permission, _userRoles?: string[]): boolean => {
|
||||
const activeRole = authStore.getActiveRole() || ''
|
||||
if (activeRole === systemCode) {
|
||||
return true
|
||||
}
|
||||
if (activeRole in roleAccesses && roleAccesses[activeRole]) {
|
||||
return roleAccesses[activeRole].includes(permission)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const getUserPermissions = (roleAccess: RoleAccess, _userRoles?: string[]): Permission[] => {
|
||||
const roles = authStore.userRole
|
||||
// const roles = ['admisi']
|
||||
const getUserPermissions = (roleAccess: RoleAccesses, _userRoles?: string[]): Permission[] => {
|
||||
const roles = authStore.userRoles
|
||||
const permissions = new Set<Permission>()
|
||||
|
||||
roles.forEach((role: string) => {
|
||||
@@ -39,12 +47,12 @@ export function useRBAC() {
|
||||
return Array.from(permissions)
|
||||
}
|
||||
|
||||
const hasCreateAccess = (roleAccess: RoleAccess) => checkPermission(roleAccess, 'C')
|
||||
const hasReadAccess = (roleAccess: RoleAccess) => checkPermission(roleAccess, 'R')
|
||||
const hasUpdateAccess = (roleAccess: RoleAccess) => checkPermission(roleAccess, 'U')
|
||||
const hasDeleteAccess = (roleAccess: RoleAccess) => checkPermission(roleAccess, 'D')
|
||||
const hasCreateAccess = (roleAccess: RoleAccesses) => checkPermission(roleAccess, 'C')
|
||||
const hasReadAccess = (roleAccess: RoleAccesses) => checkPermission(roleAccess, 'R')
|
||||
const hasUpdateAccess = (roleAccess: RoleAccesses) => checkPermission(roleAccess, 'U')
|
||||
const hasDeleteAccess = (roleAccess: RoleAccesses) => checkPermission(roleAccess, 'D')
|
||||
|
||||
const getPagePermissions = (roleAccess: RoleAccess): PageOperationPermission => ({
|
||||
const getPagePermissions = (roleAccess: RoleAccesses): PageOperationPermission => ({
|
||||
canRead : hasReadAccess(roleAccess),
|
||||
canCreate: hasCreateAccess(roleAccess),
|
||||
canUpdate: hasUpdateAccess(roleAccess),
|
||||
|
||||
Reference in New Issue
Block a user