Compare commits
No commits in common. "d6c72c21e8e1813dce30e65cf073aa3f4bab1178" and "2f9f42c9e26ebe7d8576d5975ad845a69874b316" have entirely different histories.
d6c72c21e8
...
2f9f42c9e2
@ -112,18 +112,6 @@
|
|||||||
--webkit-user-select: none;
|
--webkit-user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.electron-navigation-leading,
|
|
||||||
.electron-navigation-trailing {
|
|
||||||
align-self: stretch;
|
|
||||||
height: 42px;
|
|
||||||
border-bottom: 1px solid var(--color-header-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.electron-navigation-trailing {
|
|
||||||
flex: 0 1 auto;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.electron-body * {
|
.electron-body * {
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-khtml-user-select: none;
|
-khtml-user-select: none;
|
||||||
@ -157,20 +145,12 @@ html.macos-vibrancy .main-layout {
|
|||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
html.macos-vibrancy .light-mode {
|
|
||||||
--color-layout-background: rgba(255, 255, 255, 0.88);
|
|
||||||
}
|
|
||||||
|
|
||||||
html.macos-vibrancy .dark-mode {
|
|
||||||
--color-layout-background: rgba(0, 0, 0, 0.88);
|
|
||||||
}
|
|
||||||
|
|
||||||
html.macos-vibrancy .light-mode .ant-layout.main-content-layout {
|
html.macos-vibrancy .light-mode .ant-layout.main-content-layout {
|
||||||
background: var(--color-layout-background) !important;
|
background: rgba(255, 255, 255, 0.88) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
html.macos-vibrancy .dark-mode .ant-layout.main-content-layout {
|
html.macos-vibrancy .dark-mode .ant-layout.main-content-layout {
|
||||||
background: var(--color-layout-background) !important;
|
background: rgba(0, 0, 0, 0.88) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
html.macos-vibrancy .light-mode .ant-layout-sider {
|
html.macos-vibrancy .light-mode .ant-layout-sider {
|
||||||
@ -387,7 +367,6 @@ code {
|
|||||||
:root,
|
:root,
|
||||||
.light-mode,
|
.light-mode,
|
||||||
html:has(.light-mode) {
|
html:has(.light-mode) {
|
||||||
--color-layout-background: #ffffff;
|
|
||||||
--kbd-color: #363636;
|
--kbd-color: #363636;
|
||||||
--kbd-bg: #efefef;
|
--kbd-bg: #efefef;
|
||||||
--kbd-inset: #e8e8e8;
|
--kbd-inset: #e8e8e8;
|
||||||
@ -399,7 +378,6 @@ html:has(.light-mode) {
|
|||||||
|
|
||||||
.dark-mode,
|
.dark-mode,
|
||||||
html:has(.dark-mode) {
|
html:has(.dark-mode) {
|
||||||
--color-layout-background: #000000;
|
|
||||||
--kbd-color: #ececec;
|
--kbd-color: #ececec;
|
||||||
--kbd-bg: #3a3a3a;
|
--kbd-bg: #3a3a3a;
|
||||||
--kbd-inset: #323232;
|
--kbd-inset: #323232;
|
||||||
@ -3371,192 +3349,29 @@ body.objectKanbanColumnResizing * {
|
|||||||
.dashboard-tabs {
|
.dashboard-tabs {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
align-self: stretch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-tabs-wrap {
|
.dashboard-tabs .segmented-nav-item-label {
|
||||||
|
padding-inline: 0px;
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-tabs-segmented-wrap {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
height: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-tabs-wrap .simplebar-track.simplebar-vertical {
|
.dashboard-tabs-segmented-wrap .simplebar-track.simplebar-vertical {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-tabs-inner {
|
.dashboard-tabs-segmented-inner {
|
||||||
width: max-content;
|
width: max-content;
|
||||||
height: 100%;
|
|
||||||
align-items: flex-start;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tabs-list {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 4px;
|
|
||||||
padding-inline: 12px;
|
|
||||||
height: 100%;
|
|
||||||
max-height: 42px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-container {
|
|
||||||
height: 43px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-container-active {
|
|
||||||
border-bottom: none;
|
|
||||||
height: 43px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-container:before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: -2px;
|
|
||||||
right: -2px;
|
|
||||||
bottom: 0;
|
|
||||||
border-bottom: 1px solid var(--color-header-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-container-active + .dashboard-tab-item-container:before {
|
|
||||||
left: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tabs-list:has(+ .dashboard-tab-item-container-active):before {
|
|
||||||
right: 9.5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-container-active:before {
|
|
||||||
content: none;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item {
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
|
||||||
overflow: visible;
|
|
||||||
margin: 5px 0 0 0;
|
|
||||||
padding: 0 8px 0 8px;
|
|
||||||
border: 1px solid var(--color-list-view-tabs-border);
|
|
||||||
border-radius: 12px;
|
|
||||||
background: transparent;
|
|
||||||
cursor: pointer;
|
|
||||||
font-family: inherit;
|
|
||||||
font-size: inherit;
|
|
||||||
line-height: inherit;
|
|
||||||
color: inherit;
|
|
||||||
box-shadow: none;
|
|
||||||
outline: none;
|
|
||||||
|
|
||||||
transition:
|
|
||||||
background 0.3s ease,
|
|
||||||
border-color 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-icon {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
min-height: 30px;
|
|
||||||
line-height: 30px;
|
|
||||||
margin-right: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item:focus-visible {
|
|
||||||
outline: 2px solid
|
|
||||||
color-mix(in srgb, var(--color-primary, #1677ff) 45%, transparent);
|
|
||||||
outline-offset: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item:not(.dashboard-tab-item-active):hover {
|
|
||||||
background: var(--color-button-background);
|
|
||||||
border: 1px solid
|
|
||||||
color-mix(
|
|
||||||
in srgb,
|
|
||||||
var(--color-button-border) 40%,
|
|
||||||
var(--color-button-background)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-active {
|
|
||||||
z-index: 2;
|
|
||||||
align-self: stretch;
|
|
||||||
margin-bottom: -1px;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
border-color: transparent;
|
|
||||||
border-radius: 12px 12px 0 0;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-outline-container {
|
|
||||||
position: absolute;
|
|
||||||
top: -1px;
|
|
||||||
left: -1px;
|
|
||||||
right: -1px;
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-outline {
|
|
||||||
position: absolute;
|
|
||||||
inset: 0 0 20px 0;
|
|
||||||
border: 1px solid var(--color-header-border);
|
|
||||||
border-bottom: none;
|
|
||||||
border-radius: 12px 12px 0 0;
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-corner {
|
|
||||||
position: absolute;
|
|
||||||
bottom: -2px;
|
|
||||||
width: 22px;
|
|
||||||
height: 22px;
|
|
||||||
overflow: hidden;
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-corner-left {
|
|
||||||
left: -21px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-corner-right {
|
|
||||||
right: -21px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-corner-inner {
|
|
||||||
position: absolute;
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border: 1px solid var(--color-header-border);
|
|
||||||
border-radius: 15.5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-corner-left .dashboard-tab-item-corner-inner {
|
|
||||||
bottom: 1px;
|
|
||||||
right: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-corner-right .dashboard-tab-item-corner-inner {
|
|
||||||
bottom: 1px;
|
|
||||||
left: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-active .dashboard-tab-item-outline,
|
|
||||||
.dashboard-tab-item-active .dashboard-tab-item-corner {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-tabs-label {
|
.dashboard-tabs-label {
|
||||||
max-width: 280px;
|
max-width: 200px;
|
||||||
margin-top: -2px;
|
margin-top: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3580,36 +3395,7 @@ body.objectKanbanColumnResizing * {
|
|||||||
.dashboard-tabs-add-button {
|
.dashboard-tabs-add-button {
|
||||||
padding-inline: 4px;
|
padding-inline: 4px;
|
||||||
min-width: 20px;
|
min-width: 20px;
|
||||||
margin-top: 2px;
|
margin-bottom: 2px;
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-dragging {
|
|
||||||
opacity: 0.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-drop-before::before,
|
|
||||||
.dashboard-tab-item-drop-after::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 4px;
|
|
||||||
bottom: 4px;
|
|
||||||
width: 2px;
|
|
||||||
border-radius: 1px;
|
|
||||||
background: var(--color-primary, #1677ff);
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-drop-before::before {
|
|
||||||
left: -5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tab-item-drop-after::after {
|
|
||||||
right: -5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-tabs-reordering
|
|
||||||
.dashboard-tab-item:not(.dashboard-tab-item-dragging) {
|
|
||||||
cursor: default;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-tab-panes {
|
.dashboard-tab-panes {
|
||||||
|
|||||||
@ -19,7 +19,6 @@ import { useDashboardObjectTools } from '../../context/DashboardObjectToolsConte
|
|||||||
import ScrollBox from '../../common/ScrollBox.jsx'
|
import ScrollBox from '../../common/ScrollBox.jsx'
|
||||||
|
|
||||||
import TemplateEditor from '../../common/TemplateEditor.jsx'
|
import TemplateEditor from '../../common/TemplateEditor.jsx'
|
||||||
import { useObjectNavigationTabPage } from '../../hooks/useObjectNavigationTabPage'
|
|
||||||
|
|
||||||
const log = loglevel.getLogger('DocumentTemplateDesign')
|
const log = loglevel.getLogger('DocumentTemplateDesign')
|
||||||
log.setLevel(config.logLevel)
|
log.setLevel(config.logLevel)
|
||||||
@ -31,11 +30,6 @@ const DocumentTemplateDesign = () => {
|
|||||||
const documentTemplateId = new URLSearchParams(location.search).get(
|
const documentTemplateId = new URLSearchParams(location.search).get(
|
||||||
'documentTemplateId'
|
'documentTemplateId'
|
||||||
)
|
)
|
||||||
useObjectNavigationTabPage({
|
|
||||||
modelName: 'documentTemplate',
|
|
||||||
pageName: 'design',
|
|
||||||
objectId: documentTemplateId
|
|
||||||
})
|
|
||||||
const [collapseState, updateCollapseState] = useCollapseState(
|
const [collapseState, updateCollapseState] = useCollapseState(
|
||||||
'DocumentTemplateDesign',
|
'DocumentTemplateDesign',
|
||||||
{
|
{
|
||||||
|
|||||||
@ -16,7 +16,6 @@ import ObjectActions from '../../common/ObjectActions'
|
|||||||
import TemplateEditor from '../../common/TemplateEditor'
|
import TemplateEditor from '../../common/TemplateEditor'
|
||||||
import ScrollBox from '../../common/ScrollBox'
|
import ScrollBox from '../../common/ScrollBox'
|
||||||
import { useDashboardObjectTools } from '../../context/DashboardObjectToolsContext'
|
import { useDashboardObjectTools } from '../../context/DashboardObjectToolsContext'
|
||||||
import { useObjectNavigationTabPage } from '../../hooks/useObjectNavigationTabPage'
|
|
||||||
|
|
||||||
const EmailTemplateDesign = () => {
|
const EmailTemplateDesign = () => {
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
@ -25,11 +24,6 @@ const EmailTemplateDesign = () => {
|
|||||||
const emailTemplateId = new URLSearchParams(location.search).get(
|
const emailTemplateId = new URLSearchParams(location.search).get(
|
||||||
'emailTemplateId'
|
'emailTemplateId'
|
||||||
)
|
)
|
||||||
useObjectNavigationTabPage({
|
|
||||||
modelName: 'emailTemplate',
|
|
||||||
pageName: 'design',
|
|
||||||
objectId: emailTemplateId
|
|
||||||
})
|
|
||||||
const [collapseState, updateCollapseState] = useCollapseState(
|
const [collapseState, updateCollapseState] = useCollapseState(
|
||||||
'EmailTemplateDesign',
|
'EmailTemplateDesign',
|
||||||
{ preview: true, editor: true, notes: true }
|
{ preview: true, editor: true, notes: true }
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import ActivityIndicator from '../../common/ActivityIndicator.jsx'
|
|||||||
import ActionHandler from '../../common/ActionHandler.jsx'
|
import ActionHandler from '../../common/ActionHandler.jsx'
|
||||||
import ObjectActions from '../../common/ObjectActions.jsx'
|
import ObjectActions from '../../common/ObjectActions.jsx'
|
||||||
import { useDashboardObjectTools } from '../../context/DashboardObjectToolsContext'
|
import { useDashboardObjectTools } from '../../context/DashboardObjectToolsContext'
|
||||||
import { useObjectNavigationTabPage } from '../../hooks/useObjectNavigationTabPage'
|
import { useNavigationTabPage } from '../../context/NavigationTabsContext'
|
||||||
import ObjectTable from '../../common/ObjectTable.jsx'
|
import ObjectTable from '../../common/ObjectTable.jsx'
|
||||||
import InfoCollapsePlaceholder from '../../common/InfoCollapsePlaceholder.jsx'
|
import InfoCollapsePlaceholder from '../../common/InfoCollapsePlaceholder.jsx'
|
||||||
import InfoActionButtons from '../../common/InfoActionButtons.jsx'
|
import InfoActionButtons from '../../common/InfoActionButtons.jsx'
|
||||||
@ -33,15 +33,11 @@ const log = loglevel.getLogger('NoteInfo')
|
|||||||
log.setLevel(config.logLevel)
|
log.setLevel(config.logLevel)
|
||||||
|
|
||||||
const NoteInfo = () => {
|
const NoteInfo = () => {
|
||||||
|
useNavigationTabPage({ title: 'Info - Note', modelName: 'note' })
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const objectFormRef = useRef(null)
|
const objectFormRef = useRef(null)
|
||||||
const actionHandlerRef = useRef(null)
|
const actionHandlerRef = useRef(null)
|
||||||
const noteId = new URLSearchParams(location.search).get('noteId')
|
const noteId = new URLSearchParams(location.search).get('noteId')
|
||||||
useObjectNavigationTabPage({
|
|
||||||
modelName: 'note',
|
|
||||||
pageName: 'info',
|
|
||||||
objectId: noteId
|
|
||||||
})
|
|
||||||
const [collapseState, updateCollapseState] = useCollapseState('NoteInfo', {
|
const [collapseState, updateCollapseState] = useCollapseState('NoteInfo', {
|
||||||
info: true,
|
info: true,
|
||||||
content: true,
|
content: true,
|
||||||
|
|||||||
@ -21,7 +21,6 @@ import MissingPlaceholder from '../../common/MissingPlaceholder.jsx'
|
|||||||
import InfoCollapsePlaceholder from '../../common/InfoCollapsePlaceholder.jsx'
|
import InfoCollapsePlaceholder from '../../common/InfoCollapsePlaceholder.jsx'
|
||||||
import DocumentPrintButton from '../../common/DocumentPrintButton.jsx'
|
import DocumentPrintButton from '../../common/DocumentPrintButton.jsx'
|
||||||
import UserNotifierToggle from '../../common/UserNotifierToggle.jsx'
|
import UserNotifierToggle from '../../common/UserNotifierToggle.jsx'
|
||||||
import { useObjectNavigationTabPage } from '../../hooks/useObjectNavigationTabPage'
|
|
||||||
|
|
||||||
const log = loglevel.getLogger('GCodeFilePreview')
|
const log = loglevel.getLogger('GCodeFilePreview')
|
||||||
log.setLevel(config.logLevel)
|
log.setLevel(config.logLevel)
|
||||||
@ -30,11 +29,6 @@ const GCodeFilePreview = () => {
|
|||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const objectFormRef = useRef(null)
|
const objectFormRef = useRef(null)
|
||||||
const gcodeFileId = new URLSearchParams(location.search).get('gcodeFileId')
|
const gcodeFileId = new URLSearchParams(location.search).get('gcodeFileId')
|
||||||
useObjectNavigationTabPage({
|
|
||||||
modelName: 'gcodeFile',
|
|
||||||
pageName: 'preview',
|
|
||||||
objectId: gcodeFileId
|
|
||||||
})
|
|
||||||
const [collapseState, updateCollapseState] = useCollapseState(
|
const [collapseState, updateCollapseState] = useCollapseState(
|
||||||
'GCodeFilePreview',
|
'GCodeFilePreview',
|
||||||
{
|
{
|
||||||
|
|||||||
@ -37,7 +37,6 @@ import ObjectTableNavigationButtons from '../../common/ObjectTableNavigationButt
|
|||||||
import PrinterControlButtons from '../../common/PrinterControlButtons.jsx'
|
import PrinterControlButtons from '../../common/PrinterControlButtons.jsx'
|
||||||
import PrinterQueue from '../../common/PrinterQueue.jsx'
|
import PrinterQueue from '../../common/PrinterQueue.jsx'
|
||||||
import ListIcon from '../../../Icons/ListIcon.jsx'
|
import ListIcon from '../../../Icons/ListIcon.jsx'
|
||||||
import { useObjectNavigationTabPage } from '../../hooks/useObjectNavigationTabPage'
|
|
||||||
|
|
||||||
const log = loglevel.getLogger('ControlPrinter')
|
const log = loglevel.getLogger('ControlPrinter')
|
||||||
log.setLevel(config.logLevel)
|
log.setLevel(config.logLevel)
|
||||||
@ -48,11 +47,6 @@ const ControlPrinter = ({ slicerIntegration = false }) => {
|
|||||||
const actionHandlerRef = useRef(null)
|
const actionHandlerRef = useRef(null)
|
||||||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
const isMobile = useMediaQuery({ maxWidth: 768 })
|
||||||
const printerId = new URLSearchParams(location.search).get('printerId')
|
const printerId = new URLSearchParams(location.search).get('printerId')
|
||||||
useObjectNavigationTabPage({
|
|
||||||
modelName: 'printer',
|
|
||||||
pageName: 'control',
|
|
||||||
objectId: printerId
|
|
||||||
})
|
|
||||||
const [collapseState, updateCollapseState] = useCollapseState(
|
const [collapseState, updateCollapseState] = useCollapseState(
|
||||||
'ControlPrinter',
|
'ControlPrinter',
|
||||||
{
|
{
|
||||||
|
|||||||
@ -280,8 +280,75 @@ const DashboardNavigation = () => {
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
const navigationTrailing = (
|
const navigationContents = (
|
||||||
|
<Flex style={{ width: '100%' }} align='center'>
|
||||||
|
{isMacOSApp ? <DashboardWindowButtons /> : null}
|
||||||
|
{isOtherApp ? (
|
||||||
<>
|
<>
|
||||||
|
<WindowAppMenu />{' '}
|
||||||
|
<Divider
|
||||||
|
type='vertical'
|
||||||
|
style={{
|
||||||
|
height: '14px',
|
||||||
|
margin: showNavigationLabels
|
||||||
|
? '3px 3px 0 1.5px'
|
||||||
|
: '3px 0px 0 1.5px'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
{showControls && isMobile && menu}
|
||||||
|
{showDesktopLogo == true ? (
|
||||||
|
<FarmControlLogo
|
||||||
|
style={{
|
||||||
|
fontSize: '200px',
|
||||||
|
height: '18px',
|
||||||
|
marginRight: '15px'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : showMobileLogo == true ? (
|
||||||
|
<FarmControlLogoSmall
|
||||||
|
style={{
|
||||||
|
fontSize: '48px',
|
||||||
|
marginRight: isElectron ? '20px' : '25px'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
<div style={{ flexGrow: 1, minWidth: 0 }}>
|
||||||
|
{showControls && !isMobile ? (
|
||||||
|
<Flex align='center' style={{ width: '100%', minWidth: 0 }}>
|
||||||
|
{menu}
|
||||||
|
{isElectron ? (
|
||||||
|
<>
|
||||||
|
<Divider
|
||||||
|
type='vertical'
|
||||||
|
style={{
|
||||||
|
margin: showNavigationLabels
|
||||||
|
? '3px 16px 0 4px'
|
||||||
|
: '3px 16px 0 0',
|
||||||
|
height: '14px'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<DashboardTabs />
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
</Flex>
|
||||||
|
) : null}
|
||||||
|
{!showControls && (
|
||||||
|
<Text
|
||||||
|
type='secondary'
|
||||||
|
style={{
|
||||||
|
fontSize: '14px',
|
||||||
|
marginLeft: '8px',
|
||||||
|
userSelect: 'none',
|
||||||
|
'--webkit-user-select': 'none'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Farm Control
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='electrobun-webkit-app-region-no-drag'>
|
<div className='electrobun-webkit-app-region-no-drag'>
|
||||||
<Flex
|
<Flex
|
||||||
gap={'small'}
|
gap={'small'}
|
||||||
@ -394,117 +461,17 @@ const DashboardNavigation = () => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</div>
|
</div>
|
||||||
{isOtherApp ? <DashboardWindowButtons /> : null}
|
{isOtherApp ? <DashboardWindowButtons /> : null}
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
||||||
const navigationLeading = (
|
|
||||||
<>
|
|
||||||
{isMacOSApp ? <DashboardWindowButtons /> : null}
|
|
||||||
{isOtherApp ? (
|
|
||||||
<>
|
|
||||||
<WindowAppMenu />{' '}
|
|
||||||
<Divider
|
|
||||||
type='vertical'
|
|
||||||
style={{
|
|
||||||
height: '14px',
|
|
||||||
margin: showNavigationLabels
|
|
||||||
? '3px 3px 0 1.5px'
|
|
||||||
: '3px 0px 0 1.5px'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
) : null}
|
|
||||||
{showControls && isMobile && menu}
|
|
||||||
{showDesktopLogo == true ? (
|
|
||||||
<FarmControlLogo
|
|
||||||
style={{
|
|
||||||
fontSize: '200px',
|
|
||||||
height: '18px',
|
|
||||||
marginRight: '15px'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : showMobileLogo == true ? (
|
|
||||||
<FarmControlLogoSmall
|
|
||||||
style={{
|
|
||||||
fontSize: '48px',
|
|
||||||
marginRight: isElectron ? '20px' : '25px'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
||||||
const navigationContents = (
|
|
||||||
<Flex style={{ width: '100%' }} align='center'>
|
|
||||||
{navigationLeading}
|
|
||||||
<div style={{ flexGrow: 1, minWidth: 0 }}>
|
|
||||||
{showControls && !isMobile ? (
|
|
||||||
<Flex align='center' style={{ width: '100%', minWidth: 0 }}>
|
|
||||||
{menu}
|
|
||||||
</Flex>
|
|
||||||
) : null}
|
|
||||||
{!showControls && (
|
|
||||||
<Text
|
|
||||||
type='secondary'
|
|
||||||
style={{
|
|
||||||
fontSize: '14px',
|
|
||||||
marginLeft: '8px',
|
|
||||||
userSelect: 'none',
|
|
||||||
'--webkit-user-select': 'none'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Farm Control
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{navigationTrailing}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
)
|
)
|
||||||
|
|
||||||
const electronDragClass =
|
|
||||||
isFullScreen || (isMaximized && isOtherApp)
|
|
||||||
? 'electrobun-webkit-app-region-no-drag'
|
|
||||||
: 'electrobun-webkit-app-region-drag'
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isElectron ? (
|
{isElectron ? (
|
||||||
<Flex
|
<Flex
|
||||||
className={`electron-navigation-wrapper ${electronDragClass}`}
|
className={`ant-menu-horizontal electron-navigation-wrapper ant-menu-light ${isFullScreen || (isMaximized && isOtherApp) ? 'electrobun-webkit-app-region-no-drag' : 'electrobun-webkit-app-region-drag'}`}
|
||||||
style={{ lineHeight: '40px', padding: '0 2px 0 2px' }}
|
style={{ lineHeight: '40px', padding: '0 2px 0 2px' }}
|
||||||
>
|
>
|
||||||
<Flex align='center' className='electron-navigation-leading'>
|
{navigationContents}
|
||||||
{navigationLeading}
|
|
||||||
{showControls && !isMobile ? menu : null}
|
|
||||||
{showControls && !isMobile ? (
|
|
||||||
<Divider
|
|
||||||
type='vertical'
|
|
||||||
style={{
|
|
||||||
margin: showNavigationLabels
|
|
||||||
? '3px 16px 0 4px'
|
|
||||||
: '3px 16px 0 0',
|
|
||||||
height: '14px'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
{!showControls ? (
|
|
||||||
<Text
|
|
||||||
type='secondary'
|
|
||||||
style={{
|
|
||||||
fontSize: '14px',
|
|
||||||
marginLeft: '8px',
|
|
||||||
userSelect: 'none',
|
|
||||||
'--webkit-user-select': 'none'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Farm Control
|
|
||||||
</Text>
|
|
||||||
) : null}
|
|
||||||
</Flex>
|
|
||||||
{showControls && !isMobile ? <DashboardTabs /> : null}
|
|
||||||
<Flex align='center' className='electron-navigation-trailing'>
|
|
||||||
{navigationTrailing}
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
) : (
|
) : (
|
||||||
<Flex vertical>
|
<Flex vertical>
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { useCallback, useState } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { Button, Flex, Typography } from 'antd'
|
import { Button, Flex, Typography } from 'antd'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
import SegmentedNav from './SegmentedNav'
|
||||||
import ScrollBox from './ScrollBox'
|
import ScrollBox from './ScrollBox'
|
||||||
import PlusIcon from '../../Icons/PlusIcon'
|
import PlusIcon from '../../Icons/PlusIcon'
|
||||||
import XMarkIcon from '../../Icons/XMarkIcon'
|
import XMarkIcon from '../../Icons/XMarkIcon'
|
||||||
@ -13,29 +14,9 @@ import { hasExternalTabDrag, writeTabDragData } from './tabDrag'
|
|||||||
|
|
||||||
const { Text } = Typography
|
const { Text } = Typography
|
||||||
|
|
||||||
const DashboardTabChrome = () => (
|
|
||||||
<>
|
|
||||||
<span className='dashboard-tab-item-outline-container' aria-hidden='true'>
|
|
||||||
<span className='dashboard-tab-item-outline' aria-hidden='true' />
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className='dashboard-tab-item-corner dashboard-tab-item-corner-left'
|
|
||||||
aria-hidden='true'
|
|
||||||
>
|
|
||||||
<span className='dashboard-tab-item-corner-inner' />
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className='dashboard-tab-item-corner dashboard-tab-item-corner-right'
|
|
||||||
aria-hidden='true'
|
|
||||||
>
|
|
||||||
<span className='dashboard-tab-item-corner-inner' />
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
||||||
const DashboardTabLabel = ({ tab, onClose }) => (
|
const DashboardTabLabel = ({ tab, onClose }) => (
|
||||||
<Flex align='center' gap={6} className='dashboard-tabs-label'>
|
<Flex align='center' gap={6} className='dashboard-tabs-label'>
|
||||||
<Text ellipsis style={{ maxWidth: 240 }}>
|
<Text ellipsis style={{ maxWidth: 160 }}>
|
||||||
{tab.title || 'Farm Control'}
|
{tab.title || 'Farm Control'}
|
||||||
</Text>
|
</Text>
|
||||||
<span
|
<span
|
||||||
@ -74,31 +55,30 @@ const DashboardTabs = () => {
|
|||||||
handleTabDragEnd,
|
handleTabDragEnd,
|
||||||
handleExternalTabDrop
|
handleExternalTabDrop
|
||||||
} = useNavigationTabs()
|
} = useNavigationTabs()
|
||||||
const [draggedValue, setDraggedValue] = useState(null)
|
|
||||||
const [dropTarget, setDropTarget] = useState(null)
|
|
||||||
|
|
||||||
const clearDragState = useCallback(() => {
|
const options = useMemo(
|
||||||
setDraggedValue(null)
|
() =>
|
||||||
setDropTarget(null)
|
tabs.map((tab) => {
|
||||||
}, [])
|
const model = tab.modelName ? getModelByName(tab.modelName) : null
|
||||||
|
const Icon = model?.icon || HomeIcon
|
||||||
|
return {
|
||||||
|
value: tab.id,
|
||||||
|
reorderable: true,
|
||||||
|
icon: (
|
||||||
|
<Icon
|
||||||
|
style={{ fontSize: 14, marginTop: '-2px' }}
|
||||||
|
color='secondary'
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
label: <DashboardTabLabel tab={tab} onClose={closeTab} />
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
[closeTab, tabs]
|
||||||
|
)
|
||||||
|
|
||||||
const handleItemDragStart = (event, tabId) => {
|
const handleItemDragStart = (event, tabId) => {
|
||||||
const tab = tabs.find((item) => item.id === tabId)
|
const tab = tabs.find((item) => item.id === tabId)
|
||||||
if (!tab) return
|
if (!tab) return
|
||||||
|
|
||||||
event.stopPropagation()
|
|
||||||
const item = event.currentTarget
|
|
||||||
if (item) {
|
|
||||||
const rect = item.getBoundingClientRect()
|
|
||||||
event.dataTransfer.setDragImage(
|
|
||||||
item,
|
|
||||||
event.clientX - rect.left,
|
|
||||||
event.clientY - rect.top
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
setDraggedValue(tabId)
|
|
||||||
event.dataTransfer.effectAllowed = 'move'
|
|
||||||
writeTabDragData(event, {
|
writeTabDragData(event, {
|
||||||
tab,
|
tab,
|
||||||
sourceWindowId: getDesktopWindowId()
|
sourceWindowId: getDesktopWindowId()
|
||||||
@ -106,105 +86,6 @@ const DashboardTabs = () => {
|
|||||||
handleTabDragStart(tabId)
|
handleTabDragStart(tabId)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleItemDragEnd = () => {
|
|
||||||
handleTabDragEnd()
|
|
||||||
clearDragState()
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleItemDragOver = (event, tab) => {
|
|
||||||
const isExternal = hasExternalTabDrag(event)
|
|
||||||
if (draggedValue == null && !isExternal) return
|
|
||||||
if (draggedValue != null && String(tab.id) === String(draggedValue)) return
|
|
||||||
|
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
event.dataTransfer.dropEffect = 'move'
|
|
||||||
|
|
||||||
const rect = event.currentTarget.getBoundingClientRect()
|
|
||||||
setDropTarget({
|
|
||||||
value: tab.id,
|
|
||||||
insertBefore: event.clientX < rect.left + rect.width / 2
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleItemDrop = (event, tab) => {
|
|
||||||
const isExternal = draggedValue == null && hasExternalTabDrag(event)
|
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
|
|
||||||
const target = dropTarget || {
|
|
||||||
value: tab.id,
|
|
||||||
insertBefore: true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isExternal) {
|
|
||||||
void handleExternalTabDrop(target.value, target.insertBefore)
|
|
||||||
clearDragState()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (draggedValue == null) return
|
|
||||||
|
|
||||||
if (String(draggedValue) !== String(target.value)) {
|
|
||||||
reorderTabs(draggedValue, target.value, target.insertBefore)
|
|
||||||
}
|
|
||||||
|
|
||||||
clearDragState()
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleListDragOver = (event) => {
|
|
||||||
const isExternal = hasExternalTabDrag(event)
|
|
||||||
if (draggedValue == null && !isExternal) return
|
|
||||||
if (
|
|
||||||
event.target instanceof Element &&
|
|
||||||
event.target.closest('.dashboard-tab-item')
|
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault()
|
|
||||||
event.dataTransfer.dropEffect = 'move'
|
|
||||||
|
|
||||||
const lastTab = tabs[tabs.length - 1]
|
|
||||||
if (!lastTab) return
|
|
||||||
setDropTarget({
|
|
||||||
value: lastTab.id,
|
|
||||||
insertBefore: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleListDrop = (event) => {
|
|
||||||
const isExternal = draggedValue == null && hasExternalTabDrag(event)
|
|
||||||
if (draggedValue == null && !isExternal) return
|
|
||||||
if (
|
|
||||||
event.target instanceof Element &&
|
|
||||||
event.target.closest('.dashboard-tab-item')
|
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
|
|
||||||
const lastTab = tabs[tabs.length - 1]
|
|
||||||
if (!lastTab) {
|
|
||||||
clearDragState()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isExternal) {
|
|
||||||
void handleExternalTabDrop(lastTab.id, false)
|
|
||||||
clearDragState()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (String(draggedValue) !== String(lastTab.id)) {
|
|
||||||
reorderTabs(draggedValue, lastTab.id, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
clearDragState()
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleStripDragOver = (event) => {
|
const handleStripDragOver = (event) => {
|
||||||
if (!hasExternalTabDrag(event)) return
|
if (!hasExternalTabDrag(event)) return
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
@ -218,105 +99,34 @@ const DashboardTabs = () => {
|
|||||||
void handleExternalTabDrop(lastTab?.id, false)
|
void handleExternalTabDrop(lastTab?.id, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleKeyDown = (event, tabIndex) => {
|
|
||||||
if (event.key !== 'ArrowRight' && event.key !== 'ArrowLeft') return
|
|
||||||
|
|
||||||
event.preventDefault()
|
|
||||||
const direction = event.key === 'ArrowRight' ? 1 : -1
|
|
||||||
const currentIndex = tabs.findIndex((tab) => tab.id === activeTabId)
|
|
||||||
const startIndex = currentIndex === -1 ? tabIndex : currentIndex
|
|
||||||
const nextIndex = (startIndex + direction + tabs.length) % tabs.length
|
|
||||||
selectTab(tabs[nextIndex].id)
|
|
||||||
}
|
|
||||||
|
|
||||||
const isReordering = draggedValue != null || dropTarget != null
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
align='flex-start'
|
align='center'
|
||||||
gap={4}
|
gap={4}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'dashboard-tabs',
|
'dashboard-tabs',
|
||||||
'electrobun-webkit-app-region-drag'
|
'electrobun-webkit-app-region-no-drag'
|
||||||
)}
|
)}
|
||||||
style={{ flex: 1, minWidth: 0 }}
|
style={{ flex: 1, minWidth: 0 }}
|
||||||
onDragOver={handleStripDragOver}
|
onDragOver={handleStripDragOver}
|
||||||
onDrop={handleStripDrop}
|
onDrop={handleStripDrop}
|
||||||
>
|
>
|
||||||
<ScrollBox
|
<ScrollBox className='dashboard-tabs-segmented-wrap' horizontal>
|
||||||
className='dashboard-tabs-wrap'
|
<Flex align='center' gap={8} className='dashboard-tabs-segmented-inner'>
|
||||||
horizontal
|
<SegmentedNav
|
||||||
horizontalBottomPadding={0}
|
className='dashboard-tabs-segmented'
|
||||||
>
|
value={activeTabId}
|
||||||
<Flex align='flex-start' gap={8} className='dashboard-tabs-inner'>
|
options={options}
|
||||||
<div
|
onChange={selectTab}
|
||||||
className={classNames('dashboard-tabs-list', {
|
onReorder={reorderTabs}
|
||||||
'dashboard-tabs-reordering': isReordering
|
onExternalDrop={handleExternalTabDrop}
|
||||||
})}
|
onItemDragStart={handleItemDragStart}
|
||||||
role='tablist'
|
onItemDragEnd={handleTabDragEnd}
|
||||||
onDragOver={handleListDragOver}
|
|
||||||
onDrop={handleListDrop}
|
|
||||||
>
|
|
||||||
{tabs.map((tab, index) => {
|
|
||||||
const model = tab.modelName ? getModelByName(tab.modelName) : null
|
|
||||||
const Icon = model?.icon || HomeIcon
|
|
||||||
const isSelected = tab.id === activeTabId
|
|
||||||
const isDragging =
|
|
||||||
draggedValue != null && String(draggedValue) === String(tab.id)
|
|
||||||
const isDropTarget =
|
|
||||||
dropTarget != null &&
|
|
||||||
String(dropTarget.value) === String(tab.id) &&
|
|
||||||
String(draggedValue) !== String(tab.id)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={tab.id}
|
|
||||||
className={classNames('dashboard-tab-item-container', {
|
|
||||||
'dashboard-tab-item-container-active': isSelected
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
type='button'
|
|
||||||
role='tab'
|
|
||||||
aria-selected={isSelected}
|
|
||||||
tabIndex={isSelected ? 0 : -1}
|
|
||||||
className={classNames(
|
|
||||||
'dashboard-tab-item',
|
|
||||||
'electrobun-webkit-app-region-no-drag',
|
|
||||||
{
|
|
||||||
'dashboard-tab-item-active': isSelected,
|
|
||||||
'dashboard-tab-item-dragging': isDragging,
|
|
||||||
'dashboard-tab-item-drop-before':
|
|
||||||
isDropTarget && dropTarget.insertBefore,
|
|
||||||
'dashboard-tab-item-drop-after':
|
|
||||||
isDropTarget && !dropTarget.insertBefore
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
draggable
|
|
||||||
onDragStart={(event) => handleItemDragStart(event, tab.id)}
|
|
||||||
onDragEnd={handleItemDragEnd}
|
|
||||||
onClick={() => selectTab(tab.id)}
|
|
||||||
onKeyDown={(event) => handleKeyDown(event, index)}
|
|
||||||
onDragOver={(event) => handleItemDragOver(event, tab)}
|
|
||||||
onDrop={(event) => handleItemDrop(event, tab)}
|
|
||||||
>
|
|
||||||
<DashboardTabChrome />
|
|
||||||
<span className='dashboard-tab-item-icon'>
|
|
||||||
<Icon
|
|
||||||
style={{ fontSize: 14, marginTop: '-2px' }}
|
|
||||||
color='secondary'
|
|
||||||
/>
|
/>
|
||||||
</span>
|
|
||||||
<DashboardTabLabel tab={tab} onClose={closeTab} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<Button
|
<Button
|
||||||
type='text'
|
type='text'
|
||||||
size='small'
|
size='small'
|
||||||
className='dashboard-tabs-add-button electrobun-webkit-app-region-no-drag'
|
className='dashboard-tabs-add-button'
|
||||||
onClick={addTab}
|
onClick={addTab}
|
||||||
icon={<PlusIcon style={{ fontSize: 14, marginTop: 3 }} />}
|
icon={<PlusIcon style={{ fontSize: 14, marginTop: 3 }} />}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -7,8 +7,7 @@ import { getModelByName } from '../../../database/ObjectModels'
|
|||||||
import { getObjectIdFromSearch } from '../../../utils/modelActions'
|
import { getObjectIdFromSearch } from '../../../utils/modelActions'
|
||||||
import { useActions } from '../context/ActionsContext'
|
import { useActions } from '../context/ActionsContext'
|
||||||
import { AuthContext } from '../context/AuthContext'
|
import { AuthContext } from '../context/AuthContext'
|
||||||
import { useIsNavigationTabActive } from '../context/NavigationTabsContext'
|
import { useNavigationTabPage, useIsNavigationTabActive } from '../context/NavigationTabsContext'
|
||||||
import { useObjectNavigationTabPage } from '../hooks/useObjectNavigationTabPage'
|
|
||||||
|
|
||||||
const ModelPage = ({ modelName, pageName }) => {
|
const ModelPage = ({ modelName, pageName }) => {
|
||||||
const model = getModelByName(modelName)
|
const model = getModelByName(modelName)
|
||||||
@ -17,8 +16,9 @@ const ModelPage = ({ modelName, pageName }) => {
|
|||||||
const { setCurrentObject, setCurrentObjectType } = useActions()
|
const { setCurrentObject, setCurrentObjectType } = useActions()
|
||||||
const { userProfile } = useContext(AuthContext)
|
const { userProfile } = useContext(AuthContext)
|
||||||
const objectId = getObjectIdFromSearch(modelName, location.search)
|
const objectId = getObjectIdFromSearch(modelName, location.search)
|
||||||
|
const pageTitle = `${pageName.charAt(0).toUpperCase()}${pageName.slice(1)} - ${model?.label || modelName}`
|
||||||
const isTabActive = useIsNavigationTabActive()
|
const isTabActive = useIsNavigationTabActive()
|
||||||
useObjectNavigationTabPage({ modelName, pageName, objectId })
|
useNavigationTabPage({ title: pageTitle, modelName })
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isTabActive) return undefined
|
if (!isTabActive) return undefined
|
||||||
|
|||||||
@ -265,10 +265,7 @@ const SegmentedNav = ({
|
|||||||
const handleGroupDragOver = useCallback(
|
const handleGroupDragOver = useCallback(
|
||||||
(event) => {
|
(event) => {
|
||||||
const isExternal = acceptsExternal && hasExternalTabDrag(event)
|
const isExternal = acceptsExternal && hasExternalTabDrag(event)
|
||||||
if (
|
if ((!onReorder && !isExternal) || (draggedValue == null && !isExternal)) {
|
||||||
(!onReorder && !isExternal) ||
|
|
||||||
(draggedValue == null && !isExternal)
|
|
||||||
) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,10 +296,7 @@ const SegmentedNav = ({
|
|||||||
const handleGroupDrop = useCallback(
|
const handleGroupDrop = useCallback(
|
||||||
(event) => {
|
(event) => {
|
||||||
const isExternal = acceptsExternal && draggedValue == null
|
const isExternal = acceptsExternal && draggedValue == null
|
||||||
if (
|
if ((!onReorder && !isExternal) || (draggedValue == null && !isExternal)) {
|
||||||
(!onReorder && !isExternal) ||
|
|
||||||
(draggedValue == null && !isExternal)
|
|
||||||
) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -131,9 +131,7 @@ export const ObjectListViewProvider = ({ children, objectType, tableRef }) => {
|
|||||||
const { getViewFromUrl, persistView, setObjectListView } = useTableState()
|
const { getViewFromUrl, persistView, setObjectListView } = useTableState()
|
||||||
const listModel = getModelByName(objectType)
|
const listModel = getModelByName(objectType)
|
||||||
useNavigationTabPage({
|
useNavigationTabPage({
|
||||||
title: listModel?.labelPlural
|
title: listModel?.label ? `List - ${listModel.label}` : 'List',
|
||||||
? `List - ${listModel.labelPlural}`
|
|
||||||
: 'List',
|
|
||||||
modelName: objectType
|
modelName: objectType
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -216,10 +216,6 @@ export const ThemeProvider = ({ children }) => {
|
|||||||
'--color-mobile-footer-item-border',
|
'--color-mobile-footer-item-border',
|
||||||
isDarkMode ? '#303030' : '#f0f0f0'
|
isDarkMode ? '#303030' : '#f0f0f0'
|
||||||
)
|
)
|
||||||
root.style.setProperty(
|
|
||||||
'--color-header-border',
|
|
||||||
isDarkMode ? 'rgba(253,253,253,0.12)' : 'rgba(10,10,10,0.12)'
|
|
||||||
)
|
|
||||||
}, [isDarkMode, primaryColorOverride])
|
}, [isDarkMode, primaryColorOverride])
|
||||||
|
|
||||||
const themeConfig = {
|
const themeConfig = {
|
||||||
|
|||||||
@ -1,82 +0,0 @@
|
|||||||
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