Integrate TableStateProvider into App and Dashboard components for enhanced state management
- Added TableStateProvider to the App component, encapsulating routing logic to manage table states effectively. - Removed redundant TableStateProvider from the DashboardLayout component, streamlining the component structure. - Updated ControlPrinter and ObjectActions components to improve action visibility and navigation button rendering based on slicer integration state. - Enhanced action filtering in ObjectActions to eliminate unnecessary dividers, improving menu item clarity.
This commit is contained in:
parent
12cae32e33
commit
f3d6bebc38
141
src/App.jsx
141
src/App.jsx
@ -34,6 +34,7 @@ import AuthCallback from './components/App/AuthCallback.jsx'
|
||||
import EmailNotificationTemplate from './components/Email/EmailNotificationTemplate.jsx'
|
||||
import MarketplaceAuthCallback from './components/Dashboard/Sales/Marketplaces/MarketplaceAuthCallback.jsx'
|
||||
import AuthLaunch from './components/App/AppLaunch.jsx'
|
||||
import { TableStateProvider } from './components/Dashboard/context/TableStateContext.jsx'
|
||||
const SlicerIntegration = lazy(
|
||||
() =>
|
||||
import('./components/Dashboard/Production/Printers/SlicerIntegration.jsx')
|
||||
@ -86,76 +87,78 @@ const AppContent = () => {
|
||||
<NotificationProvider>
|
||||
<SpotlightProvider>
|
||||
<ActionsModalProvider>
|
||||
<Routes>
|
||||
<Route
|
||||
path='/applaunch'
|
||||
element={<AuthLaunch />}
|
||||
/>
|
||||
<Route
|
||||
path='/dashboard/electron/spotlightcontent'
|
||||
element={
|
||||
<PrivateRoute
|
||||
component={() => (
|
||||
<ElectronSpotlightContentPage />
|
||||
)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path='/'
|
||||
element={
|
||||
<PrivateRoute
|
||||
component={() => (
|
||||
<Navigate
|
||||
to='/dashboard/production/overview'
|
||||
replace
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path='/auth/callback'
|
||||
element={<AuthCallback />}
|
||||
/>
|
||||
<Route
|
||||
path='/auth/marketplace/callback'
|
||||
element={<MarketplaceAuthCallback />}
|
||||
/>
|
||||
<Route
|
||||
path='/email/notification'
|
||||
element={<EmailNotificationTemplate />}
|
||||
/>
|
||||
<Route
|
||||
path='/slicer'
|
||||
element={<SlicerIntegration />}
|
||||
/>
|
||||
<TableStateProvider>
|
||||
<Routes>
|
||||
<Route
|
||||
path='/applaunch'
|
||||
element={<AuthLaunch />}
|
||||
/>
|
||||
<Route
|
||||
path='/dashboard/electron/spotlightcontent'
|
||||
element={
|
||||
<PrivateRoute
|
||||
component={() => (
|
||||
<ElectronSpotlightContentPage />
|
||||
)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path='/'
|
||||
element={
|
||||
<PrivateRoute
|
||||
component={() => (
|
||||
<Navigate
|
||||
to='/dashboard/production/overview'
|
||||
replace
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path='/auth/callback'
|
||||
element={<AuthCallback />}
|
||||
/>
|
||||
<Route
|
||||
path='/auth/marketplace/callback'
|
||||
element={<MarketplaceAuthCallback />}
|
||||
/>
|
||||
<Route
|
||||
path='/email/notification'
|
||||
element={<EmailNotificationTemplate />}
|
||||
/>
|
||||
<Route
|
||||
path='/slicer'
|
||||
element={<SlicerIntegration />}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path='/dashboard'
|
||||
element={
|
||||
<PrivateRoute
|
||||
component={() => <Dashboard />}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{ProductionRoutes}
|
||||
{InventoryRoutes}
|
||||
{FinanceRoutes}
|
||||
{SalesRoutes}
|
||||
{ManagementRoutes}
|
||||
{DeveloperRoutes}
|
||||
</Route>
|
||||
<Route
|
||||
path='*'
|
||||
element={
|
||||
<AppError
|
||||
message='Error 404. Page not found.'
|
||||
showRefresh={false}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
<Route
|
||||
path='/dashboard'
|
||||
element={
|
||||
<PrivateRoute
|
||||
component={() => <Dashboard />}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{ProductionRoutes}
|
||||
{InventoryRoutes}
|
||||
{FinanceRoutes}
|
||||
{SalesRoutes}
|
||||
{ManagementRoutes}
|
||||
{DeveloperRoutes}
|
||||
</Route>
|
||||
<Route
|
||||
path='*'
|
||||
element={
|
||||
<AppError
|
||||
message='Error 404. Page not found.'
|
||||
showRefresh={false}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
</TableStateProvider>
|
||||
</ActionsModalProvider>
|
||||
</SpotlightProvider>
|
||||
</NotificationProvider>
|
||||
|
||||
@ -12,7 +12,6 @@ import DashboardBreadcrumb from './common/DashboardBreadcrumb'
|
||||
import DeveloperSidebar from './Developer/DeveloperSidebar'
|
||||
import { useThemeContext } from './context/ThemeContext'
|
||||
import { MessageProvider } from './context/MessageContext'
|
||||
import { TableStateProvider } from './context/TableStateContext'
|
||||
|
||||
const { Content } = Layout
|
||||
|
||||
@ -29,42 +28,40 @@ const DashboardLayout = ({ children }) => {
|
||||
|
||||
return (
|
||||
<MessageProvider>
|
||||
<TableStateProvider>
|
||||
<Layout
|
||||
style={{ height: 'var(--unit-100vh)' }}
|
||||
className={isDarkMode ? 'dark-mode' : 'light-mode'}
|
||||
>
|
||||
<DashboardNavigation />
|
||||
<Layout>
|
||||
{isProduction ? (
|
||||
<ProductionSidebar />
|
||||
) : isInventory ? (
|
||||
<InventorySidebar />
|
||||
) : isFinance ? (
|
||||
<FinanceSidebar />
|
||||
) : isSales ? (
|
||||
<SalesSidebar />
|
||||
) : isManagement ? (
|
||||
<ManagementSidebar />
|
||||
) : isDeveloper ? (
|
||||
<DeveloperSidebar />
|
||||
) : (
|
||||
<ProductionSidebar /> // Default to production sidebar
|
||||
)}
|
||||
<Layout style={{ padding: '24px' }}>
|
||||
<Content>
|
||||
<Flex vertical style={{ height: '100%' }} gap='20px'>
|
||||
<Flex justify='space-between'>
|
||||
<DashboardBreadcrumb style={{ margin: '16px 0' }} />
|
||||
</Flex>
|
||||
|
||||
{children}
|
||||
<Layout
|
||||
style={{ height: 'var(--unit-100vh)' }}
|
||||
className={isDarkMode ? 'dark-mode' : 'light-mode'}
|
||||
>
|
||||
<DashboardNavigation />
|
||||
<Layout>
|
||||
{isProduction ? (
|
||||
<ProductionSidebar />
|
||||
) : isInventory ? (
|
||||
<InventorySidebar />
|
||||
) : isFinance ? (
|
||||
<FinanceSidebar />
|
||||
) : isSales ? (
|
||||
<SalesSidebar />
|
||||
) : isManagement ? (
|
||||
<ManagementSidebar />
|
||||
) : isDeveloper ? (
|
||||
<DeveloperSidebar />
|
||||
) : (
|
||||
<ProductionSidebar /> // Default to production sidebar
|
||||
)}
|
||||
<Layout style={{ padding: '24px' }}>
|
||||
<Content>
|
||||
<Flex vertical style={{ height: '100%' }} gap='20px'>
|
||||
<Flex justify='space-between'>
|
||||
<DashboardBreadcrumb style={{ margin: '16px 0' }} />
|
||||
</Flex>
|
||||
</Content>
|
||||
</Layout>
|
||||
|
||||
{children}
|
||||
</Flex>
|
||||
</Content>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</TableStateProvider>
|
||||
</Layout>
|
||||
</MessageProvider>
|
||||
)
|
||||
}
|
||||
|
||||
@ -272,7 +272,8 @@ const ControlPrinter = ({ slicerIntegration = false }) => {
|
||||
visibleActions={{
|
||||
edit: false,
|
||||
info: !slicerIntegration,
|
||||
control: !slicerIntegration
|
||||
control: !slicerIntegration,
|
||||
newPrinterProfile: !slicerIntegration
|
||||
}}
|
||||
objectData={objectFormState.objectData}
|
||||
/>
|
||||
@ -318,11 +319,13 @@ const ControlPrinter = ({ slicerIntegration = false }) => {
|
||||
/>
|
||||
</Space>
|
||||
</Space>
|
||||
<ObjectTableNavigationButtons
|
||||
disabled={objectFormState.loading}
|
||||
_id={printerId}
|
||||
objectType='printer'
|
||||
/>
|
||||
{!slicerIntegration && (
|
||||
<ObjectTableNavigationButtons
|
||||
disabled={objectFormState.loading}
|
||||
_id={printerId}
|
||||
objectType='printer'
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
<AlertsDisplay
|
||||
|
||||
@ -37,54 +37,95 @@ function filterActionsByVisibility(actions, visibleActions) {
|
||||
})
|
||||
}
|
||||
|
||||
function cleanDividers(items) {
|
||||
if (!Array.isArray(items) || items.length === 0) return []
|
||||
|
||||
const cleaned = []
|
||||
|
||||
for (const item of items) {
|
||||
if (!item) continue
|
||||
|
||||
if (item.type === 'divider') {
|
||||
if (cleaned.length === 0) continue
|
||||
if (cleaned[cleaned.length - 1]?.type === 'divider') continue
|
||||
cleaned.push(item)
|
||||
continue
|
||||
}
|
||||
|
||||
if (item.children && Array.isArray(item.children)) {
|
||||
const children = cleanDividers(item.children)
|
||||
if (children.length === 0) continue
|
||||
cleaned.push({ ...item, children })
|
||||
continue
|
||||
}
|
||||
|
||||
cleaned.push(item)
|
||||
}
|
||||
|
||||
if (cleaned[cleaned.length - 1]?.type === 'divider') {
|
||||
cleaned.pop()
|
||||
}
|
||||
|
||||
return cleaned
|
||||
}
|
||||
|
||||
// Recursively map actions to AntD Dropdown items
|
||||
function mapActionsToMenuItems(actions, currentUrlWithActions, id, objectData) {
|
||||
return actions.map((action) => {
|
||||
if (action.type === 'divider') {
|
||||
return { type: 'divider' }
|
||||
}
|
||||
const actionUrl = action.url ? action.url(id) : undefined
|
||||
|
||||
var disabled = actionUrl && actionUrl === currentUrlWithActions
|
||||
var visible = true
|
||||
|
||||
const { userProfile } = useContext(AuthContext)
|
||||
|
||||
if (action.disabled) {
|
||||
if (typeof action.disabled === 'function') {
|
||||
disabled = action.disabled({ ...objectData, _user: userProfile })
|
||||
} else {
|
||||
disabled = action.disabled
|
||||
function mapActionsToMenuItems(
|
||||
actions,
|
||||
currentUrlWithActions,
|
||||
id,
|
||||
objectData,
|
||||
userProfile
|
||||
) {
|
||||
return cleanDividers(
|
||||
actions.map((action) => {
|
||||
if (action.type === 'divider') {
|
||||
return { type: 'divider' }
|
||||
}
|
||||
}
|
||||
const actionUrl = action.url ? action.url(id) : undefined
|
||||
|
||||
if (action.visible) {
|
||||
if (typeof action.visible === 'function') {
|
||||
visible = action.visible(objectData)
|
||||
} else {
|
||||
visible = action.visible
|
||||
var disabled = actionUrl && actionUrl === currentUrlWithActions
|
||||
var visible = true
|
||||
|
||||
if (action.disabled) {
|
||||
if (typeof action.disabled === 'function') {
|
||||
disabled = action.disabled({ ...objectData, _user: userProfile })
|
||||
} else {
|
||||
disabled = action.disabled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const item = {
|
||||
key: action.key || action.name,
|
||||
label: action.label,
|
||||
danger: action?.danger || false,
|
||||
icon: action.icon ? createElement(action.icon) : undefined,
|
||||
disabled
|
||||
}
|
||||
if (action.children && Array.isArray(action.children)) {
|
||||
item.children = mapActionsToMenuItems(
|
||||
action.children,
|
||||
currentUrlWithActions,
|
||||
id,
|
||||
objectData
|
||||
)
|
||||
}
|
||||
if (visible == true) {
|
||||
if (action.visible) {
|
||||
if (typeof action.visible === 'function') {
|
||||
visible = action.visible(objectData)
|
||||
} else {
|
||||
visible = action.visible
|
||||
}
|
||||
}
|
||||
|
||||
if (visible != true) {
|
||||
return null
|
||||
}
|
||||
|
||||
const item = {
|
||||
key: action.key || action.name,
|
||||
label: action.label,
|
||||
danger: action?.danger || false,
|
||||
icon: action.icon ? createElement(action.icon) : undefined,
|
||||
disabled
|
||||
}
|
||||
if (action.children && Array.isArray(action.children)) {
|
||||
item.children = mapActionsToMenuItems(
|
||||
action.children,
|
||||
currentUrlWithActions,
|
||||
id,
|
||||
objectData,
|
||||
userProfile
|
||||
)
|
||||
}
|
||||
return item
|
||||
}
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const stripActionParam = (pathname, search) => {
|
||||
@ -108,6 +149,7 @@ const ObjectActions = ({
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
const { showActionsModal } = useActionsModal()
|
||||
const { userProfile } = useContext(AuthContext)
|
||||
// Get current url without 'action' param
|
||||
const currentUrlWithoutActions = stripActionParam(
|
||||
location.pathname,
|
||||
@ -120,10 +162,13 @@ const ObjectActions = ({
|
||||
visibleActions
|
||||
)
|
||||
|
||||
const filteredActions = visibilityFilteredActions.filter(
|
||||
(action) =>
|
||||
typeof action.url !== 'function' ||
|
||||
action.url(id) !== currentUrlWithoutActions
|
||||
const filteredActions = cleanDividers(
|
||||
visibilityFilteredActions.filter(
|
||||
(action) =>
|
||||
action.type === 'divider' ||
|
||||
typeof action.url !== 'function' ||
|
||||
action.url(id) !== currentUrlWithoutActions
|
||||
)
|
||||
)
|
||||
|
||||
const currentUrlWithActions = location.pathname + location.search
|
||||
@ -134,7 +179,8 @@ const ObjectActions = ({
|
||||
filteredActions,
|
||||
currentUrlWithActions,
|
||||
id,
|
||||
objectData
|
||||
objectData,
|
||||
userProfile
|
||||
),
|
||||
onClick: (info) => {
|
||||
// Find the action by key
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user