Add accessibility
This commit is contained in:
parent
540bbaa443
commit
924e424251
2
app.vue
2
app.vue
@ -17,7 +17,7 @@ onMounted(() => {
|
||||
}, 1000);
|
||||
|
||||
// Get theme from localStorage
|
||||
let theme = localStorage.getItem("theme") || "default";
|
||||
let theme = localStorage.getItem("theme") || "biasa";
|
||||
document.documentElement.setAttribute("data-theme", theme);
|
||||
});
|
||||
</script>
|
||||
|
@ -1,4 +1,4 @@
|
||||
html[data-theme="default"] {
|
||||
html[data-theme="biasa"] {
|
||||
--color-primary: 0, 165, 154;
|
||||
--color-secondary: 97, 176, 183;
|
||||
--color-accent: 243, 244, 246;
|
||||
@ -36,7 +36,7 @@ html[data-theme="default"] {
|
||||
--tw-shadow: #e5eaf2;
|
||||
}
|
||||
|
||||
html[data-theme="dark"] {
|
||||
html[data-theme="gelap"] {
|
||||
--color-primary: 97, 176, 183;
|
||||
--color-secondary: 13, 27, 42;
|
||||
--color-accent: 15, 23, 42;
|
||||
@ -48,6 +48,11 @@ html[data-theme="dark"] {
|
||||
--border-color: 30, 41, 59;
|
||||
--bg-1: 15, 23, 42;
|
||||
--bg-2: 30, 41, 59;
|
||||
--sidebar: 38, 50, 55;
|
||||
--sidebar-menu: 26, 35, 38;
|
||||
--sidebar-text: 255, 255, 255;
|
||||
--header: 49, 65, 71;
|
||||
--header-text: 255, 255, 255;
|
||||
--scroll-color: 170, 170, 170;
|
||||
--scroll-hover-color: 155, 155, 155;
|
||||
--fk-border-color: 71, 85, 105;
|
||||
@ -68,53 +73,143 @@ html[data-theme="dark"] {
|
||||
--tw-shadow: #e5eaf2;
|
||||
}
|
||||
|
||||
html[data-theme="nier"] {
|
||||
--color-primary: 99, 95, 84;
|
||||
--color-secondary: 207, 107, 83;
|
||||
--color-accent: 243, 88, 106;
|
||||
--color-success: 79, 192, 103;
|
||||
--color-info: 65, 133, 242;
|
||||
--color-warning: 246, 141, 32;
|
||||
--color-danger: 229, 83, 69;
|
||||
--text-color: 78, 75, 66;
|
||||
--border-color: 153, 152, 131;
|
||||
--bg-1: 205, 200, 176;
|
||||
--bg-2: 218, 212, 187;
|
||||
--scroll-color: 99, 95, 84;
|
||||
--scroll-hover-color: 99, 95, 84;
|
||||
--fk-border-color: 99, 95, 84;
|
||||
--fk-placeholder-color: 188, 175, 145;
|
||||
--box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||
--cp-bg: 255, 255, 255;
|
||||
--rounded-box: 0.5rem;
|
||||
--rounded-btn: 0.5rem;
|
||||
--rounded-badge: 1.9rem;
|
||||
--animation-btn: 0.25s;
|
||||
--animation-input: 0.2s;
|
||||
--btn-text-case: uppercase;
|
||||
--btn-focus-scale: 0.95;
|
||||
--padding-btn: 0.625rem 0.875rem;
|
||||
--border-btn: 1px;
|
||||
--tab-border: 1px;
|
||||
--tab-radius: 0.5rem;
|
||||
--tw-shadow: #e5eaf2;
|
||||
}
|
||||
|
||||
html[data-theme="custom1"] {
|
||||
--color-primary: 9, 76, 90;
|
||||
--color-secondary: 62, 72, 83;
|
||||
--color-accent: 0, 103, 236;
|
||||
--color-success: 11, 152, 76;
|
||||
--color-info: 208, 89, 41;
|
||||
--color-warning: 229, 197, 13;
|
||||
--color-danger: 238, 5, 34;
|
||||
--text-color: 15, 15, 14;
|
||||
--border-color: 153, 152, 131;
|
||||
--bg-1: 214, 215, 206;
|
||||
--bg-2: 235, 232, 217;
|
||||
--scroll-color: 9, 76, 90;
|
||||
--scroll-hover-color: 9, 76, 90;
|
||||
--box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||
html[data-theme="biru"] {
|
||||
--color-primary: 0, 102, 204;
|
||||
--color-secondary: 51, 153, 255;
|
||||
--color-accent: 255, 204, 0;
|
||||
--color-success: 46, 204, 113;
|
||||
--color-info: 52, 152, 219;
|
||||
--color-warning: 241, 196, 15;
|
||||
--color-danger: 231, 76, 60;
|
||||
--text-color: 0, 0, 0;
|
||||
--border-color: 200, 200, 200;
|
||||
--bg-1: 240, 248, 255;
|
||||
--bg-2: 230, 240, 250;
|
||||
--sidebar: 38, 50, 55;
|
||||
--sidebar-menu: 26, 35, 38;
|
||||
--sidebar-text: 255, 255, 255;
|
||||
--header: 49, 65, 71;
|
||||
--header-text: 255, 255, 255;
|
||||
--scroll-color: 180, 180, 180;
|
||||
--scroll-hover-color: 150, 150, 150;
|
||||
--fk-border-color: 200, 200, 200;
|
||||
--fk-placeholder-color: 150, 150, 150;
|
||||
--box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
||||
0 2px 4px -2px rgba(0, 0, 0, 0.1);
|
||||
--cp-bg: 255, 255, 255;
|
||||
--rounded-box: 0.5rem;
|
||||
--rounded-btn: 0.5rem;
|
||||
--rounded-badge: 1.9rem;
|
||||
--animation-btn: 0.25s;
|
||||
--animation-input: 0.2s;
|
||||
--btn-text-case: uppercase;
|
||||
--btn-focus-scale: 0.95;
|
||||
--padding-btn: 0.625rem 1.5rem;
|
||||
--border-btn: 1px;
|
||||
--tab-border: 1px;
|
||||
--tab-radius: 0.5rem;
|
||||
--tw-shadow: #e5eaf2;
|
||||
}
|
||||
|
||||
html[data-theme="merah"] {
|
||||
--color-primary: 204, 0, 0;
|
||||
--color-secondary: 255, 102, 102;
|
||||
--color-accent: 255, 255, 153;
|
||||
--color-success: 46, 204, 113;
|
||||
--color-info: 52, 152, 219;
|
||||
--color-warning: 241, 196, 15;
|
||||
--color-danger: 231, 76, 60;
|
||||
--text-color: 0, 0, 0;
|
||||
--border-color: 200, 200, 200;
|
||||
--bg-1: 255, 240, 240;
|
||||
--bg-2: 255, 230, 230;
|
||||
--sidebar: 38, 50, 55;
|
||||
--sidebar-menu: 26, 35, 38;
|
||||
--sidebar-text: 255, 255, 255;
|
||||
--header: 49, 65, 71;
|
||||
--header-text: 255, 255, 255;
|
||||
--scroll-color: 180, 180, 180;
|
||||
--scroll-hover-color: 150, 150, 150;
|
||||
--fk-border-color: 200, 200, 200;
|
||||
--fk-placeholder-color: 150, 150, 150;
|
||||
--box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
||||
0 2px 4px -2px rgba(0, 0, 0, 0.1);
|
||||
--cp-bg: 255, 255, 255;
|
||||
--rounded-box: 0.5rem;
|
||||
--rounded-btn: 0.5rem;
|
||||
--rounded-badge: 1.9rem;
|
||||
--animation-btn: 0.25s;
|
||||
--animation-input: 0.2s;
|
||||
--btn-text-case: uppercase;
|
||||
--btn-focus-scale: 0.95;
|
||||
--padding-btn: 0.625rem 1.5rem;
|
||||
--border-btn: 1px;
|
||||
--tab-border: 1px;
|
||||
--tab-radius: 0.5rem;
|
||||
--tw-shadow: #e5eaf2;
|
||||
}
|
||||
|
||||
html[data-theme="ungu"] {
|
||||
--color-primary: 75, 0, 130;
|
||||
--color-secondary: 138, 43, 226;
|
||||
--color-accent: 255, 215, 0;
|
||||
--color-success: 46, 204, 113;
|
||||
--color-info: 52, 152, 219;
|
||||
--color-warning: 241, 196, 15;
|
||||
--color-danger: 231, 76, 60;
|
||||
--text-color: 0, 0, 0;
|
||||
--border-color: 200, 200, 200;
|
||||
--bg-1: 240, 248, 255;
|
||||
--bg-2: 230, 240, 250;
|
||||
--sidebar: 38, 50, 55;
|
||||
--sidebar-menu: 26, 35, 38;
|
||||
--sidebar-text: 255, 255, 255;
|
||||
--header: 49, 65, 71;
|
||||
--header-text: 255, 255, 255;
|
||||
--scroll-color: 180, 180, 180;
|
||||
--scroll-hover-color: 150, 150, 150;
|
||||
--fk-border-color: 200, 200, 200;
|
||||
--fk-placeholder-color: 150, 150, 150;
|
||||
--box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
||||
0 2px 4px -2px rgba(0, 0, 0, 0.1);
|
||||
--cp-bg: 255, 255, 255;
|
||||
--rounded-box: 0.5rem;
|
||||
--rounded-btn: 0.5rem;
|
||||
--rounded-badge: 1.9rem;
|
||||
--animation-btn: 0.25s;
|
||||
--animation-input: 0.2s;
|
||||
--btn-text-case: uppercase;
|
||||
--btn-focus-scale: 0.95;
|
||||
--padding-btn: 0.625rem 1.5rem;
|
||||
--border-btn: 1px;
|
||||
--tab-border: 1px;
|
||||
--tab-radius: 0.5rem;
|
||||
--tw-shadow: #e5eaf2;
|
||||
}
|
||||
|
||||
html[data-theme="oren"] {
|
||||
--color-primary: 255, 103, 0;
|
||||
--color-secondary: 255, 159, 64;
|
||||
--color-accent: 0, 128, 128;
|
||||
--color-success: 46, 204, 113;
|
||||
--color-info: 52, 152, 219;
|
||||
--color-warning: 241, 196, 15;
|
||||
--color-danger: 231, 76, 60;
|
||||
--text-color: 0, 0, 0;
|
||||
--border-color: 200, 200, 200;
|
||||
--bg-1: 255, 250, 240;
|
||||
--bg-2: 255, 245, 230;
|
||||
--sidebar: 38, 50, 55;
|
||||
--sidebar-menu: 26, 35, 38;
|
||||
--sidebar-text: 255, 255, 255;
|
||||
--header: 49, 65, 71;
|
||||
--header-text: 255, 255, 255;
|
||||
--scroll-color: 180, 180, 180;
|
||||
--scroll-hover-color: 150, 150, 150;
|
||||
--fk-border-color: 200, 200, 200;
|
||||
--fk-placeholder-color: 150, 150, 150;
|
||||
--box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
||||
0 2px 4px -2px rgba(0, 0, 0, 0.1);
|
||||
--cp-bg: 255, 255, 255;
|
||||
--rounded-box: 0.5rem;
|
||||
--rounded-btn: 0.5rem;
|
||||
|
35
components/VoiceReader.vue
Normal file
35
components/VoiceReader.vue
Normal file
@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div class="voice-reader">
|
||||
<rs-button
|
||||
@click="toggleReading"
|
||||
:variant="isReading ? 'danger' : 'primary'"
|
||||
class="p-2 rounded-full"
|
||||
>
|
||||
<Icon
|
||||
:name="isReading ? 'ph:ear' : 'ph:ear-slash'"
|
||||
:class="['text-2xl', { 'animate-pulse text-white': isReading }]"
|
||||
/>
|
||||
</rs-button>
|
||||
<span ref="announceElement" class="sr-only" aria-live="polite"></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useVoiceReader } from "~/composables/useVoiceReader";
|
||||
|
||||
const { isReading, toggleReading, announceElement } = useVoiceReader();
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
</style>
|
@ -11,6 +11,7 @@ const langList = languageList();
|
||||
const locale = ref("en");
|
||||
|
||||
const themes = themeList();
|
||||
const themes2 = themeList2();
|
||||
|
||||
function setTheme(theme) {
|
||||
document.documentElement.setAttribute("data-theme", theme);
|
||||
@ -85,6 +86,66 @@ onMounted(() => {
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2 item-center justify-items-end">
|
||||
<VoiceReader class="ml-4" />
|
||||
|
||||
<!-- New dropdown for themeList.js -->
|
||||
<VDropdown placement="bottom-end" distance="13" name="theme">
|
||||
<button class="icon-btn h-10 w-10 rounded-full">
|
||||
<Icon size="22px" name="ph:paint-brush-broad" />
|
||||
</button>
|
||||
<template #popper>
|
||||
<ul class="header-dropdown w-full md:w-52">
|
||||
<li v-for="(val, index) in themes" :key="index">
|
||||
<a
|
||||
@click="setTheme(val.theme)"
|
||||
class="flex justify-between items-center cursor-pointer py-2 px-4 hover:bg-[rgb(var(--bg-1))]"
|
||||
>
|
||||
<span class="capitalize"> {{ val.theme }} </span>
|
||||
<div class="flex items-center gap-x-1">
|
||||
<div
|
||||
v-for="(color, colorIndex) in val.colors"
|
||||
:key="colorIndex"
|
||||
class="h-[25px] w-[10px] rounded-lg"
|
||||
:style="{
|
||||
backgroundColor: rgbToHex(color.value),
|
||||
}"
|
||||
></div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
</VDropdown>
|
||||
|
||||
<!-- New dropdown for themeList2.js -->
|
||||
<VDropdown placement="bottom-end" distance="13" name="theme2">
|
||||
<button class="icon-btn h-10 w-10 rounded-full">
|
||||
<Icon size="22px" name="ph:wheelchair" />
|
||||
</button>
|
||||
<template #popper>
|
||||
<ul class="header-dropdown w-full md:w-52">
|
||||
<li v-for="(val, index) in themes2" :key="index">
|
||||
<a
|
||||
@click="setTheme(val.theme)"
|
||||
class="flex justify-between items-center cursor-pointer py-2 px-4 hover:bg-[rgb(var(--bg-1))]"
|
||||
>
|
||||
<span class="capitalize"> {{ val.theme }} </span>
|
||||
<div class="flex items-center gap-x-1">
|
||||
<div
|
||||
v-for="(color, colorIndex) in val.colors"
|
||||
:key="colorIndex"
|
||||
class="h-[25px] w-[10px] rounded-lg"
|
||||
:style="{
|
||||
backgroundColor: rgbToHex(color.value),
|
||||
}"
|
||||
></div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
</VDropdown>
|
||||
|
||||
<VDropdown placement="bottom-end" distance="13" name="notification">
|
||||
<button class="relative icon-btn h-10 w-10 rounded-full">
|
||||
<span
|
||||
|
@ -1,7 +1,7 @@
|
||||
export default function () {
|
||||
return [
|
||||
{
|
||||
theme: "default",
|
||||
theme: "biasa",
|
||||
colors: [
|
||||
{
|
||||
name: "primary",
|
||||
@ -18,7 +18,7 @@ export default function () {
|
||||
],
|
||||
},
|
||||
{
|
||||
theme: "dark",
|
||||
theme: "gelap",
|
||||
colors: [
|
||||
{
|
||||
name: "primary",
|
||||
@ -34,39 +34,5 @@ export default function () {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
theme: "nier",
|
||||
colors: [
|
||||
{
|
||||
name: "primary",
|
||||
value: "99, 95, 84",
|
||||
},
|
||||
{
|
||||
name: "secondary",
|
||||
value: "207, 107, 83",
|
||||
},
|
||||
{
|
||||
name: "accent",
|
||||
value: "243, 88, 106",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
theme: "custom1",
|
||||
colors: [
|
||||
{
|
||||
name: "primary",
|
||||
value: "9, 76, 90",
|
||||
},
|
||||
{
|
||||
name: "secondary",
|
||||
value: "62, 72, 83",
|
||||
},
|
||||
{
|
||||
name: "accent",
|
||||
value: "0, 103, 236",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
104
composables/themeList2.js
Normal file
104
composables/themeList2.js
Normal file
@ -0,0 +1,104 @@
|
||||
export default function () {
|
||||
return [
|
||||
{
|
||||
theme: "biru",
|
||||
colors: [
|
||||
{
|
||||
name: "primary",
|
||||
value: "0, 102, 204", // Strong blue
|
||||
},
|
||||
{
|
||||
name: "secondary",
|
||||
value: "51, 153, 255", // Lighter blue
|
||||
},
|
||||
{
|
||||
name: "accent",
|
||||
value: "255, 204, 0", // Gold
|
||||
},
|
||||
{
|
||||
name: "background",
|
||||
value: "240, 248, 255", // Alice blue
|
||||
},
|
||||
{
|
||||
name: "text",
|
||||
value: "0, 0, 0", // Black
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
theme: "merah",
|
||||
colors: [
|
||||
{
|
||||
name: "primary",
|
||||
value: "204, 0, 0", // Strong red
|
||||
},
|
||||
{
|
||||
name: "secondary",
|
||||
value: "255, 102, 102", // Lighter red
|
||||
},
|
||||
{
|
||||
name: "accent",
|
||||
value: "255, 255, 153", // Light yellow
|
||||
},
|
||||
{
|
||||
name: "background",
|
||||
value: "255, 240, 240", // Very light pink
|
||||
},
|
||||
{
|
||||
name: "text",
|
||||
value: "0, 0, 0", // Black
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
theme: "ungu",
|
||||
colors: [
|
||||
{
|
||||
name: "primary",
|
||||
value: "75, 0, 130", // Indigo
|
||||
},
|
||||
{
|
||||
name: "secondary",
|
||||
value: "138, 43, 226", // Blue violet
|
||||
},
|
||||
{
|
||||
name: "accent",
|
||||
value: "255, 215, 0", // Gold
|
||||
},
|
||||
{
|
||||
name: "background",
|
||||
value: "240, 248, 255", // Alice blue
|
||||
},
|
||||
{
|
||||
name: "text",
|
||||
value: "0, 0, 0", // Black
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
theme: "oren",
|
||||
colors: [
|
||||
{
|
||||
name: "primary",
|
||||
value: "255, 103, 0", // Dark orange
|
||||
},
|
||||
{
|
||||
name: "secondary",
|
||||
value: "255, 159, 64", // Lighter orange
|
||||
},
|
||||
{
|
||||
name: "accent",
|
||||
value: "0, 128, 128", // Teal
|
||||
},
|
||||
{
|
||||
name: "background",
|
||||
value: "255, 250, 240", // Floral white
|
||||
},
|
||||
{
|
||||
name: "text",
|
||||
value: "0, 0, 0", // Black
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
55
composables/useVoiceReader.js
Normal file
55
composables/useVoiceReader.js
Normal file
@ -0,0 +1,55 @@
|
||||
export function useVoiceReader() {
|
||||
const isReading = ref(false);
|
||||
const announceElement = ref(null);
|
||||
let speechSynthesis;
|
||||
let speechUtterance;
|
||||
|
||||
onMounted(() => {
|
||||
speechSynthesis = window.speechSynthesis;
|
||||
speechUtterance = new SpeechSynthesisUtterance();
|
||||
|
||||
window.addEventListener("keydown", handleKeydown);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (speechSynthesis) {
|
||||
speechSynthesis.cancel();
|
||||
}
|
||||
window.removeEventListener("keydown", handleKeydown);
|
||||
});
|
||||
|
||||
const toggleReading = () => {
|
||||
if (!speechSynthesis) return;
|
||||
|
||||
if (isReading.value) {
|
||||
speechSynthesis.pause();
|
||||
isReading.value = false;
|
||||
announce("Reading paused");
|
||||
} else {
|
||||
const textToRead = document.body.innerText;
|
||||
speechUtterance.text = textToRead;
|
||||
speechSynthesis.speak(speechUtterance);
|
||||
isReading.value = true;
|
||||
announce("Reading started");
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeydown = (event) => {
|
||||
if (event.ctrlKey && event.key === "r") {
|
||||
event.preventDefault();
|
||||
toggleReading();
|
||||
}
|
||||
};
|
||||
|
||||
const announce = (message) => {
|
||||
if (announceElement.value) {
|
||||
announceElement.value.textContent = message;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
isReading,
|
||||
toggleReading,
|
||||
announceElement,
|
||||
};
|
||||
}
|
@ -1,58 +1,4 @@
|
||||
export default [
|
||||
{
|
||||
header: "Forensik",
|
||||
description: "",
|
||||
child: [
|
||||
{
|
||||
title: "FOR-01",
|
||||
icon: "ph:number-circle-one-fill",
|
||||
child: [
|
||||
{
|
||||
title: "Permohonan Temujanji",
|
||||
path: "/permohonan-temujanji/senarai",
|
||||
child: [],
|
||||
meta: {},
|
||||
},
|
||||
{
|
||||
title: "Kaunter Semakan ",
|
||||
path: "/kemaskini-daftar/senarai",
|
||||
child: [],
|
||||
meta: {},
|
||||
},
|
||||
// {
|
||||
// title: "Kemaskini Daftar",
|
||||
// path: "/kemaskini-daftar/senarai",
|
||||
// child: [],
|
||||
// meta: {},
|
||||
// },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "FOR-02",
|
||||
icon: "ph:number-circle-two-fill",
|
||||
child: [
|
||||
{
|
||||
title: "Pengesanan Penyamaran",
|
||||
path: "/pengesanan-penyamaran/senarai",
|
||||
child: [],
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "FOR-03",
|
||||
icon: "ph:number-circle-two-fill",
|
||||
child: [
|
||||
{
|
||||
title: "e-library",
|
||||
path: "/e-library",
|
||||
child: [],
|
||||
meta: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
header: "Utama",
|
||||
description: "",
|
||||
@ -176,71 +122,4 @@ export default [
|
||||
],
|
||||
meta: {},
|
||||
},
|
||||
|
||||
{
|
||||
header: "Pengurusan",
|
||||
description: "",
|
||||
child: [
|
||||
{
|
||||
title: "Konfigurasi",
|
||||
icon: "ic:outline-settings",
|
||||
child: [
|
||||
{
|
||||
title: "Persekitaran",
|
||||
path: "/devtool/config/environment",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Penyelia Menu",
|
||||
icon: "ci:menu-alt-03",
|
||||
path: "/devtool/menu-editor",
|
||||
child: [],
|
||||
},
|
||||
{
|
||||
title: "Penyelia Pengguna",
|
||||
path: "/devtool/user-management",
|
||||
icon: "ph:user-circle-gear",
|
||||
child: [
|
||||
{
|
||||
title: "Pengguna",
|
||||
path: "/devtool/user-management/user-list",
|
||||
icon: "",
|
||||
child: [],
|
||||
},
|
||||
{
|
||||
title: "Peranan",
|
||||
path: "/devtool/user-management/role-list",
|
||||
icon: "",
|
||||
child: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Kandungan",
|
||||
icon: "mdi:pencil-ruler",
|
||||
child: [
|
||||
{
|
||||
title: "Penyelia Kandungan",
|
||||
path: "/devtool/content-editor",
|
||||
},
|
||||
{
|
||||
title: "Templat",
|
||||
path: "/devtool/content-editor/template",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Penyelia API",
|
||||
path: "/devtool/api-editor",
|
||||
icon: "material-symbols:api-rounded",
|
||||
child: [],
|
||||
},
|
||||
],
|
||||
meta: {
|
||||
auth: {
|
||||
role: ["Developer"],
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
Loading…
x
Reference in New Issue
Block a user