update
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,68 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { useDisplay } from 'vuetify';
|
||||
const { xs, lgAndUp } = useDisplay();
|
||||
const sDrawer = ref(false);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!---/Left chat list -->
|
||||
<div class="d-flex mainbox rounded-md">
|
||||
<div class="left-part" v-if="lgAndUp">
|
||||
<!-- <perfect-scrollbar style="height: calc(100vh - 290px)"> -->
|
||||
<slot name="leftpart"></slot>
|
||||
<!-- </perfect-scrollbar> -->
|
||||
</div>
|
||||
|
||||
<!---right chat conversation -->
|
||||
<div class="right-part">
|
||||
<!---Toggle Button For mobile-->
|
||||
<v-btn block @click="sDrawer = !sDrawer" variant="text" class="d-lg-none d-md-flex d-sm-flex">
|
||||
<Menu2Icon size="20" class="mr-2" /> Menu
|
||||
</v-btn>
|
||||
<v-divider class="d-lg-none d-block" />
|
||||
<slot name="rightpart"></slot>
|
||||
</div>
|
||||
|
||||
<!---right chat conversation -->
|
||||
</div>
|
||||
|
||||
<v-navigation-drawer temporary v-model="sDrawer" width="320" top v-if="!lgAndUp">
|
||||
<v-card-text class="pa-0">
|
||||
<slot name="mobileLeftContent"></slot>
|
||||
</v-card-text>
|
||||
</v-navigation-drawer>
|
||||
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.mainbox {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.left-part {
|
||||
width: 320px;
|
||||
border-inline-end-width: thin !important;
|
||||
border-inline-end-style: solid !important;
|
||||
border-inline-end-color: rgba(var(--v-border-color), var(--v-border-opacity)) !important;
|
||||
min-height: 500px;
|
||||
transition: 0.1s ease-in;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.v-theme--light {
|
||||
.left-part {
|
||||
background: white;
|
||||
}
|
||||
}
|
||||
.v-theme--dark {
|
||||
.left-part {
|
||||
background: #2b2b2b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.right-part{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,62 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { useDisplay } from "vuetify";
|
||||
const { xs, lgAndUp } = useDisplay();
|
||||
|
||||
const sDrawer = ref(false); // Sidebar drawer for mobile
|
||||
const eDrawer = ref(false); // Email details drawer
|
||||
const selectedEmail = ref(null); // To store the selected email details
|
||||
|
||||
// Method to select an email and open the email details drawer
|
||||
const openEmailDetails = (email:any) => {
|
||||
selectedEmail.value = email; // Store the selected email
|
||||
eDrawer.value = true; // Open the email details drawer
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="d-flex mainbox">
|
||||
<div class="compose pa-6 " v-if="lgAndUp">
|
||||
<slot name="mailCompose"></slot>
|
||||
</div>
|
||||
|
||||
<div class="mail-list">
|
||||
|
||||
<v-divider class="d-lg-none d-block" />
|
||||
<slot name="mailList" :openEmailDetails="openEmailDetails"></slot> <!-- Pass the method as a slot prop -->
|
||||
</div>
|
||||
|
||||
<div class="mail-details pa-6 d-md-block d-none">
|
||||
<slot name="mailDetail"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.compose {
|
||||
max-width: 235px;
|
||||
width: 100%;
|
||||
}
|
||||
.mail-list {
|
||||
max-width: 340px;
|
||||
width: 100%;
|
||||
}
|
||||
.mail-details {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 991px) {
|
||||
.mail-list {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 991px) {
|
||||
.compose,.mail-list{
|
||||
border-inline-end-width: thin !important;
|
||||
border-inline-end-style: solid !important;
|
||||
border-inline-end-color: rgba(var(--v-border-color), var(--v-border-opacity)) !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,43 @@
|
||||
<script setup >
|
||||
import { Icon } from '@iconify/vue';
|
||||
const props = defineProps({
|
||||
title: String,
|
||||
breadcrumbs: Array ,
|
||||
icon: String,
|
||||
text: String
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-card elevation="10" class="mb-8">
|
||||
<div class="px-6 py-4">
|
||||
<div class="d-flex justify-space-between align-center">
|
||||
<h5 class="text-h5">{{ title }}</h5>
|
||||
<v-breadcrumbs :items="breadcrumbs" class="pa-0">
|
||||
<template v-slot:prepend>
|
||||
<router-link to="/" class="textSecondary lh-0">
|
||||
<Icon icon="solar:home-2-line-duotone" height="20" />
|
||||
</router-link>
|
||||
</template>
|
||||
<template v-slot:divider>
|
||||
<div class="d-flex align-center textSecondary "></div>
|
||||
</template>
|
||||
<template v-slot:title="{ item }">
|
||||
<v-chip size="small" class="rounded-sm" color="primary" >{{ item.text }}</v-chip>
|
||||
</template>
|
||||
</v-breadcrumbs>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.page-breadcrumb {
|
||||
.v-toolbar {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -7,13 +7,14 @@ const props = defineProps({
|
||||
// ===============================|| Ui Parent Card||=============================== //
|
||||
<template>
|
||||
<v-card elevation="10" >
|
||||
<v-card-item>
|
||||
<v-card-item class="py-4 px-6">
|
||||
<div class="d-sm-flex align-center justify-space-between">
|
||||
<v-card-title class="text-h5 mb-0">{{ title }}</v-card-title>
|
||||
<slot name="action"></slot>
|
||||
<!-- </template> -->
|
||||
</div>
|
||||
</v-card-item>
|
||||
<v-divider></v-divider>
|
||||
<v-card-text>
|
||||
<slot />
|
||||
</v-card-text>
|
||||
|
||||
Generated
+34
@@ -19,6 +19,7 @@
|
||||
"axios-mock-adapter": "^2.1.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"pinia": "^3.0.3",
|
||||
"pinia-plugin-persistedstate": "^4.4.1",
|
||||
"sass": "1.70.0",
|
||||
"sass-loader": "^16.0.5",
|
||||
"typescript": "^5.8.3",
|
||||
@@ -4993,6 +4994,12 @@
|
||||
"callsite": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/deep-pick-omit": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/deep-pick-omit/-/deep-pick-omit-1.2.1.tgz",
|
||||
"integrity": "sha512-2J6Kc/m3irCeqVG42T+SaUMesaK7oGWaedGnQQK/+O0gYc+2SP5bKh/KKTE7d7SJ+GCA9UUE1GRzh6oDe0EnGw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/deepmerge": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||
@@ -8925,6 +8932,33 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/pinia-plugin-persistedstate": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-4.4.1.tgz",
|
||||
"integrity": "sha512-lmuMPpXla2zJKjxEq34e1E9P9jxkWEhcVwwioCCE0izG45kkTOvQfCzvwhW3i38cvnaWC7T1eRdkd15Re59ldw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"deep-pick-omit": "^1.2.1",
|
||||
"defu": "^6.1.4",
|
||||
"destr": "^2.0.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nuxt/kit": ">=3.0.0",
|
||||
"@pinia/nuxt": ">=0.10.0",
|
||||
"pinia": ">=3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@nuxt/kit": {
|
||||
"optional": true
|
||||
},
|
||||
"@pinia/nuxt": {
|
||||
"optional": true
|
||||
},
|
||||
"pinia": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/pinia/node_modules/@vue/devtools-api": {
|
||||
"version": "7.7.7",
|
||||
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.7.tgz",
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"axios-mock-adapter": "^2.1.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"pinia": "^3.0.3",
|
||||
"pinia-plugin-persistedstate": "^4.4.1",
|
||||
"sass": "1.70.0",
|
||||
"sass-loader": "^16.0.5",
|
||||
"typescript": "^5.8.3",
|
||||
|
||||
@@ -15,6 +15,7 @@ definePageMeta({
|
||||
});
|
||||
|
||||
const permissions = route.meta || []
|
||||
const permStore = aksesMenu.permissionPage || []
|
||||
</script>
|
||||
<template>
|
||||
<v-row>
|
||||
@@ -22,7 +23,7 @@ const permissions = route.meta || []
|
||||
<v-card elevation="10">
|
||||
<v-card-item>
|
||||
<h5 class="text-h5 mb-3">Sample Page {{ permissions }}</h5>
|
||||
<p class="text-body-1">This is a sample page</p>
|
||||
<p class="text-body-1">This is a sample page {{ permStore }}</p>
|
||||
</v-card-item>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
// common components
|
||||
import BaseBreadcrumb from '@/components/shared/BaseBreadcrumb.vue';
|
||||
import UiParentCard from '@/components/shared/UiParentCard.vue';
|
||||
import BaseBreadcrumb from '~/components/shared/BaseBreadcrumb.vue';
|
||||
import UiParentCard from '~/components/shared/UiParentCard.vue';
|
||||
|
||||
//Table
|
||||
import Table1 from '@/components/table/Table1.vue';
|
||||
import Table2 from '@/components/table/Table2.vue';
|
||||
import Table3 from '@/components/table/Table3.vue';
|
||||
import Table4 from '@/components/table/Table4.vue';
|
||||
import Table5 from '@/components/table/Table5.vue';
|
||||
import Table1 from '~/components/table/Table1.vue';
|
||||
import Table2 from '~/components/table/Table2.vue';
|
||||
import Table3 from '~/components/table/Table3.vue';
|
||||
import Table4 from '~/components/table/Table4.vue';
|
||||
import Table5 from '~/components/table/Table5.vue';
|
||||
|
||||
// template breadcrumb
|
||||
const page = ref({ title: 'Basic Table' });
|
||||
|
||||
@@ -172,6 +172,7 @@ initialize()
|
||||
|
||||
<template>
|
||||
<BaseBreadcrumb :title="page.title" :breadcrumbs="breadcrumbs"></BaseBreadcrumb>
|
||||
<!-- <SharedBaseBreadcrumb :title="page.title" :breadcrumbs="breadcrumbs"></SharedBaseBreadcrumb> -->
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<UiParentCard title="Crud Table">
|
||||
|
||||
+22
-20
@@ -1,23 +1,25 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { defineStore } from "pinia";
|
||||
// project imports
|
||||
import axios from '@/utils/axios';
|
||||
import axios from "@/utils/axios";
|
||||
|
||||
export const useContactStore = defineStore({
|
||||
id: 'Contact',
|
||||
state: () => ({
|
||||
contacts: []
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
// Fetch followers from action
|
||||
async fetchContacts() {
|
||||
try {
|
||||
const response = await axios.get('/api/contacts');
|
||||
this.contacts = response.data.contacts;
|
||||
} catch (error) {
|
||||
alert(error);
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
export const useContactStore = defineStore('Contact', {
|
||||
|
||||
state: () => ({
|
||||
contacts: [],
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
// Fetch followers from action
|
||||
async fetchContacts() {
|
||||
try {
|
||||
const response = await axios.get("/api/contacts");
|
||||
this.contacts = response.data.contacts;
|
||||
} catch (error) {
|
||||
alert(error);
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
|
||||
+22
-2
@@ -74,9 +74,29 @@ const rolePages = [
|
||||
permissions: ["create", "view", "update"],
|
||||
},
|
||||
{
|
||||
title: "Sample Editable Table",
|
||||
title: "CRUD Table",
|
||||
path: "/tables/datatables/crudtable",
|
||||
permissions: ["view"],
|
||||
},
|
||||
{
|
||||
title: "Basic Table",
|
||||
path: "/tables/datatables/BasicTable",
|
||||
permissions: ["view"],
|
||||
},
|
||||
{
|
||||
title: "Basic Table",
|
||||
permissions: ["view"],
|
||||
path: "/tables/TableBasic",
|
||||
},
|
||||
{
|
||||
title: "Editable Table",
|
||||
permissions: ["view"],
|
||||
path: "/tables/TableEditable",
|
||||
permissions: ["create", "view", "update"],
|
||||
},
|
||||
{
|
||||
title: "Height Table",
|
||||
permissions: ["view"],
|
||||
path: "/tables/tableheight",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1,65 +1,66 @@
|
||||
|
||||
import type { SidebarItem } from '~/types/menuAkses/sidebar'
|
||||
import type { PageAccess } from '~/types/menuAkses/access'
|
||||
import type { SidebarItem } from "~/types/menuAkses/sidebar";
|
||||
import type { PageAccess } from "~/types/menuAkses/access";
|
||||
interface SidebarItemWithPermissions extends SidebarItem {
|
||||
permissions: string[];
|
||||
}
|
||||
|
||||
export function mergeSidebar(menuItems: SidebarItem[], allowedPages: PageAccess[]): SidebarItem[] {
|
||||
const result: SidebarItem[] = []
|
||||
export function mergeSidebar(
|
||||
menuItems: SidebarItem[],
|
||||
allowedPages: PageAccess[]
|
||||
): SidebarItem[] {
|
||||
const result: SidebarItem[] = [];
|
||||
|
||||
for (const item of menuItems) {
|
||||
// Jika punya anak (children)
|
||||
//console.log('item', item);
|
||||
//console.log('allowedPages', allowedPages);
|
||||
if (Array.isArray(item.children)) {
|
||||
const filteredChildren = mergeSidebar(item.children, allowedPages)
|
||||
const filteredChildren = mergeSidebar(item.children, allowedPages);
|
||||
// console.log('ada array item', item);
|
||||
|
||||
//console.log('filteredChildren', filteredChildren);
|
||||
|
||||
//console.log('filteredChildren', filteredChildren);
|
||||
if (filteredChildren.length > 0) {
|
||||
result.push({
|
||||
...item,
|
||||
children: filteredChildren
|
||||
})
|
||||
children: filteredChildren,
|
||||
});
|
||||
}
|
||||
//console.log('result', result);
|
||||
}
|
||||
|
||||
// Jika punya path, cocokkan dengan json dummy / backend
|
||||
else if (item.to) {
|
||||
const matchPage = allowedPages.find(page => page.title === item.title && page.path === item.to) //cocokkan title dan path link path halaman
|
||||
const matchPage = allowedPages.find(
|
||||
(page) =>
|
||||
page.title?.toLowerCase() === item.title?.toLowerCase() &&
|
||||
page.path?.toLowerCase() === item.to?.toLowerCase()
|
||||
); //cocokkan title dan path link path halaman
|
||||
|
||||
//console.log('match', matchPage,matchPage?.permissions);
|
||||
if (matchPage && matchPage.permissions?.includes('view')) {
|
||||
if (matchPage && matchPage.permissions?.includes("view")) {
|
||||
result.push({
|
||||
...item,
|
||||
permissions: matchPage?.permissions,
|
||||
|
||||
} as SidebarItemWithPermissions)
|
||||
} as SidebarItemWithPermissions);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
return result;
|
||||
}
|
||||
|
||||
export function mergeSidebarIcon(staticIcon: any[], IconAccess: any[]) {
|
||||
const result : any[] = []
|
||||
const result: any[] = [];
|
||||
|
||||
for (const item of staticIcon) {
|
||||
const matchIcon = IconAccess.find(icon => icon.id === item.id)
|
||||
const matchIcon = IconAccess.find((icon) => icon.id === item.id);
|
||||
//console.log('matchIcon', matchIcon);
|
||||
if (matchIcon) {
|
||||
result.push({
|
||||
...item,
|
||||
|
||||
})
|
||||
...item,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user