Compare commits
4 Commits
f50949a192
...
8adea62218
| Author | SHA1 | Date | |
|---|---|---|---|
| 8adea62218 | |||
| 349431c310 | |||
| 15ce7123a2 | |||
| 247bcc0ee5 |
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
@ -78,7 +78,7 @@ def buildOnLabel(label, buildCommand) {
|
||||
}
|
||||
|
||||
stage("Archive Artifacts (${label})") {
|
||||
archiveArtifacts artifacts: 'app_dist/**/*.dmg, app_dist/**/*.exe', fingerprint: true
|
||||
archiveArtifacts artifacts: 'app_dist/**/*.dmg, app_dist/**/*.exe, app_dist/**/*.pkg', fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
assets/dmg/background.png
Normal file
BIN
assets/dmg/background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
assets/dmg/background@2x.png
Normal file
BIN
assets/dmg/background@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
38
package.json
38
package.json
@ -148,11 +148,23 @@
|
||||
"arm64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"target": "pkg",
|
||||
"arch": [
|
||||
"arm64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"target": "dmg",
|
||||
"arch": [
|
||||
"x64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"target": "pkg",
|
||||
"arch": [
|
||||
"x64"
|
||||
]
|
||||
}
|
||||
],
|
||||
"mergeASARs": true,
|
||||
@ -169,6 +181,32 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"dmg": {
|
||||
"background": "assets/dmg/background.png",
|
||||
"iconSize": 100,
|
||||
"window": {
|
||||
"width": 540,
|
||||
"height": 380
|
||||
},
|
||||
"contents": [
|
||||
{
|
||||
"x": 130,
|
||||
"y": 220
|
||||
},
|
||||
{
|
||||
"x": 410,
|
||||
"y": 220,
|
||||
"type": "link",
|
||||
"path": "/Applications"
|
||||
}
|
||||
]
|
||||
},
|
||||
"pkg": {
|
||||
"installLocation": "/Applications",
|
||||
"mustClose": [
|
||||
"com.tombutcher.farmcontrol"
|
||||
]
|
||||
},
|
||||
"win": {
|
||||
"target": "nsis"
|
||||
},
|
||||
|
||||
@ -6,6 +6,7 @@ const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = dirname(__filename)
|
||||
|
||||
let win
|
||||
let sidebarViewMenuSections = []
|
||||
|
||||
const PROTOCOL_PREFIX = 'farmcontrol://'
|
||||
|
||||
@ -40,6 +41,76 @@ function sendNavigateToRenderer(redirectPath) {
|
||||
deliver()
|
||||
}
|
||||
|
||||
function toElectronSidebarMenuItems(items = []) {
|
||||
return items
|
||||
.map((item) => {
|
||||
if (item?.type === 'divider') {
|
||||
return { type: 'separator' }
|
||||
}
|
||||
|
||||
const menuItem = {
|
||||
label: item.label
|
||||
}
|
||||
|
||||
if (item?.children && Array.isArray(item.children) && item.children.length) {
|
||||
menuItem.submenu = toElectronSidebarMenuItems(item.children)
|
||||
} else if (item?.path) {
|
||||
menuItem.click = () => sendNavigateToRenderer(item.path)
|
||||
} else {
|
||||
menuItem.enabled = false
|
||||
}
|
||||
|
||||
return menuItem
|
||||
})
|
||||
.filter(Boolean)
|
||||
}
|
||||
|
||||
function buildApplicationMenuTemplate() {
|
||||
const env = (process.env.NODE_ENV || 'development').trim()
|
||||
const viewSubmenu = sidebarViewMenuSections.map((section) => ({
|
||||
label: section.label,
|
||||
submenu: toElectronSidebarMenuItems(section.items || [])
|
||||
}))
|
||||
|
||||
if (viewSubmenu.length === 0) {
|
||||
viewSubmenu.push({ label: 'No sidebar items available', enabled: false })
|
||||
}
|
||||
|
||||
if (env === 'development') {
|
||||
viewSubmenu.push(
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: 'Toggle Developer Tools',
|
||||
accelerator:
|
||||
process.platform === 'darwin' ? 'Alt+Command+I' : 'Ctrl+Shift+I',
|
||||
click: () => {
|
||||
if (win && !win.isDestroyed()) {
|
||||
win.webContents.toggleDevTools()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const template = [
|
||||
{ role: 'fileMenu' },
|
||||
{ role: 'editMenu' },
|
||||
{ label: 'View', submenu: viewSubmenu },
|
||||
{ role: 'windowMenu' }
|
||||
]
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
template.unshift({ role: 'appMenu' })
|
||||
}
|
||||
|
||||
return template
|
||||
}
|
||||
|
||||
function applyApplicationMenu() {
|
||||
const menu = Menu.buildFromTemplate(buildApplicationMenuTemplate())
|
||||
Menu.setApplicationMenu(menu)
|
||||
}
|
||||
|
||||
export function handleDeepLink(url) {
|
||||
if (!url?.startsWith(`${PROTOCOL_PREFIX}app`)) return
|
||||
const redirectPath = url.replace(`${PROTOCOL_PREFIX}app`, '') || '/'
|
||||
@ -118,29 +189,7 @@ export function createWindow() {
|
||||
}
|
||||
})
|
||||
|
||||
// Set up custom menu bar
|
||||
const env = (process.env.NODE_ENV || 'development').trim()
|
||||
if (env === 'development') {
|
||||
const devMenu = [
|
||||
{
|
||||
label: 'Developer',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Toggle Developer Tools',
|
||||
accelerator:
|
||||
process.platform === 'darwin' ? 'Alt+Command+I' : 'Ctrl+Shift+I',
|
||||
click: () => {
|
||||
win.webContents.toggleDevTools()
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
const menu = Menu.buildFromTemplate(devMenu)
|
||||
Menu.setApplicationMenu(menu)
|
||||
} else {
|
||||
Menu.setApplicationMenu(null)
|
||||
}
|
||||
applyApplicationMenu()
|
||||
|
||||
// For development, load from localhost; for production, load the built index.html
|
||||
if (process.env.ELECTRON_START_URL) {
|
||||
@ -208,6 +257,16 @@ export function setupMainWindowIPC() {
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
ipcMain.handle('set-sidebar-view-menu', (event, sidebarSections) => {
|
||||
if (!Array.isArray(sidebarSections)) {
|
||||
return false
|
||||
}
|
||||
|
||||
sidebarViewMenuSections = sidebarSections
|
||||
applyApplicationMenu()
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
export function setupMainWindowAppEvents(app) {
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import { useContext, useEffect, useRef, useState } from 'react'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import { Flex, Card, Alert } from 'antd'
|
||||
import { Flex, Card, Alert, Button } from 'antd'
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import { customAlphabet } from 'nanoid'
|
||||
import AuthParticles from './AppParticles'
|
||||
import FarmControlLogo from '../Logos/FarmControlLogo'
|
||||
import ExclamationOctagonIcon from '../Icons/ExclamationOctagonIcon'
|
||||
import CheckIcon from '../Icons/CheckIcon'
|
||||
import ReloadIcon from '../Icons/ReloadIcon'
|
||||
import { ApiServerContext } from '../Dashboard/context/ApiServerContext'
|
||||
|
||||
const createLaunchSession = customAlphabet(
|
||||
@ -24,6 +25,10 @@ const AuthLaunch = () => {
|
||||
const [launchErrorMessage, setLaunchErrorMessage] = useState('')
|
||||
const [launchSuccess, setLaunchSuccess] = useState(false)
|
||||
|
||||
const handleRefresh = () => {
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false
|
||||
const redirect = new URLSearchParams(location.search).get('redirect')
|
||||
@ -168,12 +173,19 @@ const AuthLaunch = () => {
|
||||
/>
|
||||
)}
|
||||
{launchError && (
|
||||
<Alert
|
||||
message={launchErrorMessage}
|
||||
icon={<ExclamationOctagonIcon />}
|
||||
type='error'
|
||||
showIcon
|
||||
/>
|
||||
<>
|
||||
<Alert
|
||||
message={launchErrorMessage}
|
||||
icon={<ExclamationOctagonIcon />}
|
||||
type='error'
|
||||
showIcon
|
||||
/>
|
||||
<Button
|
||||
icon={<ReloadIcon />}
|
||||
onClick={handleRefresh}
|
||||
size='large'
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{launchSuccess && (
|
||||
<Alert
|
||||
|
||||
@ -1,50 +1,14 @@
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import DashboardSidebar from '../common/DashboardSidebar'
|
||||
import { Typography } from 'antd'
|
||||
|
||||
const { Text } = Typography
|
||||
|
||||
const items = [
|
||||
{
|
||||
key: 'sessionstorage',
|
||||
label: 'Session Storage',
|
||||
icon: <Text>🗃️</Text>,
|
||||
path: '/dashboard/developer/sessionstorage'
|
||||
},
|
||||
{
|
||||
key: 'authcontextdebug',
|
||||
label: 'Auth Debug',
|
||||
icon: <Text>🔐</Text>,
|
||||
path: '/dashboard/developer/authcontextdebug'
|
||||
},
|
||||
{
|
||||
key: 'apicontextdebug',
|
||||
label: 'API Debug',
|
||||
icon: <Text>🌐</Text>,
|
||||
path: '/dashboard/developer/apicontextdebug'
|
||||
}
|
||||
]
|
||||
|
||||
const routeKeyMap = {
|
||||
'/dashboard/developer/sessionstorage': 'sessionstorage',
|
||||
'/dashboard/developer/authcontextdebug': 'authcontextdebug',
|
||||
'/dashboard/developer/apicontextdebug': 'apicontextdebug'
|
||||
}
|
||||
import { getSidebarItems, getSidebarSelectedKey } from '../../../database/Sidebars'
|
||||
|
||||
const DeveloperSidebar = (props) => {
|
||||
const location = useLocation()
|
||||
const selectedKey = (() => {
|
||||
const match = Object.keys(routeKeyMap).find((path) => {
|
||||
const pathSplit = path.split('/')
|
||||
const locationPathSplit = location.pathname.split('/')
|
||||
if (pathSplit.length > locationPathSplit.length) return false
|
||||
for (let i = 0; i < pathSplit.length; i++) {
|
||||
if (pathSplit[i] !== locationPathSplit[i]) return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return match ? routeKeyMap[match] : 'sessionstorage'
|
||||
})()
|
||||
const includeDev = import.meta.env.MODE === 'development'
|
||||
const items = getSidebarItems('developer', { includeDev })
|
||||
const selectedKey = getSidebarSelectedKey('developer', location.pathname, {
|
||||
includeDev
|
||||
})
|
||||
|
||||
return <DashboardSidebar items={items} selectedKey={selectedKey} {...props} />
|
||||
}
|
||||
|
||||
@ -1,51 +1,14 @@
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import DashboardSidebar from '../common/DashboardSidebar'
|
||||
import InvoiceIcon from '../../Icons/InvoiceIcon'
|
||||
import PaymentIcon from '../../Icons/PaymentIcon'
|
||||
import FinanceIcon from '../../Icons/FinanceIcon'
|
||||
|
||||
const items = [
|
||||
{
|
||||
key: 'overview',
|
||||
label: 'Overview',
|
||||
icon: <FinanceIcon />,
|
||||
path: '/dashboard/finance/overview'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'invoices',
|
||||
label: 'Invoices',
|
||||
icon: <InvoiceIcon />,
|
||||
path: '/dashboard/finance/invoices'
|
||||
},
|
||||
{
|
||||
key: 'payments',
|
||||
label: 'Payments',
|
||||
icon: <PaymentIcon />,
|
||||
path: '/dashboard/finance/payments'
|
||||
}
|
||||
]
|
||||
|
||||
const routeKeyMap = {
|
||||
'/dashboard/finance/overview': 'overview',
|
||||
'/dashboard/finance/invoices': 'invoices',
|
||||
'/dashboard/finance/payments': 'payments'
|
||||
}
|
||||
import { getSidebarItems, getSidebarSelectedKey } from '../../../database/Sidebars'
|
||||
|
||||
const FinanceSidebar = (props) => {
|
||||
const location = useLocation()
|
||||
const selectedKey = (() => {
|
||||
const match = Object.keys(routeKeyMap).find((path) => {
|
||||
const pathSplit = path.split('/')
|
||||
const locationPathSplit = location.pathname.split('/')
|
||||
if (pathSplit.length > locationPathSplit.length) return false
|
||||
for (let i = 0; i < pathSplit.length; i++) {
|
||||
if (pathSplit[i] !== locationPathSplit[i]) return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return match ? routeKeyMap[match] : 'overview'
|
||||
})()
|
||||
const includeDev = import.meta.env.MODE === 'development'
|
||||
const items = getSidebarItems('finance', { includeDev })
|
||||
const selectedKey = getSidebarSelectedKey('finance', location.pathname, {
|
||||
includeDev
|
||||
})
|
||||
|
||||
return <DashboardSidebar items={items} selectedKey={selectedKey} {...props} />
|
||||
}
|
||||
|
||||
@ -1,118 +1,14 @@
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import DashboardSidebar from '../common/DashboardSidebar'
|
||||
import FilamentStockIcon from '../../Icons/FilamentStockIcon'
|
||||
import PartStockIcon from '../../Icons/PartStockIcon'
|
||||
import ProductStockIcon from '../../Icons/ProductStockIcon'
|
||||
import StockEventIcon from '../../Icons/StockEventIcon'
|
||||
import StockAuditIcon from '../../Icons/StockAuditIcon'
|
||||
import PurchaseOrderIcon from '../../Icons/PurchaseOrderIcon'
|
||||
import ShipmentIcon from '../../Icons/ShipmentIcon'
|
||||
import OrderItemIcon from '../../Icons/OrderItemIcon'
|
||||
import InventoryIcon from '../../Icons/InventoryIcon'
|
||||
import StockLocationIcon from '../../Icons/StockLocationIcon'
|
||||
import StockTransferIcon from '../../Icons/StockTransferIcon'
|
||||
|
||||
const items = [
|
||||
{
|
||||
key: 'overview',
|
||||
label: 'Overview',
|
||||
icon: <InventoryIcon />,
|
||||
path: '/dashboard/inventory/overview'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'filamentstocks',
|
||||
label: 'Filament Stocks',
|
||||
icon: <FilamentStockIcon />,
|
||||
path: '/dashboard/inventory/filamentstocks'
|
||||
},
|
||||
{
|
||||
key: 'partstocks',
|
||||
label: 'Part Stocks',
|
||||
icon: <PartStockIcon />,
|
||||
path: '/dashboard/inventory/partstocks'
|
||||
},
|
||||
{
|
||||
key: 'productstocks',
|
||||
label: 'Product Stocks',
|
||||
icon: <ProductStockIcon />,
|
||||
path: '/dashboard/inventory/productstocks'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'purchaseorders',
|
||||
label: 'Purchase Orders',
|
||||
icon: <PurchaseOrderIcon />,
|
||||
path: '/dashboard/inventory/purchaseorders'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'orderitems',
|
||||
label: 'Order Items',
|
||||
icon: <OrderItemIcon />,
|
||||
path: '/dashboard/inventory/orderitems'
|
||||
},
|
||||
{
|
||||
key: 'shipments',
|
||||
label: 'Shipments',
|
||||
icon: <ShipmentIcon />,
|
||||
path: '/dashboard/inventory/shipments'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'stocklocations',
|
||||
label: 'Stock Locations',
|
||||
icon: <StockLocationIcon />,
|
||||
path: '/dashboard/inventory/stocklocations'
|
||||
},
|
||||
{
|
||||
key: 'stockevents',
|
||||
label: 'Stock Events',
|
||||
icon: <StockEventIcon />,
|
||||
path: '/dashboard/inventory/stockevents'
|
||||
},
|
||||
{
|
||||
key: 'stockaudits',
|
||||
label: 'Stock Audits',
|
||||
icon: <StockAuditIcon />,
|
||||
path: '/dashboard/inventory/stockaudits'
|
||||
},
|
||||
{
|
||||
key: 'stocktransfers',
|
||||
label: 'Stock Transfers',
|
||||
icon: <StockTransferIcon />,
|
||||
path: '/dashboard/inventory/stocktransfers'
|
||||
}
|
||||
]
|
||||
|
||||
const routeKeyMap = {
|
||||
'/dashboard/inventory/overview': 'overview',
|
||||
'/dashboard/inventory/filamentstocks': 'filamentstocks',
|
||||
'/dashboard/inventory/partstocks': 'partstocks',
|
||||
'/dashboard/inventory/productstocks': 'productstocks',
|
||||
'/dashboard/inventory/stocklocations': 'stocklocations',
|
||||
'/dashboard/inventory/stocktransfers': 'stocktransfers',
|
||||
'/dashboard/inventory/stockevents': 'stockevents',
|
||||
'/dashboard/inventory/stockaudits': 'stockaudits',
|
||||
'/dashboard/inventory/purchaseorders': 'purchaseorders',
|
||||
'/dashboard/inventory/orderitems': 'orderitems',
|
||||
'/dashboard/inventory/shipments': 'shipments'
|
||||
}
|
||||
import { getSidebarItems, getSidebarSelectedKey } from '../../../database/Sidebars'
|
||||
|
||||
const InventorySidebar = (props) => {
|
||||
const location = useLocation()
|
||||
const selectedKey = (() => {
|
||||
const match = Object.keys(routeKeyMap).find((path) => {
|
||||
const pathSplit = path.split('/')
|
||||
const locationPathSplit = location.pathname.split('/')
|
||||
if (pathSplit.length > locationPathSplit.length) return false
|
||||
for (let i = 0; i < pathSplit.length; i++) {
|
||||
if (pathSplit[i] !== locationPathSplit[i]) return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return match ? routeKeyMap[match] : 'overview'
|
||||
})()
|
||||
const includeDev = import.meta.env.MODE === 'development'
|
||||
const items = getSidebarItems('inventory', { includeDev })
|
||||
const selectedKey = getSidebarSelectedKey('inventory', location.pathname, {
|
||||
includeDev
|
||||
})
|
||||
|
||||
return <DashboardSidebar items={items} selectedKey={selectedKey} {...props} />
|
||||
}
|
||||
|
||||
@ -1,244 +1,14 @@
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import DashboardSidebar from '../common/DashboardSidebar'
|
||||
import FilamentIcon from '../../Icons/FilamentIcon'
|
||||
import FilamentSkuIcon from '../../Icons/FilamentSkuIcon'
|
||||
import PartIcon from '../../Icons/PartIcon'
|
||||
import PartSkuIcon from '../../Icons/PartSkuIcon'
|
||||
import ProductIcon from '../../Icons/ProductIcon'
|
||||
import ProductCategoryIcon from '../../Icons/ProductCategoryIcon'
|
||||
import ProductSkuIcon from '../../Icons/ProductSkuIcon'
|
||||
import VendorIcon from '../../Icons/VendorIcon'
|
||||
import MaterialIcon from '../../Icons/MaterialIcon'
|
||||
import NoteTypeIcon from '../../Icons/NoteTypeIcon'
|
||||
import SettingsIcon from '../../Icons/SettingsIcon'
|
||||
import AuditLogIcon from '../../Icons/AuditLogIcon'
|
||||
import DeveloperIcon from '../../Icons/DeveloperIcon'
|
||||
import PersonIcon from '../../Icons/PersonIcon'
|
||||
import HostIcon from '../../Icons/HostIcon'
|
||||
import DocumentPrinterIcon from '../../Icons/DocumentPrinterIcon'
|
||||
import DocumentTemplateIcon from '../../Icons/DocumentTemplateIcon'
|
||||
import DocumentIcon from '../../Icons/DocumentIcon'
|
||||
import DocumentSizeIcon from '../../Icons/DocumentSizeIcon'
|
||||
import DocumentJobIcon from '../../Icons/DocumentJobIcon'
|
||||
import FileIcon from '../../Icons/FileIcon'
|
||||
import CourierIcon from '../../Icons/CourierIcon'
|
||||
import CourierServiceIcon from '../../Icons/CourierServiceIcon'
|
||||
import TaxRateIcon from '../../Icons/TaxRateIcon'
|
||||
import TaxRecordIcon from '../../Icons/TaxRecordIcon'
|
||||
import AppPasswordIcon from '../../Icons/AppPasswordIcon'
|
||||
|
||||
const items = [
|
||||
{
|
||||
key: 'filaments',
|
||||
icon: <FilamentIcon />,
|
||||
label: 'Filaments',
|
||||
path: '/dashboard/management/filaments'
|
||||
},
|
||||
{
|
||||
key: 'filamentSkus',
|
||||
icon: <FilamentSkuIcon />,
|
||||
label: 'Filament SKUs',
|
||||
path: '/dashboard/management/filamentskus'
|
||||
},
|
||||
{
|
||||
key: 'parts',
|
||||
icon: <PartIcon />,
|
||||
label: 'Parts',
|
||||
path: '/dashboard/management/parts'
|
||||
},
|
||||
{
|
||||
key: 'partSkus',
|
||||
icon: <PartSkuIcon />,
|
||||
label: 'Part SKUs',
|
||||
path: '/dashboard/management/partskus'
|
||||
},
|
||||
{
|
||||
key: 'products',
|
||||
icon: <ProductIcon />,
|
||||
label: 'Products',
|
||||
path: '/dashboard/management/products'
|
||||
},
|
||||
{
|
||||
key: 'productCategories',
|
||||
icon: <ProductCategoryIcon />,
|
||||
label: 'Product Categories',
|
||||
path: '/dashboard/management/productcategories'
|
||||
},
|
||||
{
|
||||
key: 'productSkus',
|
||||
icon: <ProductSkuIcon />,
|
||||
label: 'Product SKUs',
|
||||
path: '/dashboard/management/productskus'
|
||||
},
|
||||
{
|
||||
key: 'vendors',
|
||||
icon: <VendorIcon />,
|
||||
label: 'Vendors',
|
||||
path: '/dashboard/management/vendors'
|
||||
},
|
||||
{
|
||||
key: 'materials',
|
||||
icon: <MaterialIcon />,
|
||||
label: 'Materials',
|
||||
path: '/dashboard/management/materials'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'couriers',
|
||||
icon: <CourierIcon />,
|
||||
label: 'Couriers',
|
||||
path: '/dashboard/management/couriers'
|
||||
},
|
||||
{
|
||||
key: 'courierServices',
|
||||
icon: <CourierServiceIcon />,
|
||||
label: 'Courier Services',
|
||||
path: '/dashboard/management/courierservices'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'taxRates',
|
||||
icon: <TaxRateIcon />,
|
||||
label: 'Tax Rates',
|
||||
path: '/dashboard/management/taxrates'
|
||||
},
|
||||
{
|
||||
key: 'taxRecords',
|
||||
icon: <TaxRecordIcon />,
|
||||
label: 'Tax Records',
|
||||
path: '/dashboard/management/taxrecords'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'noteTypes',
|
||||
icon: <NoteTypeIcon />,
|
||||
label: 'Note Types',
|
||||
path: '/dashboard/management/notetypes'
|
||||
},
|
||||
{
|
||||
key: 'documents',
|
||||
icon: <DocumentIcon />,
|
||||
label: 'Documents',
|
||||
children: [
|
||||
{
|
||||
key: 'documentPrinters',
|
||||
icon: <DocumentPrinterIcon />,
|
||||
label: 'Document Printers',
|
||||
path: '/dashboard/management/documentprinters'
|
||||
},
|
||||
{
|
||||
key: 'documentJobs',
|
||||
icon: <DocumentJobIcon />,
|
||||
label: 'Document Jobs',
|
||||
path: '/dashboard/management/documentjobs'
|
||||
},
|
||||
{
|
||||
key: 'documentTemplates',
|
||||
icon: <DocumentTemplateIcon />,
|
||||
label: 'Document Templates',
|
||||
path: '/dashboard/management/documenttemplates'
|
||||
},
|
||||
{
|
||||
key: 'documentSizes',
|
||||
icon: <DocumentSizeIcon />,
|
||||
label: 'Document Sizes',
|
||||
path: '/dashboard/management/documentsizes'
|
||||
}
|
||||
]
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'hosts',
|
||||
icon: <HostIcon />,
|
||||
label: 'Hosts',
|
||||
path: '/dashboard/management/hosts'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'users',
|
||||
icon: <PersonIcon />,
|
||||
label: 'Users',
|
||||
path: '/dashboard/management/users'
|
||||
},
|
||||
{
|
||||
key: 'appPasswords',
|
||||
icon: <AppPasswordIcon />,
|
||||
label: 'App Passwords',
|
||||
path: '/dashboard/management/apppasswords'
|
||||
},
|
||||
{
|
||||
key: 'settings',
|
||||
icon: <SettingsIcon />,
|
||||
label: 'Settings',
|
||||
path: '/dashboard/management/settings'
|
||||
},
|
||||
{
|
||||
key: 'files',
|
||||
icon: <FileIcon />,
|
||||
label: 'Files',
|
||||
path: '/dashboard/management/files'
|
||||
},
|
||||
{
|
||||
key: 'auditLogs',
|
||||
icon: <AuditLogIcon />,
|
||||
label: 'Audit Logs',
|
||||
path: '/dashboard/management/auditlogs'
|
||||
}
|
||||
]
|
||||
|
||||
if (import.meta.env.MODE === 'development') {
|
||||
items.push(
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'developer',
|
||||
icon: <DeveloperIcon />,
|
||||
label: 'Developer',
|
||||
path: '/dashboard/developer/sessionstorage'
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const routeKeyMap = {
|
||||
'/dashboard/management/filaments': 'filaments',
|
||||
'/dashboard/management/filamentskus': 'filamentSkus',
|
||||
'/dashboard/management/parts': 'parts',
|
||||
'/dashboard/management/partskus': 'partSkus',
|
||||
'/dashboard/management/users': 'users',
|
||||
'/dashboard/management/apppasswords': 'appPasswords',
|
||||
'/dashboard/management/products': 'products',
|
||||
'/dashboard/management/productcategories': 'productCategories',
|
||||
'/dashboard/management/productskus': 'productSkus',
|
||||
'/dashboard/management/vendors': 'vendors',
|
||||
'/dashboard/management/couriers': 'couriers',
|
||||
'/dashboard/management/courierservices': 'courierServices',
|
||||
'/dashboard/management/taxrates': 'taxRates',
|
||||
'/dashboard/management/taxrecords': 'taxRecords',
|
||||
'/dashboard/management/materials': 'materials',
|
||||
'/dashboard/management/notetypes': 'noteTypes',
|
||||
'/dashboard/management/settings': 'settings',
|
||||
'/dashboard/management/auditlogs': 'auditLogs',
|
||||
'/dashboard/management/files': 'files',
|
||||
'/dashboard/management/hosts': 'hosts',
|
||||
'/dashboard/management/documentsizes': 'documentSizes',
|
||||
'/dashboard/management/documentprinters': 'documentPrinters',
|
||||
'/dashboard/management/documenttemplates': 'documentTemplates',
|
||||
'/dashboard/management/documentjobs': 'documentJobs'
|
||||
}
|
||||
import { getSidebarItems, getSidebarSelectedKey } from '../../../database/Sidebars'
|
||||
|
||||
const ManagementSidebar = (props) => {
|
||||
const location = useLocation()
|
||||
const selectedKey = (() => {
|
||||
const match = Object.keys(routeKeyMap).find((path) => {
|
||||
const pathSplit = path.split('/')
|
||||
const locationPathSplit = location.pathname.split('/')
|
||||
if (pathSplit.length > locationPathSplit.length) return false
|
||||
for (let i = 0; i < pathSplit.length; i++) {
|
||||
if (pathSplit[i] !== locationPathSplit[i]) return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return match ? routeKeyMap[match] : 'filaments'
|
||||
})()
|
||||
const includeDev = import.meta.env.MODE === 'development'
|
||||
const items = getSidebarItems('management', { includeDev })
|
||||
const selectedKey = getSidebarSelectedKey('management', location.pathname, {
|
||||
includeDev
|
||||
})
|
||||
|
||||
return <DashboardSidebar items={items} selectedKey={selectedKey} {...props} />
|
||||
}
|
||||
|
||||
@ -1,67 +1,14 @@
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import DashboardSidebar from '../common/DashboardSidebar'
|
||||
import ProductionIcon from '../../Icons/ProductionIcon'
|
||||
import PrinterIcon from '../../Icons/PrinterIcon'
|
||||
import JobIcon from '../../Icons/JobIcon'
|
||||
import GCodeFileIcon from '../../Icons/GCodeFileIcon'
|
||||
import SubJobIcon from '../../Icons/SubJobIcon'
|
||||
|
||||
const items = [
|
||||
{
|
||||
key: 'overview',
|
||||
icon: <ProductionIcon />,
|
||||
label: 'Overview',
|
||||
path: '/dashboard/production/overview'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'printers',
|
||||
icon: <PrinterIcon />,
|
||||
label: 'Printers',
|
||||
path: '/dashboard/production/printers'
|
||||
},
|
||||
{
|
||||
key: 'jobs',
|
||||
icon: <JobIcon />,
|
||||
label: 'Jobs',
|
||||
path: '/dashboard/production/jobs'
|
||||
},
|
||||
{
|
||||
key: 'subJobs',
|
||||
icon: <SubJobIcon />,
|
||||
label: 'Sub Jobs',
|
||||
path: '/dashboard/production/subjobs'
|
||||
},
|
||||
{
|
||||
key: 'gcodeFiles',
|
||||
icon: <GCodeFileIcon />,
|
||||
label: 'GCode Files',
|
||||
path: '/dashboard/production/gcodefiles'
|
||||
}
|
||||
]
|
||||
|
||||
const routeKeyMap = {
|
||||
'/dashboard/production/overview': 'overview',
|
||||
'/dashboard/production/printers': 'printers',
|
||||
'/dashboard/production/jobs': 'jobs',
|
||||
'/dashboard/production/subjobs': 'subJobs',
|
||||
'/dashboard/production/gcodefiles': 'gcodeFiles'
|
||||
}
|
||||
import { getSidebarItems, getSidebarSelectedKey } from '../../../database/Sidebars'
|
||||
|
||||
const ProductionSidebar = (props) => {
|
||||
const location = useLocation()
|
||||
const selectedKey = (() => {
|
||||
const match = Object.keys(routeKeyMap).find((path) => {
|
||||
const pathSplit = path.split('/')
|
||||
const locationPathSplit = location.pathname.split('/')
|
||||
if (pathSplit.length > locationPathSplit.length) return false
|
||||
for (let i = 0; i < pathSplit.length; i++) {
|
||||
if (pathSplit[i] !== locationPathSplit[i]) return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return match ? routeKeyMap[match] : 'overview'
|
||||
})()
|
||||
const includeDev = import.meta.env.MODE === 'development'
|
||||
const items = getSidebarItems('production', { includeDev })
|
||||
const selectedKey = getSidebarSelectedKey('production', location.pathname, {
|
||||
includeDev
|
||||
})
|
||||
|
||||
return <DashboardSidebar items={items} selectedKey={selectedKey} {...props} />
|
||||
}
|
||||
|
||||
@ -1,68 +1,14 @@
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import DashboardSidebar from '../common/DashboardSidebar'
|
||||
import ClientIcon from '../../Icons/ClientIcon'
|
||||
import SalesIcon from '../../Icons/SalesIcon'
|
||||
import SalesOrderIcon from '../../Icons/SalesOrderIcon'
|
||||
import MarketplaceIcon from '../../Icons/MarketplaceIcon'
|
||||
import ListingIcon from '../../Icons/ListingIcon'
|
||||
|
||||
const items = [
|
||||
{
|
||||
key: 'overview',
|
||||
label: 'Overview',
|
||||
icon: <SalesIcon />,
|
||||
path: '/dashboard/sales/overview'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'clients',
|
||||
label: 'Clients',
|
||||
icon: <ClientIcon />,
|
||||
path: '/dashboard/sales/clients'
|
||||
},
|
||||
{
|
||||
key: 'salesorders',
|
||||
label: 'Sales Orders',
|
||||
icon: <SalesOrderIcon />,
|
||||
path: '/dashboard/sales/salesorders'
|
||||
},
|
||||
{
|
||||
key: 'marketplaces',
|
||||
label: 'Marketplaces',
|
||||
icon: <MarketplaceIcon />,
|
||||
path: '/dashboard/sales/marketplaces'
|
||||
},
|
||||
{
|
||||
key: 'listings',
|
||||
label: 'Listings',
|
||||
icon: <ListingIcon />,
|
||||
path: '/dashboard/sales/listings'
|
||||
}
|
||||
]
|
||||
|
||||
const routeKeyMap = {
|
||||
'/dashboard/sales/overview': 'overview',
|
||||
'/dashboard/sales/clients': 'clients',
|
||||
'/dashboard/sales/salesorders': 'salesorders',
|
||||
'/dashboard/sales/marketplaces': 'marketplaces',
|
||||
'/dashboard/sales/listings': 'listings',
|
||||
'/dashboard/sales/listingvarients': 'listings'
|
||||
}
|
||||
import { getSidebarItems, getSidebarSelectedKey } from '../../../database/Sidebars'
|
||||
|
||||
const SalesSidebar = (props) => {
|
||||
const location = useLocation()
|
||||
const selectedKey = (() => {
|
||||
const match = Object.keys(routeKeyMap).find((path) => {
|
||||
const pathSplit = path.split('/')
|
||||
const locationPathSplit = location.pathname.split('/')
|
||||
if (pathSplit.length > locationPathSplit.length) return false
|
||||
for (let i = 0; i < pathSplit.length; i++) {
|
||||
if (pathSplit[i] !== locationPathSplit[i]) return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return match ? routeKeyMap[match] : 'overview'
|
||||
})()
|
||||
const includeDev = import.meta.env.MODE === 'development'
|
||||
const items = getSidebarItems('sales', { includeDev })
|
||||
const selectedKey = getSidebarSelectedKey('sales', location.pathname, {
|
||||
includeDev
|
||||
})
|
||||
|
||||
return <DashboardSidebar items={items} selectedKey={selectedKey} {...props} />
|
||||
}
|
||||
|
||||
@ -38,6 +38,10 @@ import SettingsIcon from '../../Icons/SettingsIcon'
|
||||
import DeveloperIcon from '../../Icons/DeveloperIcon'
|
||||
import { ElectronContext } from '../context/ElectronContext'
|
||||
import DashboardWindowButtons from './DashboardWindowButtons'
|
||||
import {
|
||||
getSidebarDefaultPath,
|
||||
getSidebarMenuSections
|
||||
} from '../../../database/Sidebars'
|
||||
|
||||
const { Text } = Typography
|
||||
|
||||
@ -57,7 +61,8 @@ const DashboardNavigation = () => {
|
||||
icon: <ProductionIcon />
|
||||
})
|
||||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
||||
const { platform, isElectron, isFullScreen } = useContext(ElectronContext)
|
||||
const { platform, isElectron, isFullScreen, setSidebarViewMenu } =
|
||||
useContext(ElectronContext)
|
||||
|
||||
const mainMenuItems = useMemo(
|
||||
() => [
|
||||
@ -117,19 +122,16 @@ const DashboardNavigation = () => {
|
||||
}, [connecting, connected])
|
||||
|
||||
const handleMainMenuClick = ({ key }) => {
|
||||
if (key === 'production') {
|
||||
navigate('/dashboard/production/overview')
|
||||
} else if (key === 'inventory') {
|
||||
navigate('/dashboard/inventory/overview')
|
||||
} else if (key === 'finance') {
|
||||
navigate('/dashboard/finance/overview')
|
||||
} else if (key === 'sales') {
|
||||
navigate('/dashboard/sales/overview')
|
||||
} else if (key === 'management') {
|
||||
navigate('/dashboard/management/filaments')
|
||||
}
|
||||
navigate(getSidebarDefaultPath(key, { includeDev: import.meta.env.DEV }))
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!isElectron || !setSidebarViewMenu) return
|
||||
const includeDev = import.meta.env.DEV
|
||||
const sections = getSidebarMenuSections({ includeDev })
|
||||
setSidebarViewMenu(sections)
|
||||
}, [isElectron, setSidebarViewMenu])
|
||||
|
||||
const showAppLogo =
|
||||
(isElectron && platform == 'darwin' && isFullScreen == true) ||
|
||||
(isElectron && platform != 'darwin')
|
||||
|
||||
@ -7,6 +7,7 @@ import { useMediaQuery } from 'react-responsive'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import PropTypes from 'prop-types'
|
||||
import { ElectronContext } from '../context/ElectronContext'
|
||||
import { getSidebarIconNode } from '../../Icons/sidebarIconMap'
|
||||
const { Sider } = Layout
|
||||
|
||||
const DashboardSidebar = ({
|
||||
@ -47,7 +48,7 @@ const DashboardSidebar = ({
|
||||
|
||||
const mappedItem = {
|
||||
key: item.key,
|
||||
icon: item.icon,
|
||||
icon: item.icon || getSidebarIconNode(item.iconKey),
|
||||
label: item.label
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { createContext, useEffect, useState } from 'react'
|
||||
import { createContext, useCallback, useEffect, useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
||||
@ -144,6 +144,14 @@ const ElectronProvider = ({ children }) => {
|
||||
}
|
||||
}
|
||||
|
||||
const setSidebarViewMenu = useCallback(
|
||||
async (sections) => {
|
||||
if (!electronAvailable || !ipcRenderer) return false
|
||||
return await ipcRenderer.invoke('set-sidebar-view-menu', sections)
|
||||
},
|
||||
[electronAvailable]
|
||||
)
|
||||
|
||||
return (
|
||||
<ElectronContext.Provider
|
||||
value={{
|
||||
@ -159,7 +167,8 @@ const ElectronProvider = ({ children }) => {
|
||||
clearAuthSession,
|
||||
getToken,
|
||||
setToken,
|
||||
resizeSpotlightWindow
|
||||
resizeSpotlightWindow,
|
||||
setSidebarViewMenu
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
113
src/components/Icons/sidebarIconMap.jsx
Normal file
113
src/components/Icons/sidebarIconMap.jsx
Normal file
@ -0,0 +1,113 @@
|
||||
import ProductionIcon from './ProductionIcon'
|
||||
import PrinterIcon from './PrinterIcon'
|
||||
import JobIcon from './JobIcon'
|
||||
import GCodeFileIcon from './GCodeFileIcon'
|
||||
import SubJobIcon from './SubJobIcon'
|
||||
import InventoryIcon from './InventoryIcon'
|
||||
import FilamentStockIcon from './FilamentStockIcon'
|
||||
import PartStockIcon from './PartStockIcon'
|
||||
import ProductStockIcon from './ProductStockIcon'
|
||||
import StockEventIcon from './StockEventIcon'
|
||||
import StockAuditIcon from './StockAuditIcon'
|
||||
import PurchaseOrderIcon from './PurchaseOrderIcon'
|
||||
import ShipmentIcon from './ShipmentIcon'
|
||||
import OrderItemIcon from './OrderItemIcon'
|
||||
import StockLocationIcon from './StockLocationIcon'
|
||||
import StockTransferIcon from './StockTransferIcon'
|
||||
import SalesIcon from './SalesIcon'
|
||||
import ClientIcon from './ClientIcon'
|
||||
import SalesOrderIcon from './SalesOrderIcon'
|
||||
import MarketplaceIcon from './MarketplaceIcon'
|
||||
import ListingIcon from './ListingIcon'
|
||||
import FinanceIcon from './FinanceIcon'
|
||||
import InvoiceIcon from './InvoiceIcon'
|
||||
import PaymentIcon from './PaymentIcon'
|
||||
import FilamentIcon from './FilamentIcon'
|
||||
import FilamentSkuIcon from './FilamentSkuIcon'
|
||||
import PartIcon from './PartIcon'
|
||||
import PartSkuIcon from './PartSkuIcon'
|
||||
import ProductIcon from './ProductIcon'
|
||||
import ProductCategoryIcon from './ProductCategoryIcon'
|
||||
import ProductSkuIcon from './ProductSkuIcon'
|
||||
import VendorIcon from './VendorIcon'
|
||||
import MaterialIcon from './MaterialIcon'
|
||||
import NoteTypeIcon from './NoteTypeIcon'
|
||||
import SettingsIcon from './SettingsIcon'
|
||||
import AuditLogIcon from './AuditLogIcon'
|
||||
import DeveloperIcon from './DeveloperIcon'
|
||||
import PersonIcon from './PersonIcon'
|
||||
import HostIcon from './HostIcon'
|
||||
import DocumentPrinterIcon from './DocumentPrinterIcon'
|
||||
import DocumentTemplateIcon from './DocumentTemplateIcon'
|
||||
import DocumentIcon from './DocumentIcon'
|
||||
import DocumentSizeIcon from './DocumentSizeIcon'
|
||||
import DocumentJobIcon from './DocumentJobIcon'
|
||||
import FileIcon from './FileIcon'
|
||||
import CourierIcon from './CourierIcon'
|
||||
import CourierServiceIcon from './CourierServiceIcon'
|
||||
import TaxRateIcon from './TaxRateIcon'
|
||||
import TaxRecordIcon from './TaxRecordIcon'
|
||||
import AppPasswordIcon from './AppPasswordIcon'
|
||||
|
||||
const toEmoji = (emoji) => <span aria-hidden>{emoji}</span>
|
||||
|
||||
const sidebarIconMap = {
|
||||
production: <ProductionIcon />,
|
||||
printer: <PrinterIcon />,
|
||||
job: <JobIcon />,
|
||||
subJob: <SubJobIcon />,
|
||||
gcodeFile: <GCodeFileIcon />,
|
||||
inventory: <InventoryIcon />,
|
||||
filamentStock: <FilamentStockIcon />,
|
||||
partStock: <PartStockIcon />,
|
||||
productStock: <ProductStockIcon />,
|
||||
stockEvent: <StockEventIcon />,
|
||||
stockAudit: <StockAuditIcon />,
|
||||
purchaseOrder: <PurchaseOrderIcon />,
|
||||
orderItem: <OrderItemIcon />,
|
||||
shipment: <ShipmentIcon />,
|
||||
stockLocation: <StockLocationIcon />,
|
||||
stockTransfer: <StockTransferIcon />,
|
||||
sales: <SalesIcon />,
|
||||
client: <ClientIcon />,
|
||||
salesOrder: <SalesOrderIcon />,
|
||||
marketplace: <MarketplaceIcon />,
|
||||
listing: <ListingIcon />,
|
||||
finance: <FinanceIcon />,
|
||||
invoice: <InvoiceIcon />,
|
||||
payment: <PaymentIcon />,
|
||||
filament: <FilamentIcon />,
|
||||
filamentSku: <FilamentSkuIcon />,
|
||||
part: <PartIcon />,
|
||||
partSku: <PartSkuIcon />,
|
||||
product: <ProductIcon />,
|
||||
productCategory: <ProductCategoryIcon />,
|
||||
productSku: <ProductSkuIcon />,
|
||||
vendor: <VendorIcon />,
|
||||
material: <MaterialIcon />,
|
||||
noteType: <NoteTypeIcon />,
|
||||
settings: <SettingsIcon />,
|
||||
auditLog: <AuditLogIcon />,
|
||||
developer: <DeveloperIcon />,
|
||||
person: <PersonIcon />,
|
||||
host: <HostIcon />,
|
||||
documentPrinter: <DocumentPrinterIcon />,
|
||||
documentTemplate: <DocumentTemplateIcon />,
|
||||
document: <DocumentIcon />,
|
||||
documentSize: <DocumentSizeIcon />,
|
||||
documentJob: <DocumentJobIcon />,
|
||||
file: <FileIcon />,
|
||||
courier: <CourierIcon />,
|
||||
courierService: <CourierServiceIcon />,
|
||||
taxRate: <TaxRateIcon />,
|
||||
taxRecord: <TaxRecordIcon />,
|
||||
appPassword: <AppPasswordIcon />,
|
||||
sessionStorage: toEmoji('🗃️'),
|
||||
authDebug: toEmoji('🔐'),
|
||||
apiDebug: toEmoji('🌐')
|
||||
}
|
||||
|
||||
export const getSidebarIconNode = (iconKey) => {
|
||||
if (!iconKey) return null
|
||||
return sidebarIconMap[iconKey] || null
|
||||
}
|
||||
160
src/database/Sidebars.js
Normal file
160
src/database/Sidebars.js
Normal file
@ -0,0 +1,160 @@
|
||||
import productionSidebarItems from './sidebars/production'
|
||||
import inventorySidebarItems from './sidebars/inventory'
|
||||
import salesSidebarItems from './sidebars/sales'
|
||||
import financeSidebarItems from './sidebars/finance'
|
||||
import managementSidebarItems from './sidebars/management'
|
||||
import developerSidebarItems from './sidebars/developer'
|
||||
|
||||
const SIDEBARS = {
|
||||
production: {
|
||||
key: 'production',
|
||||
label: 'Production',
|
||||
iconKey: 'production',
|
||||
items: productionSidebarItems
|
||||
},
|
||||
inventory: {
|
||||
key: 'inventory',
|
||||
label: 'Inventory',
|
||||
iconKey: 'inventory',
|
||||
items: inventorySidebarItems
|
||||
},
|
||||
sales: {
|
||||
key: 'sales',
|
||||
label: 'Sales',
|
||||
iconKey: 'sales',
|
||||
items: salesSidebarItems,
|
||||
routeAliases: {
|
||||
'/dashboard/sales/listingvarients': 'listings'
|
||||
}
|
||||
},
|
||||
finance: {
|
||||
key: 'finance',
|
||||
label: 'Finance',
|
||||
iconKey: 'finance',
|
||||
items: financeSidebarItems
|
||||
},
|
||||
management: {
|
||||
key: 'management',
|
||||
label: 'Management',
|
||||
iconKey: 'settings',
|
||||
items: managementSidebarItems
|
||||
},
|
||||
developer: {
|
||||
key: 'developer',
|
||||
label: 'Developer',
|
||||
iconKey: 'developer',
|
||||
items: developerSidebarItems
|
||||
}
|
||||
}
|
||||
|
||||
const splitPath = (path) => path.split('/').filter(Boolean)
|
||||
|
||||
const isPathPrefixMatch = (candidatePath, pathname) => {
|
||||
const candidateParts = splitPath(candidatePath)
|
||||
const pathParts = splitPath(pathname)
|
||||
if (candidateParts.length > pathParts.length) return false
|
||||
for (let i = 0; i < candidateParts.length; i++) {
|
||||
if (candidateParts[i] !== pathParts[i]) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const getFilteredItems = (items = [], includeDev = false) =>
|
||||
items
|
||||
.filter((item) => item?.devOnly !== true || includeDev)
|
||||
.map((item) => {
|
||||
if (item?.children && Array.isArray(item.children)) {
|
||||
return { ...item, children: getFilteredItems(item.children, includeDev) }
|
||||
}
|
||||
return { ...item }
|
||||
})
|
||||
|
||||
const flattenPathEntries = (items = [], acc = []) => {
|
||||
items.forEach((item) => {
|
||||
if (item?.type === 'divider') return
|
||||
if (item?.path) {
|
||||
acc.push({ path: item.path, key: item.key })
|
||||
}
|
||||
if (item?.children && Array.isArray(item.children)) {
|
||||
flattenPathEntries(item.children, acc)
|
||||
}
|
||||
})
|
||||
return acc
|
||||
}
|
||||
|
||||
const findDefaultKey = (items = []) => {
|
||||
for (const item of items) {
|
||||
if (item?.type === 'divider') continue
|
||||
if (item?.children && item.children.length > 0) {
|
||||
const childKey = findDefaultKey(item.children)
|
||||
if (childKey) return childKey
|
||||
}
|
||||
if (item?.key) return item.key
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
const toMenuItems = (items = []) =>
|
||||
items.map((item) => {
|
||||
if (item?.type === 'divider') return { type: 'divider' }
|
||||
|
||||
const menuItem = {
|
||||
key: item.key,
|
||||
label: item.label,
|
||||
iconKey: item.iconKey
|
||||
}
|
||||
|
||||
if (item?.path) {
|
||||
menuItem.path = item.path
|
||||
}
|
||||
|
||||
if (item?.children && Array.isArray(item.children)) {
|
||||
menuItem.children = toMenuItems(item.children)
|
||||
}
|
||||
|
||||
return menuItem
|
||||
})
|
||||
|
||||
export const getSidebar = (sidebarKey) => SIDEBARS[sidebarKey] || null
|
||||
|
||||
export const getSidebarItems = (sidebarKey, options = {}) => {
|
||||
const sidebar = getSidebar(sidebarKey)
|
||||
if (!sidebar) return []
|
||||
const { includeDev = false } = options
|
||||
return getFilteredItems(sidebar.items, includeDev)
|
||||
}
|
||||
|
||||
export const getSidebarSelectedKey = (sidebarKey, pathname, options = {}) => {
|
||||
const sidebar = getSidebar(sidebarKey)
|
||||
if (!sidebar) return ''
|
||||
|
||||
const items = getSidebarItems(sidebarKey, options)
|
||||
const pathEntries = flattenPathEntries(items)
|
||||
const aliasEntries = Object.entries(sidebar.routeAliases || {}).map(
|
||||
([path, key]) => ({ path, key })
|
||||
)
|
||||
|
||||
const match = [...pathEntries, ...aliasEntries]
|
||||
.filter((entry) => isPathPrefixMatch(entry.path, pathname))
|
||||
.sort((a, b) => splitPath(b.path).length - splitPath(a.path).length)[0]
|
||||
|
||||
return match?.key || findDefaultKey(items)
|
||||
}
|
||||
|
||||
export const getSidebarMenuSections = (options = {}) => {
|
||||
const { includeDev = false } = options
|
||||
return Object.values(SIDEBARS)
|
||||
.filter((sidebar) => includeDev || sidebar.key !== 'developer')
|
||||
.map((sidebar) => ({
|
||||
key: sidebar.key,
|
||||
label: sidebar.label,
|
||||
iconKey: sidebar.iconKey,
|
||||
items: toMenuItems(getSidebarItems(sidebar.key, { includeDev }))
|
||||
}))
|
||||
}
|
||||
|
||||
export const getSidebarDefaultPath = (sidebarKey, options = {}) => {
|
||||
const items = getSidebarItems(sidebarKey, options)
|
||||
const first = flattenPathEntries(items)[0]
|
||||
return first?.path || '/dashboard/production/overview'
|
||||
}
|
||||
@ -186,14 +186,13 @@ export const Filament = {
|
||||
columnWidth: 150,
|
||||
value: (objectData) => {
|
||||
const cost = objectData?.cost
|
||||
if (!cost) return undefined
|
||||
if (!cost) return 0
|
||||
if (objectData?.costTaxRate?.rateType == 'percentage') {
|
||||
return (
|
||||
(cost * (1 + objectData?.costTaxRate?.rate / 100)).toFixed(2) ||
|
||||
undefined
|
||||
(cost * (1 + objectData?.costTaxRate?.rate / 100)).toFixed(2) || 0
|
||||
)
|
||||
} else if (objectData?.costTaxRate?.rateType == 'amount') {
|
||||
return (cost + objectData?.costTaxRate?.rate).toFixed(2) || undefined
|
||||
return (cost + objectData?.costTaxRate?.rate).toFixed(2) || 0
|
||||
}
|
||||
return cost
|
||||
}
|
||||
|
||||
@ -201,11 +201,11 @@ export const FilamentSku = {
|
||||
if (!objectData?.overrideCost) return undefined
|
||||
const cost = objectData?.cost
|
||||
const taxRate = objectData?.costTaxRate
|
||||
if (!cost) return undefined
|
||||
if (!cost) return 0
|
||||
if (taxRate?.rateType == 'percentage') {
|
||||
return (cost * (1 + taxRate?.rate / 100)).toFixed(2) || undefined
|
||||
return (cost * (1 + taxRate?.rate / 100)).toFixed(2) || 0
|
||||
} else if (taxRate?.rateType == 'amount') {
|
||||
return (cost + taxRate?.rate).toFixed(2) || undefined
|
||||
return (cost + taxRate?.rate).toFixed(2) || 0
|
||||
}
|
||||
return cost
|
||||
},
|
||||
|
||||
@ -395,20 +395,19 @@ export const Invoice = {
|
||||
columnWidth: 200,
|
||||
value: (objectData) => {
|
||||
const invoiceAmount = objectData?.invoiceAmount || 0
|
||||
if (!invoiceAmount) return 0
|
||||
if (objectData?.taxRate?.rateType == 'percentage') {
|
||||
return (
|
||||
(invoiceAmount * (1 + objectData?.taxRate?.rate / 100)).toFixed(
|
||||
2
|
||||
) || undefined
|
||||
) || 0
|
||||
)
|
||||
} else if (objectData?.taxRate?.rateType == 'amount') {
|
||||
return (
|
||||
(invoiceAmount + objectData?.taxRate?.rate).toFixed(2) ||
|
||||
undefined
|
||||
(invoiceAmount + objectData?.taxRate?.rate).toFixed(2) || 0
|
||||
)
|
||||
} else {
|
||||
return invoiceAmount || 0
|
||||
}
|
||||
return invoiceAmount
|
||||
}
|
||||
}
|
||||
],
|
||||
@ -505,20 +504,19 @@ export const Invoice = {
|
||||
columnWidth: 200,
|
||||
value: (objectData) => {
|
||||
const invoiceAmount = objectData?.invoiceAmount || 0
|
||||
if (!invoiceAmount) return 0
|
||||
if (objectData?.taxRate?.rateType == 'percentage') {
|
||||
return (
|
||||
(invoiceAmount * (1 + objectData?.taxRate?.rate / 100)).toFixed(
|
||||
2
|
||||
) || undefined
|
||||
) || 0
|
||||
)
|
||||
} else if (objectData?.taxRate?.rateType == 'amount') {
|
||||
return (
|
||||
(invoiceAmount + objectData?.taxRate?.rate).toFixed(2) ||
|
||||
undefined
|
||||
(invoiceAmount + objectData?.taxRate?.rate).toFixed(2) || 0
|
||||
)
|
||||
} else {
|
||||
return invoiceAmount || 0
|
||||
}
|
||||
return invoiceAmount
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@ -370,24 +370,20 @@ export const OrderItem = {
|
||||
columnWidth: 175,
|
||||
value: (objectData) => {
|
||||
const totalAmount = objectData?.itemAmount * objectData?.quantity || 0
|
||||
if (!totalAmount) return 0
|
||||
if (objectData?.taxRate?.rateType == 'percentage') {
|
||||
if (objectData?.quantity == undefined || objectData?.quantity == 0) {
|
||||
return undefined
|
||||
}
|
||||
return (
|
||||
(
|
||||
(totalAmount || 0) *
|
||||
totalAmount *
|
||||
(1 + objectData?.taxRate?.rate / 100)
|
||||
).toFixed(2) || undefined
|
||||
).toFixed(2) || 0
|
||||
)
|
||||
} else if (objectData?.taxRate?.rateType == 'amount') {
|
||||
return (
|
||||
((totalAmount || 0) + objectData?.taxRate?.rate).toFixed(2) ||
|
||||
undefined
|
||||
(totalAmount + objectData?.taxRate?.rate).toFixed(2) || 0
|
||||
)
|
||||
} else {
|
||||
return totalAmount || 0
|
||||
}
|
||||
return totalAmount
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -155,14 +155,13 @@ export const Part = {
|
||||
columnWidth: 150,
|
||||
value: (objectData) => {
|
||||
const cost = objectData?.cost
|
||||
if (!cost) return undefined
|
||||
if (!cost) return 0
|
||||
if (objectData?.costTaxRate?.rateType == 'percentage') {
|
||||
return (
|
||||
(cost * (1 + objectData?.costTaxRate?.rate / 100)).toFixed(2) ||
|
||||
undefined
|
||||
(cost * (1 + objectData?.costTaxRate?.rate / 100)).toFixed(2) || 0
|
||||
)
|
||||
} else if (objectData?.costTaxRate?.rateType == 'amount') {
|
||||
return (cost + objectData?.costTaxRate?.rate).toFixed(2) || undefined
|
||||
return (cost + objectData?.costTaxRate?.rate).toFixed(2) || 0
|
||||
}
|
||||
return cost
|
||||
}
|
||||
@ -241,16 +240,13 @@ export const Part = {
|
||||
} else {
|
||||
price = objectData?.price
|
||||
}
|
||||
if (!price) return undefined
|
||||
if (!price) return 0
|
||||
if (objectData?.priceTaxRate?.rateType == 'percentage') {
|
||||
return (
|
||||
(price * (1 + objectData?.priceTaxRate?.rate / 100)).toFixed(2) ||
|
||||
undefined
|
||||
(price * (1 + objectData?.priceTaxRate?.rate / 100)).toFixed(2) || 0
|
||||
)
|
||||
} else if (objectData?.priceTaxRate?.rateType == 'amount') {
|
||||
return (
|
||||
(price + objectData?.priceTaxRate?.rate).toFixed(2) || undefined
|
||||
)
|
||||
return (price + objectData?.priceTaxRate?.rate).toFixed(2) || 0
|
||||
}
|
||||
return price
|
||||
}
|
||||
|
||||
@ -201,11 +201,11 @@ export const PartSku = {
|
||||
if (!objectData?.overrideCost) return undefined
|
||||
const cost = objectData?.cost
|
||||
const taxRate = objectData?.costTaxRate
|
||||
if (!cost) return undefined
|
||||
if (!cost) return 0
|
||||
if (taxRate?.rateType == 'percentage') {
|
||||
return (cost * (1 + taxRate?.rate / 100)).toFixed(2) || undefined
|
||||
return (cost * (1 + taxRate?.rate / 100)).toFixed(2) || 0
|
||||
} else if (taxRate?.rateType == 'amount') {
|
||||
return (cost + taxRate?.rate).toFixed(2) || undefined
|
||||
return (cost + taxRate?.rate).toFixed(2) || 0
|
||||
}
|
||||
return cost
|
||||
},
|
||||
@ -276,13 +276,13 @@ export const PartSku = {
|
||||
} else {
|
||||
price = objectData?.price
|
||||
}
|
||||
if (price == null) return undefined
|
||||
if (!price) return 0
|
||||
const taxRate =
|
||||
objectData?.priceTaxRate ?? objectData?.part?.priceTaxRate
|
||||
if (taxRate?.rateType == 'percentage') {
|
||||
return (price * (1 + taxRate?.rate / 100)).toFixed(2) || undefined
|
||||
return (price * (1 + taxRate?.rate / 100)).toFixed(2) || 0
|
||||
} else if (taxRate?.rateType == 'amount') {
|
||||
return (price + taxRate?.rate).toFixed(2) || undefined
|
||||
return (price + taxRate?.rate).toFixed(2) || 0
|
||||
}
|
||||
return price
|
||||
},
|
||||
|
||||
@ -212,11 +212,11 @@ export const ProductSku = {
|
||||
if (!objectData?.overrideCost) return undefined
|
||||
const cost = objectData?.cost
|
||||
const taxRate = objectData?.costTaxRate
|
||||
if (!cost) return undefined
|
||||
if (!cost) return 0
|
||||
if (taxRate?.rateType == 'percentage') {
|
||||
return (cost * (1 + taxRate?.rate / 100)).toFixed(2) || undefined
|
||||
return (cost * (1 + taxRate?.rate / 100)).toFixed(2) || 0
|
||||
} else if (taxRate?.rateType == 'amount') {
|
||||
return (cost + taxRate?.rate).toFixed(2) || undefined
|
||||
return (cost + taxRate?.rate).toFixed(2) || 0
|
||||
}
|
||||
return cost
|
||||
},
|
||||
@ -289,13 +289,13 @@ export const ProductSku = {
|
||||
} else {
|
||||
price = objectData?.price
|
||||
}
|
||||
if (price == null) return undefined
|
||||
if (!price) return 0
|
||||
const taxRate =
|
||||
objectData?.priceTaxRate ?? objectData?.product?.priceTaxRate
|
||||
if (taxRate?.rateType == 'percentage') {
|
||||
return (price * (1 + taxRate?.rate / 100)).toFixed(2) || undefined
|
||||
return (price * (1 + taxRate?.rate / 100)).toFixed(2) || 0
|
||||
} else if (taxRate?.rateType == 'amount') {
|
||||
return (price + taxRate?.rate).toFixed(2) || undefined
|
||||
return (price + taxRate?.rate).toFixed(2) || 0
|
||||
}
|
||||
return price
|
||||
},
|
||||
|
||||
22
src/database/sidebars/developer.js
Normal file
22
src/database/sidebars/developer.js
Normal file
@ -0,0 +1,22 @@
|
||||
const developerSidebarItems = [
|
||||
{
|
||||
key: 'sessionstorage',
|
||||
label: 'Session Storage',
|
||||
iconKey: 'sessionStorage',
|
||||
path: '/dashboard/developer/sessionstorage'
|
||||
},
|
||||
{
|
||||
key: 'authcontextdebug',
|
||||
label: 'Auth Debug',
|
||||
iconKey: 'authDebug',
|
||||
path: '/dashboard/developer/authcontextdebug'
|
||||
},
|
||||
{
|
||||
key: 'apicontextdebug',
|
||||
label: 'API Debug',
|
||||
iconKey: 'apiDebug',
|
||||
path: '/dashboard/developer/apicontextdebug'
|
||||
}
|
||||
]
|
||||
|
||||
export default developerSidebarItems
|
||||
23
src/database/sidebars/finance.js
Normal file
23
src/database/sidebars/finance.js
Normal file
@ -0,0 +1,23 @@
|
||||
const financeSidebarItems = [
|
||||
{
|
||||
key: 'overview',
|
||||
label: 'Overview',
|
||||
iconKey: 'finance',
|
||||
path: '/dashboard/finance/overview'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'invoices',
|
||||
label: 'Invoices',
|
||||
iconKey: 'invoice',
|
||||
path: '/dashboard/finance/invoices'
|
||||
},
|
||||
{
|
||||
key: 'payments',
|
||||
label: 'Payments',
|
||||
iconKey: 'payment',
|
||||
path: '/dashboard/finance/payments'
|
||||
}
|
||||
]
|
||||
|
||||
export default financeSidebarItems
|
||||
74
src/database/sidebars/inventory.js
Normal file
74
src/database/sidebars/inventory.js
Normal file
@ -0,0 +1,74 @@
|
||||
const inventorySidebarItems = [
|
||||
{
|
||||
key: 'overview',
|
||||
label: 'Overview',
|
||||
iconKey: 'inventory',
|
||||
path: '/dashboard/inventory/overview'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'filamentstocks',
|
||||
label: 'Filament Stocks',
|
||||
iconKey: 'filamentStock',
|
||||
path: '/dashboard/inventory/filamentstocks'
|
||||
},
|
||||
{
|
||||
key: 'partstocks',
|
||||
label: 'Part Stocks',
|
||||
iconKey: 'partStock',
|
||||
path: '/dashboard/inventory/partstocks'
|
||||
},
|
||||
{
|
||||
key: 'productstocks',
|
||||
label: 'Product Stocks',
|
||||
iconKey: 'productStock',
|
||||
path: '/dashboard/inventory/productstocks'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'purchaseorders',
|
||||
label: 'Purchase Orders',
|
||||
iconKey: 'purchaseOrder',
|
||||
path: '/dashboard/inventory/purchaseorders'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'orderitems',
|
||||
label: 'Order Items',
|
||||
iconKey: 'orderItem',
|
||||
path: '/dashboard/inventory/orderitems'
|
||||
},
|
||||
{
|
||||
key: 'shipments',
|
||||
label: 'Shipments',
|
||||
iconKey: 'shipment',
|
||||
path: '/dashboard/inventory/shipments'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'stocklocations',
|
||||
label: 'Stock Locations',
|
||||
iconKey: 'stockLocation',
|
||||
path: '/dashboard/inventory/stocklocations'
|
||||
},
|
||||
{
|
||||
key: 'stockevents',
|
||||
label: 'Stock Events',
|
||||
iconKey: 'stockEvent',
|
||||
path: '/dashboard/inventory/stockevents'
|
||||
},
|
||||
{
|
||||
key: 'stockaudits',
|
||||
label: 'Stock Audits',
|
||||
iconKey: 'stockAudit',
|
||||
path: '/dashboard/inventory/stockaudits'
|
||||
},
|
||||
{
|
||||
key: 'stocktransfers',
|
||||
label: 'Stock Transfers',
|
||||
iconKey: 'stockTransfer',
|
||||
path: '/dashboard/inventory/stocktransfers'
|
||||
}
|
||||
]
|
||||
|
||||
export default inventorySidebarItems
|
||||
168
src/database/sidebars/management.js
Normal file
168
src/database/sidebars/management.js
Normal file
@ -0,0 +1,168 @@
|
||||
const managementSidebarItems = [
|
||||
{
|
||||
key: 'filaments',
|
||||
iconKey: 'filament',
|
||||
label: 'Filaments',
|
||||
path: '/dashboard/management/filaments'
|
||||
},
|
||||
{
|
||||
key: 'filamentSkus',
|
||||
iconKey: 'filamentSku',
|
||||
label: 'Filament SKUs',
|
||||
path: '/dashboard/management/filamentskus'
|
||||
},
|
||||
{
|
||||
key: 'parts',
|
||||
iconKey: 'part',
|
||||
label: 'Parts',
|
||||
path: '/dashboard/management/parts'
|
||||
},
|
||||
{
|
||||
key: 'partSkus',
|
||||
iconKey: 'partSku',
|
||||
label: 'Part SKUs',
|
||||
path: '/dashboard/management/partskus'
|
||||
},
|
||||
{
|
||||
key: 'products',
|
||||
iconKey: 'product',
|
||||
label: 'Products',
|
||||
path: '/dashboard/management/products'
|
||||
},
|
||||
{
|
||||
key: 'productCategories',
|
||||
iconKey: 'productCategory',
|
||||
label: 'Product Categories',
|
||||
path: '/dashboard/management/productcategories'
|
||||
},
|
||||
{
|
||||
key: 'productSkus',
|
||||
iconKey: 'productSku',
|
||||
label: 'Product SKUs',
|
||||
path: '/dashboard/management/productskus'
|
||||
},
|
||||
{
|
||||
key: 'vendors',
|
||||
iconKey: 'vendor',
|
||||
label: 'Vendors',
|
||||
path: '/dashboard/management/vendors'
|
||||
},
|
||||
{
|
||||
key: 'materials',
|
||||
iconKey: 'material',
|
||||
label: 'Materials',
|
||||
path: '/dashboard/management/materials'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'couriers',
|
||||
iconKey: 'courier',
|
||||
label: 'Couriers',
|
||||
path: '/dashboard/management/couriers'
|
||||
},
|
||||
{
|
||||
key: 'courierServices',
|
||||
iconKey: 'courierService',
|
||||
label: 'Courier Services',
|
||||
path: '/dashboard/management/courierservices'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'taxRates',
|
||||
iconKey: 'taxRate',
|
||||
label: 'Tax Rates',
|
||||
path: '/dashboard/management/taxrates'
|
||||
},
|
||||
{
|
||||
key: 'taxRecords',
|
||||
iconKey: 'taxRecord',
|
||||
label: 'Tax Records',
|
||||
path: '/dashboard/management/taxrecords'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'noteTypes',
|
||||
iconKey: 'noteType',
|
||||
label: 'Note Types',
|
||||
path: '/dashboard/management/notetypes'
|
||||
},
|
||||
{
|
||||
key: 'documents',
|
||||
iconKey: 'document',
|
||||
label: 'Documents',
|
||||
children: [
|
||||
{
|
||||
key: 'documentPrinters',
|
||||
iconKey: 'documentPrinter',
|
||||
label: 'Document Printers',
|
||||
path: '/dashboard/management/documentprinters'
|
||||
},
|
||||
{
|
||||
key: 'documentJobs',
|
||||
iconKey: 'documentJob',
|
||||
label: 'Document Jobs',
|
||||
path: '/dashboard/management/documentjobs'
|
||||
},
|
||||
{
|
||||
key: 'documentTemplates',
|
||||
iconKey: 'documentTemplate',
|
||||
label: 'Document Templates',
|
||||
path: '/dashboard/management/documenttemplates'
|
||||
},
|
||||
{
|
||||
key: 'documentSizes',
|
||||
iconKey: 'documentSize',
|
||||
label: 'Document Sizes',
|
||||
path: '/dashboard/management/documentsizes'
|
||||
}
|
||||
]
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'hosts',
|
||||
iconKey: 'host',
|
||||
label: 'Hosts',
|
||||
path: '/dashboard/management/hosts'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'users',
|
||||
iconKey: 'person',
|
||||
label: 'Users',
|
||||
path: '/dashboard/management/users'
|
||||
},
|
||||
{
|
||||
key: 'appPasswords',
|
||||
iconKey: 'appPassword',
|
||||
label: 'App Passwords',
|
||||
path: '/dashboard/management/apppasswords'
|
||||
},
|
||||
{
|
||||
key: 'settings',
|
||||
iconKey: 'settings',
|
||||
label: 'Settings',
|
||||
path: '/dashboard/management/settings'
|
||||
},
|
||||
{
|
||||
key: 'files',
|
||||
iconKey: 'file',
|
||||
label: 'Files',
|
||||
path: '/dashboard/management/files'
|
||||
},
|
||||
{
|
||||
key: 'auditLogs',
|
||||
iconKey: 'auditLog',
|
||||
label: 'Audit Logs',
|
||||
path: '/dashboard/management/auditlogs'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'developer',
|
||||
iconKey: 'developer',
|
||||
label: 'Developer',
|
||||
path: '/dashboard/developer/sessionstorage',
|
||||
devOnly: true
|
||||
}
|
||||
]
|
||||
|
||||
export default managementSidebarItems
|
||||
35
src/database/sidebars/production.js
Normal file
35
src/database/sidebars/production.js
Normal file
@ -0,0 +1,35 @@
|
||||
const productionSidebarItems = [
|
||||
{
|
||||
key: 'overview',
|
||||
iconKey: 'production',
|
||||
label: 'Overview',
|
||||
path: '/dashboard/production/overview'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'printers',
|
||||
iconKey: 'printer',
|
||||
label: 'Printers',
|
||||
path: '/dashboard/production/printers'
|
||||
},
|
||||
{
|
||||
key: 'jobs',
|
||||
iconKey: 'job',
|
||||
label: 'Jobs',
|
||||
path: '/dashboard/production/jobs'
|
||||
},
|
||||
{
|
||||
key: 'subJobs',
|
||||
iconKey: 'subJob',
|
||||
label: 'Sub Jobs',
|
||||
path: '/dashboard/production/subjobs'
|
||||
},
|
||||
{
|
||||
key: 'gcodeFiles',
|
||||
iconKey: 'gcodeFile',
|
||||
label: 'GCode Files',
|
||||
path: '/dashboard/production/gcodefiles'
|
||||
}
|
||||
]
|
||||
|
||||
export default productionSidebarItems
|
||||
35
src/database/sidebars/sales.js
Normal file
35
src/database/sidebars/sales.js
Normal file
@ -0,0 +1,35 @@
|
||||
const salesSidebarItems = [
|
||||
{
|
||||
key: 'overview',
|
||||
label: 'Overview',
|
||||
iconKey: 'sales',
|
||||
path: '/dashboard/sales/overview'
|
||||
},
|
||||
{ type: 'divider' },
|
||||
{
|
||||
key: 'clients',
|
||||
label: 'Clients',
|
||||
iconKey: 'client',
|
||||
path: '/dashboard/sales/clients'
|
||||
},
|
||||
{
|
||||
key: 'salesorders',
|
||||
label: 'Sales Orders',
|
||||
iconKey: 'salesOrder',
|
||||
path: '/dashboard/sales/salesorders'
|
||||
},
|
||||
{
|
||||
key: 'marketplaces',
|
||||
label: 'Marketplaces',
|
||||
iconKey: 'marketplace',
|
||||
path: '/dashboard/sales/marketplaces'
|
||||
},
|
||||
{
|
||||
key: 'listings',
|
||||
label: 'Listings',
|
||||
iconKey: 'listing',
|
||||
path: '/dashboard/sales/listings'
|
||||
}
|
||||
]
|
||||
|
||||
export default salesSidebarItems
|
||||
Loading…
x
Reference in New Issue
Block a user