DONE: layout letter with letterhead and footer, notification for newly...
This commit is contained in:
@@ -6,5 +6,6 @@ export interface Menu {
|
||||
route_name?: string
|
||||
params?: Record<string, unknown>
|
||||
badge?: number
|
||||
permission?: string
|
||||
sub_menu?: Menu[]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import type { AuthPermission, AuthRole, AuthUser } from '@/modules/auth/types/auth.types'
|
||||
|
||||
const DEVELOPER_ROLE = 'DEVELOPER'
|
||||
|
||||
export function getActiveRolePermissions(
|
||||
user: AuthUser | null | undefined,
|
||||
activeRole: AuthRole | null | undefined,
|
||||
): AuthPermission[] {
|
||||
if (!user?.roles?.length || !activeRole) {
|
||||
return []
|
||||
}
|
||||
|
||||
return user.roles.find((role) => role.id === activeRole.id)?.permissions ?? []
|
||||
}
|
||||
|
||||
export function hasActiveRolePermission(
|
||||
user: AuthUser | null | undefined,
|
||||
activeRole: AuthRole | null | undefined,
|
||||
permission: string,
|
||||
): boolean {
|
||||
if (activeRole?.name === DEVELOPER_ROLE) {
|
||||
return true
|
||||
}
|
||||
|
||||
return getActiveRolePermissions(user, activeRole).some(
|
||||
(item) => item.name === permission,
|
||||
)
|
||||
}
|
||||
|
||||
export function hasAnyActiveRolePermission(
|
||||
user: AuthUser | null | undefined,
|
||||
activeRole: AuthRole | null | undefined,
|
||||
permissions: string[],
|
||||
): boolean {
|
||||
return permissions.some((permission) =>
|
||||
hasActiveRolePermission(user, activeRole, permission),
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import type { Menu } from '@/core/types/menu'
|
||||
|
||||
export type MenuList = (string | Menu)[]
|
||||
|
||||
function isMenuVisible(menu: Menu, hasPermission: (permission: string) => boolean): boolean {
|
||||
if (menu.sub_menu?.length) {
|
||||
return menu.sub_menu.some((item) => isMenuVisible(item, hasPermission))
|
||||
}
|
||||
|
||||
if (!menu.permission) {
|
||||
return true
|
||||
}
|
||||
|
||||
return hasPermission(menu.permission)
|
||||
}
|
||||
|
||||
function filterMenuItem(menu: Menu, hasPermission: (permission: string) => boolean): Menu | null {
|
||||
if (menu.sub_menu?.length) {
|
||||
const subMenu = menu.sub_menu
|
||||
.map((item) => filterMenuItem(item, hasPermission))
|
||||
.filter((item): item is Menu => item !== null)
|
||||
|
||||
if (!subMenu.length) {
|
||||
return null
|
||||
}
|
||||
|
||||
return { ...menu, sub_menu: subMenu }
|
||||
}
|
||||
|
||||
return isMenuVisible(menu, hasPermission) ? menu : null
|
||||
}
|
||||
|
||||
function sectionHasVisibleItems(
|
||||
menu: MenuList,
|
||||
startIndex: number,
|
||||
hasPermission: (permission: string) => boolean,
|
||||
): boolean {
|
||||
for (let index = startIndex + 1; index < menu.length; index += 1) {
|
||||
const entry = menu[index]
|
||||
|
||||
if (typeof entry === 'string') {
|
||||
break
|
||||
}
|
||||
|
||||
if (entry && isMenuVisible(entry, hasPermission)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
export function filterMenuByPermission(
|
||||
menu: MenuList,
|
||||
hasPermission: (permission: string) => boolean,
|
||||
): MenuList {
|
||||
const filtered: MenuList = []
|
||||
|
||||
menu.forEach((entry, index) => {
|
||||
if (typeof entry === 'string') {
|
||||
if (sectionHasVisibleItems(menu, index, hasPermission)) {
|
||||
filtered.push(entry)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const visibleItem = filterMenuItem(entry, hasPermission)
|
||||
if (visibleItem) {
|
||||
filtered.push(visibleItem)
|
||||
}
|
||||
})
|
||||
|
||||
return filtered
|
||||
}
|
||||
@@ -5,6 +5,18 @@ type ApiErrorBody = {
|
||||
errors?: Record<string, string[]>
|
||||
}
|
||||
|
||||
export function getApiValidationErrors(error: unknown): Record<string, string[]> | null {
|
||||
if (axios.isAxiosError(error)) {
|
||||
const data = error.response?.data as ApiErrorBody | undefined
|
||||
|
||||
if (data?.errors && Object.keys(data.errors).length > 0) {
|
||||
return data.errors
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export function getApiErrorMessage(
|
||||
error: unknown,
|
||||
fallback = 'Something went wrong. Please try again.',
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import type { RouteLocationNormalized } from 'vue-router'
|
||||
|
||||
export function getRouteRequiredPermissions(
|
||||
route: RouteLocationNormalized,
|
||||
): string[] {
|
||||
for (const record of [...route.matched].reverse()) {
|
||||
if (typeof record.meta.permission === 'string') {
|
||||
return [record.meta.permission]
|
||||
}
|
||||
|
||||
if (Array.isArray(record.meta.permissions) && record.meta.permissions.length) {
|
||||
return record.meta.permissions
|
||||
}
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
Reference in New Issue
Block a user