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:
Tom Butcher 2026-08-01 15:21:58 +01:00
parent 12cae32e33
commit f3d6bebc38
4 changed files with 205 additions and 156 deletions

View File

@ -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,6 +87,7 @@ const AppContent = () => {
<NotificationProvider>
<SpotlightProvider>
<ActionsModalProvider>
<TableStateProvider>
<Routes>
<Route
path='/applaunch'
@ -156,6 +158,7 @@ const AppContent = () => {
}
/>
</Routes>
</TableStateProvider>
</ActionsModalProvider>
</SpotlightProvider>
</NotificationProvider>

View File

@ -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,7 +28,6 @@ const DashboardLayout = ({ children }) => {
return (
<MessageProvider>
<TableStateProvider>
<Layout
style={{ height: 'var(--unit-100vh)' }}
className={isDarkMode ? 'dark-mode' : 'light-mode'}
@ -64,7 +62,6 @@ const DashboardLayout = ({ children }) => {
</Layout>
</Layout>
</Layout>
</TableStateProvider>
</MessageProvider>
)
}

View File

@ -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>
{!slicerIntegration && (
<ObjectTableNavigationButtons
disabled={objectFormState.loading}
_id={printerId}
objectType='printer'
/>
)}
</Flex>
<AlertsDisplay

View File

@ -37,9 +37,48 @@ 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) => {
function mapActionsToMenuItems(
actions,
currentUrlWithActions,
id,
objectData,
userProfile
) {
return cleanDividers(
actions.map((action) => {
if (action.type === 'divider') {
return { type: 'divider' }
}
@ -48,8 +87,6 @@ function mapActionsToMenuItems(actions, currentUrlWithActions, id, objectData) {
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 })
@ -66,6 +103,10 @@ function mapActionsToMenuItems(actions, currentUrlWithActions, id, objectData) {
}
}
if (visible != true) {
return null
}
const item = {
key: action.key || action.name,
label: action.label,
@ -78,13 +119,13 @@ function mapActionsToMenuItems(actions, currentUrlWithActions, id, objectData) {
action.children,
currentUrlWithActions,
id,
objectData
objectData,
userProfile
)
}
if (visible == true) {
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,11 +162,14 @@ const ObjectActions = ({
visibleActions
)
const filteredActions = visibilityFilteredActions.filter(
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