upgade package
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import {useEffect} from 'react'
|
||||
import {useLocation} from 'react-router'
|
||||
import clsx from 'clsx'
|
||||
import {useLayout} from '../../core'
|
||||
import {DrawerComponent} from '../../../assets/ts/components'
|
||||
import {WithChildren} from '../../../helpers'
|
||||
|
||||
const Content = ({children}: WithChildren) => {
|
||||
const {config, classes} = useLayout()
|
||||
const location = useLocation()
|
||||
useEffect(() => {
|
||||
DrawerComponent.hideAll()
|
||||
}, [location])
|
||||
|
||||
const appContentContainer = config.app?.content?.container
|
||||
return (
|
||||
<div
|
||||
id='kt_app_content'
|
||||
className={clsx(
|
||||
'app-content flex-column-fluid',
|
||||
classes.content.join(' '),
|
||||
config?.app?.content?.class
|
||||
)}
|
||||
>
|
||||
{appContentContainer ? (
|
||||
<div
|
||||
id='kt_app_content_container'
|
||||
className={clsx('app-container', classes.contentContainer.join(' '), {
|
||||
'container-xxl': appContentContainer === 'fixed',
|
||||
'container-fluid': appContentContainer === 'fluid',
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
) : (
|
||||
<>{children}</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export {Content}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './Content'
|
||||
@@ -0,0 +1,61 @@
|
||||
import {useEffect} from 'react'
|
||||
import {ILayout, useLayout} from '../../core'
|
||||
|
||||
const Footer = () => {
|
||||
const {config} = useLayout()
|
||||
useEffect(() => {
|
||||
updateDOM(config)
|
||||
}, [config])
|
||||
return (
|
||||
<>
|
||||
<div className='text-gray-900 order-2 order-md-1'>
|
||||
<span className='text-muted fw-semibold me-1'>
|
||||
{new Date().getFullYear().toString()}©
|
||||
</span>
|
||||
<a
|
||||
href='https://keenthemes.com/'
|
||||
target='_blank'
|
||||
className='text-gray-800 text-hover-primary'
|
||||
>
|
||||
Keenthemes
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<ul className='menu menu-gray-600 menu-hover-primary fw-semibold order-1'>
|
||||
<li className='menu-item'>
|
||||
<a href='https://keenthemes.com/' target='_blank' className='menu-link px-2'>
|
||||
About
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className='menu-item'>
|
||||
<a href='https://devs.keenthemes.com/' target='_blank' className='menu-link px-2'>
|
||||
Support
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className='menu-item'>
|
||||
<a
|
||||
href='https://themeforest.net/item/metronic-responsive-admin-dashboard-template/4021469'
|
||||
target='_blank'
|
||||
className='menu-link px-2'
|
||||
>
|
||||
Purchase
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const updateDOM = (config: ILayout) => {
|
||||
if (config.app?.footer?.fixed?.desktop) {
|
||||
document.body.classList.add('data-kt-app-footer-fixed', 'true')
|
||||
}
|
||||
|
||||
if (config.app?.footer?.fixed?.mobile) {
|
||||
document.body.classList.add('data-kt-app-footer-fixed-mobile', 'true')
|
||||
}
|
||||
}
|
||||
|
||||
export {Footer}
|
||||
@@ -0,0 +1,30 @@
|
||||
import clsx from 'clsx'
|
||||
import {useLayout} from '../../core'
|
||||
import {Footer} from './Footer'
|
||||
|
||||
const FooterWrapper = () => {
|
||||
const {config} = useLayout()
|
||||
if (!config.app?.footer?.display) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='app-footer' id='kt_app_footer'>
|
||||
{config.app.footer.containerClass ? (
|
||||
<div
|
||||
className={clsx(
|
||||
'app-container',
|
||||
config.app.footer.container === 'fixed' ? 'container-xxl' : 'container-fluid',
|
||||
config.app.footer.containerClass
|
||||
)}
|
||||
>
|
||||
<Footer />
|
||||
</div>
|
||||
) : (
|
||||
<Footer />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export {FooterWrapper}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './FooterWrapper'
|
||||
@@ -0,0 +1,92 @@
|
||||
/* eslint-disable no-prototype-builtins */
|
||||
import {FC, useEffect} from 'react'
|
||||
import {ILayout, useLayout} from '../../core'
|
||||
import {MenuInner} from './header-menus'
|
||||
|
||||
const Header: FC = () => {
|
||||
const {config} = useLayout()
|
||||
useEffect(() => {
|
||||
updateDOM(config)
|
||||
}, [config])
|
||||
|
||||
return (
|
||||
<div
|
||||
className='
|
||||
menu
|
||||
menu-rounded
|
||||
menu-column
|
||||
menu-lg-row
|
||||
my-5
|
||||
my-lg-0
|
||||
align-items-stretch
|
||||
fw-semibold
|
||||
px-2 px-lg-0
|
||||
'
|
||||
id='kt_app_header_menu'
|
||||
data-kt-menu='true'
|
||||
>
|
||||
<MenuInner />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const updateDOM = (config: ILayout) => {
|
||||
if (config.app?.header?.default?.fixed?.desktop) {
|
||||
document.body.setAttribute('data-kt-app-header-fixed', 'true')
|
||||
|
||||
document.body.setAttribute('data-kt-app-header-minimize', 'on')
|
||||
}
|
||||
|
||||
if (config.app?.header?.default?.fixed?.mobile) {
|
||||
document.body.setAttribute('data-kt-app-header-fixed-mobile', 'true')
|
||||
}
|
||||
|
||||
if (config.app?.header?.default?.stacked) {
|
||||
document.body.setAttribute('data-kt-app-header-stacked', 'true')
|
||||
}
|
||||
|
||||
const appHeaderDefaultStickyEnabled = config.app?.header?.default?.sticky?.enabled
|
||||
let appHeaderDefaultStickyAttributes: {[attrName: string]: string} = {}
|
||||
if (appHeaderDefaultStickyEnabled) {
|
||||
appHeaderDefaultStickyAttributes = config.app?.header?.default?.sticky?.attributes as {
|
||||
[attrName: string]: string
|
||||
}
|
||||
}
|
||||
|
||||
const appHeaderDefaultMinimizeEnabled = config.app?.header?.default?.minimize?.enabled
|
||||
let appHeaderDefaultMinimizeAttributes: {[attrName: string]: string} = {}
|
||||
if (appHeaderDefaultMinimizeEnabled) {
|
||||
appHeaderDefaultMinimizeAttributes = config.app?.header?.default?.minimize?.attributes as {
|
||||
[attrName: string]: string
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
const headerElement = document.getElementById('kt_app_header')
|
||||
// header
|
||||
if (headerElement) {
|
||||
const headerAttributes = headerElement
|
||||
.getAttributeNames()
|
||||
.filter((t) => t.indexOf('data-') > -1)
|
||||
headerAttributes.forEach((attr) => headerElement.removeAttribute(attr))
|
||||
|
||||
if (appHeaderDefaultStickyEnabled) {
|
||||
for (const key in appHeaderDefaultStickyAttributes) {
|
||||
if (appHeaderDefaultStickyAttributes.hasOwnProperty(key)) {
|
||||
headerElement.setAttribute(key, appHeaderDefaultStickyAttributes[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (appHeaderDefaultMinimizeEnabled) {
|
||||
for (const key in appHeaderDefaultMinimizeAttributes) {
|
||||
if (appHeaderDefaultMinimizeAttributes.hasOwnProperty(key)) {
|
||||
headerElement.setAttribute(key, appHeaderDefaultMinimizeAttributes[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 0)
|
||||
}
|
||||
|
||||
export {Header}
|
||||
@@ -0,0 +1,111 @@
|
||||
|
||||
import clsx from 'clsx'
|
||||
import {Link} from 'react-router-dom'
|
||||
import {KTIcon, toAbsoluteUrl} from '../../../helpers'
|
||||
import {LayoutSetup, useLayout} from '../../core'
|
||||
import {Header} from './Header'
|
||||
import {Navbar} from './Navbar'
|
||||
|
||||
export function HeaderWrapper() {
|
||||
const {config, classes} = useLayout()
|
||||
if (config.app?.header?.default?.container === 'fluid') {
|
||||
LayoutSetup.classes.headerContainer.push("container-fluid");
|
||||
} else {
|
||||
LayoutSetup.classes.headerContainer.push("container-xxl");
|
||||
}
|
||||
if (!config.app?.header?.display) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div id='kt_app_header' className='app-header'>
|
||||
<div
|
||||
id='kt_app_header_container'
|
||||
className={clsx(
|
||||
'app-container',
|
||||
classes.headerContainer.join(' '),
|
||||
config.app?.header?.default?.containerClass
|
||||
)}
|
||||
>
|
||||
{config.app.sidebar?.display && (
|
||||
<>
|
||||
{config.layoutType !== 'dark-header' && config.layoutType !== 'light-header' ? (
|
||||
<div
|
||||
className='d-flex align-items-center d-lg-none ms-n2 me-2'
|
||||
title='Show sidebar menu'
|
||||
>
|
||||
<div
|
||||
className='btn btn-icon btn-active-color-primary w-35px h-35px'
|
||||
id='kt_app_sidebar_mobile_toggle'
|
||||
>
|
||||
<KTIcon iconName='abstract-14' className=' fs-1' />
|
||||
</div>
|
||||
<div className='d-flex align-items-center flex-grow-1 flex-lg-grow-0'>
|
||||
<Link to='/dashboard' className='d-lg-none'>
|
||||
<img
|
||||
alt='Logo'
|
||||
src={toAbsoluteUrl('media/logos/default-small.svg')}
|
||||
className='h-30px'
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
|
||||
{!(config.layoutType === 'dark-sidebar' || config.layoutType === 'light-sidebar') && (
|
||||
<div className='d-flex align-items-center flex-grow-1 flex-lg-grow-0 me-lg-15'>
|
||||
<Link to='/dashboard'>
|
||||
{config.layoutType === 'dark-header' ? (
|
||||
<img
|
||||
alt='Logo'
|
||||
src={toAbsoluteUrl('media/logos/sidelogo.png')}
|
||||
className='h-20px h-lg-30px app-sidebar-logo-default'
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<img
|
||||
alt='Logo'
|
||||
src={toAbsoluteUrl('media/logos/sidelogo.png')}
|
||||
className='h-20px h-lg-30px app-sidebar-logo-default theme-light-show'
|
||||
/>
|
||||
<img
|
||||
alt='Logo'
|
||||
src={toAbsoluteUrl('media/logos/sidelogo.png')}
|
||||
className='h-20px h-lg-30px app-sidebar-logo-default theme-dark-show'
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
id='kt_app_header_wrapper'
|
||||
className='d-flex align-items-stretch justify-content-between flex-lg-grow-1'
|
||||
>
|
||||
{config.app.header.default?.content === 'menu' &&
|
||||
config.app.header.default.menu?.display && (
|
||||
<div
|
||||
className='app-header-menu app-header-mobile-drawer align-items-stretch'
|
||||
data-kt-drawer='true'
|
||||
data-kt-drawer-name='app-header-menu'
|
||||
data-kt-drawer-activate='{default: true, lg: false}'
|
||||
data-kt-drawer-overlay='true'
|
||||
data-kt-drawer-width='225px'
|
||||
data-kt-drawer-direction='end'
|
||||
data-kt-drawer-toggle='#kt_app_header_menu_toggle'
|
||||
data-kt-swapper='true'
|
||||
data-kt-swapper-mode="{default: 'append', lg: 'prepend'}"
|
||||
data-kt-swapper-parent="{default: '#kt_app_body', lg: '#kt_app_header_wrapper'}"
|
||||
>
|
||||
<Header />
|
||||
</div>
|
||||
)}
|
||||
<Navbar />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import clsx from 'clsx'
|
||||
import {KTIcon, toAbsoluteUrl} from '../../../helpers'
|
||||
import {HeaderNotificationsMenu, HeaderUserMenu, Search, ThemeModeSwitcher} from '../../../partials'
|
||||
import {useLayout} from '../../core'
|
||||
|
||||
const itemClass = 'ms-1 ms-md-4'
|
||||
const btnClass =
|
||||
'btn btn-icon btn-custom btn-icon-muted btn-active-light btn-active-color-primary w-35px h-35px'
|
||||
const userAvatarClass = 'symbol-35px'
|
||||
const btnIconClass = 'fs-2'
|
||||
|
||||
const Navbar = () => {
|
||||
const {config} = useLayout()
|
||||
return (
|
||||
<div className='app-navbar flex-shrink-0'>
|
||||
<div className={clsx('app-navbar-item align-items-stretch', itemClass)}>
|
||||
<Search />
|
||||
</div>
|
||||
|
||||
<div className={clsx('app-navbar-item', itemClass)}>
|
||||
<div id='kt_activities_toggle' className={btnClass}>
|
||||
<KTIcon iconName='chart-simple' className={btnIconClass} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={clsx('app-navbar-item', itemClass)}>
|
||||
<div
|
||||
data-kt-menu-trigger="{default: 'click'}"
|
||||
data-kt-menu-attach='parent'
|
||||
data-kt-menu-placement='bottom-end'
|
||||
className={btnClass}
|
||||
>
|
||||
<KTIcon iconName='element-plus' className={btnIconClass} />
|
||||
</div>
|
||||
<HeaderNotificationsMenu />
|
||||
</div>
|
||||
|
||||
<div className={clsx('app-navbar-item', itemClass)}>
|
||||
<div className={clsx('position-relative', btnClass)} id='kt_drawer_chat_toggle'>
|
||||
<KTIcon iconName='message-text-2' className={btnIconClass} />
|
||||
<span className='bullet bullet-dot bg-success h-6px w-6px position-absolute translate-middle top-0 start-50 animation-blink' />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={clsx('app-navbar-item', itemClass)}>
|
||||
<ThemeModeSwitcher toggleBtnClass={clsx('btn-active-light-primary btn-custom')} />
|
||||
</div>
|
||||
|
||||
<div className={clsx('app-navbar-item', itemClass)}>
|
||||
<div
|
||||
className={clsx('cursor-pointer symbol', userAvatarClass)}
|
||||
data-kt-menu-trigger="{default: 'click'}"
|
||||
data-kt-menu-attach='parent'
|
||||
data-kt-menu-placement='bottom-end'
|
||||
>
|
||||
<img src={toAbsoluteUrl('media/avatars/300-3.jpg')} alt='' />
|
||||
</div>
|
||||
<HeaderUserMenu />
|
||||
</div>
|
||||
|
||||
{config.app?.header?.default?.menu?.display && (
|
||||
<div className='app-navbar-item d-lg-none ms-2 me-n3' title='Show header menu'>
|
||||
<div
|
||||
className='btn btn-icon btn-active-color-primary w-35px h-35px'
|
||||
id='kt_app_header_menu_toggle'
|
||||
>
|
||||
<KTIcon iconName='text-align-left' className={btnIconClass} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export {Navbar}
|
||||
@@ -0,0 +1,162 @@
|
||||
|
||||
import {FC} from 'react'
|
||||
import {Link} from 'react-router-dom'
|
||||
import {toAbsoluteUrl} from '../../../../helpers'
|
||||
import {useLayout} from '../../../core'
|
||||
|
||||
const MegaMenu: FC = () => {
|
||||
const {setLayoutType, setToolbarType} = useLayout()
|
||||
return (
|
||||
<div className='row'>
|
||||
{/* begin:Col */}
|
||||
<div className='col-lg-6'>
|
||||
{/* begin:Row */}
|
||||
<div className='row'>
|
||||
{/* begin:Col */}
|
||||
<div className='col-lg-6 mb-3'>
|
||||
{/* begin:Heading */}
|
||||
<h4 className='fs-6 fs-lg-4 text-gray-800 fw-bold mt-3 mb-3 ms-4'>Layouts</h4>
|
||||
{/* end:Heading */}
|
||||
{/* begin:Menu item */}
|
||||
<div className='menu-item p-0 m-0'>
|
||||
{/* begin:Menu link */}
|
||||
<a onClick={() => setLayoutType('light-sidebar')} className='menu-link'>
|
||||
<span className='menu-bullet'>
|
||||
<span className='bullet bullet-dot bg-gray-300i h-6px w-6px'></span>
|
||||
</span>
|
||||
<span className='menu-title'>Light Sidebar</span>
|
||||
</a>
|
||||
{/* end:Menu link */}
|
||||
</div>
|
||||
{/* end:Menu item */}
|
||||
{/* begin:Menu item */}
|
||||
<div className='menu-item p-0 m-0'>
|
||||
{/* begin:Menu link */}
|
||||
<a onClick={() => setLayoutType('dark-sidebar')} className='menu-link'>
|
||||
<span className='menu-bullet'>
|
||||
<span className='bullet bullet-dot bg-gray-300i h-6px w-6px'></span>
|
||||
</span>
|
||||
<span className='menu-title'>Dark Sidebar</span>
|
||||
</a>
|
||||
{/* end:Menu link */}
|
||||
</div>
|
||||
{/* end:Menu item */}
|
||||
{/* begin:Menu item */}
|
||||
<div className='menu-item p-0 m-0'>
|
||||
{/* begin:Menu link */}
|
||||
<a onClick={() => setLayoutType('light-header')} className='menu-link'>
|
||||
<span className='menu-bullet'>
|
||||
<span className='bullet bullet-dot bg-gray-300i h-6px w-6px'></span>
|
||||
</span>
|
||||
<span className='menu-title'>Light Header</span>
|
||||
</a>
|
||||
{/* end:Menu link */}
|
||||
</div>
|
||||
{/* end:Menu item */}
|
||||
{/* begin:Menu item */}
|
||||
<div className='menu-item p-0 m-0'>
|
||||
{/* begin:Menu link */}
|
||||
<a onClick={() => setLayoutType('dark-header')} className='menu-link'>
|
||||
<span className='menu-bullet'>
|
||||
<span className='bullet bullet-dot bg-gray-300i h-6px w-6px'></span>
|
||||
</span>
|
||||
<span className='menu-title'>Dark Header</span>
|
||||
</a>
|
||||
{/* end:Menu link */}
|
||||
</div>
|
||||
{/* end:Menu item */}
|
||||
</div>
|
||||
{/* end:Col */}
|
||||
{/* begin:Col */}
|
||||
<div className='col-lg-6 mb-3'>
|
||||
{/* begin:Heading */}
|
||||
<h4 className='fs-6 fs-lg-4 text-gray-800 fw-bold mt-3 mb-3 ms-4'>Toolbars</h4>
|
||||
{/* end:Heading */}
|
||||
{/* begin:Menu item */}
|
||||
<div className='menu-item p-0 m-0'>
|
||||
{/* begin:Menu link */}
|
||||
<a onClick={() => setToolbarType('classic')} className='menu-link'>
|
||||
<span className='menu-bullet'>
|
||||
<span className='bullet bullet-dot bg-gray-300i h-6px w-6px'></span>
|
||||
</span>
|
||||
<span className='menu-title'>Classic</span>
|
||||
</a>
|
||||
{/* end:Menu link */}
|
||||
</div>
|
||||
{/* end:Menu item */}
|
||||
{/* begin:Menu item */}
|
||||
<div className='menu-item p-0 m-0'>
|
||||
{/* begin:Menu link */}
|
||||
<a onClick={() => setToolbarType('saas')} className='menu-link'>
|
||||
<span className='menu-bullet'>
|
||||
<span className='bullet bullet-dot bg-gray-300i h-6px w-6px'></span>
|
||||
</span>
|
||||
<span className='menu-title'>SaaS</span>
|
||||
</a>
|
||||
{/* end:Menu link */}
|
||||
</div>
|
||||
{/* end:Menu item */}
|
||||
{/* begin:Menu item */}
|
||||
<div className='menu-item p-0 m-0'>
|
||||
{/* begin:Menu link */}
|
||||
<a onClick={() => setToolbarType('accounting')} className='menu-link'>
|
||||
<span className='menu-bullet'>
|
||||
<span className='bullet bullet-dot bg-gray-300i h-6px w-6px'></span>
|
||||
</span>
|
||||
<span className='menu-title'>Accounting</span>
|
||||
</a>
|
||||
{/* end:Menu link */}
|
||||
</div>
|
||||
{/* end:Menu item */}
|
||||
{/* begin:Menu item */}
|
||||
<div className='menu-item p-0 m-0'>
|
||||
{/* begin:Menu link */}
|
||||
<a onClick={() => setToolbarType('extended')} className='menu-link'>
|
||||
<span className='menu-bullet'>
|
||||
<span className='bullet bullet-dot bg-gray-300i h-6px w-6px'></span>
|
||||
</span>
|
||||
<span className='menu-title'>Extended</span>
|
||||
</a>
|
||||
{/* end:Menu link */}
|
||||
</div>
|
||||
{/* end:Menu item */}
|
||||
{/* begin:Menu item */}
|
||||
<div className='menu-item p-0 m-0'>
|
||||
{/* begin:Menu link */}
|
||||
<a onClick={() => setToolbarType('reports')} className='menu-link'>
|
||||
<span className='menu-bullet'>
|
||||
<span className='bullet bullet-dot bg-gray-300i h-6px w-6px'></span>
|
||||
</span>
|
||||
<span className='menu-title'>Reports</span>
|
||||
</a>
|
||||
{/* end:Menu link */}
|
||||
</div>
|
||||
{/* end:Menu item */}
|
||||
</div>
|
||||
{/* end:Col */}
|
||||
</div>
|
||||
{/* end:Row */}
|
||||
<div className='separator separator-dashed mx-lg-5 mt-2 mb-6'></div>
|
||||
{/* begin:Layout Builder */}
|
||||
<div className='d-flex flex-stack flex-wrap flex-lg-nowrap gap-2 mb-5 mb-lg-0 mx-lg-5'>
|
||||
<div className='d-flex flex-column me-5'>
|
||||
<div className='fs-6 fw-bold text-gray-800'>Layout Builder</div>
|
||||
<div className='fs-7 fw-semibold text-muted'>Customize view</div>
|
||||
</div>
|
||||
<Link to='/builder' className='btn btn-sm btn-primary fw-bold'>
|
||||
Try Builder
|
||||
</Link>
|
||||
</div>
|
||||
{/* end:Layout Builder */}
|
||||
</div>
|
||||
{/* end:Col */}
|
||||
{/* begin:Col */}
|
||||
<div className='col-lg-6 mb-3 py-lg-3 pe-lg-8 d-flex align-items-center'>
|
||||
<img src={toAbsoluteUrl('media/stock/900x600/45.jpg')} className='rounded mw-100' alt='' />
|
||||
</div>
|
||||
{/* end:Col */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export {MegaMenu}
|
||||
@@ -0,0 +1,130 @@
|
||||
import {useIntl} from 'react-intl'
|
||||
import {MenuItem} from './MenuItem'
|
||||
import {MenuInnerWithSub} from './MenuInnerWithSub'
|
||||
import {MegaMenu} from './MegaMenu'
|
||||
|
||||
export function MenuInner() {
|
||||
const intl = useIntl()
|
||||
return (
|
||||
<>
|
||||
<MenuItem title={intl.formatMessage({id: 'MENU.DASHBOARD'})} to='/dashboard' />
|
||||
<MenuItem title='Layout Builder' to='/builder' />
|
||||
<MenuInnerWithSub
|
||||
title='Crafted'
|
||||
to='/crafted'
|
||||
menuPlacement='bottom-start'
|
||||
menuTrigger='click'
|
||||
>
|
||||
{/* PAGES */}
|
||||
<MenuInnerWithSub
|
||||
title='Pages'
|
||||
to='/crafted/pages'
|
||||
fontIcon='bi-archive'
|
||||
hasArrow={true}
|
||||
menuPlacement='right-start'
|
||||
menuTrigger={`{default:'click', lg: 'hover'}`}
|
||||
>
|
||||
<MenuInnerWithSub
|
||||
title='Profile'
|
||||
to='/crafted/pages/profile'
|
||||
hasArrow={true}
|
||||
hasBullet={true}
|
||||
menuPlacement='right-start'
|
||||
menuTrigger={`{default:'click', lg: 'hover'}`}
|
||||
>
|
||||
<MenuItem to='/crafted/pages/profile/overview' title='Overview' hasBullet={true} />
|
||||
<MenuItem to='/crafted/pages/profile/projects' title='Projects' hasBullet={true} />
|
||||
<MenuItem to='/crafted/pages/profile/campaigns' title='Campaigns' hasBullet={true} />
|
||||
<MenuItem to='/crafted/pages/profile/documents' title='Documents' hasBullet={true} />
|
||||
<MenuItem
|
||||
to='/crafted/pages/profile/connections'
|
||||
title='Connections'
|
||||
hasBullet={true}
|
||||
/>
|
||||
</MenuInnerWithSub>
|
||||
<MenuInnerWithSub
|
||||
title='Wizards'
|
||||
to='/crafted/pages/wizards'
|
||||
hasArrow={true}
|
||||
hasBullet={true}
|
||||
menuPlacement='right-start'
|
||||
menuTrigger={`{default:'click', lg: 'hover'}`}
|
||||
>
|
||||
<MenuItem to='/crafted/pages/wizards/horizontal' title='Horizontal' hasBullet={true} />
|
||||
<MenuItem to='/crafted/pages/wizards/vertical' title='Vertical' hasBullet={true} />
|
||||
</MenuInnerWithSub>
|
||||
</MenuInnerWithSub>
|
||||
|
||||
{/* ACCOUNT */}
|
||||
<MenuInnerWithSub
|
||||
title='Accounts'
|
||||
to='/crafted/accounts'
|
||||
fontIcon='bi-person'
|
||||
hasArrow={true}
|
||||
menuPlacement='right-start'
|
||||
menuTrigger={`{default:'click', lg: 'hover'}`}
|
||||
>
|
||||
<MenuItem to='/crafted/account/overview' title='Overview' hasBullet={true} />
|
||||
<MenuItem to='/crafted/account/settings' title='Settings' hasBullet={true} />
|
||||
</MenuInnerWithSub>
|
||||
|
||||
{/* ERRORS */}
|
||||
<MenuInnerWithSub
|
||||
title='Errors'
|
||||
to='/error'
|
||||
fontIcon='bi-sticky'
|
||||
hasArrow={true}
|
||||
menuPlacement='right-start'
|
||||
menuTrigger={`{default:'click', lg: 'hover'}`}
|
||||
>
|
||||
<MenuItem to='/error/404' title='Error 404' hasBullet={true} />
|
||||
<MenuItem to='/error/500' title='Error 500' hasBullet={true} />
|
||||
</MenuInnerWithSub>
|
||||
|
||||
{/* Widgets */}
|
||||
<MenuInnerWithSub
|
||||
title='Widgets'
|
||||
to='/crafted/widgets'
|
||||
fontIcon='bi-layers'
|
||||
hasArrow={true}
|
||||
menuPlacement='right-start'
|
||||
menuTrigger={`{default:'click', lg: 'hover'}`}
|
||||
>
|
||||
<MenuItem to='/crafted/widgets/lists' title='Lists' hasBullet={true} />
|
||||
<MenuItem to='/crafted/widgets/statistics' title='Statistics' hasBullet={true} />
|
||||
<MenuItem to='/crafted/widgets/charts' title='Charts' hasBullet={true} />
|
||||
<MenuItem to='/crafted/widgets/mixed' title='Mixed' hasBullet={true} />
|
||||
<MenuItem to='/crafted/widgets/tables' title='Tables' hasBullet={true} />
|
||||
<MenuItem to='/crafted/widgets/feeds' title='Feeds' hasBullet={true} />
|
||||
</MenuInnerWithSub>
|
||||
</MenuInnerWithSub>
|
||||
|
||||
<MenuInnerWithSub title='Apps' to='/apps' menuPlacement='bottom-start' menuTrigger='click'>
|
||||
{/* PAGES */}
|
||||
<MenuInnerWithSub
|
||||
title='Chat'
|
||||
to='/apps/chat'
|
||||
icon='message-text-2'
|
||||
hasArrow={true}
|
||||
menuPlacement='right-start'
|
||||
menuTrigger={`{default:'click', lg: 'hover'}`}
|
||||
>
|
||||
<MenuItem to='/apps/chat/private-chat' title='Private Chat' hasBullet={true} />
|
||||
<MenuItem to='/apps/chat/group-chat' title='Group Chart' hasBullet={true} />
|
||||
<MenuItem to='/apps/chat/drawer-chat' title='Drawer Chart' hasBullet={true} />
|
||||
</MenuInnerWithSub>
|
||||
<MenuItem icon='abstract-28' to='/apps/user-management/users' title='User management' />
|
||||
</MenuInnerWithSub>
|
||||
|
||||
<MenuInnerWithSub
|
||||
isMega={true}
|
||||
title='Layouts'
|
||||
to='/mega-menu'
|
||||
menuPlacement='bottom-start'
|
||||
menuTrigger='click'
|
||||
>
|
||||
<MegaMenu />
|
||||
</MenuInnerWithSub>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
import {FC, useEffect, useRef} from 'react'
|
||||
import {useLocation} from 'react-router'
|
||||
import clsx from 'clsx'
|
||||
import {checkIsActive, KTIcon, WithChildren} from '../../../../helpers'
|
||||
|
||||
type Props = {
|
||||
to: string
|
||||
title: string
|
||||
icon?: string
|
||||
fontIcon?: string
|
||||
menuTrigger?: 'click' | `{default:'click', lg: 'hover'}`
|
||||
menuPlacement?: 'right-start' | 'bottom-start' | 'left-start'
|
||||
hasArrow?: boolean
|
||||
hasBullet?: boolean
|
||||
isMega?: boolean
|
||||
}
|
||||
|
||||
const MenuInnerWithSub: FC<Props & WithChildren> = ({
|
||||
children,
|
||||
to,
|
||||
title,
|
||||
icon,
|
||||
fontIcon,
|
||||
menuTrigger,
|
||||
menuPlacement,
|
||||
hasArrow = false,
|
||||
hasBullet = false,
|
||||
isMega = false,
|
||||
}) => {
|
||||
const menuItemRef = useRef<HTMLDivElement>(null)
|
||||
const {pathname} = useLocation()
|
||||
|
||||
useEffect(() => {
|
||||
if (menuItemRef.current && menuTrigger && menuPlacement) {
|
||||
menuItemRef.current.setAttribute('data-kt-menu-trigger', menuTrigger)
|
||||
menuItemRef.current.setAttribute('data-kt-menu-placement', menuPlacement)
|
||||
}
|
||||
}, [menuTrigger, menuPlacement])
|
||||
|
||||
return (
|
||||
<div ref={menuItemRef} className='menu-item menu-lg-down-accordion me-lg-1'>
|
||||
<span
|
||||
className={clsx('menu-link py-3', {
|
||||
active: checkIsActive(pathname, to),
|
||||
})}
|
||||
>
|
||||
{hasBullet && (
|
||||
<span className='menu-bullet'>
|
||||
<span className='bullet bullet-dot'></span>
|
||||
</span>
|
||||
)}
|
||||
|
||||
{icon && (
|
||||
<span className='menu-icon'>
|
||||
<KTIcon iconName={icon} className='fs-2' />
|
||||
</span>
|
||||
)}
|
||||
|
||||
{fontIcon && (
|
||||
<span className='menu-icon'>
|
||||
<i className={clsx('bi fs-3', fontIcon)}></i>
|
||||
</span>
|
||||
)}
|
||||
|
||||
<span className='menu-title'>{title}</span>
|
||||
|
||||
{hasArrow && <span className='menu-arrow'></span>}
|
||||
</span>
|
||||
<div
|
||||
className={clsx(
|
||||
'menu-sub menu-sub-lg-down-accordion menu-sub-lg-dropdown',
|
||||
isMega ? 'w-100 w-lg-850px p-5 p-lg-5' : 'menu-rounded-0 py-lg-4 w-lg-225px'
|
||||
)}
|
||||
data-kt-menu-dismiss='true'
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export {MenuInnerWithSub}
|
||||
@@ -0,0 +1,53 @@
|
||||
import {FC} from 'react'
|
||||
import {useLocation} from 'react-router'
|
||||
import {Link} from 'react-router-dom'
|
||||
import clsx from 'clsx'
|
||||
import {checkIsActive, KTIcon} from '../../../../helpers'
|
||||
|
||||
type Props = {
|
||||
to: string
|
||||
title: string
|
||||
icon?: string
|
||||
fontIcon?: string
|
||||
hasArrow?: boolean
|
||||
hasBullet?: boolean
|
||||
}
|
||||
|
||||
const MenuItem: FC<Props> = ({to, title, icon, fontIcon, hasArrow = false, hasBullet = false}) => {
|
||||
const {pathname} = useLocation()
|
||||
|
||||
return (
|
||||
<div className='menu-item me-lg-1'>
|
||||
<Link
|
||||
className={clsx('menu-link py-3', {
|
||||
'active menu-here': checkIsActive(pathname, to),
|
||||
})}
|
||||
to={to}
|
||||
>
|
||||
{hasBullet && (
|
||||
<span className='menu-bullet'>
|
||||
<span className='bullet bullet-dot'></span>
|
||||
</span>
|
||||
)}
|
||||
|
||||
{icon && (
|
||||
<span className='menu-icon'>
|
||||
<KTIcon iconName={icon} className='fs-2' />
|
||||
</span>
|
||||
)}
|
||||
|
||||
{fontIcon && (
|
||||
<span className='menu-icon'>
|
||||
<i className={clsx('bi fs-3', fontIcon)}></i>
|
||||
</span>
|
||||
)}
|
||||
|
||||
<span className='menu-title'>{title}</span>
|
||||
|
||||
{hasArrow && <span className='menu-arrow'></span>}
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export {MenuItem}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './MenuInner'
|
||||
@@ -0,0 +1 @@
|
||||
export * from './HeaderWrapper'
|
||||
@@ -0,0 +1,57 @@
|
||||
import {useEffect, useState} from 'react'
|
||||
import {useLocation} from 'react-router-dom'
|
||||
import {
|
||||
DrawerComponent,
|
||||
ScrollTopComponent,
|
||||
StickyComponent,
|
||||
ToggleComponent,
|
||||
} from '../../../assets/ts/components'
|
||||
import {KTIcon} from '../../../helpers'
|
||||
|
||||
export function ScrollTop() {
|
||||
const {pathname} = useLocation()
|
||||
const [initialized, setInintialized] = useState(false)
|
||||
|
||||
const pluginsReinitialization = () => {
|
||||
setTimeout(() => {
|
||||
StickyComponent.reInitialization()
|
||||
setTimeout(() => {
|
||||
ToggleComponent.reinitialization()
|
||||
DrawerComponent.reinitialization()
|
||||
}, 70)
|
||||
}, 140)
|
||||
}
|
||||
|
||||
const scrollTop = () => {
|
||||
ScrollTopComponent.goTop()
|
||||
}
|
||||
|
||||
const updateHeaderSticky = () => {
|
||||
const stickyHeader = document.body.querySelectorAll(`[data-kt-sticky-name="header"]`)
|
||||
if (stickyHeader && stickyHeader.length > 0) {
|
||||
const sticky = StickyComponent.getInstance(stickyHeader[0] as HTMLElement)
|
||||
if (sticky) {
|
||||
sticky.update()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!initialized) {
|
||||
setInintialized(true)
|
||||
} else {
|
||||
pluginsReinitialization()
|
||||
}
|
||||
|
||||
updateHeaderSticky()
|
||||
setTimeout(() => {
|
||||
scrollTop()
|
||||
}, 0)
|
||||
}, [initialized, pathname])
|
||||
|
||||
return (
|
||||
<div id='kt_scrolltop' className='scrolltop' data-kt-scrolltop='true'>
|
||||
<KTIcon iconName='arrow-up' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './ScrollTop'
|
||||
@@ -0,0 +1,141 @@
|
||||
/* eslint-disable no-prototype-builtins */
|
||||
import clsx from 'clsx'
|
||||
import {useEffect, useRef} from 'react'
|
||||
import {ILayout, useLayout} from '../../core'
|
||||
import {SidebarMenu} from './sidebar-menu/SidebarMenu'
|
||||
import {SidebarFooter} from './SidebarFooter'
|
||||
import {SidebarLogo} from './SidebarLogo'
|
||||
|
||||
const Sidebar = () => {
|
||||
const {config} = useLayout()
|
||||
const sidebarRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
updateDOM(config)
|
||||
}, [config])
|
||||
|
||||
if (!config.app?.sidebar?.display) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{(config.layoutType === 'dark-sidebar' || config.layoutType === 'light-sidebar') && (
|
||||
<div
|
||||
ref={sidebarRef}
|
||||
id='kt_app_sidebar'
|
||||
className={clsx('app-sidebar', config.app?.sidebar?.default?.class)}
|
||||
>
|
||||
<SidebarLogo sidebarRef={sidebarRef} />
|
||||
<SidebarMenu />
|
||||
<SidebarFooter />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const updateDOM = (config: ILayout) => {
|
||||
if (config.layoutType === 'dark-sidebar' || config.layoutType === 'light-sidebar') {
|
||||
if (config.app?.sidebar?.default?.minimize?.desktop?.enabled) {
|
||||
if (config.app?.sidebar?.default?.minimize?.desktop?.default) {
|
||||
document.body.setAttribute('data-kt-app-sidebar-minimize', 'on')
|
||||
}
|
||||
|
||||
if (config.app?.sidebar?.default?.minimize?.desktop?.hoverable) {
|
||||
document.body.setAttribute('data-kt-app-sidebar-hoverable', 'true')
|
||||
}
|
||||
}
|
||||
|
||||
if (config.app?.sidebar?.default?.minimize?.mobile?.enabled) {
|
||||
if (config.app?.sidebar?.default?.minimize?.mobile?.default) {
|
||||
document.body.setAttribute('data-kt-app-sidebar-minimize-mobile', 'on')
|
||||
}
|
||||
|
||||
if (config.app?.sidebar?.default?.minimize?.mobile?.hoverable) {
|
||||
document.body.setAttribute('data-kt-app-sidebar-hoverable-mobile', 'true')
|
||||
}
|
||||
}
|
||||
|
||||
if (config.app?.sidebar?.default?.collapse?.desktop?.enabled) {
|
||||
if (config.app?.sidebar?.default?.collapse?.desktop?.default) {
|
||||
document.body.setAttribute('data-kt-app-sidebar-collapse', 'on')
|
||||
}
|
||||
}
|
||||
|
||||
if (config.app?.sidebar?.default?.collapse?.mobile?.enabled) {
|
||||
if (config.app?.sidebar?.default?.collapse?.mobile?.default) {
|
||||
document.body.setAttribute('data-kt-app-sidebar-collapse-mobile', 'on')
|
||||
}
|
||||
}
|
||||
|
||||
if (config.app?.sidebar?.default?.push) {
|
||||
if (config.app?.sidebar?.default?.push?.header) {
|
||||
document.body.setAttribute('data-kt-app-sidebar-push-header', 'true')
|
||||
}
|
||||
|
||||
if (config.app?.sidebar?.default?.push?.toolbar) {
|
||||
document.body.setAttribute('data-kt-app-sidebar-push-toolbar', 'true')
|
||||
}
|
||||
|
||||
if (config.app?.sidebar?.default?.push?.footer) {
|
||||
document.body.setAttribute('data-kt-app-sidebar-push-footer', 'true')
|
||||
}
|
||||
}
|
||||
|
||||
if (config.app?.sidebar?.default?.stacked) {
|
||||
document.body.setAttribute('app-sidebar-stacked', 'true')
|
||||
}
|
||||
|
||||
document.body.setAttribute('data-kt-app-sidebar-enabled', 'true')
|
||||
document.body.setAttribute(
|
||||
'data-kt-app-sidebar-fixed',
|
||||
config.app?.sidebar?.default?.fixed?.desktop?.toString() || ''
|
||||
)
|
||||
|
||||
const appSidebarDefaultDrawerEnabled = config.app?.sidebar?.default?.drawer?.enabled
|
||||
let appSidebarDefaultDrawerAttributes: {[attrName: string]: string} = {}
|
||||
if (appSidebarDefaultDrawerEnabled) {
|
||||
appSidebarDefaultDrawerAttributes = config.app?.sidebar?.default?.drawer?.attributes as {
|
||||
[attrName: string]: string
|
||||
}
|
||||
}
|
||||
|
||||
const appSidebarDefaultStickyEnabled = config.app?.sidebar?.default?.sticky?.enabled
|
||||
let appSidebarDefaultStickyAttributes: {[attrName: string]: string} = {}
|
||||
if (appSidebarDefaultStickyEnabled) {
|
||||
appSidebarDefaultStickyAttributes = config.app?.sidebar?.default?.sticky?.attributes as {
|
||||
[attrName: string]: string
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
const sidebarElement = document.getElementById('kt_app_sidebar')
|
||||
// sidebar
|
||||
if (sidebarElement) {
|
||||
const sidebarAttributes = sidebarElement
|
||||
.getAttributeNames()
|
||||
.filter((t) => t.indexOf('data-') > -1)
|
||||
sidebarAttributes.forEach((attr) => sidebarElement.removeAttribute(attr))
|
||||
|
||||
if (appSidebarDefaultDrawerEnabled) {
|
||||
for (const key in appSidebarDefaultDrawerAttributes) {
|
||||
if (appSidebarDefaultDrawerAttributes.hasOwnProperty(key)) {
|
||||
sidebarElement.setAttribute(key, appSidebarDefaultDrawerAttributes[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (appSidebarDefaultStickyEnabled) {
|
||||
for (const key in appSidebarDefaultStickyAttributes) {
|
||||
if (appSidebarDefaultStickyAttributes.hasOwnProperty(key)) {
|
||||
sidebarElement.setAttribute(key, appSidebarDefaultStickyAttributes[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
|
||||
export {Sidebar}
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
import {KTIcon} from '../../../helpers'
|
||||
|
||||
const SidebarFooter = () => {
|
||||
return (
|
||||
<div>
|
||||
|
||||
</div>
|
||||
// <div className='app-sidebar-footer flex-column-auto pt-2 pb-6 px-6' id='kt_app_sidebar_footer'>
|
||||
// <a
|
||||
// href={import.meta.env.VITE_APP_PREVIEW_DOCS_URL}
|
||||
// target='_blank'
|
||||
// className='btn btn-flex flex-center btn-custom btn-primary overflow-hidden text-nowrap px-0 h-40px w-100'
|
||||
// data-bs-toggle='tooltip'
|
||||
// data-bs-trigger='hover'
|
||||
// data-bs-dismiss-='click'
|
||||
// title='Metronic Docs & Components'
|
||||
// >
|
||||
// {/*<span className='btn-label'>Docs & Components</span>*/}
|
||||
// <KTIcon iconName='document' className='btn-icon fs-2 m-0' />
|
||||
// </a>
|
||||
// </div>
|
||||
)
|
||||
}
|
||||
|
||||
export {SidebarFooter}
|
||||
@@ -0,0 +1,101 @@
|
||||
import {Link} from 'react-router-dom'
|
||||
import clsx from 'clsx'
|
||||
import {KTIcon, toAbsoluteUrl} from '../../../helpers'
|
||||
import {useLayout} from '../../core'
|
||||
import {MutableRefObject, useEffect, useRef} from 'react'
|
||||
import {ToggleComponent} from '../../../assets/ts/components'
|
||||
|
||||
type PropsType = {
|
||||
sidebarRef: MutableRefObject<HTMLDivElement | null>
|
||||
}
|
||||
|
||||
const SidebarLogo = (props: PropsType) => {
|
||||
const {config} = useLayout()
|
||||
const toggleRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const appSidebarDefaultMinimizeDesktopEnabled =
|
||||
config?.app?.sidebar?.default?.minimize?.desktop?.enabled
|
||||
const appSidebarDefaultCollapseDesktopEnabled =
|
||||
config?.app?.sidebar?.default?.collapse?.desktop?.enabled
|
||||
const toggleType = appSidebarDefaultCollapseDesktopEnabled
|
||||
? 'collapse'
|
||||
: appSidebarDefaultMinimizeDesktopEnabled
|
||||
? 'minimize'
|
||||
: ''
|
||||
const toggleState = appSidebarDefaultMinimizeDesktopEnabled ? 'active' : ''
|
||||
const appSidebarDefaultMinimizeDefault = config.app?.sidebar?.default?.minimize?.desktop?.default
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
const toggleObj = ToggleComponent.getInstance(toggleRef.current!) as ToggleComponent | null
|
||||
|
||||
if (toggleObj === null) {
|
||||
return
|
||||
}
|
||||
|
||||
// Add a class to prevent sidebar hover effect after toggle click
|
||||
toggleObj.on('kt.toggle.change', function () {
|
||||
// Set animation state
|
||||
props.sidebarRef.current!.classList.add('animating')
|
||||
|
||||
// Wait till animation finishes
|
||||
setTimeout(function () {
|
||||
// Remove animation state
|
||||
props.sidebarRef.current!.classList.remove('animating')
|
||||
}, 300)
|
||||
})
|
||||
}, 600)
|
||||
}, [toggleRef, props.sidebarRef])
|
||||
|
||||
return (
|
||||
<div className='app-sidebar-logo px-6' id='kt_app_sidebar_logo'>
|
||||
<Link to='/dashboard'>
|
||||
{config.layoutType === 'dark-sidebar' ? (
|
||||
<img
|
||||
alt='Logo'
|
||||
src={toAbsoluteUrl('media/logos/default-dark.svg')}
|
||||
className='h-25px app-sidebar-logo-default'
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<img
|
||||
alt='Logo'
|
||||
src={toAbsoluteUrl('media/logos/sidelogo.png')}
|
||||
className='h-25px app-sidebar-logo-default theme-light-show'
|
||||
/>
|
||||
<img
|
||||
alt='Logo'
|
||||
src={toAbsoluteUrl('media/logos/default-dark.svg')}
|
||||
className='h-25px app-sidebar-logo-default theme-dark-show'
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
<img
|
||||
alt='Logo'
|
||||
src={toAbsoluteUrl('media/logos/default-small.svg')}
|
||||
className='h-20px app-sidebar-logo-minimize'
|
||||
/>
|
||||
</Link>
|
||||
|
||||
{(appSidebarDefaultMinimizeDesktopEnabled || appSidebarDefaultCollapseDesktopEnabled) && (
|
||||
<div
|
||||
ref={toggleRef}
|
||||
id='kt_app_sidebar_toggle'
|
||||
className={clsx(
|
||||
'app-sidebar-toggle btn btn-icon btn-shadow btn-sm btn-color-muted btn-active-color-primary h-30px w-30px position-absolute top-50 start-100 translate-middle rotate',
|
||||
{active: appSidebarDefaultMinimizeDefault}
|
||||
)}
|
||||
data-kt-toggle='true'
|
||||
data-kt-toggle-state={toggleState}
|
||||
data-kt-toggle-target='body'
|
||||
data-kt-toggle-name={`app-sidebar-${toggleType}`}
|
||||
>
|
||||
<KTIcon iconName='black-left-line' className='fs-3 rotate-180 ms-1' />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export {SidebarLogo}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './Sidebar'
|
||||
@@ -0,0 +1,30 @@
|
||||
import {SidebarMenuMain} from './SidebarMenuMain'
|
||||
|
||||
const SidebarMenu = () => {
|
||||
return (
|
||||
<div className='app-sidebar-menu overflow-hidden flex-column-fluid'>
|
||||
<div
|
||||
id='kt_app_sidebar_menu_wrapper'
|
||||
className='app-sidebar-wrapper hover-scroll-overlay-y my-5'
|
||||
data-kt-scroll='true'
|
||||
data-kt-scroll-activate='true'
|
||||
data-kt-scroll-height='auto'
|
||||
data-kt-scroll-dependencies='#kt_app_sidebar_logo, #kt_app_sidebar_footer'
|
||||
data-kt-scroll-wrappers='#kt_app_sidebar_menu'
|
||||
data-kt-scroll-offset='5px'
|
||||
data-kt-scroll-save-state='true'
|
||||
>
|
||||
<div
|
||||
className='menu menu-column menu-rounded menu-sub-indention px-3'
|
||||
id='#kt_app_sidebar_menu'
|
||||
data-kt-menu='true'
|
||||
data-kt-menu-expand='false'
|
||||
>
|
||||
<SidebarMenuMain />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export {SidebarMenu}
|
||||
@@ -0,0 +1,53 @@
|
||||
import {FC} from 'react'
|
||||
import clsx from 'clsx'
|
||||
import {Link} from 'react-router-dom'
|
||||
import {useLocation} from 'react-router'
|
||||
import {checkIsActive, KTIcon, WithChildren} from '../../../../helpers'
|
||||
import {useLayout} from '../../../core'
|
||||
|
||||
type Props = {
|
||||
to: string
|
||||
title: string
|
||||
icon?: string
|
||||
fontIcon?: string
|
||||
hasBullet?: boolean
|
||||
}
|
||||
|
||||
const SidebarMenuItem: FC<Props & WithChildren> = ({
|
||||
children,
|
||||
to,
|
||||
title,
|
||||
icon,
|
||||
fontIcon,
|
||||
hasBullet = false,
|
||||
}) => {
|
||||
const {pathname} = useLocation()
|
||||
const isActive = checkIsActive(pathname, to)
|
||||
const {config} = useLayout()
|
||||
const {app} = config
|
||||
|
||||
return (
|
||||
<div className='menu-item'>
|
||||
<Link className={clsx('menu-link without-sub', {active: isActive})} to={to}>
|
||||
{hasBullet && (
|
||||
<span className='menu-bullet'>
|
||||
<span className='bullet bullet-dot'></span>
|
||||
</span>
|
||||
)}
|
||||
{icon && app?.sidebar?.default?.menu?.iconType === 'svg' && (
|
||||
<span className='menu-icon'>
|
||||
{' '}
|
||||
<KTIcon iconName={icon} className='fs-2' />
|
||||
</span>
|
||||
)}
|
||||
{fontIcon && app?.sidebar?.default?.menu?.iconType === 'font' && (
|
||||
<i className={clsx('bi fs-3', fontIcon)}></i>
|
||||
)}
|
||||
<span className='menu-title'>{title}</span>
|
||||
</Link>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export {SidebarMenuItem}
|
||||
@@ -0,0 +1,57 @@
|
||||
import React from 'react'
|
||||
import clsx from 'clsx'
|
||||
import {useLocation} from 'react-router'
|
||||
import {checkIsActive, KTIcon, WithChildren} from '../../../../helpers'
|
||||
import {useLayout} from '../../../core'
|
||||
|
||||
type Props = {
|
||||
to: string
|
||||
title: string
|
||||
icon?: string
|
||||
fontIcon?: string
|
||||
hasBullet?: boolean
|
||||
}
|
||||
|
||||
const SidebarMenuItemWithSub: React.FC<Props & WithChildren> = ({
|
||||
children,
|
||||
to,
|
||||
title,
|
||||
icon,
|
||||
fontIcon,
|
||||
hasBullet,
|
||||
}) => {
|
||||
const {pathname} = useLocation()
|
||||
const isActive = checkIsActive(pathname, to)
|
||||
const {config} = useLayout()
|
||||
const {app} = config
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx('menu-item', {'here show': isActive}, 'menu-accordion')}
|
||||
data-kt-menu-trigger='click'
|
||||
>
|
||||
<span className='menu-link'>
|
||||
{hasBullet && (
|
||||
<span className='menu-bullet'>
|
||||
<span className='bullet bullet-dot'></span>
|
||||
</span>
|
||||
)}
|
||||
{icon && app?.sidebar?.default?.menu?.iconType === 'svg' && (
|
||||
<span className='menu-icon'>
|
||||
<KTIcon iconName={icon} className='fs-2' />
|
||||
</span>
|
||||
)}
|
||||
{fontIcon && app?.sidebar?.default?.menu?.iconType === 'font' && (
|
||||
<i className={clsx('bi fs-3', fontIcon)}></i>
|
||||
)}
|
||||
<span className='menu-title'>{title}</span>
|
||||
<span className='menu-arrow'></span>
|
||||
</span>
|
||||
<div className={clsx('menu-sub menu-sub-accordion', {'menu-active-bg': isActive})}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export {SidebarMenuItemWithSub}
|
||||
@@ -0,0 +1,121 @@
|
||||
import {useIntl} from 'react-intl'
|
||||
import {KTIcon} from '../../../../helpers'
|
||||
import {SidebarMenuItemWithSub} from './SidebarMenuItemWithSub'
|
||||
import {SidebarMenuItem} from './SidebarMenuItem'
|
||||
|
||||
const SidebarMenuMain = () => {
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<>
|
||||
<SidebarMenuItem
|
||||
to='/dashboard'
|
||||
icon='element-11'
|
||||
title={intl.formatMessage({id: 'MENU.DASHBOARD'})}
|
||||
fontIcon='bi-app-indicator'
|
||||
/>
|
||||
{/*<SidebarMenuItem to='/builder' icon='switch' title='Layout Builder' fontIcon='bi-layers' />*/}
|
||||
<div className='menu-item'>
|
||||
<div className='menu-content pt-8 pb-2'>
|
||||
<span className='menu-section text-muted text-uppercase fs-8 ls-1'>Crafted</span>
|
||||
</div>
|
||||
</div>
|
||||
<SidebarMenuItemWithSub
|
||||
to='/crafted/pages'
|
||||
title='Pages'
|
||||
fontIcon='bi-archive'
|
||||
icon='element-plus'
|
||||
>
|
||||
<SidebarMenuItemWithSub to='/crafted/pages/profile' title='Profile' hasBullet={true}>
|
||||
<SidebarMenuItem to='/crafted/pages/profile/overview' title='Overview' hasBullet={true} />
|
||||
<SidebarMenuItem to='/crafted/pages/profile/projects' title='Projects' hasBullet={true} />
|
||||
<SidebarMenuItem
|
||||
to='/crafted/pages/profile/campaigns'
|
||||
title='Campaigns'
|
||||
hasBullet={true}
|
||||
/>
|
||||
<SidebarMenuItem
|
||||
to='/crafted/pages/profile/documents'
|
||||
title='Documents'
|
||||
hasBullet={true}
|
||||
/>
|
||||
<SidebarMenuItem
|
||||
to='/crafted/pages/profile/connections'
|
||||
title='Connections'
|
||||
hasBullet={true}
|
||||
/>
|
||||
</SidebarMenuItemWithSub>
|
||||
|
||||
<SidebarMenuItemWithSub to='/crafted/pages/wizards' title='Wizards' hasBullet={true}>
|
||||
<SidebarMenuItem
|
||||
to='/crafted/pages/wizards/horizontal'
|
||||
title='Horizontal'
|
||||
hasBullet={true}
|
||||
/>
|
||||
<SidebarMenuItem to='/crafted/pages/wizards/vertical' title='Vertical' hasBullet={true} />
|
||||
</SidebarMenuItemWithSub>
|
||||
</SidebarMenuItemWithSub>
|
||||
<SidebarMenuItemWithSub
|
||||
to='/crafted/accounts'
|
||||
title='Accounts'
|
||||
icon='profile-circle'
|
||||
fontIcon='bi-person'
|
||||
>
|
||||
<SidebarMenuItem to='/crafted/account/overview' title='Overview' hasBullet={true} />
|
||||
<SidebarMenuItem to='/crafted/account/settings' title='Settings' hasBullet={true} />
|
||||
</SidebarMenuItemWithSub>
|
||||
<SidebarMenuItemWithSub to='/error' title='Errors' fontIcon='bi-sticky' icon='cross-circle'>
|
||||
<SidebarMenuItem to='/error/404' title='Error 404' hasBullet={true} />
|
||||
<SidebarMenuItem to='/error/500' title='Error 500' hasBullet={true} />
|
||||
</SidebarMenuItemWithSub>
|
||||
<SidebarMenuItemWithSub
|
||||
to='/crafted/widgets'
|
||||
title='Widgets'
|
||||
icon='element-7'
|
||||
fontIcon='bi-layers'
|
||||
>
|
||||
<SidebarMenuItem to='/crafted/widgets/lists' title='Lists' hasBullet={true} />
|
||||
<SidebarMenuItem to='/crafted/widgets/statistics' title='Statistics' hasBullet={true} />
|
||||
<SidebarMenuItem to='/crafted/widgets/charts' title='Charts' hasBullet={true} />
|
||||
<SidebarMenuItem to='/crafted/widgets/mixed' title='Mixed' hasBullet={true} />
|
||||
<SidebarMenuItem to='/crafted/widgets/tables' title='Tables' hasBullet={true} />
|
||||
<SidebarMenuItem to='/crafted/widgets/feeds' title='Feeds' hasBullet={true} />
|
||||
</SidebarMenuItemWithSub>
|
||||
<div className='menu-item'>
|
||||
<div className='menu-content pt-8 pb-2'>
|
||||
<span className='menu-section text-muted text-uppercase fs-8 ls-1'>Apps</span>
|
||||
</div>
|
||||
</div>
|
||||
<SidebarMenuItemWithSub
|
||||
to='/apps/chat'
|
||||
title='Chat'
|
||||
fontIcon='bi-chat-left'
|
||||
icon='message-text-2'
|
||||
>
|
||||
<SidebarMenuItem to='/apps/chat/private-chat' title='Private Chat' hasBullet={true} />
|
||||
<SidebarMenuItem to='/apps/chat/group-chat' title='Group Chart' hasBullet={true} />
|
||||
<SidebarMenuItem to='/apps/chat/drawer-chat' title='Drawer Chart' hasBullet={true} />
|
||||
</SidebarMenuItemWithSub>
|
||||
<SidebarMenuItem
|
||||
to='/apps/user-management/users'
|
||||
icon='abstract-28'
|
||||
title='User management'
|
||||
fontIcon='bi-layers'
|
||||
/>
|
||||
{/*<div className='menu-item'>*/}
|
||||
{/* <a*/}
|
||||
{/* target='_blank'*/}
|
||||
{/* className='menu-link'*/}
|
||||
{/* href={import.meta.env.VITE_APP_PREVIEW_DOCS_URL + '/changelog'}*/}
|
||||
{/* >*/}
|
||||
{/* <span className='menu-icon'>*/}
|
||||
{/* <KTIcon iconName='code' className='fs-2' />*/}
|
||||
{/* </span>*/}
|
||||
{/* <span className='menu-title'>Changelog {import.meta.env.VITE_APP_VERSION}</span>*/}
|
||||
{/* </a>*/}
|
||||
{/*</div>*/}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export {SidebarMenuMain}
|
||||
@@ -0,0 +1,102 @@
|
||||
/* eslint-disable no-prototype-builtins */
|
||||
import {useEffect} from 'react'
|
||||
import {ILayout, useLayout} from '../../core'
|
||||
import {
|
||||
ToolbarAccounting,
|
||||
ToolbarClassic,
|
||||
ToolbarExtended,
|
||||
ToolbarReports,
|
||||
ToolbarSaas,
|
||||
} from './toolbars'
|
||||
|
||||
const Toolbar = () => {
|
||||
const {config} = useLayout()
|
||||
useEffect(() => {
|
||||
updateDOM(config)
|
||||
document.body.setAttribute('data-kt-app-toolbar-enabled', 'true')
|
||||
}, [config])
|
||||
|
||||
switch (config.app?.toolbar?.layout) {
|
||||
case 'classic':
|
||||
return <ToolbarClassic />
|
||||
case 'accounting':
|
||||
return <ToolbarAccounting />
|
||||
case 'extended':
|
||||
return <ToolbarExtended />
|
||||
case 'reports':
|
||||
return <ToolbarReports />
|
||||
case 'saas':
|
||||
return <ToolbarSaas />
|
||||
default:
|
||||
return <ToolbarClassic />
|
||||
}
|
||||
}
|
||||
|
||||
const updateDOM = (config: ILayout) => {
|
||||
let appToolbarSwapAttributes: {[attrName: string]: string} = {}
|
||||
const appToolbarSwapEnabled = config.app?.toolbar?.swap?.enabled
|
||||
if (appToolbarSwapEnabled) {
|
||||
appToolbarSwapAttributes = config.app?.toolbar?.swap?.attributes as {[attrName: string]: string}
|
||||
}
|
||||
|
||||
let appToolbarStickyAttributes: {[attrName: string]: string} = {}
|
||||
const appToolbarStickyEnabled = config.app?.toolbar?.sticky?.enabled
|
||||
if (appToolbarStickyEnabled) {
|
||||
appToolbarStickyAttributes = config.app?.toolbar?.sticky?.attributes as {
|
||||
[attrName: string]: string
|
||||
}
|
||||
|
||||
let appToolbarMinimizeAttributes: {[attrName: string]: string} = {}
|
||||
const appToolbarMinimizeEnabled = config.app?.toolbar?.minimize?.enabled
|
||||
if (appToolbarMinimizeEnabled) {
|
||||
appToolbarMinimizeAttributes = config.app?.toolbar?.minimize?.attributes as {
|
||||
[attrName: string]: string
|
||||
}
|
||||
}
|
||||
|
||||
if (config.app?.toolbar?.fixed?.desktop) {
|
||||
document.body.setAttribute('data-kt-app-toolbar-fixed', 'true')
|
||||
}
|
||||
|
||||
if (config.app?.toolbar?.fixed?.mobile) {
|
||||
document.body.setAttribute('data-kt-app-toolbar-fixed-mobile', 'true')
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
const toolbarElement = document.getElementById('kt_app_toolbar')
|
||||
// toolbar
|
||||
if (toolbarElement) {
|
||||
const toolbarAttributes = toolbarElement
|
||||
.getAttributeNames()
|
||||
.filter((t) => t.indexOf('data-') > -1)
|
||||
toolbarAttributes.forEach((attr) => toolbarElement.removeAttribute(attr))
|
||||
|
||||
if (appToolbarSwapEnabled) {
|
||||
for (const key in appToolbarSwapAttributes) {
|
||||
if (appToolbarSwapAttributes.hasOwnProperty(key)) {
|
||||
toolbarElement.setAttribute(key, appToolbarSwapAttributes[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (appToolbarStickyEnabled) {
|
||||
for (const key in appToolbarStickyAttributes) {
|
||||
if (appToolbarStickyAttributes.hasOwnProperty(key)) {
|
||||
toolbarElement.setAttribute(key, appToolbarStickyAttributes[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (appToolbarMinimizeEnabled) {
|
||||
for (const key in appToolbarMinimizeAttributes) {
|
||||
if (appToolbarMinimizeAttributes.hasOwnProperty(key)) {
|
||||
toolbarElement.setAttribute(key, appToolbarMinimizeAttributes[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
|
||||
export {Toolbar}
|
||||
@@ -0,0 +1,51 @@
|
||||
import clsx from 'clsx'
|
||||
import {ToolbarType, useLayout} from '../../core'
|
||||
import {Toolbar} from './Toolbar'
|
||||
import {PageTitleWrapper} from './page-title'
|
||||
|
||||
const ToolbarWrapper = () => {
|
||||
const {config, classes} = useLayout()
|
||||
if (!config.app?.toolbar?.display) {
|
||||
return null
|
||||
}
|
||||
|
||||
const isPageTitleVisible = showPageTitle(
|
||||
config.app?.toolbar?.layout,
|
||||
config.app?.pageTitle?.display
|
||||
)
|
||||
|
||||
return (
|
||||
<div
|
||||
id='kt_app_toolbar'
|
||||
className={clsx('app-toolbar', classes.toolbar.join(' '), config?.app?.toolbar?.class)}
|
||||
>
|
||||
<div
|
||||
id='kt_app_toolbar_container'
|
||||
className={clsx(
|
||||
'app-container',
|
||||
classes.toolbarContainer.join(' '),
|
||||
config.app?.toolbar?.containerClass,
|
||||
config.app?.toolbar?.minimize?.enabled ? 'app-toolbar-minimize' : '',
|
||||
{
|
||||
'container-fluid': config.app?.toolbar?.container === 'fluid',
|
||||
'container-xxl': config.app?.toolbar?.container === 'fixed',
|
||||
}
|
||||
)}
|
||||
>
|
||||
{isPageTitleVisible && <PageTitleWrapper />}
|
||||
<Toolbar />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const showPageTitle = (appToolbarLayout?: ToolbarType, appPageTitleDisplay?: boolean): boolean => {
|
||||
const viewsWithPageTitles = ['classic', 'reports', 'saas']
|
||||
if (!appToolbarLayout || !appPageTitleDisplay) {
|
||||
return false
|
||||
}
|
||||
|
||||
return appPageTitleDisplay && viewsWithPageTitles.some((t) => t === appToolbarLayout)
|
||||
}
|
||||
|
||||
export {ToolbarWrapper}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './ToolbarWrapper'
|
||||
@@ -0,0 +1,86 @@
|
||||
import clsx from 'clsx'
|
||||
import {Link} from 'react-router-dom'
|
||||
import {useLayout} from '../../../core'
|
||||
import {usePageData} from '../../../core/PageData'
|
||||
|
||||
const PageTitle = () => {
|
||||
const {pageTitle, pageDescription, pageBreadcrumbs} = usePageData()
|
||||
const {config, classes} = useLayout()
|
||||
const appPageTitleDirection = config.app?.pageTitle?.direction
|
||||
|
||||
return (
|
||||
<div
|
||||
id='kt_page_title'
|
||||
data-kt-swapper='true'
|
||||
data-kt-swapper-mode='prepend'
|
||||
data-kt-swapper-parent="{default: '#kt_content_container', 'lg': '#kt_toolbar_container'}"
|
||||
className={clsx(
|
||||
'page-title d-flex flex-wrap me-3',
|
||||
classes.pageTitle.join(' '),
|
||||
config.app?.pageTitle?.class,
|
||||
{
|
||||
'flex-column justify-content-center': appPageTitleDirection === 'column',
|
||||
'align-items-center': appPageTitleDirection !== 'column',
|
||||
}
|
||||
)}
|
||||
>
|
||||
{/* begin::Title */}
|
||||
{config.app?.pageTitle?.display && pageTitle && (
|
||||
<h1
|
||||
className={clsx('page-heading d-flex text-gray-900 fw-bold fs-3 my-0', {
|
||||
'flex-column justify-content-center': appPageTitleDirection,
|
||||
'align-items-center': !appPageTitleDirection,
|
||||
})}
|
||||
>
|
||||
{pageTitle}
|
||||
{pageDescription && config.app?.pageTitle && config.app?.pageTitle?.description && (
|
||||
<span
|
||||
className={clsx('page-desc text-muted fs-7 fw-semibold', {
|
||||
'pt-2': appPageTitleDirection === 'column',
|
||||
})}
|
||||
>
|
||||
{config.app?.pageTitle?.direction === 'row' && (
|
||||
<span className='h-20px border-1 border-gray-300 border-start ms-3 mx-2'></span>
|
||||
)}
|
||||
{pageDescription}{' '}
|
||||
</span>
|
||||
)}
|
||||
</h1>
|
||||
)}
|
||||
{/* end::Title */}
|
||||
|
||||
{pageBreadcrumbs &&
|
||||
pageBreadcrumbs.length > 0 &&
|
||||
config.app?.pageTitle &&
|
||||
config.app?.pageTitle?.breadCrumb && (
|
||||
<>
|
||||
{config.app?.pageTitle?.direction === 'row' && (
|
||||
<span className='h-20px border-gray-300 border-start mx-4'></span>
|
||||
)}
|
||||
<ul className='breadcrumb breadcrumb-separatorless fw-semibold fs-7 my-0'>
|
||||
{Array.from(pageBreadcrumbs).map((item, index) => (
|
||||
<li
|
||||
className={clsx('breadcrumb-item', {
|
||||
'text-gray-900': !item.isSeparator && item.isActive,
|
||||
'text-muted': !item.isSeparator && !item.isActive,
|
||||
})}
|
||||
key={`${item.path}${index}`}
|
||||
>
|
||||
{!item.isSeparator ? (
|
||||
<Link className='text-muted text-hover-primary' to={item.path}>
|
||||
{item.title}
|
||||
</Link>
|
||||
) : (
|
||||
<span className='bullet bg-gray-500 w-5px h-2px'></span>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
<li className='breadcrumb-item text-gray-900'>{pageTitle}</li>
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export {PageTitle}
|
||||
@@ -0,0 +1,13 @@
|
||||
import {useLayout} from '../../../core'
|
||||
import {PageTitle} from './PageTitle'
|
||||
|
||||
const PageTitleWrapper = () => {
|
||||
const {config} = useLayout()
|
||||
if (!config.app?.pageTitle?.display) {
|
||||
return null
|
||||
}
|
||||
|
||||
return <PageTitle />
|
||||
}
|
||||
|
||||
export {PageTitleWrapper}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './PageTitleWrapper'
|
||||
@@ -0,0 +1,139 @@
|
||||
|
||||
import {FC, useEffect, useState} from 'react'
|
||||
import {KTIcon} from '../../../../helpers'
|
||||
|
||||
const ToolbarAccounting: FC = () => {
|
||||
const [progress, setProgress] = useState<string>('1')
|
||||
const [filter, setFilter] = useState<string>('1')
|
||||
|
||||
useEffect(() => {
|
||||
document.body.setAttribute('data-kt-app-toolbar-fixed', 'true')
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='d-flex align-items-center me-5'>
|
||||
{/* begin::Input group */}
|
||||
<div className='d-flex align-items-center flex-shrink-0'>
|
||||
{/* begin::Label */}
|
||||
<span className='fs-7 text-gray-700 fw-bold pe-3 d-none d-md-block'>Actions:</span>
|
||||
{/* end::Label */}
|
||||
|
||||
{/* begin::Actions */}
|
||||
<div className='d-flex flex-shrink-0'>
|
||||
{/* begin::Button */}
|
||||
<div
|
||||
data-bs-toggle='tooltip'
|
||||
data-bs-placement='top'
|
||||
data-bs-trigger='hover'
|
||||
title='Add a team member'
|
||||
>
|
||||
<a href='#' className='btn btn-sm btn-icon btn-active-color-success'>
|
||||
<KTIcon iconName='plus-square' className='fs-2x' />
|
||||
</a>
|
||||
</div>
|
||||
{/* end::Button */}
|
||||
|
||||
{/* begin::Button */}
|
||||
<div
|
||||
data-bs-toggle='tooltip'
|
||||
data-bs-placement='top'
|
||||
data-bs-trigger='hover'
|
||||
title='Create new account'
|
||||
>
|
||||
<a href='#' className='btn btn-sm btn-icon btn-active-color-success'>
|
||||
<KTIcon iconName='minus-square' className='fs-2x' />
|
||||
</a>
|
||||
</div>
|
||||
{/* end::Button */}
|
||||
|
||||
{/* begin::Button */}
|
||||
<div
|
||||
data-bs-toggle='tooltip'
|
||||
data-bs-placement='top'
|
||||
data-bs-trigger='hover'
|
||||
title='Invite friends'
|
||||
>
|
||||
<a href='#' className='btn btn-sm btn-icon btn-active-color-success'>
|
||||
<KTIcon iconName='dots-square' className='fs-2x' />
|
||||
</a>
|
||||
</div>
|
||||
{/* end::Button */}
|
||||
</div>
|
||||
{/* end::Actions */}
|
||||
</div>
|
||||
{/* end::Input group */}
|
||||
|
||||
{/* begin::Input group */}
|
||||
<div className='d-flex align-items-center flex-shrink-0'>
|
||||
{/* begin::Desktop separartor */}
|
||||
<div className='bullet bg-secondary h-35px w-1px mx-5'></div>
|
||||
{/* end::Desktop separartor */}
|
||||
|
||||
{/* begin::Label */}
|
||||
<span className='fs-7 text-gray-700 fw-bold pe-4 ps-1 d-none d-md-block'>Progress:</span>
|
||||
{/* end::Label */}
|
||||
|
||||
<div className='progress w-100px w-xl-150px w-xxl-300px h-25px bg-light-success'>
|
||||
<div
|
||||
className='progress-bar rounded bg-success fs-7 fw-bold'
|
||||
role='progressbar'
|
||||
style={{width: '72%'}}
|
||||
aria-valuenow={72}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
>
|
||||
72%
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* end::Input group */}
|
||||
{/* end::Toolbar start */}
|
||||
</div>
|
||||
{/* begin::Toolbar end */}
|
||||
<div className='d-flex align-items-center'>
|
||||
{/* begin::Input group */}
|
||||
<div className='me-3'>
|
||||
{/* begin::Select */}
|
||||
<select
|
||||
className='form-select form-select-sm form-select-solid'
|
||||
data-control='select2'
|
||||
data-placeholder='Latest'
|
||||
data-hide-search='true'
|
||||
value={progress}
|
||||
onChange={(e) => setProgress(e.target.value)}
|
||||
>
|
||||
<option value=''></option>
|
||||
<option value='1'>Today 16 Feb</option>
|
||||
<option value='2'>In Progress</option>
|
||||
<option value='3'>Done</option>
|
||||
</select>
|
||||
{/* end::Select */}
|
||||
</div>
|
||||
{/* end::Input group- */}
|
||||
|
||||
{/* begin::Input group- */}
|
||||
<div className='m-0'>
|
||||
{/* begin::Select */}
|
||||
<select
|
||||
className='form-select form-select-sm form-select-solid w-md-125px'
|
||||
data-control='select2'
|
||||
data-placeholder='Filters'
|
||||
data-hide-search='true'
|
||||
value={filter}
|
||||
onChange={(e) => setFilter(e.target.value)}
|
||||
>
|
||||
<option value=''></option>
|
||||
<option value='1'>Filters</option>
|
||||
<option value='2'>In Progress</option>
|
||||
<option value='3'>Done</option>
|
||||
</select>
|
||||
{/* end::Content */}
|
||||
</div>
|
||||
{/* end::Input group- */}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export {ToolbarAccounting}
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
import clsx from 'clsx'
|
||||
import {useState} from 'react'
|
||||
import {KTIcon} from '../../../../helpers'
|
||||
import {CreateAppModal, Dropdown1} from '../../../../partials'
|
||||
import {useLayout} from '../../../core'
|
||||
|
||||
const ToolbarClassic = () => {
|
||||
const {config} = useLayout()
|
||||
const [showCreateAppModal, setShowCreateAppModal] = useState<boolean>(false)
|
||||
const daterangepickerButtonClass = config.app?.toolbar?.fixed?.desktop
|
||||
? 'btn-light'
|
||||
: 'bg-body btn-color-gray-700 btn-active-color-primary'
|
||||
|
||||
return (
|
||||
<div className='d-flex align-items-center gap-2 gap-lg-3'>
|
||||
{config.app?.toolbar?.filterButton && (
|
||||
<div className='m-0'>
|
||||
<a
|
||||
href='#'
|
||||
className={clsx('btn btn-sm btn-flex fw-bold', daterangepickerButtonClass)}
|
||||
data-kt-menu-trigger='click'
|
||||
data-kt-menu-placement='bottom-end'
|
||||
>
|
||||
<KTIcon iconName='filter' className='fs-6 text-muted me-1' />
|
||||
Filter
|
||||
</a>
|
||||
<Dropdown1 />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{config.app?.toolbar?.daterangepickerButton && (
|
||||
<div
|
||||
data-kt-daterangepicker='true'
|
||||
data-kt-daterangepicker-opens='left'
|
||||
className={clsx(
|
||||
'btn btn-sm fw-bold d-flex align-items-center px-4',
|
||||
daterangepickerButtonClass
|
||||
)}
|
||||
>
|
||||
<div className='text-gray-600 fw-bold'>Loading date range...</div>
|
||||
<KTIcon iconName='calendar-8' className='fs-1 ms-2 me-0' />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{config.app?.toolbar?.secondaryButton && (
|
||||
<a href='#' className='btn btn-sm btn-flex btn-light fw-bold'>
|
||||
Filter
|
||||
</a>
|
||||
)}
|
||||
|
||||
{config.app?.toolbar?.primaryButton && (
|
||||
<a
|
||||
href='#'
|
||||
onClick={() => setShowCreateAppModal(true)}
|
||||
className='btn btn-sm fw-bold btn-primary'
|
||||
>
|
||||
Create
|
||||
</a>
|
||||
)}
|
||||
<CreateAppModal show={showCreateAppModal} handleClose={() => setShowCreateAppModal(false)} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export {ToolbarClassic}
|
||||
@@ -0,0 +1,154 @@
|
||||
|
||||
import {FC, useEffect, useState} from 'react'
|
||||
import {KTIcon, toAbsoluteUrl} from '../../../../helpers'
|
||||
|
||||
const ToolbarExtended: FC = () => {
|
||||
const [progress, setProgress] = useState<string>('1')
|
||||
const [search, setSearch] = useState<string>('')
|
||||
|
||||
useEffect(() => {
|
||||
document.body.setAttribute('data-kt-app-toolbar-fixed', 'true')
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='d-flex align-items-center flex-shrink-0 me-5'>
|
||||
{/* begin::Label */}
|
||||
<span className='fs-7 fw-bold text-gray-700 pe-4 d-none d-md-block'>Team:</span>
|
||||
{/* end::Label */}
|
||||
|
||||
{/* begin::Users */}
|
||||
<div className='symbol-group symbol-hover flex-shrink-0 me-2'>
|
||||
{/* begin::User */}
|
||||
<div className='symbol symbol-circle symbol-35px'>
|
||||
<div className='symbol-label fw-bold bg-warning text-inverse-warning'>A</div>
|
||||
</div>
|
||||
{/* end::User */}
|
||||
|
||||
{/* begin::User */}
|
||||
<div className='symbol symbol-circle symbol-35px'>
|
||||
<img src={toAbsoluteUrl('media/avatars/300-1.jpg')} alt='' />
|
||||
</div>
|
||||
{/* end::User */}
|
||||
|
||||
{/* begin::User */}
|
||||
<div className='symbol symbol-circle symbol-35px'>
|
||||
<img src={toAbsoluteUrl('media/avatars/300-2.jpg')} alt='' />
|
||||
</div>
|
||||
{/* end::User */}
|
||||
|
||||
{/* begin::User */}
|
||||
<div className='symbol symbol-circle symbol-35px'>
|
||||
<div className='symbol-label fw-bold bg-primary text-inverse-primary'>S</div>
|
||||
</div>
|
||||
{/* end::User */}
|
||||
|
||||
{/* begin::User */}
|
||||
<div className='symbol symbol-circle symbol-35px'>
|
||||
<img src={toAbsoluteUrl('media/avatars/300-5.jpg')} alt='' />
|
||||
</div>
|
||||
{/* end::User */}
|
||||
|
||||
{/* begin::User */}
|
||||
<div className='symbol symbol-circle symbol-35px'>
|
||||
<div className='symbol-label fw-bold bg-danger text-inverse-danger'>P</div>
|
||||
</div>
|
||||
{/* end::User */}
|
||||
|
||||
{/* begin::User */}
|
||||
<div className='symbol symbol-circle symbol-35px'>
|
||||
<img src={toAbsoluteUrl('media/avatars/300-20.jpg')} alt='' />
|
||||
</div>
|
||||
{/* end::User */}
|
||||
</div>
|
||||
{/* end::Users */}
|
||||
|
||||
{/* begin::Button */}
|
||||
<div
|
||||
data-bs-toggle='tooltip'
|
||||
data-bs-placement='top'
|
||||
data-bs-trigger='hover'
|
||||
title='Invite a team member'
|
||||
>
|
||||
<a href='#' className='btn btn-sm btn-icon'>
|
||||
<KTIcon iconName='plus-square' className='fs-2hx text-success' />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{/* end::Button */}
|
||||
{/* end::Toolbar start */}
|
||||
|
||||
{/* begin::Toolbar end */}
|
||||
<div className='d-flex align-items-center overflow-auto'>
|
||||
{/* begin::Search */}
|
||||
<div className='position-relative my-1'>
|
||||
<KTIcon
|
||||
iconName='magnifier'
|
||||
className='fs-3 text-gray-500 position-absolute top-50 translate-middle ps-10'
|
||||
/>
|
||||
<input
|
||||
type='text'
|
||||
className='form-control form-control-sm form-control-solid w-150px ps-10'
|
||||
name='Search Team'
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
placeholder='Search Team'
|
||||
/>
|
||||
</div>
|
||||
{/* end::Search */}
|
||||
|
||||
{/* begin::Separartor */}
|
||||
<div className='bullet bg-secondary h-35px w-1px mx-6'></div>
|
||||
{/* end::Separartor */}
|
||||
|
||||
{/* begin::Label */}
|
||||
<span className='fs-7 fw-bold text-gray-700 flex-shrink-0 pe-4 d-none d-md-block'>
|
||||
Sort By:
|
||||
</span>
|
||||
{/* end::Label */}
|
||||
|
||||
{/* begin::Select */}
|
||||
<select
|
||||
className='form-select form-select-sm w-125px form-select-solid me-6'
|
||||
data-control='select2'
|
||||
data-placeholder='Latest'
|
||||
data-hide-search='true'
|
||||
value={progress}
|
||||
onChange={(e) => setProgress(e.target.value)}
|
||||
>
|
||||
<option value=''></option>
|
||||
<option value='1'>Latest</option>
|
||||
<option value='2'>In Progress</option>
|
||||
<option value='3'>Done</option>
|
||||
</select>
|
||||
{/* end::Select */}
|
||||
|
||||
{/* begin::Actions */}
|
||||
<div className='d-flex align-items-center'>
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-sm btn-icon btn-light-primary me-3'
|
||||
data-bs-toggle='tooltip'
|
||||
data-bs-placement='top'
|
||||
title='Enable grid view'
|
||||
>
|
||||
<KTIcon iconName='element-11' className='fs-3 text-primary' />
|
||||
</button>
|
||||
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-sm btn-icon btn-light'
|
||||
data-bs-toggle='tooltip'
|
||||
data-bs-placement='top'
|
||||
title='Enable row view'
|
||||
>
|
||||
<KTIcon iconName='row-horizontal' className='fs-3 text-gray-500' />
|
||||
</button>
|
||||
</div>
|
||||
{/* end::Actions */}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export {ToolbarExtended}
|
||||
@@ -0,0 +1,115 @@
|
||||
|
||||
import {useEffect, useState} from 'react'
|
||||
import {KTIcon} from '../../../../helpers'
|
||||
|
||||
const ToolbarReports = () => {
|
||||
const [progress, setProgress] = useState<string>('1')
|
||||
|
||||
useEffect(() => {
|
||||
document.body.setAttribute('data-kt-app-toolbar-fixed', 'true')
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className='d-flex align-items-center overflow-auto'>
|
||||
{/* begin::Wrapper */}
|
||||
<div className='d-flex align-items-center flex-shrink-0'>
|
||||
{/* begin::Label */}
|
||||
<span className='fs-7 fw-bold text-gray-700 flex-shrink-0 pe-4 d-none d-md-block'>
|
||||
Filter By:
|
||||
</span>
|
||||
{/* end::Label */}
|
||||
|
||||
<div className='flex-shrink-0 '>
|
||||
<ul className='nav'>
|
||||
<li className='nav-item'>
|
||||
<a
|
||||
className='nav-link btn btn-sm btn-color-muted btn-active-color-primary btn-active-light active fw-semibold fs-7 px-4 me-1'
|
||||
data-bs-toggle='tab'
|
||||
href='#'
|
||||
>
|
||||
Today
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className='nav-item'>
|
||||
<a
|
||||
className='nav-link btn btn-sm btn-color-muted btn-active-color-primary btn-active-light fw-semibold fs-7 px-4 me-1'
|
||||
data-bs-toggle='tab'
|
||||
href=''
|
||||
>
|
||||
Week
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li className='nav-item'>
|
||||
<a
|
||||
className='nav-link btn btn-sm btn-color-muted btn-active-color-primary btn-active-light fw-semibold fs-7 px-4'
|
||||
data-bs-toggle='tab'
|
||||
href='#'
|
||||
>
|
||||
Day
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{/* end::Wrapper */}
|
||||
|
||||
{/* begin::Separartor */}
|
||||
<div className='bullet bg-secondary h-35px w-1px mx-5'></div>
|
||||
{/* end::Separartor */}
|
||||
|
||||
{/* begin::Wrapper */}
|
||||
<div className='d-flex align-items-center'>
|
||||
{/* begin::Label */}
|
||||
<span className='fs-7 fw-bold text-gray-700 flex-shrink-0 pe-4 d-none d-md-block'>
|
||||
Sort By:
|
||||
</span>
|
||||
{/* end::Label */}
|
||||
|
||||
{/* begin::Select */}
|
||||
<select
|
||||
className='form-select form-select-sm w-md-125px form-select-solid'
|
||||
data-control='select2'
|
||||
data-placeholder='Latest'
|
||||
data-hide-search='true'
|
||||
value={progress}
|
||||
onChange={(e) => setProgress(e.target.value)}
|
||||
>
|
||||
<option value=''></option>
|
||||
<option value='1'>Latest</option>
|
||||
<option value='2'>In Progress</option>
|
||||
<option value='3'>Done</option>
|
||||
</select>
|
||||
{/* end::Select */}
|
||||
|
||||
{/* begin::Actions */}
|
||||
<div className='d-flex align-items-center ms-3'>
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-sm btn-icon btn-light-primary me-3'
|
||||
data-bs-toggle='tooltip'
|
||||
data-bs-placement='top'
|
||||
title='Enable grid view'
|
||||
>
|
||||
<KTIcon iconName='element-11' className='fs-2 text-primary' />
|
||||
</button>
|
||||
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-sm btn-icon btn-light'
|
||||
data-bs-toggle='tooltip'
|
||||
data-bs-placement='top'
|
||||
title='Enable row view'
|
||||
>
|
||||
<KTIcon iconName='abstract-14' className=' fs-2 text-gray-500' />
|
||||
</button>
|
||||
</div>
|
||||
{/* end::Actions */}
|
||||
</div>
|
||||
{/* end::Wrapper */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export {ToolbarReports}
|
||||
@@ -0,0 +1,126 @@
|
||||
|
||||
import {FC, useEffect, useState} from 'react'
|
||||
import {KTIcon} from '../../../../helpers'
|
||||
|
||||
const ToolbarSaas: FC = () => {
|
||||
const [progress, setProgress] = useState<string>('1')
|
||||
useEffect(() => {
|
||||
document.body.setAttribute('data-kt-app-toolbar-fixed', 'true')
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className='d-flex align-items-center gap-2'>
|
||||
{/* begin::Action wrapper */}
|
||||
<div className='d-flex align-items-center'>
|
||||
{/* begin::Label */}
|
||||
<span className='fs-7 fw-bold text-gray-700 pe-4 text-nowrap d-none d-md-block'>
|
||||
Sort By:
|
||||
</span>
|
||||
{/* end::Label */}
|
||||
|
||||
{/* begin::Select */}
|
||||
<select
|
||||
className='form-select form-select-sm form-select-solid w-100px w-xxl-125px'
|
||||
data-control='select2'
|
||||
data-placeholder='Latest'
|
||||
data-hide-search='true'
|
||||
onChange={(e) => setProgress(e.target.value)}
|
||||
value={progress}
|
||||
>
|
||||
<option value=''></option>
|
||||
<option value='1'>Latest</option>
|
||||
<option value='2'>In Progress</option>
|
||||
<option value='3'>Done</option>
|
||||
</select>
|
||||
{/* end::Select */}
|
||||
</div>
|
||||
{/* end::Action wrapper */}
|
||||
|
||||
{/* begin::Action wrapper */}
|
||||
<div className='d-flex align-items-center'>
|
||||
{/* begin::Separartor */}
|
||||
<div className='bullet bg-secondary h-35px w-1px mx-5'></div>
|
||||
{/* end::Separartor */}
|
||||
|
||||
{/* begin::Label */}
|
||||
<span className='fs-7 text-gray-700 fw-bold'>Impact Level:</span>
|
||||
{/* end::Label */}
|
||||
|
||||
{/* begin::NoUiSlider */}
|
||||
<div className='d-flex align-items-center ps-4'>
|
||||
<div
|
||||
id='kt_app_toolbar_slider'
|
||||
className='noUi-target noUi-target-success w-75px w-xxl-150px noUi-sm'
|
||||
></div>
|
||||
|
||||
<span
|
||||
id='kt_app_toolbar_slider_value'
|
||||
className='d-flex flex-center bg-light-success rounded-circle w-35px h-35px ms-4 fs-7 fw-bold text-success'
|
||||
data-bs-toggle='tooltip'
|
||||
data-bs-placement='top'
|
||||
title='Set impact level'
|
||||
></span>
|
||||
</div>
|
||||
{/* end::NoUiSlider */}
|
||||
|
||||
{/* begin::Separartor */}
|
||||
<div className='bullet bg-secondary h-35px w-1px mx-5'></div>
|
||||
{/* end::Separartor */}
|
||||
</div>
|
||||
{/* end::Action wrapper */}
|
||||
|
||||
{/* begin::Action wrapper */}
|
||||
<div className='d-flex align-items-center'>
|
||||
{/* begin::Label */}
|
||||
<span className='fs-7 text-gray-700 fw-bold pe-3 d-none d-md-block'>Quick Tools:</span>
|
||||
{/* end::Label */}
|
||||
|
||||
{/* begin::Actions */}
|
||||
<div className='d-flex'>
|
||||
{/* begin::Action */}
|
||||
<a
|
||||
href='#'
|
||||
className='btn btn-sm btn-icon btn-icon-muted btn-active-icon-success'
|
||||
data-bs-toggle='tooltip'
|
||||
data-bs-trigger='hover'
|
||||
data-bs-placement='top'
|
||||
title='Add new page'
|
||||
>
|
||||
<KTIcon iconName='files' className='fs-2x' />
|
||||
</a>
|
||||
{/* end::Action */}
|
||||
|
||||
{/* begin::Action */}
|
||||
<a
|
||||
href='#'
|
||||
className='btn btn-sm btn-icon btn-icon-muted btn-active-icon-success'
|
||||
data-bs-toggle='tooltip'
|
||||
data-bs-trigger='hover'
|
||||
data-bs-placement='top'
|
||||
title='Add new category'
|
||||
>
|
||||
<KTIcon iconName='add-files' className='fs-2x' />
|
||||
</a>
|
||||
{/* end::Action */}
|
||||
|
||||
{/* begin::Action */}
|
||||
<a
|
||||
href='#'
|
||||
className='btn btn-sm btn-icon btn-icon-muted btn-active-icon-success'
|
||||
data-bs-toggle='tooltip'
|
||||
data-bs-trigger='hover'
|
||||
data-bs-placement='top'
|
||||
title='Add new section'
|
||||
>
|
||||
<KTIcon iconName='search-list' className='fs-2x' />
|
||||
</a>
|
||||
{/* end::Action */}
|
||||
</div>
|
||||
{/* end::Actions */}
|
||||
</div>
|
||||
{/* end::Action wrapper */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export {ToolbarSaas}
|
||||
@@ -0,0 +1,5 @@
|
||||
export * from './ToolbarAccounting'
|
||||
export * from './ToolbarClassic'
|
||||
export * from './ToolbarExtended'
|
||||
export * from './ToolbarReports'
|
||||
export * from './ToolbarSaas'
|
||||
Reference in New Issue
Block a user