Add Dashboard Development Controls and Update Navigation Styles
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
- Introduced a new DashboardDevControls component to manage API server connection states and provide visual feedback. - Enhanced DashboardNavigation with improved layout and styling, including new transition effects for navigation elements. - Adjusted CSS styles for better spacing and visibility of dashboard components, ensuring a more cohesive user experience.
This commit is contained in:
parent
f3af883bd2
commit
d52eea3a41
@ -125,14 +125,17 @@
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transition:
|
||||
opacity 0.2s ease,
|
||||
visibility 0.2s ease;
|
||||
opacity 0.2s ease 0.2s,
|
||||
visibility 0s linear 0.2s;
|
||||
}
|
||||
|
||||
.dashboard-navigation-fade-hidden {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
transition:
|
||||
opacity 0.2s ease 0s,
|
||||
visibility 0s linear 0.2s;
|
||||
}
|
||||
|
||||
.dashboard-navigation-window-title {
|
||||
@ -140,12 +143,46 @@
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 14px;
|
||||
justify-content: space-between;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
font-size: 14px;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.dashboard-navigation-center-border {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 1px;
|
||||
background: var(--color-header-border);
|
||||
pointer-events: none;
|
||||
opacity: 1;
|
||||
/* Wait for outgoing chrome to finish fading before this line appears. */
|
||||
transition: opacity 0.2s ease 0.2s;
|
||||
}
|
||||
|
||||
.dashboard-navigation-center-border-hidden {
|
||||
opacity: 0;
|
||||
/* Stay through the gap, then fade out as incoming chrome fades in. */
|
||||
transition: opacity 0.2s ease 0.2s;
|
||||
}
|
||||
|
||||
.dashboard-menu-container {
|
||||
position: relative;
|
||||
height: 42px;
|
||||
padding-top: 2px;
|
||||
}
|
||||
.dashboard-menu-container:after {
|
||||
border-bottom: 1px solid var(--color-header-border);
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: -2px;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.electron-navigation-leading,
|
||||
@ -3460,7 +3497,7 @@ body.objectKanbanColumnResizing * {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 4px;
|
||||
padding-left: 12px;
|
||||
padding-left: 14px;
|
||||
height: 100%;
|
||||
max-height: 42px;
|
||||
}
|
||||
@ -3486,7 +3523,7 @@ body.objectKanbanColumnResizing * {
|
||||
}
|
||||
|
||||
.dashboard-tab-item-container:first-child:before {
|
||||
left: -12px;
|
||||
left: -14px;
|
||||
}
|
||||
|
||||
.dashboard-tab-item-container:last-child:before {
|
||||
|
||||
70
src/components/Dashboard/common/DashboardDevControls.jsx
Normal file
70
src/components/Dashboard/common/DashboardDevControls.jsx
Normal file
@ -0,0 +1,70 @@
|
||||
import { useContext, useEffect, useState } from 'react'
|
||||
import { Space, Tag } from 'antd'
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { ApiServerContext } from '../context/ApiServerContext'
|
||||
import Tooltip from './Tooltip'
|
||||
import CloudIcon from '../../Icons/CloudIcon'
|
||||
import DeveloperIcon from '../../Icons/DeveloperIcon'
|
||||
|
||||
const DashboardDevControls = () => {
|
||||
const { connecting, connected } = useContext(ApiServerContext)
|
||||
const navigate = useNavigate()
|
||||
const [apiServerState, setApiServerState] = useState('disconnected')
|
||||
|
||||
useEffect(() => {
|
||||
if (connecting == true) {
|
||||
setApiServerState('connecting')
|
||||
} else if (connected == true) {
|
||||
setApiServerState('connected')
|
||||
} else {
|
||||
setApiServerState('disconnected')
|
||||
}
|
||||
}, [connecting, connected])
|
||||
|
||||
if (import.meta.env.MODE !== 'development') return null
|
||||
|
||||
return (
|
||||
<Space>
|
||||
{apiServerState === 'connected' ? (
|
||||
<Tooltip content='Connected to api server'>
|
||||
<Tag
|
||||
color='success'
|
||||
style={{ marginRight: 0 }}
|
||||
icon={<CloudIcon />}
|
||||
/>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
{apiServerState === 'connecting' ? (
|
||||
<Tooltip content='Connecting to api server...'>
|
||||
<Tag
|
||||
color='warning'
|
||||
style={{ marginRight: 0 }}
|
||||
icon={<LoadingOutlined />}
|
||||
/>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
{apiServerState === 'disconnected' ? (
|
||||
<Tooltip content='Disconnected from api server'>
|
||||
<Tag
|
||||
color='error'
|
||||
style={{ marginRight: 0 }}
|
||||
icon={<CloudIcon />}
|
||||
/>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
<Tooltip content='Developer'>
|
||||
<Tag
|
||||
color='yellow'
|
||||
style={{ marginRight: 0 }}
|
||||
icon={<DeveloperIcon />}
|
||||
onClick={() => {
|
||||
navigate('/dashboard/developer/sessionstorage')
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Space>
|
||||
)
|
||||
}
|
||||
|
||||
export default DashboardDevControls
|
||||
@ -1,5 +1,6 @@
|
||||
// DashboardNavigation.js
|
||||
import { useContext, useEffect, useState, useMemo } from 'react'
|
||||
import { useContext, useEffect, useState, useMemo, useCallback, memo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {
|
||||
Menu,
|
||||
Flex,
|
||||
@ -11,7 +12,6 @@ import {
|
||||
Typography,
|
||||
Popover
|
||||
} from 'antd'
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import { AuthContext } from '../context/AuthContext'
|
||||
import { SpotlightContext } from '../context/SpotlightContext'
|
||||
import { ApiServerContext } from '../context/ApiServerContext'
|
||||
@ -35,9 +35,9 @@ import CloudIcon from '../../Icons/CloudIcon'
|
||||
import BellIcon from '../../Icons/BellIcon'
|
||||
import SearchIcon from '../../Icons/SearchIcon'
|
||||
import SettingsIcon from '../../Icons/SettingsIcon'
|
||||
import DeveloperIcon from '../../Icons/DeveloperIcon'
|
||||
import { ElectronContext } from '../context/ElectronContext'
|
||||
import DashboardWindowButtons from './DashboardWindowButtons'
|
||||
import DashboardDevControls from './DashboardDevControls'
|
||||
import WindowAppMenu from './WindowAppMenu'
|
||||
import WebAppSwitcher from './WebAppSwitcher'
|
||||
import DashboardTabs from './DashboardTabs'
|
||||
@ -57,6 +57,225 @@ import { getEffectiveAppearance } from '../../../database/Settings'
|
||||
|
||||
const { Text } = Typography
|
||||
|
||||
const NAV_CENTER_FADE_STYLE = {
|
||||
width: '100%',
|
||||
minWidth: 0,
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
}
|
||||
const NAV_ELECTRON_CENTER_FADE_STYLE = {
|
||||
flex: 1,
|
||||
minWidth: 0,
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
}
|
||||
const NAV_ELECTRON_TABS_STYLE = { flex: 1, minWidth: 0, display: 'flex' }
|
||||
const NAV_ELECTRON_DIVIDER_STYLE_WITH_LABELS = {
|
||||
margin: '3px 1px 0 4px',
|
||||
height: '14px'
|
||||
}
|
||||
const NAV_ELECTRON_DIVIDER_STYLE = {
|
||||
margin: '3px 1px 0 0',
|
||||
height: '14px'
|
||||
}
|
||||
const NAV_TRAILING_FLEX_STYLE = { marginTop: '-2px', marginRight: '6px' }
|
||||
const NAV_TRAILING_SPACE_STYLE = { paddingTop: '2px', marginRight: '8px' }
|
||||
const NAV_SEARCH_BUTTON_STYLE = { marginTop: '4px' }
|
||||
const NAV_BELL_BUTTON_STYLE = { marginTop: '2px' }
|
||||
const NAV_BADGE_STYLE = { padding: 0, fontWeight: 600 }
|
||||
const NAV_UPDATE_TAG_STYLE = { cursor: 'pointer', margin: '2px 0 0 0' }
|
||||
const NAV_OVERFLOW_BUTTON_STYLE = { marginBottom: '4px' }
|
||||
|
||||
const navigationFadeClass = (visible) =>
|
||||
`dashboard-navigation-fade${visible ? '' : ' dashboard-navigation-fade-hidden'}`
|
||||
|
||||
const NavigationFade = memo(function NavigationFade({ visible, children, style }) {
|
||||
return (
|
||||
<div
|
||||
className={navigationFadeClass(visible)}
|
||||
inert={visible ? undefined : true}
|
||||
aria-hidden={visible ? undefined : true}
|
||||
style={style}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
NavigationFade.propTypes = {
|
||||
visible: PropTypes.bool,
|
||||
children: PropTypes.node,
|
||||
style: PropTypes.object
|
||||
}
|
||||
|
||||
const DashboardNavigationTrailingItems = memo(
|
||||
function DashboardNavigationTrailingItems({
|
||||
controlsReady,
|
||||
isMobile,
|
||||
isElectron,
|
||||
unreadCount,
|
||||
userProfile,
|
||||
availableUpdate,
|
||||
userPopoverOpen,
|
||||
onUserPopoverOpenChange,
|
||||
onSearch,
|
||||
onNotifications,
|
||||
onCheckUpdates
|
||||
}) {
|
||||
return (
|
||||
<Flex gap='small' align='center' style={NAV_TRAILING_FLEX_STYLE}>
|
||||
{controlsReady ? (
|
||||
<Space style={NAV_TRAILING_SPACE_STYLE}>
|
||||
<WebAppSwitcher />
|
||||
<KeyboardShortcut
|
||||
shortcut='alt+q'
|
||||
hint='ALT Q'
|
||||
onTrigger={onSearch}
|
||||
>
|
||||
<Button
|
||||
icon={<SearchIcon />}
|
||||
type='text'
|
||||
style={NAV_SEARCH_BUTTON_STYLE}
|
||||
onClick={onSearch}
|
||||
/>
|
||||
</KeyboardShortcut>
|
||||
<Badge
|
||||
count={unreadCount}
|
||||
size='small'
|
||||
offset={[-5, 8]}
|
||||
style={NAV_BADGE_STYLE}
|
||||
>
|
||||
<KeyboardShortcut
|
||||
shortcut='alt+n'
|
||||
hint='ALT N'
|
||||
onTrigger={onNotifications}
|
||||
>
|
||||
<Button
|
||||
icon={<BellIcon />}
|
||||
type='text'
|
||||
style={NAV_BELL_BUTTON_STYLE}
|
||||
onClick={onNotifications}
|
||||
/>
|
||||
</KeyboardShortcut>
|
||||
</Badge>
|
||||
</Space>
|
||||
) : null}
|
||||
<DashboardDevControls />
|
||||
{controlsReady && userProfile ? (
|
||||
<Space>
|
||||
<Popover
|
||||
content={
|
||||
<UserProfilePopover
|
||||
onClose={() => onUserPopoverOpenChange(false)}
|
||||
/>
|
||||
}
|
||||
placement='bottomRight'
|
||||
trigger='hover'
|
||||
open={userPopoverOpen}
|
||||
onOpenChange={onUserPopoverOpenChange}
|
||||
arrow={false}
|
||||
>
|
||||
<Tag style={{ marginRight: 0 }} icon={<PersonIcon />}>
|
||||
{!isMobile && (userProfile?.name || userProfile.username)}
|
||||
</Tag>
|
||||
</Popover>
|
||||
</Space>
|
||||
) : null}
|
||||
{controlsReady && isElectron && availableUpdate ? (
|
||||
<Tag
|
||||
icon={<CloudIcon />}
|
||||
style={NAV_UPDATE_TAG_STYLE}
|
||||
color='cyan'
|
||||
onClick={onCheckUpdates}
|
||||
>
|
||||
Update Available
|
||||
</Tag>
|
||||
) : null}
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
DashboardNavigationTrailingItems.propTypes = {
|
||||
controlsReady: PropTypes.bool,
|
||||
isMobile: PropTypes.bool,
|
||||
isElectron: PropTypes.bool,
|
||||
unreadCount: PropTypes.number,
|
||||
userProfile: PropTypes.shape({
|
||||
name: PropTypes.string,
|
||||
username: PropTypes.string
|
||||
}),
|
||||
availableUpdate: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
|
||||
userPopoverOpen: PropTypes.bool,
|
||||
onUserPopoverOpenChange: PropTypes.func,
|
||||
onSearch: PropTypes.func,
|
||||
onNotifications: PropTypes.func,
|
||||
onCheckUpdates: PropTypes.func
|
||||
}
|
||||
|
||||
const DashboardElectronCenterItems = memo(function DashboardElectronCenterItems({
|
||||
menu,
|
||||
showNavigationLabels
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<div className='dashboard-menu-container'>{menu}</div>
|
||||
<Divider
|
||||
type='vertical'
|
||||
style={
|
||||
showNavigationLabels
|
||||
? NAV_ELECTRON_DIVIDER_STYLE_WITH_LABELS
|
||||
: NAV_ELECTRON_DIVIDER_STYLE
|
||||
}
|
||||
/>
|
||||
<div style={NAV_ELECTRON_TABS_STYLE}>
|
||||
<DashboardTabs />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
DashboardElectronCenterItems.propTypes = {
|
||||
menu: PropTypes.node,
|
||||
showNavigationLabels: PropTypes.bool
|
||||
}
|
||||
|
||||
const DashboardNavigationTrailing = memo(function DashboardNavigationTrailing({
|
||||
showControls,
|
||||
isOtherApp,
|
||||
...itemProps
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<div className='electrobun-webkit-app-region-no-drag'>
|
||||
<NavigationFade visible={showControls}>
|
||||
<DashboardNavigationTrailingItems {...itemProps} />
|
||||
</NavigationFade>
|
||||
</div>
|
||||
{isOtherApp ? <DashboardWindowButtons /> : null}
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
DashboardNavigationTrailing.propTypes = {
|
||||
showControls: PropTypes.bool,
|
||||
isOtherApp: PropTypes.bool,
|
||||
controlsReady: PropTypes.bool,
|
||||
isMobile: PropTypes.bool,
|
||||
isElectron: PropTypes.bool,
|
||||
unreadCount: PropTypes.number,
|
||||
userProfile: PropTypes.shape({
|
||||
name: PropTypes.string,
|
||||
username: PropTypes.string
|
||||
}),
|
||||
availableUpdate: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
|
||||
userPopoverOpen: PropTypes.bool,
|
||||
onUserPopoverOpenChange: PropTypes.func,
|
||||
onSearch: PropTypes.func,
|
||||
onNotifications: PropTypes.func,
|
||||
onCheckUpdates: PropTypes.func
|
||||
}
|
||||
|
||||
const mapSidebarItemsToMenu = (items, navigate) =>
|
||||
items.map((item) => {
|
||||
if (item?.type === 'divider') {
|
||||
@ -83,8 +302,7 @@ const mapSidebarItemsToMenu = (items, navigate) =>
|
||||
const DashboardNavigation = () => {
|
||||
const { userProfile } = useContext(AuthContext)
|
||||
const { showSpotlight } = useContext(SpotlightContext)
|
||||
const { connecting, connected, userSettings, userSettingsLoaded } =
|
||||
useContext(ApiServerContext)
|
||||
const { userSettings, userSettingsLoaded } = useContext(ApiServerContext)
|
||||
const { authenticated } = useContext(AuthContext)
|
||||
const {
|
||||
showNavigationLabels,
|
||||
@ -94,7 +312,6 @@ const DashboardNavigation = () => {
|
||||
} = useThemeContext()
|
||||
const { toggleNotificationCenter, unreadCount } =
|
||||
useContext(NotificationContext)
|
||||
const [apiServerState, setApiServerState] = useState('disconnected')
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
const [selectedKey, setSelectedKey] = useState('production')
|
||||
@ -209,19 +426,19 @@ const DashboardNavigation = () => {
|
||||
[includeDevItems, location.pathname, selectedKey, userProfile]
|
||||
)
|
||||
|
||||
const headerMenuItems = isMobile
|
||||
? sidebarMenuItems
|
||||
: showNavigationLabels
|
||||
? mainMenuItems
|
||||
: mainMenuItems.map((item) => ({ ...item, label: undefined }))
|
||||
const headerMenuItems = useMemo(
|
||||
() =>
|
||||
isMobile
|
||||
? sidebarMenuItems
|
||||
: showNavigationLabels
|
||||
? mainMenuItems
|
||||
: mainMenuItems.map((item) => ({ ...item, label: undefined })),
|
||||
[isMobile, mainMenuItems, showNavigationLabels, sidebarMenuItems]
|
||||
)
|
||||
|
||||
const [userPopoverOpen, setUserPopoverOpen] = useState(false)
|
||||
const [anyModalVisible, setAnyModalVisible] = useState(false)
|
||||
|
||||
const userPopoverContent = (
|
||||
<UserProfilePopover onClose={() => setUserPopoverOpen(false)} />
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
const pathParts = location.pathname.split('/').filter(Boolean)
|
||||
const sectionKey = pathParts[1]
|
||||
@ -230,19 +447,12 @@ const DashboardNavigation = () => {
|
||||
setSelectedKey(nextItem?.key || sectionKey)
|
||||
}, [location.pathname, mainMenuItems])
|
||||
|
||||
useEffect(() => {
|
||||
if (connecting == true) {
|
||||
setApiServerState('connecting')
|
||||
} else if (connected == true) {
|
||||
setApiServerState('connected')
|
||||
} else {
|
||||
setApiServerState('disconnected')
|
||||
}
|
||||
}, [connecting, connected])
|
||||
|
||||
const handleMainMenuClick = ({ key }) => {
|
||||
navigate(getSidebarDefaultPath(key, { includeDev, userProfile }))
|
||||
}
|
||||
const handleMainMenuClick = useCallback(
|
||||
({ key }) => {
|
||||
navigate(getSidebarDefaultPath(key, { includeDev, userProfile }))
|
||||
},
|
||||
[includeDev, navigate, userProfile]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (!isElectron || !setSidebarViewMenu) return
|
||||
@ -297,146 +507,69 @@ const DashboardNavigation = () => {
|
||||
}
|
||||
}, [])
|
||||
|
||||
const showControls = (!isElectron || authenticated) && !anyModalVisible
|
||||
const controlsReady = !isElectron || authenticated
|
||||
const showControls = controlsReady && !anyModalVisible
|
||||
const handleSearch = useCallback(() => {
|
||||
showSpotlight()
|
||||
}, [showSpotlight])
|
||||
const handleNotifications = useCallback(() => {
|
||||
toggleNotificationCenter()
|
||||
}, [toggleNotificationCenter])
|
||||
const handleCheckUpdates = useCallback(() => {
|
||||
checkForUpdates()
|
||||
}, [checkForUpdates])
|
||||
const overflowedIndicator = useMemo(
|
||||
() => (
|
||||
<Button type='text' icon={<MenuIcon />} style={NAV_OVERFLOW_BUTTON_STYLE} />
|
||||
),
|
||||
[]
|
||||
)
|
||||
|
||||
const menu = (
|
||||
<Menu
|
||||
mode='horizontal'
|
||||
className={`${isElectron ? 'electron-navigation' : null} ${!showNavigationLabels && !isMobile ? 'no-navigation-labels' : ''}${isMobile ? 'mobile-menu' : ''}`}
|
||||
items={headerMenuItems}
|
||||
style={{
|
||||
flexWrap: 'wrap',
|
||||
flexGrow: isElectron && !isMobile ? 0 : 1,
|
||||
border: 0,
|
||||
minWidth: 0
|
||||
}}
|
||||
onClick={isMobile ? undefined : handleMainMenuClick}
|
||||
selectedKeys={[isMobile ? selectedSidebarItemKey : selectedKey]}
|
||||
overflowedIndicator={
|
||||
<Button
|
||||
type='text'
|
||||
icon={<MenuIcon />}
|
||||
style={{ marginBottom: '4px' }}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
const menu = useMemo(
|
||||
() => (
|
||||
<Menu
|
||||
mode='horizontal'
|
||||
className={`${isElectron ? 'electron-navigation' : null} ${!showNavigationLabels && !isMobile ? 'no-navigation-labels' : ''}${isMobile ? 'mobile-menu' : ''}`}
|
||||
items={headerMenuItems}
|
||||
style={{
|
||||
flexWrap: 'wrap',
|
||||
flexGrow: isElectron && !isMobile ? 0 : 1,
|
||||
border: 0,
|
||||
minWidth: 0
|
||||
}}
|
||||
onClick={isMobile ? undefined : handleMainMenuClick}
|
||||
selectedKeys={[isMobile ? selectedSidebarItemKey : selectedKey]}
|
||||
overflowedIndicator={overflowedIndicator}
|
||||
/>
|
||||
),
|
||||
[
|
||||
handleMainMenuClick,
|
||||
headerMenuItems,
|
||||
isElectron,
|
||||
isMobile,
|
||||
overflowedIndicator,
|
||||
selectedKey,
|
||||
selectedSidebarItemKey,
|
||||
showNavigationLabels
|
||||
]
|
||||
)
|
||||
|
||||
const navigationTrailing = (
|
||||
<>
|
||||
<div className='electrobun-webkit-app-region-no-drag'>
|
||||
<Flex
|
||||
gap={'small'}
|
||||
align='center'
|
||||
style={{ marginTop: '-2px', marginRight: '6px' }}
|
||||
>
|
||||
{showControls && (
|
||||
<Space style={{ paddingTop: '2px', marginRight: '8px' }}>
|
||||
<WebAppSwitcher />
|
||||
<KeyboardShortcut
|
||||
shortcut='alt+q'
|
||||
hint='ALT Q'
|
||||
onTrigger={() => showSpotlight()}
|
||||
>
|
||||
<Button
|
||||
icon={<SearchIcon />}
|
||||
type='text'
|
||||
style={{ marginTop: '4px' }}
|
||||
onClick={() => showSpotlight()}
|
||||
/>
|
||||
</KeyboardShortcut>
|
||||
<Badge
|
||||
count={unreadCount}
|
||||
size='small'
|
||||
offset={[-5, 8]}
|
||||
style={{ padding: 0, fontWeight: 600 }}
|
||||
>
|
||||
<KeyboardShortcut
|
||||
shortcut='alt+n'
|
||||
hint='ALT N'
|
||||
onTrigger={() => toggleNotificationCenter()}
|
||||
>
|
||||
<Button
|
||||
icon={<BellIcon />}
|
||||
type='text'
|
||||
style={{ marginTop: '2px' }}
|
||||
onClick={() => toggleNotificationCenter()}
|
||||
/>
|
||||
</KeyboardShortcut>
|
||||
</Badge>
|
||||
</Space>
|
||||
)}
|
||||
{import.meta.env.MODE === 'development' && (
|
||||
<Space>
|
||||
{apiServerState === 'connected' ? (
|
||||
<Tooltip content='Connected to api server'>
|
||||
<Tag
|
||||
color='success'
|
||||
style={{ marginRight: 0 }}
|
||||
icon={<CloudIcon />}
|
||||
/>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
{apiServerState === 'connecting' ? (
|
||||
<Tooltip content='Connecting to api erver...'>
|
||||
<Tag
|
||||
color='warning'
|
||||
style={{ marginRight: 0 }}
|
||||
icon={<LoadingOutlined />}
|
||||
/>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
{apiServerState === 'disconnected' ? (
|
||||
<Tooltip content='Disconnected from api server'>
|
||||
<Tag
|
||||
color='error'
|
||||
style={{ marginRight: 0 }}
|
||||
icon={<CloudIcon />}
|
||||
/>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
<Tooltip content='Developer'>
|
||||
<Tag
|
||||
color='yellow'
|
||||
style={{ marginRight: 0 }}
|
||||
icon={<DeveloperIcon />}
|
||||
onClick={() => {
|
||||
navigate('/dashboard/developer/sessionstorage')
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Space>
|
||||
)}
|
||||
{showControls && userProfile ? (
|
||||
<Space>
|
||||
<Popover
|
||||
content={userPopoverContent}
|
||||
placement='bottomRight'
|
||||
trigger='hover'
|
||||
open={userPopoverOpen}
|
||||
onOpenChange={setUserPopoverOpen}
|
||||
arrow={false}
|
||||
>
|
||||
<Tag style={{ marginRight: 0 }} icon={<PersonIcon />}>
|
||||
{!isMobile && (userProfile?.name || userProfile.username)}
|
||||
</Tag>
|
||||
</Popover>
|
||||
</Space>
|
||||
) : null}
|
||||
{showControls && isElectron && availableUpdate ? (
|
||||
<Tag
|
||||
icon={<CloudIcon />}
|
||||
style={{ cursor: 'pointer', margin: '2px 0 0 0' }}
|
||||
color='cyan'
|
||||
onClick={() => checkForUpdates()}
|
||||
>
|
||||
Update Available
|
||||
</Tag>
|
||||
) : null}
|
||||
</Flex>
|
||||
</div>
|
||||
{isOtherApp ? <DashboardWindowButtons /> : null}
|
||||
</>
|
||||
<DashboardNavigationTrailing
|
||||
showControls={showControls}
|
||||
isOtherApp={isOtherApp}
|
||||
controlsReady={controlsReady}
|
||||
isMobile={isMobile}
|
||||
isElectron={isElectron}
|
||||
unreadCount={unreadCount}
|
||||
userProfile={userProfile}
|
||||
availableUpdate={availableUpdate}
|
||||
userPopoverOpen={userPopoverOpen}
|
||||
onUserPopoverOpenChange={setUserPopoverOpen}
|
||||
onSearch={handleSearch}
|
||||
onNotifications={handleNotifications}
|
||||
onCheckUpdates={handleCheckUpdates}
|
||||
/>
|
||||
)
|
||||
|
||||
const navigationLeading = (
|
||||
@ -456,7 +589,9 @@ const DashboardNavigation = () => {
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
{showControls && isMobile && menu}
|
||||
{isMobile ? (
|
||||
<NavigationFade visible={showControls}>{menu}</NavigationFade>
|
||||
) : null}
|
||||
{showDesktopLogo == true ? (
|
||||
<FarmControlLogo
|
||||
style={{
|
||||
@ -477,15 +612,24 @@ const DashboardNavigation = () => {
|
||||
)
|
||||
|
||||
const windowTitle = (
|
||||
<Text
|
||||
type='secondary'
|
||||
className={`dashboard-navigation-window-title dashboard-navigation-fade${
|
||||
showControls ? ' dashboard-navigation-fade-hidden' : ''
|
||||
}`}
|
||||
<div
|
||||
className={`dashboard-navigation-window-title ${navigationFadeClass(
|
||||
!showControls
|
||||
)}`}
|
||||
aria-hidden={showControls}
|
||||
inert={showControls ? true : undefined}
|
||||
>
|
||||
Farm Control
|
||||
</Text>
|
||||
<Text type='secondary'>Farm Control</Text>
|
||||
</div>
|
||||
)
|
||||
|
||||
const navigationCenterBorder = (
|
||||
<div
|
||||
className={`dashboard-navigation-center-border${
|
||||
showControls ? ' dashboard-navigation-center-border-hidden' : ''
|
||||
}`}
|
||||
aria-hidden='true'
|
||||
/>
|
||||
)
|
||||
|
||||
const navigationContents = (
|
||||
@ -493,18 +637,12 @@ const DashboardNavigation = () => {
|
||||
{navigationLeading}
|
||||
<div className='dashboard-navigation-center'>
|
||||
{!isMobile ? (
|
||||
<Flex
|
||||
align='center'
|
||||
className={`dashboard-navigation-fade${
|
||||
showControls ? '' : ' dashboard-navigation-fade-hidden'
|
||||
}`}
|
||||
style={{ width: '100%', minWidth: 0 }}
|
||||
aria-hidden={!showControls}
|
||||
>
|
||||
<NavigationFade visible={showControls} style={NAV_CENTER_FADE_STYLE}>
|
||||
{menu}
|
||||
</Flex>
|
||||
</NavigationFade>
|
||||
) : null}
|
||||
{windowTitle}
|
||||
{navigationCenterBorder}
|
||||
</div>
|
||||
{navigationTrailing}
|
||||
</Flex>
|
||||
@ -524,32 +662,21 @@ const DashboardNavigation = () => {
|
||||
>
|
||||
<Flex align='center' className='electron-navigation-leading'>
|
||||
{navigationLeading}
|
||||
{showControls && !isMobile ? menu : null}
|
||||
{showControls && !isMobile ? (
|
||||
<Divider
|
||||
type='vertical'
|
||||
style={{
|
||||
margin: showNavigationLabels
|
||||
? '3px 1px 0 4px'
|
||||
: '3px 1px 0 0',
|
||||
height: '14px'
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
</Flex>
|
||||
<div className='dashboard-navigation-center'>
|
||||
{!isMobile ? (
|
||||
<div
|
||||
className={`dashboard-navigation-fade${
|
||||
showControls ? '' : ' dashboard-navigation-fade-hidden'
|
||||
}`}
|
||||
style={{ flex: 1, minWidth: 0, display: 'flex' }}
|
||||
aria-hidden={!showControls}
|
||||
<NavigationFade
|
||||
visible={showControls}
|
||||
style={NAV_ELECTRON_CENTER_FADE_STYLE}
|
||||
>
|
||||
<DashboardTabs />
|
||||
</div>
|
||||
<DashboardElectronCenterItems
|
||||
menu={menu}
|
||||
showNavigationLabels={showNavigationLabels}
|
||||
/>
|
||||
</NavigationFade>
|
||||
) : null}
|
||||
{windowTitle}
|
||||
{navigationCenterBorder}
|
||||
</div>
|
||||
<Flex align='center' className='electron-navigation-trailing'>
|
||||
{navigationTrailing}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user