Compare commits
No commits in common. "5e46de8b6099fa3e44b68147c492dfd291178f28" and "88d6ef6f134a315220b8f68f04ce596daaa31e99" have entirely different histories.
5e46de8b60
...
88d6ef6f13
@ -253,8 +253,8 @@ html.macos-vibrancy .dark-mode .ant-layout.main-content-layout .ant-card {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.electron-sider.ant-layout-sider-collapsed {
|
.electron-sider.ant-layout-sider-collapsed {
|
||||||
min-width: var(--dashboard-sidebar-collapsed-width, 55px) !important;
|
max-width: 55px !important;
|
||||||
max-width: var(--dashboard-sidebar-collapsed-width, 55px) !important;
|
min-width: 55px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-modal .ant-modal-footer {
|
.loading-modal .ant-modal-footer {
|
||||||
@ -362,10 +362,8 @@ code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.cursor-tooltip .ant-card {
|
.cursor-tooltip .ant-card {
|
||||||
box-shadow:
|
box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08),
|
||||||
0 6px 16px 0 rgba(0, 0, 0, 0.08),
|
0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
||||||
0 3px 6px -4px rgba(0, 0, 0, 0.12),
|
|
||||||
0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Start of src/index.css --- */
|
/* --- Start of src/index.css --- */
|
||||||
@ -414,21 +412,9 @@ body {
|
|||||||
|
|
||||||
/* --- Start of src/components/Dashboard/common/DashboardSidebar.css --- */
|
/* --- Start of src/components/Dashboard/common/DashboardSidebar.css --- */
|
||||||
.ant-layout-sider {
|
.ant-layout-sider {
|
||||||
height: 100%;
|
width: 250px; /* Adjust the width as per your preference */
|
||||||
}
|
min-width: 250px; /* Ensure a minimum width to avoid collapsing */
|
||||||
|
max-width: 400px; /* Optionally set a maximum width */
|
||||||
.dashboard-sider.ant-layout-sider {
|
|
||||||
width: 100% !important;
|
|
||||||
min-width: 0 !important;
|
|
||||||
max-width: 100% !important;
|
|
||||||
flex: 0 0 100% !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-sider.ant-layout-sider-collapsed {
|
|
||||||
width: var(--dashboard-sidebar-collapsed-width, 80px) !important;
|
|
||||||
min-width: var(--dashboard-sidebar-collapsed-width, 80px) !important;
|
|
||||||
max-width: var(--dashboard-sidebar-collapsed-width, 80px) !important;
|
|
||||||
flex: 0 0 var(--dashboard-sidebar-collapsed-width, 80px) !important;
|
|
||||||
}
|
}
|
||||||
/* --- End of src/components/Dashboard/common/DashboardSidebar.css --- */
|
/* --- End of src/components/Dashboard/common/DashboardSidebar.css --- */
|
||||||
|
|
||||||
@ -1009,11 +995,6 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.farmcontrol-splitter.ant-splitter-horizontal.is-size-transitioning
|
|
||||||
.ant-splitter-panel {
|
|
||||||
transition: flex-basis 0.15s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.farmcontrol-splitter
|
.farmcontrol-splitter
|
||||||
.ant-splitter-panel:has(~ .ant-splitter-panel)
|
.ant-splitter-panel:has(~ .ant-splitter-panel)
|
||||||
.info-collapse.ant-collapse.ant-collapse-icon-position-end
|
.info-collapse.ant-collapse.ant-collapse-icon-position-end
|
||||||
@ -1374,8 +1355,7 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
|
|||||||
1,
|
1,
|
||||||
abs(
|
abs(
|
||||||
calc(
|
calc(
|
||||||
var(--permissions-col, 0) -
|
var(--permissions-col, 0) - var(--permissions-hovered-col, -1)
|
||||||
var(--permissions-hovered-col, -1)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -1532,19 +1512,3 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
|
|||||||
stroke: currentColor;
|
stroke: currentColor;
|
||||||
stroke-width: 8px;
|
stroke-width: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-splitter.farmcontrol-splitter > .ant-splitter-bar {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-splitter.farmcontrol-splitter
|
|
||||||
> .ant-splitter-bar
|
|
||||||
.ant-splitter-bar-dragger::before {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-splitter.farmcontrol-splitter
|
|
||||||
> .ant-splitter-bar
|
|
||||||
.ant-splitter-bar-dragger::after {
|
|
||||||
content: none;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -10,7 +10,6 @@ import ManagementSidebar from './Management/ManagementSidebar'
|
|||||||
import DashboardNavigation from './common/DashboardNavigation'
|
import DashboardNavigation from './common/DashboardNavigation'
|
||||||
import DashboardBreadcrumb from './common/DashboardBreadcrumb'
|
import DashboardBreadcrumb from './common/DashboardBreadcrumb'
|
||||||
import DeveloperSidebar from './Developer/DeveloperSidebar'
|
import DeveloperSidebar from './Developer/DeveloperSidebar'
|
||||||
import DashboardSidebarSplitter from './common/DashboardSidebarSplitter'
|
|
||||||
import { useThemeContext } from './context/ThemeContext'
|
import { useThemeContext } from './context/ThemeContext'
|
||||||
import { MessageProvider } from './context/MessageContext'
|
import { MessageProvider } from './context/MessageContext'
|
||||||
|
|
||||||
@ -27,22 +26,6 @@ const DashboardLayout = ({ children }) => {
|
|||||||
|
|
||||||
const { isDarkMode } = useThemeContext()
|
const { isDarkMode } = useThemeContext()
|
||||||
|
|
||||||
const sidebar = isProduction ? (
|
|
||||||
<ProductionSidebar />
|
|
||||||
) : isInventory ? (
|
|
||||||
<InventorySidebar />
|
|
||||||
) : isFinance ? (
|
|
||||||
<FinanceSidebar />
|
|
||||||
) : isSales ? (
|
|
||||||
<SalesSidebar />
|
|
||||||
) : isManagement ? (
|
|
||||||
<ManagementSidebar />
|
|
||||||
) : isDeveloper ? (
|
|
||||||
<DeveloperSidebar />
|
|
||||||
) : (
|
|
||||||
<ProductionSidebar />
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MessageProvider>
|
<MessageProvider>
|
||||||
<Layout
|
<Layout
|
||||||
@ -50,18 +33,34 @@ const DashboardLayout = ({ children }) => {
|
|||||||
className={`${isDarkMode ? 'dark-mode' : 'light-mode'} main-layout`}
|
className={`${isDarkMode ? 'dark-mode' : 'light-mode'} main-layout`}
|
||||||
>
|
>
|
||||||
<DashboardNavigation />
|
<DashboardNavigation />
|
||||||
<DashboardSidebarSplitter sidebar={sidebar}>
|
<Layout>
|
||||||
|
{isProduction ? (
|
||||||
|
<ProductionSidebar />
|
||||||
|
) : isInventory ? (
|
||||||
|
<InventorySidebar />
|
||||||
|
) : isFinance ? (
|
||||||
|
<FinanceSidebar />
|
||||||
|
) : isSales ? (
|
||||||
|
<SalesSidebar />
|
||||||
|
) : isManagement ? (
|
||||||
|
<ManagementSidebar />
|
||||||
|
) : isDeveloper ? (
|
||||||
|
<DeveloperSidebar />
|
||||||
|
) : (
|
||||||
|
<ProductionSidebar /> // Default to production sidebar
|
||||||
|
)}
|
||||||
<Layout style={{ padding: '24px' }} className='main-content-layout'>
|
<Layout style={{ padding: '24px' }} className='main-content-layout'>
|
||||||
<Content>
|
<Content>
|
||||||
<Flex vertical style={{ height: '100%' }} gap='20px'>
|
<Flex vertical style={{ height: '100%' }} gap='20px'>
|
||||||
<Flex justify='space-between'>
|
<Flex justify='space-between'>
|
||||||
<DashboardBreadcrumb style={{ margin: '16px 0' }} />
|
<DashboardBreadcrumb style={{ margin: '16px 0' }} />
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
{children}
|
{children}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Content>
|
</Content>
|
||||||
</Layout>
|
</Layout>
|
||||||
</DashboardSidebarSplitter>
|
</Layout>
|
||||||
</Layout>
|
</Layout>
|
||||||
</MessageProvider>
|
</MessageProvider>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { cloneElement, isValidElement, useState, useEffect, useContext } from 'react'
|
import { useState, useEffect, useContext } from 'react'
|
||||||
import { Layout, Menu, Flex, Button } from 'antd'
|
import { Layout, Menu, Flex, Button } from 'antd'
|
||||||
import { CaretDownFilled } from '@ant-design/icons'
|
import { CaretDownFilled } from '@ant-design/icons'
|
||||||
import CollapseSidebarIcon from '../../Icons/CollapseSidebarIcon'
|
import CollapseSidebarIcon from '../../Icons/CollapseSidebarIcon'
|
||||||
@ -12,35 +12,13 @@ import { getSidebarIconNode } from '../../Icons/sidebarIconMap'
|
|||||||
import SimpleBar from 'simplebar-react'
|
import SimpleBar from 'simplebar-react'
|
||||||
import { useThemeContext } from '../context/ThemeContext'
|
import { useThemeContext } from '../context/ThemeContext'
|
||||||
import { filterSidebarItemsByListPermission } from '../../../database/Sidebars'
|
import { filterSidebarItemsByListPermission } from '../../../database/Sidebars'
|
||||||
import Tooltip from './Tooltip'
|
|
||||||
const { Sider } = Layout
|
const { Sider } = Layout
|
||||||
|
|
||||||
const CollapsedItemIcon = ({ className, icon, title }) => {
|
|
||||||
const iconNode = isValidElement(icon)
|
|
||||||
? cloneElement(icon, {
|
|
||||||
className: [icon.props.className, className].filter(Boolean).join(' ')
|
|
||||||
})
|
|
||||||
: icon
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Tooltip title={title}>
|
|
||||||
{iconNode ?? <span className={className} />}
|
|
||||||
</Tooltip>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
CollapsedItemIcon.propTypes = {
|
|
||||||
className: PropTypes.string,
|
|
||||||
icon: PropTypes.node,
|
|
||||||
title: PropTypes.node
|
|
||||||
}
|
|
||||||
|
|
||||||
const DashboardSidebar = ({
|
const DashboardSidebar = ({
|
||||||
items = [],
|
items = [],
|
||||||
selectedKey = '',
|
selectedKey = '',
|
||||||
onCollapse,
|
onCollapse,
|
||||||
collapsed: collapsedProp,
|
collapsed: collapsedProp,
|
||||||
collapsedWidth: collapsedWidthProp,
|
|
||||||
key = 'DashboardSidebar_collapseState'
|
key = 'DashboardSidebar_collapseState'
|
||||||
}) => {
|
}) => {
|
||||||
const [collapsed, setCollapsed] = useState(() => {
|
const [collapsed, setCollapsed] = useState(() => {
|
||||||
@ -52,7 +30,6 @@ const DashboardSidebar = ({
|
|||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { isDarkMode } = useThemeContext()
|
const { isDarkMode } = useThemeContext()
|
||||||
const { isElectron } = useContext(ElectronContext)
|
const { isElectron } = useContext(ElectronContext)
|
||||||
const collapsedWidth = collapsedWidthProp ?? (isElectron ? 55 : 80)
|
|
||||||
const { userProfile } = useContext(AuthContext)
|
const { userProfile } = useContext(AuthContext)
|
||||||
const allowedItems = filterSidebarItemsByListPermission(items, userProfile)
|
const allowedItems = filterSidebarItemsByListPermission(items, userProfile)
|
||||||
|
|
||||||
@ -75,15 +52,9 @@ const DashboardSidebar = ({
|
|||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
|
|
||||||
const icon = item.icon || getSidebarIconNode(item.iconKey)
|
|
||||||
const mappedItem = {
|
const mappedItem = {
|
||||||
key: item.key,
|
key: item.key,
|
||||||
icon:
|
icon: item.icon || getSidebarIconNode(item.iconKey),
|
||||||
collapsed && !isMobile ? (
|
|
||||||
<CollapsedItemIcon title={item.label} icon={icon} />
|
|
||||||
) : (
|
|
||||||
icon
|
|
||||||
),
|
|
||||||
label: item.label
|
label: item.label
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,14 +90,10 @@ const DashboardSidebar = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Sider
|
<Sider
|
||||||
width='100%'
|
width={250}
|
||||||
collapsedWidth={collapsedWidth}
|
|
||||||
theme='light'
|
theme='light'
|
||||||
collapsed={collapsed}
|
collapsed={collapsed}
|
||||||
className={`dashboard-sider${isElectron ? ' electron-sider' : ''}`}
|
className={isElectron ? 'electron-sider' : ''}
|
||||||
style={{
|
|
||||||
'--dashboard-sidebar-collapsed-width': `${collapsedWidth}px`
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Flex
|
<Flex
|
||||||
style={{ height: '100%', minHeight: 0 }}
|
style={{ height: '100%', minHeight: 0 }}
|
||||||
@ -165,7 +132,6 @@ DashboardSidebar.propTypes = {
|
|||||||
selectedKey: PropTypes.string,
|
selectedKey: PropTypes.string,
|
||||||
onCollapse: PropTypes.func,
|
onCollapse: PropTypes.func,
|
||||||
collapsed: PropTypes.bool,
|
collapsed: PropTypes.bool,
|
||||||
collapsedWidth: PropTypes.number,
|
|
||||||
key: PropTypes.string
|
key: PropTypes.string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,222 +0,0 @@
|
|||||||
import {
|
|
||||||
cloneElement,
|
|
||||||
isValidElement,
|
|
||||||
useCallback,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useRef,
|
|
||||||
useState
|
|
||||||
} from 'react'
|
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import { Layout, Splitter } from 'antd'
|
|
||||||
import { useMediaQuery } from 'react-responsive'
|
|
||||||
import { ElectronContext } from '../context/ElectronContext'
|
|
||||||
|
|
||||||
const COLLAPSE_BELOW_PX = 150
|
|
||||||
const DEFAULT_SIDEBAR_PX = 300
|
|
||||||
const MAX_SIDEBAR_PX = 400
|
|
||||||
const COLLAPSED_WIDTH_PX = 80
|
|
||||||
const ELECTRON_COLLAPSED_WIDTH_PX = 55
|
|
||||||
const COLLAPSE_STORAGE_KEY = 'DashboardSidebar_collapseState'
|
|
||||||
const SIZE_STORAGE_KEY = 'DashboardSidebar_width'
|
|
||||||
|
|
||||||
const readStoredBoolean = (key, fallback) => {
|
|
||||||
try {
|
|
||||||
const saved = sessionStorage.getItem(key)
|
|
||||||
return saved ? JSON.parse(saved) : fallback
|
|
||||||
} catch {
|
|
||||||
return fallback
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const readStoredNumber = (key, fallback) => {
|
|
||||||
try {
|
|
||||||
const saved = sessionStorage.getItem(key)
|
|
||||||
const value = saved ? JSON.parse(saved) : fallback
|
|
||||||
return typeof value === 'number' && !Number.isNaN(value) ? value : fallback
|
|
||||||
} catch {
|
|
||||||
return fallback
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const clampExpandedSize = (size) =>
|
|
||||||
Math.min(MAX_SIDEBAR_PX, Math.max(size, COLLAPSE_BELOW_PX))
|
|
||||||
|
|
||||||
const DashboardSidebarSplitter = ({ sidebar, children }) => {
|
|
||||||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
|
||||||
const { isElectron } = useContext(ElectronContext)
|
|
||||||
const collapsedWidth = isElectron
|
|
||||||
? ELECTRON_COLLAPSED_WIDTH_PX
|
|
||||||
: COLLAPSED_WIDTH_PX
|
|
||||||
|
|
||||||
const [collapsed, setCollapsed] = useState(() =>
|
|
||||||
readStoredBoolean(COLLAPSE_STORAGE_KEY, false)
|
|
||||||
)
|
|
||||||
const [sidebarSize, setSidebarSize] = useState(() => {
|
|
||||||
if (readStoredBoolean(COLLAPSE_STORAGE_KEY, false)) {
|
|
||||||
return isElectron ? ELECTRON_COLLAPSED_WIDTH_PX : COLLAPSED_WIDTH_PX
|
|
||||||
}
|
|
||||||
return clampExpandedSize(
|
|
||||||
readStoredNumber(SIZE_STORAGE_KEY, DEFAULT_SIDEBAR_PX)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const collapsedRef = useRef(collapsed)
|
|
||||||
collapsedRef.current = collapsed
|
|
||||||
const lastExpandedSizeRef = useRef(
|
|
||||||
clampExpandedSize(readStoredNumber(SIZE_STORAGE_KEY, DEFAULT_SIDEBAR_PX))
|
|
||||||
)
|
|
||||||
const [sizeTransitioning, setSizeTransitioning] = useState(false)
|
|
||||||
const sizeTransitionTimeoutRef = useRef(null)
|
|
||||||
|
|
||||||
const startSizeTransition = useCallback(() => {
|
|
||||||
setSizeTransitioning(true)
|
|
||||||
if (sizeTransitionTimeoutRef.current) {
|
|
||||||
clearTimeout(sizeTransitionTimeoutRef.current)
|
|
||||||
}
|
|
||||||
sizeTransitionTimeoutRef.current = setTimeout(() => {
|
|
||||||
setSizeTransitioning(false)
|
|
||||||
sizeTransitionTimeoutRef.current = null
|
|
||||||
}, 150)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
useEffect(
|
|
||||||
() => () => {
|
|
||||||
if (sizeTransitionTimeoutRef.current) {
|
|
||||||
clearTimeout(sizeTransitionTimeoutRef.current)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[]
|
|
||||||
)
|
|
||||||
|
|
||||||
const persistCollapsed = (nextCollapsed) => {
|
|
||||||
sessionStorage.setItem(COLLAPSE_STORAGE_KEY, JSON.stringify(nextCollapsed))
|
|
||||||
}
|
|
||||||
|
|
||||||
const persistSize = (size) => {
|
|
||||||
sessionStorage.setItem(SIZE_STORAGE_KEY, JSON.stringify(size))
|
|
||||||
}
|
|
||||||
|
|
||||||
const collapseSidebar = useCallback(
|
|
||||||
(expandedSize) => {
|
|
||||||
if (expandedSize >= COLLAPSE_BELOW_PX) {
|
|
||||||
lastExpandedSizeRef.current = expandedSize
|
|
||||||
persistSize(expandedSize)
|
|
||||||
}
|
|
||||||
collapsedRef.current = true
|
|
||||||
setCollapsed(true)
|
|
||||||
persistCollapsed(true)
|
|
||||||
startSizeTransition()
|
|
||||||
setSidebarSize(collapsedWidth)
|
|
||||||
},
|
|
||||||
[collapsedWidth, startSizeTransition]
|
|
||||||
)
|
|
||||||
|
|
||||||
const expandSidebar = useCallback(() => {
|
|
||||||
collapsedRef.current = false
|
|
||||||
setCollapsed(false)
|
|
||||||
persistCollapsed(false)
|
|
||||||
startSizeTransition()
|
|
||||||
setSidebarSize(DEFAULT_SIDEBAR_PX)
|
|
||||||
persistSize(DEFAULT_SIDEBAR_PX)
|
|
||||||
lastExpandedSizeRef.current = DEFAULT_SIDEBAR_PX
|
|
||||||
}, [startSizeTransition])
|
|
||||||
|
|
||||||
const handleSidebarCollapse = useCallback(
|
|
||||||
(nextCollapsed) => {
|
|
||||||
if (nextCollapsed) {
|
|
||||||
collapseSidebar(sidebarSize)
|
|
||||||
} else {
|
|
||||||
expandSidebar()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[collapseSidebar, expandSidebar, sidebarSize]
|
|
||||||
)
|
|
||||||
|
|
||||||
const handleResize = useCallback(
|
|
||||||
(sizes) => {
|
|
||||||
if (collapsedRef.current) {
|
|
||||||
setSidebarSize(collapsedWidth)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const size = sizes[0]
|
|
||||||
if (size < COLLAPSE_BELOW_PX) {
|
|
||||||
collapseSidebar(lastExpandedSizeRef.current)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
setSidebarSize(size)
|
|
||||||
lastExpandedSizeRef.current = clampExpandedSize(size)
|
|
||||||
},
|
|
||||||
[collapseSidebar, collapsedWidth]
|
|
||||||
)
|
|
||||||
|
|
||||||
const handleResizeEnd = useCallback(
|
|
||||||
(sizes) => {
|
|
||||||
if (collapsedRef.current) {
|
|
||||||
setSidebarSize(collapsedWidth)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const next = clampExpandedSize(sizes[0])
|
|
||||||
lastExpandedSizeRef.current = next
|
|
||||||
setSidebarSize(next)
|
|
||||||
persistSize(next)
|
|
||||||
},
|
|
||||||
[collapsedWidth]
|
|
||||||
)
|
|
||||||
|
|
||||||
const sidebarNode = isValidElement(sidebar)
|
|
||||||
? cloneElement(sidebar, {
|
|
||||||
collapsed,
|
|
||||||
collapsedWidth,
|
|
||||||
onCollapse: handleSidebarCollapse
|
|
||||||
})
|
|
||||||
: sidebar
|
|
||||||
|
|
||||||
if (isMobile) {
|
|
||||||
return (
|
|
||||||
<Layout>
|
|
||||||
{sidebarNode}
|
|
||||||
{children}
|
|
||||||
</Layout>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Layout style={{ height: '100%', minHeight: 0 }}>
|
|
||||||
<Splitter
|
|
||||||
className={`farmcontrol-splitter dashboard-splitter${
|
|
||||||
sizeTransitioning ? ' is-size-transitioning' : ''
|
|
||||||
}`}
|
|
||||||
style={{ height: '100%' }}
|
|
||||||
onResize={handleResize}
|
|
||||||
onResizeEnd={handleResizeEnd}
|
|
||||||
>
|
|
||||||
<Splitter.Panel
|
|
||||||
size={sidebarSize}
|
|
||||||
min={collapsedWidth}
|
|
||||||
max={collapsed ? collapsedWidth : MAX_SIDEBAR_PX}
|
|
||||||
resizable={!collapsed}
|
|
||||||
style={{
|
|
||||||
overflow: 'hidden',
|
|
||||||
minWidth: collapsedWidth,
|
|
||||||
maxWidth:
|
|
||||||
collapsed && !sizeTransitioning ? collapsedWidth : undefined
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{sidebarNode}
|
|
||||||
</Splitter.Panel>
|
|
||||||
<Splitter.Panel min={320}>{children}</Splitter.Panel>
|
|
||||||
</Splitter>
|
|
||||||
</Layout>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
DashboardSidebarSplitter.propTypes = {
|
|
||||||
sidebar: PropTypes.node.isRequired,
|
|
||||||
children: PropTypes.node.isRequired
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DashboardSidebarSplitter
|
|
||||||
@ -1,7 +1,6 @@
|
|||||||
import { useLayoutEffect, useRef, useState } from 'react'
|
import { useLayoutEffect, useRef, useState } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Typography } from 'antd'
|
import { Typography } from 'antd'
|
||||||
import Tooltip from './Tooltip'
|
|
||||||
|
|
||||||
const { Text } = Typography
|
const { Text } = Typography
|
||||||
|
|
||||||
@ -71,32 +70,29 @@ const ElipsisText = ({ children, style, className, title, code, ...rest }) => {
|
|||||||
const showTruncated = truncated && Boolean(end)
|
const showTruncated = truncated && Boolean(end)
|
||||||
const RootTag = code ? 'code' : 'span'
|
const RootTag = code ? 'code' : 'span'
|
||||||
|
|
||||||
const content = (
|
|
||||||
<span
|
|
||||||
className={showTruncated ? 'elipsis-text is-truncated' : 'elipsis-text'}
|
|
||||||
ref={containerRef}
|
|
||||||
>
|
|
||||||
<RootTag className='elipsis-text-measure' ref={measureRef}>
|
|
||||||
{text}
|
|
||||||
</RootTag>
|
|
||||||
<RootTag className='elipsis-text-full'>{text}</RootTag>
|
|
||||||
<RootTag className='elipsis-text-truncated'>
|
|
||||||
<span className='elipsis-text-start'>{start}</span>
|
|
||||||
<span className='elipsis-text-dots'>...</span>
|
|
||||||
<span className='elipsis-text-end'>
|
|
||||||
<span className='elipsis-text-end-inner'>{end}</span>
|
|
||||||
</span>
|
|
||||||
</RootTag>
|
|
||||||
</span>
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text
|
||||||
{...rest}
|
{...rest}
|
||||||
className={['elipsis-text-wrapper', className].filter(Boolean).join(' ')}
|
className={['elipsis-text-wrapper', className].filter(Boolean).join(' ')}
|
||||||
|
title={title ?? text}
|
||||||
style={style}
|
style={style}
|
||||||
>
|
>
|
||||||
{truncated ? <Tooltip title={title ?? text}>{content}</Tooltip> : content}
|
<span
|
||||||
|
className={showTruncated ? 'elipsis-text is-truncated' : 'elipsis-text'}
|
||||||
|
ref={containerRef}
|
||||||
|
>
|
||||||
|
<RootTag className='elipsis-text-measure' ref={measureRef}>
|
||||||
|
{text}
|
||||||
|
</RootTag>
|
||||||
|
<RootTag className='elipsis-text-full'>{text}</RootTag>
|
||||||
|
<RootTag className='elipsis-text-truncated'>
|
||||||
|
<span className='elipsis-text-start'>{start}</span>
|
||||||
|
<span className='elipsis-text-dots'>...</span>
|
||||||
|
<span className='elipsis-text-end'>
|
||||||
|
<span className='elipsis-text-end-inner'>{end}</span>
|
||||||
|
</span>
|
||||||
|
</RootTag>
|
||||||
|
</span>
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user