Enhance Dashboard Navigation with Object Navigation Hook
- Introduced `useObjectNavigationTabPage` hook to streamline navigation tab management for various dashboard components, improving consistency in object handling. - Updated multiple components (DocumentTemplateDesign, EmailTemplateDesign, NoteInfo, GCodeFilePreview, ControlPrinter) to utilize the new hook for better object navigation and state management. - Adjusted CSS styles for dashboard tabs to improve layout and responsiveness, enhancing user experience across devices.
This commit is contained in:
parent
2f9f42c9e2
commit
7fef25d911
@ -3371,7 +3371,7 @@ body.objectKanbanColumnResizing * {
|
||||
}
|
||||
|
||||
.dashboard-tabs-label {
|
||||
max-width: 200px;
|
||||
max-width: 280px;
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ import { useDashboardObjectTools } from '../../context/DashboardObjectToolsConte
|
||||
import ScrollBox from '../../common/ScrollBox.jsx'
|
||||
|
||||
import TemplateEditor from '../../common/TemplateEditor.jsx'
|
||||
import { useObjectNavigationTabPage } from '../../hooks/useObjectNavigationTabPage'
|
||||
|
||||
const log = loglevel.getLogger('DocumentTemplateDesign')
|
||||
log.setLevel(config.logLevel)
|
||||
@ -30,6 +31,11 @@ const DocumentTemplateDesign = () => {
|
||||
const documentTemplateId = new URLSearchParams(location.search).get(
|
||||
'documentTemplateId'
|
||||
)
|
||||
useObjectNavigationTabPage({
|
||||
modelName: 'documentTemplate',
|
||||
pageName: 'design',
|
||||
objectId: documentTemplateId
|
||||
})
|
||||
const [collapseState, updateCollapseState] = useCollapseState(
|
||||
'DocumentTemplateDesign',
|
||||
{
|
||||
|
||||
@ -16,6 +16,7 @@ import ObjectActions from '../../common/ObjectActions'
|
||||
import TemplateEditor from '../../common/TemplateEditor'
|
||||
import ScrollBox from '../../common/ScrollBox'
|
||||
import { useDashboardObjectTools } from '../../context/DashboardObjectToolsContext'
|
||||
import { useObjectNavigationTabPage } from '../../hooks/useObjectNavigationTabPage'
|
||||
|
||||
const EmailTemplateDesign = () => {
|
||||
const location = useLocation()
|
||||
@ -24,6 +25,11 @@ const EmailTemplateDesign = () => {
|
||||
const emailTemplateId = new URLSearchParams(location.search).get(
|
||||
'emailTemplateId'
|
||||
)
|
||||
useObjectNavigationTabPage({
|
||||
modelName: 'emailTemplate',
|
||||
pageName: 'design',
|
||||
objectId: emailTemplateId
|
||||
})
|
||||
const [collapseState, updateCollapseState] = useCollapseState(
|
||||
'EmailTemplateDesign',
|
||||
{ preview: true, editor: true, notes: true }
|
||||
|
||||
@ -21,7 +21,7 @@ import ActivityIndicator from '../../common/ActivityIndicator.jsx'
|
||||
import ActionHandler from '../../common/ActionHandler.jsx'
|
||||
import ObjectActions from '../../common/ObjectActions.jsx'
|
||||
import { useDashboardObjectTools } from '../../context/DashboardObjectToolsContext'
|
||||
import { useNavigationTabPage } from '../../context/NavigationTabsContext'
|
||||
import { useObjectNavigationTabPage } from '../../hooks/useObjectNavigationTabPage'
|
||||
import ObjectTable from '../../common/ObjectTable.jsx'
|
||||
import InfoCollapsePlaceholder from '../../common/InfoCollapsePlaceholder.jsx'
|
||||
import InfoActionButtons from '../../common/InfoActionButtons.jsx'
|
||||
@ -33,11 +33,15 @@ const log = loglevel.getLogger('NoteInfo')
|
||||
log.setLevel(config.logLevel)
|
||||
|
||||
const NoteInfo = () => {
|
||||
useNavigationTabPage({ title: 'Info - Note', modelName: 'note' })
|
||||
const location = useLocation()
|
||||
const objectFormRef = useRef(null)
|
||||
const actionHandlerRef = useRef(null)
|
||||
const noteId = new URLSearchParams(location.search).get('noteId')
|
||||
useObjectNavigationTabPage({
|
||||
modelName: 'note',
|
||||
pageName: 'info',
|
||||
objectId: noteId
|
||||
})
|
||||
const [collapseState, updateCollapseState] = useCollapseState('NoteInfo', {
|
||||
info: true,
|
||||
content: true,
|
||||
|
||||
@ -21,6 +21,7 @@ import MissingPlaceholder from '../../common/MissingPlaceholder.jsx'
|
||||
import InfoCollapsePlaceholder from '../../common/InfoCollapsePlaceholder.jsx'
|
||||
import DocumentPrintButton from '../../common/DocumentPrintButton.jsx'
|
||||
import UserNotifierToggle from '../../common/UserNotifierToggle.jsx'
|
||||
import { useObjectNavigationTabPage } from '../../hooks/useObjectNavigationTabPage'
|
||||
|
||||
const log = loglevel.getLogger('GCodeFilePreview')
|
||||
log.setLevel(config.logLevel)
|
||||
@ -29,6 +30,11 @@ const GCodeFilePreview = () => {
|
||||
const location = useLocation()
|
||||
const objectFormRef = useRef(null)
|
||||
const gcodeFileId = new URLSearchParams(location.search).get('gcodeFileId')
|
||||
useObjectNavigationTabPage({
|
||||
modelName: 'gcodeFile',
|
||||
pageName: 'preview',
|
||||
objectId: gcodeFileId
|
||||
})
|
||||
const [collapseState, updateCollapseState] = useCollapseState(
|
||||
'GCodeFilePreview',
|
||||
{
|
||||
|
||||
@ -37,6 +37,7 @@ import ObjectTableNavigationButtons from '../../common/ObjectTableNavigationButt
|
||||
import PrinterControlButtons from '../../common/PrinterControlButtons.jsx'
|
||||
import PrinterQueue from '../../common/PrinterQueue.jsx'
|
||||
import ListIcon from '../../../Icons/ListIcon.jsx'
|
||||
import { useObjectNavigationTabPage } from '../../hooks/useObjectNavigationTabPage'
|
||||
|
||||
const log = loglevel.getLogger('ControlPrinter')
|
||||
log.setLevel(config.logLevel)
|
||||
@ -47,6 +48,11 @@ const ControlPrinter = ({ slicerIntegration = false }) => {
|
||||
const actionHandlerRef = useRef(null)
|
||||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
||||
const printerId = new URLSearchParams(location.search).get('printerId')
|
||||
useObjectNavigationTabPage({
|
||||
modelName: 'printer',
|
||||
pageName: 'control',
|
||||
objectId: printerId
|
||||
})
|
||||
const [collapseState, updateCollapseState] = useCollapseState(
|
||||
'ControlPrinter',
|
||||
{
|
||||
|
||||
@ -16,7 +16,7 @@ const { Text } = Typography
|
||||
|
||||
const DashboardTabLabel = ({ tab, onClose }) => (
|
||||
<Flex align='center' gap={6} className='dashboard-tabs-label'>
|
||||
<Text ellipsis style={{ maxWidth: 160 }}>
|
||||
<Text ellipsis style={{ maxWidth: 240 }}>
|
||||
{tab.title || 'Farm Control'}
|
||||
</Text>
|
||||
<span
|
||||
|
||||
@ -7,7 +7,8 @@ import { getModelByName } from '../../../database/ObjectModels'
|
||||
import { getObjectIdFromSearch } from '../../../utils/modelActions'
|
||||
import { useActions } from '../context/ActionsContext'
|
||||
import { AuthContext } from '../context/AuthContext'
|
||||
import { useNavigationTabPage, useIsNavigationTabActive } from '../context/NavigationTabsContext'
|
||||
import { useIsNavigationTabActive } from '../context/NavigationTabsContext'
|
||||
import { useObjectNavigationTabPage } from '../hooks/useObjectNavigationTabPage'
|
||||
|
||||
const ModelPage = ({ modelName, pageName }) => {
|
||||
const model = getModelByName(modelName)
|
||||
@ -16,9 +17,8 @@ const ModelPage = ({ modelName, pageName }) => {
|
||||
const { setCurrentObject, setCurrentObjectType } = useActions()
|
||||
const { userProfile } = useContext(AuthContext)
|
||||
const objectId = getObjectIdFromSearch(modelName, location.search)
|
||||
const pageTitle = `${pageName.charAt(0).toUpperCase()}${pageName.slice(1)} - ${model?.label || modelName}`
|
||||
const isTabActive = useIsNavigationTabActive()
|
||||
useNavigationTabPage({ title: pageTitle, modelName })
|
||||
useObjectNavigationTabPage({ modelName, pageName, objectId })
|
||||
|
||||
useEffect(() => {
|
||||
if (!isTabActive) return undefined
|
||||
|
||||
@ -131,7 +131,9 @@ export const ObjectListViewProvider = ({ children, objectType, tableRef }) => {
|
||||
const { getViewFromUrl, persistView, setObjectListView } = useTableState()
|
||||
const listModel = getModelByName(objectType)
|
||||
useNavigationTabPage({
|
||||
title: listModel?.label ? `List - ${listModel.label}` : 'List',
|
||||
title: listModel?.labelPlural
|
||||
? `List - ${listModel.labelPlural}`
|
||||
: 'List',
|
||||
modelName: objectType
|
||||
})
|
||||
|
||||
|
||||
@ -0,0 +1,82 @@
|
||||
import { useContext, useEffect, useRef, useState } from 'react'
|
||||
import { getModelByName } from '../../../database/ObjectModels'
|
||||
import { ApiServerContext } from '../context/ApiServerContext'
|
||||
import { AuthContext } from '../context/AuthContext'
|
||||
import { useNavigationTabPage } from '../context/NavigationTabsContext'
|
||||
|
||||
const formatPageLabel = (pageName) =>
|
||||
pageName
|
||||
? `${pageName.charAt(0).toUpperCase()}${pageName.slice(1)}`
|
||||
: 'Page'
|
||||
|
||||
const getObjectDisplayName = (objectData, model) => {
|
||||
if (objectData?.name) return objectData.name
|
||||
if (objectData?._reference && model?.prefix) {
|
||||
return `${model.prefix}:${objectData._reference}`
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export const formatObjectPageTabTitle = ({
|
||||
pageName,
|
||||
model,
|
||||
objectName
|
||||
} = {}) => {
|
||||
const pageLabel = formatPageLabel(pageName)
|
||||
const collectionLabel = model?.labelPlural
|
||||
if (objectName && collectionLabel) {
|
||||
return `${pageLabel} (${objectName}) - ${collectionLabel}`
|
||||
}
|
||||
if (objectName) return `${pageLabel} (${objectName})`
|
||||
if (collectionLabel) return `${pageLabel} - ${collectionLabel}`
|
||||
return pageLabel
|
||||
}
|
||||
|
||||
export const useObjectNavigationTabPage = ({
|
||||
modelName,
|
||||
pageName,
|
||||
objectId
|
||||
} = {}) => {
|
||||
const model = getModelByName(modelName)
|
||||
const { fetchSpotlightData, subscribeToObjectUpdates, connected } =
|
||||
useContext(ApiServerContext)
|
||||
const { token } = useContext(AuthContext)
|
||||
const [objectName, setObjectName] = useState(null)
|
||||
const fetchSpotlightDataRef = useRef(fetchSpotlightData)
|
||||
fetchSpotlightDataRef.current = fetchSpotlightData
|
||||
|
||||
useEffect(() => {
|
||||
if (!objectId || !model?.prefix || token == null) {
|
||||
setObjectName(null)
|
||||
return undefined
|
||||
}
|
||||
|
||||
let cancelled = false
|
||||
const query = `${model.prefix}:${objectId}`
|
||||
|
||||
void fetchSpotlightDataRef.current(query).then((result) => {
|
||||
if (cancelled) return
|
||||
if (result && typeof result === 'object' && !Array.isArray(result)) {
|
||||
setObjectName(getObjectDisplayName(result, model))
|
||||
}
|
||||
})
|
||||
|
||||
return () => {
|
||||
cancelled = true
|
||||
}
|
||||
}, [model, objectId, token])
|
||||
|
||||
useEffect(() => {
|
||||
if (!objectId || !modelName || !connected) return undefined
|
||||
return subscribeToObjectUpdates(objectId, modelName, (value) => {
|
||||
setObjectName((current) => getObjectDisplayName(value, model) || current)
|
||||
})
|
||||
}, [connected, model, modelName, objectId, subscribeToObjectUpdates])
|
||||
|
||||
useNavigationTabPage({
|
||||
title: formatObjectPageTabTitle({ pageName, model, objectName }),
|
||||
modelName
|
||||
})
|
||||
}
|
||||
|
||||
export default useObjectNavigationTabPage
|
||||
Loading…
x
Reference in New Issue
Block a user