Compare commits

..

No commits in common. "127fefc39acc4943333b770a19445fc1481d96ec" and "c57446836ec533ea08f0d3b5d732486ec6534cfa" have entirely different histories.

104 changed files with 659 additions and 1321 deletions

2
Jenkinsfile vendored
View File

@ -14,7 +14,7 @@ def deploy() {
stage('Install Dependencies (Ubuntu)') { stage('Install Dependencies (Ubuntu)') {
nodejs(nodeJSInstallationName: 'Node23') { nodejs(nodeJSInstallationName: 'Node23') {
sh 'pnpm install --frozen-lockfile --production=false --ignore-scripts=false' sh 'pnpm install --frozen-lockfile --production=false'
} }
} }

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(0.983114,0,0,0.983114,0.872652,-3.62694)">
<path d="M29.119,60.411L19.595,65.918C18.255,66.699 16.701,66.699 15.368,65.918L3.47,59.042C2.153,58.292 1.364,56.929 1.364,55.39L1.364,41.653C1.364,40.114 2.153,38.751 3.47,37.993L15.368,31.125C15.408,31.101 15.448,31.079 15.488,31.057C15.484,30.981 15.482,30.906 15.482,30.83L15.482,17.094C15.482,15.554 16.271,14.192 17.588,13.433L29.487,6.565C30.819,5.777 32.374,5.777 33.714,6.565L45.605,13.433C46.922,14.192 47.71,15.554 47.71,17.094L47.71,30.83C47.71,30.882 47.71,30.934 47.708,30.986C47.794,31.029 47.879,31.075 47.963,31.125L59.854,37.993C60.373,38.292 60.811,38.685 61.15,39.146C60.959,39.134 60.762,39.128 60.56,39.128L54.077,39.128L46.646,34.839C46.14,34.532 45.551,34.532 45.045,34.839L37.619,39.128L35.314,39.128C33.245,39.128 31.768,39.759 30.759,40.772C29.905,41.629 29.317,42.828 29.16,44.457L19.411,50.038L19.411,61.546C19.603,61.446 19.687,61.393 19.886,61.278L28.929,56.048C29.434,55.75 30.678,54.945 30.755,55.126L30.857,55.226L30.757,55.324C29.753,56.334 29.119,57.815 29.119,59.896L29.119,60.411ZM33.53,36.986C33.721,36.887 33.805,36.833 34.005,36.718L43.047,31.489C43.553,31.19 43.844,30.685 43.844,30.103L43.844,19.574L33.53,25.478L33.53,36.986ZM29.663,36.94L29.663,25.531L19.341,19.62L19.341,30.103C19.341,30.57 19.539,30.987 19.878,31.288L29.663,36.94ZM31.554,22.132L42.251,15.999C42.197,15.953 42.182,15.93 42.067,15.861L32.397,10.279C31.891,9.973 31.302,9.973 30.796,10.279L21.133,15.861C21.011,15.93 20.98,15.96 20.896,16.029L31.554,22.132ZM17.928,34.679C17.513,34.548 17.07,34.601 16.678,34.839L7.015,40.42C6.892,40.489 6.862,40.52 6.777,40.589L17.436,46.692L28.117,40.567L17.928,34.679ZM15.545,61.546L15.545,50.091L5.223,44.18L5.223,54.662C5.223,55.244 5.529,55.75 6.035,56.048L15.261,61.385C15.391,61.462 15.414,61.477 15.545,61.546Z"/>
</g>
<g transform="matrix(0.446187,0,0,0.446187,32,37.312437)">
<path d="M46.094,59.812L63.672,59.812C69.125,59.812 71.719,57.234 71.719,51.688L71.719,40.219C71.719,34.703 69.125,32.109 63.672,32.109L46.094,32.109C40.641,32.109 38.047,34.703 38.047,40.219L38.047,51.688C38.047,57.234 40.641,59.812 46.094,59.812ZM46.109,53.375C44.984,53.375 44.484,52.844 44.484,51.734L44.484,40.203C44.484,39.078 44.984,38.547 46.109,38.547L63.672,38.547C64.766,38.547 65.281,39.078 65.281,40.203L65.281,51.734C65.281,52.844 64.766,53.375 63.672,53.375L46.109,53.375Z" style="fill-rule:nonzero;"/>
<path d="M8.047,59.812L25.625,59.812C31.078,59.812 33.672,57.234 33.672,51.688L33.672,40.219C33.672,34.703 31.078,32.109 25.625,32.109L8.047,32.109C2.594,32.109 0,34.703 0,40.219L0,51.688C0,57.234 2.594,59.812 8.047,59.812ZM8.047,53.375C6.938,53.375 6.438,52.844 6.438,51.734L6.438,40.203C6.438,39.078 6.938,38.547 8.047,38.547L25.609,38.547C26.703,38.547 27.234,39.078 27.234,40.203L27.234,51.734C27.234,52.844 26.703,53.375 25.609,53.375L8.047,53.375Z" style="fill-rule:nonzero;"/>
<path d="M46.094,27.75L63.672,27.75C69.125,27.75 71.719,25.156 71.719,19.625L71.719,8.172C71.719,2.625 69.125,0.062 63.672,0.062L46.094,0.062C40.641,0.062 38.047,2.625 38.047,8.172L38.047,19.625C38.047,25.156 40.641,27.75 46.094,27.75ZM46.109,21.312C44.984,21.312 44.484,20.797 44.484,19.656L44.484,8.125C44.484,7.016 44.984,6.5 46.109,6.5L63.672,6.5C64.766,6.5 65.281,7.016 65.281,8.125L65.281,19.656C65.281,20.797 64.766,21.312 63.672,21.312L46.109,21.312Z" style="fill-rule:nonzero;"/>
<path d="M8.047,27.75L25.625,27.75C31.078,27.75 33.672,25.156 33.672,19.625L33.672,8.172C33.672,2.625 31.078,0.062 25.625,0.062L8.047,0.062C2.594,0.062 0,2.625 0,8.172L0,19.625C0,25.156 2.594,27.75 8.047,27.75ZM8.047,21.312C6.938,21.312 6.438,20.797 6.438,19.656L6.438,8.125C6.438,7.016 6.938,6.5 8.047,6.5L25.609,6.5C26.703,6.5 27.234,7.016 27.234,8.125L27.234,19.656C27.234,20.797 26.703,21.312 25.609,21.312L8.047,21.312Z" style="fill-rule:nonzero;"/>
</g>
<g transform="matrix(0.446187,0,0,0.446187,32,37.312437)">
<path d="M46.094,59.812L63.672,59.812C69.125,59.812 71.719,57.234 71.719,51.688L71.719,40.219C71.719,34.703 69.125,32.109 63.672,32.109L46.094,32.109C40.641,32.109 38.047,34.703 38.047,40.219L38.047,51.688C38.047,57.234 40.641,59.812 46.094,59.812ZM46.109,53.375C44.984,53.375 44.484,52.844 44.484,51.734L44.484,40.203C44.484,39.078 44.984,38.547 46.109,38.547L63.672,38.547C64.766,38.547 65.281,39.078 65.281,40.203L65.281,51.734C65.281,52.844 64.766,53.375 63.672,53.375L46.109,53.375Z" style="fill-rule:nonzero;"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -64,6 +64,10 @@ const InvoiceInfo = () => {
const [newPaymentOpen, setNewPaymentOpen] = useState(false) const [newPaymentOpen, setNewPaymentOpen] = useState(false)
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false
@ -309,7 +313,7 @@ const InvoiceInfo = () => {
<PostInvoice <PostInvoice
onOk={() => { onOk={() => {
setPostInvoiceOpen(false) setPostInvoiceOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />
@ -327,7 +331,7 @@ const InvoiceInfo = () => {
<AcknowledgeInvoice <AcknowledgeInvoice
onOk={() => { onOk={() => {
setAcknowledgeInvoiceOpen(false) setAcknowledgeInvoiceOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />
@ -345,7 +349,7 @@ const InvoiceInfo = () => {
<NewPayment <NewPayment
onOk={() => { onOk={() => {
setNewPaymentOpen(false) setNewPaymentOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
reset={newPaymentOpen} reset={newPaymentOpen}
defaultValues={{ defaultValues={{

View File

@ -50,6 +50,10 @@ const PaymentInfo = () => {
const [postPaymentOpen, setPostPaymentOpen] = useState(false) const [postPaymentOpen, setPostPaymentOpen] = useState(false)
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false
@ -229,7 +233,7 @@ const PaymentInfo = () => {
<PostPayment <PostPayment
onOk={() => { onOk={() => {
setPostPaymentOpen(false) setPostPaymentOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />

View File

@ -47,6 +47,10 @@ const FilamentStockInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.fetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -49,6 +49,10 @@ const OrderItemInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -51,6 +51,10 @@ const PartStockInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current.handleFetchObject()
return true
},
edit: () => { edit: () => {
objectFormRef?.current.startEditing() objectFormRef?.current.startEditing()
return false return false

View File

@ -58,6 +58,10 @@ const ProductStockInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current.handleFetchObject()
return true
},
edit: () => { edit: () => {
objectFormRef?.current.startEditing() objectFormRef?.current.startEditing()
return false return false
@ -258,7 +262,7 @@ const ProductStockInfo = () => {
<PostProductStock <PostProductStock
onOk={() => { onOk={() => {
setPostProductStockOpen(false) setPostProductStockOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />

View File

@ -74,6 +74,10 @@ const PurchaseOrderInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
orderItemsTableRef?.current?.startEditing?.() orderItemsTableRef?.current?.startEditing?.()
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
@ -423,7 +427,7 @@ const PurchaseOrderInfo = () => {
<PostPurchaseOrder <PostPurchaseOrder
onOk={() => { onOk={() => {
setPostPurchaseOrderOpen(false) setPostPurchaseOrderOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />
@ -441,7 +445,7 @@ const PurchaseOrderInfo = () => {
<AcknowledgePurchaseOrder <AcknowledgePurchaseOrder
onOk={() => { onOk={() => {
setAcknowledgePurchaseOrderOpen(false) setAcknowledgePurchaseOrderOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />
@ -459,7 +463,7 @@ const PurchaseOrderInfo = () => {
<CancelPurchaseOrder <CancelPurchaseOrder
onOk={() => { onOk={() => {
setCancelPurchaseOrderOpen(false) setCancelPurchaseOrderOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />

View File

@ -64,6 +64,10 @@ const PurchaseOrderInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
orderItemsTableRef?.current?.startEditing?.() orderItemsTableRef?.current?.startEditing?.()
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
@ -328,7 +332,7 @@ const PurchaseOrderInfo = () => {
<PostPurchaseOrder <PostPurchaseOrder
onOk={() => { onOk={() => {
setPostPurchaseOrderOpen(false) setPostPurchaseOrderOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />
@ -346,7 +350,7 @@ const PurchaseOrderInfo = () => {
<AcknowledgePurchaseOrder <AcknowledgePurchaseOrder
onOk={() => { onOk={() => {
setAcknowledgePurchaseOrderOpen(false) setAcknowledgePurchaseOrderOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />

View File

@ -57,6 +57,10 @@ const ShipmentInfo = () => {
const [receiveShipmentOpen, setReceiveShipmentOpen] = useState(false) const [receiveShipmentOpen, setReceiveShipmentOpen] = useState(false)
const [cancelShipmentOpen, setCancelShipmentOpen] = useState(false) const [cancelShipmentOpen, setCancelShipmentOpen] = useState(false)
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false
@ -257,7 +261,7 @@ const ShipmentInfo = () => {
<ShipShipment <ShipShipment
onOk={() => { onOk={() => {
setShipShipmentOpen(false) setShipShipmentOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />
@ -275,7 +279,7 @@ const ShipmentInfo = () => {
<ReceiveShipment <ReceiveShipment
onOk={() => { onOk={() => {
setReceiveShipmentOpen(false) setReceiveShipmentOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />
@ -293,7 +297,7 @@ const ShipmentInfo = () => {
<CancelShipment <CancelShipment
onOk={() => { onOk={() => {
setCancelShipmentOpen(false) setCancelShipmentOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />

View File

@ -51,6 +51,10 @@ const StockAuditInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current.handleFetchObject()
return true
},
edit: () => { edit: () => {
objectFormRef?.current.startEditing() objectFormRef?.current.startEditing()
return false return false

View File

@ -52,6 +52,10 @@ const StockLocationInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current.handleFetchObject()
return true
},
edit: () => { edit: () => {
objectFormRef?.current.startEditing() objectFormRef?.current.startEditing()
return false return false

View File

@ -90,7 +90,7 @@ const StockTransfers = () => {
open={newOpen} open={newOpen}
styles={{ content: { paddingBottom: '24px' } }} styles={{ content: { paddingBottom: '24px' } }}
footer={null} footer={null}
width={740} width={960}
onCancel={() => { onCancel={() => {
setNewOpen(false) setNewOpen(false)
}} }}

View File

@ -1,40 +1,17 @@
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import dayjs from 'dayjs'
import ObjectInfo from '../../common/ObjectInfo' import ObjectInfo from '../../common/ObjectInfo'
import NewObjectForm from '../../common/NewObjectForm' import NewObjectForm from '../../common/NewObjectForm'
import WizardView from '../../common/WizardView' import WizardView from '../../common/WizardView'
const defaultTransferName = () =>
`Transfer ${dayjs().format('YYYY-MM-DD HH:mm:ss')}`
const NewStockTransfer = ({ onOk, reset }) => { const NewStockTransfer = ({ onOk, reset }) => {
return ( return (
<NewObjectForm <NewObjectForm
type={'stockTransfer'} type={'stockTransfer'}
reset={reset} reset={reset}
defaultValues={{ defaultValues={{ state: { type: 'draft' }, lines: [] }}
name: defaultTransferName(),
state: { type: 'draft' },
lines: []
}}
> >
{({ handleSubmit, submitLoading, objectData, formValid }) => { {({ handleSubmit, submitLoading, objectData }) => {
const steps = [ const steps = [
{
title: 'Required',
key: 'required',
content: (
<ObjectInfo
type='stockTransfer'
column={1}
bordered={false}
labelWidth={80}
isEditing={true}
required={true}
objectData={objectData}
/>
)
},
{ {
title: 'Summary', title: 'Summary',
key: 'summary', key: 'summary',
@ -43,7 +20,6 @@ const NewStockTransfer = ({ onOk, reset }) => {
type='stockTransfer' type='stockTransfer'
column={1} column={1}
bordered={false} bordered={false}
labelWidth={80}
visibleProperties={{ visibleProperties={{
_id: false, _id: false,
createdAt: false, createdAt: false,
@ -62,7 +38,7 @@ const NewStockTransfer = ({ onOk, reset }) => {
<WizardView <WizardView
steps={steps} steps={steps}
loading={submitLoading} loading={submitLoading}
formValid={formValid} formValid={true}
title='New Stock Transfer' title='New Stock Transfer'
onSubmit={async () => { onSubmit={async () => {
const result = await handleSubmit() const result = await handleSubmit()

View File

@ -53,6 +53,10 @@ const StockTransferInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current.handleFetchObject()
return true
},
edit: () => { edit: () => {
objectFormRef?.current.startEditing() objectFormRef?.current.startEditing()
return false return false
@ -253,7 +257,7 @@ const StockTransferInfo = () => {
<PostStockTransfer <PostStockTransfer
onOk={() => { onOk={() => {
setPostOpen(false) setPostOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />

View File

@ -48,6 +48,10 @@ const AppPasswordInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
regenerateSecret: () => { regenerateSecret: () => {
setRegenerateSecretOpen(true) setRegenerateSecretOpen(true)
return false return false

View File

@ -50,6 +50,10 @@ const CourierServiceInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -46,6 +46,10 @@ const CourierInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -51,6 +51,10 @@ const DocumentJobInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.fetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -53,6 +53,10 @@ const DocumentPrinterInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current.handleFetchObject()
return true
},
edit: () => { edit: () => {
objectFormRef?.current.startEditing() objectFormRef?.current.startEditing()
return false return false

View File

@ -51,6 +51,10 @@ const DocumentSizeInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.fetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -47,6 +47,10 @@ const DocumentTemplateDesign = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current.handleFetchObject()
return true
},
edit: () => { edit: () => {
objectFormRef?.current.startEditing() objectFormRef?.current.startEditing()
return false return false

View File

@ -53,6 +53,10 @@ const DocumentTemplateInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current.handleFetchObject()
return true
},
edit: () => { edit: () => {
objectFormRef?.current.startEditing() objectFormRef?.current.startEditing()
return false return false

View File

@ -43,6 +43,10 @@ const FilamentSkuInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.fetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -57,6 +57,10 @@ const FilamentInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.fetchObject?.()
return true
},
newFilamentSku: () => { newFilamentSku: () => {
setNewFilamentSkuOpen(true) setNewFilamentSkuOpen(true)
return true return true
@ -214,9 +218,10 @@ const FilamentInfo = () => {
) : ( ) : (
<ObjectTable <ObjectTable
type='filamentStock' type='filamentStock'
masterFilter={{ filament: filamentId }} masterFilter={{ 'filamentSku.filament._id': filamentId }}
visibleColumns={{ visibleColumns={{
filament: false, filamentSku: false,
'filamentSku.filament._id': false,
startingWeight: false startingWeight: false
}} }}
/> />

View File

@ -52,6 +52,10 @@ const FileInfo = () => {
const { fetchFileContent } = useContext(ApiServerContext) const { fetchFileContent } = useContext(ApiServerContext)
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -53,6 +53,10 @@ const HostInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current.handleFetchObject()
return true
},
hostOTP: () => { hostOTP: () => {
setHostOTPOpen(true) setHostOTPOpen(true)
return false return false
@ -68,10 +72,6 @@ const HostInfo = () => {
finishEdit: () => { finishEdit: () => {
objectFormRef?.current.handleUpdate() objectFormRef?.current.handleUpdate()
return true return true
},
delete: () => {
objectFormRef?.current?.handleDelete?.()
return true
} }
} }

View File

@ -5,7 +5,6 @@ import FilamentSkuIcon from '../../Icons/FilamentSkuIcon'
import PartIcon from '../../Icons/PartIcon' import PartIcon from '../../Icons/PartIcon'
import PartSkuIcon from '../../Icons/PartSkuIcon' import PartSkuIcon from '../../Icons/PartSkuIcon'
import ProductIcon from '../../Icons/ProductIcon' import ProductIcon from '../../Icons/ProductIcon'
import ProductCategoryIcon from '../../Icons/ProductCategoryIcon'
import ProductSkuIcon from '../../Icons/ProductSkuIcon' import ProductSkuIcon from '../../Icons/ProductSkuIcon'
import VendorIcon from '../../Icons/VendorIcon' import VendorIcon from '../../Icons/VendorIcon'
import MaterialIcon from '../../Icons/MaterialIcon' import MaterialIcon from '../../Icons/MaterialIcon'
@ -58,12 +57,6 @@ const items = [
label: 'Products', label: 'Products',
path: '/dashboard/management/products' path: '/dashboard/management/products'
}, },
{
key: 'productCategories',
icon: <ProductCategoryIcon />,
label: 'Product Categories',
path: '/dashboard/management/productcategories'
},
{ {
key: 'productSkus', key: 'productSkus',
icon: <ProductSkuIcon />, icon: <ProductSkuIcon />,
@ -206,7 +199,6 @@ const routeKeyMap = {
'/dashboard/management/users': 'users', '/dashboard/management/users': 'users',
'/dashboard/management/apppasswords': 'appPasswords', '/dashboard/management/apppasswords': 'appPasswords',
'/dashboard/management/products': 'products', '/dashboard/management/products': 'products',
'/dashboard/management/productcategories': 'productCategories',
'/dashboard/management/productskus': 'productSkus', '/dashboard/management/productskus': 'productSkus',
'/dashboard/management/vendors': 'vendors', '/dashboard/management/vendors': 'vendors',
'/dashboard/management/couriers': 'couriers', '/dashboard/management/couriers': 'couriers',

View File

@ -45,6 +45,10 @@ const MaterialInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -41,6 +41,10 @@ const NoteTypeInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.fetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -50,6 +50,10 @@ const NoteInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -40,6 +40,10 @@ const PartSkuInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.fetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -45,6 +45,10 @@ const PartInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.fetchObject?.()
return true
},
newPartSku: () => { newPartSku: () => {
setNewPartSkuOpen(true) setNewPartSkuOpen(true)
return true return true

View File

@ -1,109 +0,0 @@
import { useRef, useState } from 'react'
import { Button, Flex, Space, Modal, Dropdown } from 'antd'
import NewProductCategory from './ProductCategories/NewProductCategory'
import useColumnVisibility from '../hooks/useColumnVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ObjectTable from '../common/ObjectTable'
import PlusIcon from '../../Icons/PlusIcon'
import ReloadIcon from '../../Icons/ReloadIcon'
import ObjectTableViewButton from '../common/ObjectTableViewButton'
import FilterSidebarButton from '../common/FilterSidebarButton'
import useViewMode from '../hooks/useViewMode'
import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import ExportListButton from '../common/ExportListButton'
const ProductCategories = () => {
const [newProductCategoryOpen, setNewProductCategoryOpen] = useState(false)
const tableRef = useRef()
const [viewMode, setViewMode] = useViewMode('productCategory')
const [columnVisibility, setColumnVisibility] =
useColumnVisibility('productCategory')
const [showFilterSidebar, setShowFilterSidebar] =
useFilterSidebarVisibility('ProductCategories')
const actionItems = {
items: [
{
label: 'New Product Category',
key: 'newProductCategory',
icon: <PlusIcon />
},
{ type: 'divider' },
{
label: 'Reload List',
key: 'reloadList',
icon: <ReloadIcon />
}
],
onClick: ({ key }) => {
if (key === 'reloadList') {
tableRef.current?.reload()
} else if (key === 'newProductCategory') {
setNewProductCategoryOpen(true)
}
}
}
return (
<>
<Flex vertical={'true'} gap='large' className='h-100'>
<Flex justify={'space-between'}>
<Space>
<Dropdown menu={actionItems}>
<Button>Actions</Button>
</Dropdown>
<ColumnViewButton
type='productCategory'
loading={false}
visibleState={columnVisibility}
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='productCategory' />
</Space>
<Space>
<FilterSidebarButton
active={showFilterSidebar}
onClick={() => setShowFilterSidebar(!showFilterSidebar)}
/>
<ObjectTableViewButton
viewMode={viewMode}
setViewMode={setViewMode}
/>
</Space>
</Flex>
<ObjectTable
ref={tableRef}
type='productCategory'
cards={viewMode === 'cards'}
visibleColumns={columnVisibility}
showFilterSidebar={showFilterSidebar}
/>
<Modal
open={newProductCategoryOpen}
footer={null}
width={700}
onCancel={() => {
setNewProductCategoryOpen(false)
}}
>
<NewProductCategory
onOk={() => {
setNewProductCategoryOpen(false)
tableRef.current?.reload()
}}
reset={newProductCategoryOpen}
/>
</Modal>
</Flex>
</>
)
}
export default ProductCategories

View File

@ -1,68 +0,0 @@
import PropTypes from 'prop-types'
import ObjectInfo from '../../common/ObjectInfo'
import NewObjectForm from '../../common/NewObjectForm'
import WizardView from '../../common/WizardView'
const NewProductCategory = ({ onOk }) => {
return (
<NewObjectForm type={'productCategory'}>
{({ handleSubmit, submitLoading, objectData, formValid }) => {
const steps = [
{
title: 'Required',
key: 'required',
content: (
<ObjectInfo
type='productCategory'
column={1}
bordered={false}
isEditing={true}
required={true}
objectData={objectData}
/>
)
},
{
title: 'Summary',
key: 'summary',
content: (
<ObjectInfo
type='productCategory'
column={1}
bordered={false}
visibleProperties={{
_id: false,
createdAt: false,
updatedAt: false
}}
isEditing={false}
objectData={objectData}
/>
)
}
]
return (
<WizardView
steps={steps}
loading={submitLoading}
formValid={formValid}
title='New Product Category'
onSubmit={async () => {
const result = await handleSubmit()
if (result) {
onOk()
}
}}
/>
)
}}
</NewObjectForm>
)
}
NewProductCategory.propTypes = {
onOk: PropTypes.func.isRequired,
reset: PropTypes.bool
}
export default NewProductCategory

View File

@ -1,195 +0,0 @@
import { useRef, useState } from 'react'
import { useLocation } from 'react-router-dom'
import { Space, Flex, Card } from 'antd'
import useCollapseState from '../../hooks/useCollapseState'
import NotesPanel from '../../common/NotesPanel'
import InfoCollapse from '../../common/InfoCollapse'
import ObjectInfo from '../../common/ObjectInfo'
import ViewButton from '../../common/ViewButton'
import InfoCircleIcon from '../../../Icons/InfoCircleIcon.jsx'
import NoteIcon from '../../../Icons/NoteIcon.jsx'
import AuditLogIcon from '../../../Icons/AuditLogIcon.jsx'
import ObjectForm from '../../common/ObjectForm'
import EditButtons from '../../common/EditButtons'
import LockIndicator from '../../common/LockIndicator.jsx'
import ActionHandler from '../../common/ActionHandler.jsx'
import ObjectActions from '../../common/ObjectActions.jsx'
import ObjectTable from '../../common/ObjectTable.jsx'
import InfoCollapsePlaceholder from '../../common/InfoCollapsePlaceholder.jsx'
import DocumentPrintButton from '../../common/DocumentPrintButton.jsx'
import UserNotifierToggle from '../../common/UserNotifierToggle.jsx'
import ScrollBox from '../../common/ScrollBox.jsx'
const ProductCategoryInfo = () => {
const location = useLocation()
const objectFormRef = useRef(null)
const actionHandlerRef = useRef(null)
const productCategoryId = new URLSearchParams(location.search).get(
'productCategoryId'
)
const [collapseState, updateCollapseState] = useCollapseState(
'ProductCategoryInfo',
{
info: true,
notes: true,
auditLogs: true
}
)
const [objectFormState, setEditFormState] = useState({
isEditing: false,
editLoading: false,
formValid: false,
lock: null,
loading: false,
objectData: {}
})
const actions = {
edit: () => {
objectFormRef?.current?.startEditing?.()
return false
},
cancelEdit: () => {
objectFormRef?.current?.cancelEditing?.()
return true
},
finishEdit: () => {
objectFormRef?.current?.handleUpdate?.()
return true
},
delete: () => {
objectFormRef?.current?.handleDelete?.()
return true
}
}
return (
<>
<Flex
gap='large'
vertical='true'
style={{ maxHeight: '100%', minHeight: 0 }}
>
<Flex justify={'space-between'}>
<Space size='middle'>
<Space size='small'>
<ObjectActions
type='productCategory'
id={productCategoryId}
disabled={objectFormState.loading}
objectData={objectFormState.objectData}
/>
<ViewButton
disabled={objectFormState.loading}
items={[
{ key: 'info', label: 'Product Category Information' },
{ key: 'notes', label: 'Notes' },
{ key: 'auditLogs', label: 'Audit Logs' }
]}
visibleState={collapseState}
updateVisibleState={updateCollapseState}
/>
<UserNotifierToggle
type='productCategory'
objectData={objectFormState.objectData}
disabled={objectFormState.loading}
/>
<DocumentPrintButton
type='productCategory'
objectData={objectFormState.objectData}
disabled={objectFormState.loading}
/>
</Space>
<LockIndicator lock={objectFormState.lock} />
</Space>
<Space>
<EditButtons
isEditing={objectFormState.isEditing}
handleUpdate={() => {
actionHandlerRef.current.callAction('finishEdit')
}}
cancelEditing={() => {
actionHandlerRef.current.callAction('cancelEdit')
}}
startEditing={() => {
actionHandlerRef.current.callAction('edit')
}}
editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid}
disabled={objectFormState.lock?.locked || objectFormState.loading}
loading={objectFormState.editLoading}
/>
</Space>
</Flex>
<ScrollBox>
<Flex vertical gap={'large'}>
<ActionHandler
actions={actions}
loading={objectFormState.loading}
ref={actionHandlerRef}
>
<InfoCollapse
title='Product Category Information'
icon={<InfoCircleIcon />}
active={collapseState.info}
onToggle={(expanded) => updateCollapseState('info', expanded)}
collapseKey='info'
>
<ObjectForm
id={productCategoryId}
type='productCategory'
style={{ height: '100%' }}
ref={objectFormRef}
onStateChange={(state) => {
setEditFormState((prev) => ({ ...prev, ...state }))
}}
>
{({ loading, isEditing, objectData }) => (
<ObjectInfo
loading={loading}
isEditing={isEditing}
type='productCategory'
objectData={objectData}
/>
)}
</ObjectForm>
</InfoCollapse>
</ActionHandler>
<InfoCollapse
title='Notes'
icon={<NoteIcon />}
active={collapseState.notes}
onToggle={(expanded) => updateCollapseState('notes', expanded)}
collapseKey='notes'
>
<Card>
<NotesPanel _id={productCategoryId} type='productCategory' />
</Card>
</InfoCollapse>
<InfoCollapse
title='Audit Logs'
icon={<AuditLogIcon />}
active={collapseState.auditLogs}
onToggle={(expanded) =>
updateCollapseState('auditLogs', expanded)
}
collapseKey='auditLogs'
>
{objectFormState.loading ? (
<InfoCollapsePlaceholder />
) : (
<ObjectTable
type='auditLog'
masterFilter={{ 'parent._id': productCategoryId }}
visibleColumns={{ _id: false, 'parent._id': false }}
/>
)}
</InfoCollapse>
</Flex>
</ScrollBox>
</Flex>
</>
)
}
export default ProductCategoryInfo

View File

@ -47,6 +47,10 @@ const ProductSkuInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.fetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -46,6 +46,10 @@ const ProductInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.fetchObject?.()
return true
},
newProductSku: () => { newProductSku: () => {
setNewProductSkuOpen(true) setNewProductSkuOpen(true)
return true return true

View File

@ -45,6 +45,10 @@ const TaxRateInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -48,6 +48,10 @@ const TaxRecordInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -22,9 +22,6 @@ import DocumentPrintButton from '../../common/DocumentPrintButton.jsx'
import UserNotifierToggle from '../../common/UserNotifierToggle.jsx' import UserNotifierToggle from '../../common/UserNotifierToggle.jsx'
import ScrollBox from '../../common/ScrollBox.jsx' import ScrollBox from '../../common/ScrollBox.jsx'
import NewAppPassword from '../AppPasswords/NewAppPassword.jsx' import NewAppPassword from '../AppPasswords/NewAppPassword.jsx'
import ObjectProperty from '../../common/ObjectProperty.jsx'
import { getModelProperty } from '../../../../database/ObjectModels.js'
import { useMediaQuery } from 'react-responsive'
const UserInfo = () => { const UserInfo = () => {
const location = useLocation() const location = useLocation()
@ -47,9 +44,12 @@ const UserInfo = () => {
loading: false, loading: false,
objectData: {} objectData: {}
}) })
const isMobile = useMediaQuery({ maxWidth: 768 })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
newAppPassword: () => { newAppPassword: () => {
setNewAppPasswordOpen(true) setNewAppPasswordOpen(true)
return false return false
@ -151,34 +151,13 @@ const UserInfo = () => {
}} }}
> >
{({ loading, isEditing, objectData }) => ( {({ loading, isEditing, objectData }) => (
<Flex gap='large' vertical={isMobile}> <ObjectInfo
<div loading={loading}
style={ indicator={<LoadingOutlined />}
isMobile isEditing={isEditing}
? { width: '100%' } type='user'
: { width: '20%', maxWidth: '238px' } objectData={objectData}
} />
>
<Card styles={{ body: { padding: 18 } }}>
<ObjectProperty
{...getModelProperty('user', 'profileImage')}
isEditing={isEditing}
objectData={objectData}
loading={loading}
/>
</Card>
</div>
<ObjectInfo
loading={loading}
indicator={<LoadingOutlined />}
isEditing={isEditing}
type='user'
objectData={objectData}
visibleProperties={{
profileImage: false
}}
/>
</Flex>
)} )}
</ObjectForm> </ObjectForm>
</InfoCollapse> </InfoCollapse>

View File

@ -45,6 +45,10 @@ const VendorInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -20,8 +20,11 @@ import ActionHandler from '../../common/ActionHandler.jsx'
import ObjectActions from '../../common/ObjectActions.jsx' import ObjectActions from '../../common/ObjectActions.jsx'
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 EyeIcon from '../../../Icons/EyeIcon.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 MissingPlaceholder from '../../common/MissingPlaceholder.jsx'
import FilePreview from '../../common/FilePreview.jsx'
import ScrollBox from '../../common/ScrollBox.jsx' import ScrollBox from '../../common/ScrollBox.jsx'
import { getModelProperty } from '../../../../database/ObjectModels.js' import { getModelProperty } from '../../../../database/ObjectModels.js'
import PartIcon from '../../../Icons/PartIcon.jsx' import PartIcon from '../../../Icons/PartIcon.jsx'
@ -39,6 +42,7 @@ const GCodeFileInfo = () => {
{ {
info: true, info: true,
parts: true, parts: true,
preview: true,
notes: true, notes: true,
auditLogs: true auditLogs: true
} }
@ -54,6 +58,10 @@ const GCodeFileInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current.handleFetchObject()
return true
},
edit: () => { edit: () => {
objectFormRef?.current.startEditing() objectFormRef?.current.startEditing()
return false return false
@ -92,6 +100,7 @@ const GCodeFileInfo = () => {
items={[ items={[
{ key: 'info', label: 'GCode File Information' }, { key: 'info', label: 'GCode File Information' },
{ key: 'parts', label: 'Parts' }, { key: 'parts', label: 'Parts' },
{ key: 'preview', label: 'GCode File Preview' },
{ key: 'notes', label: 'Notes' }, { key: 'notes', label: 'Notes' },
{ key: 'auditLogs', label: 'Audit Logs' } { key: 'auditLogs', label: 'Audit Logs' }
]} ]}
@ -187,6 +196,26 @@ const GCodeFileInfo = () => {
loading={loading} loading={loading}
/> />
</InfoCollapse> </InfoCollapse>
<InfoCollapse
title='GCode File Preview'
icon={<EyeIcon />}
active={collapseState.preview}
onToggle={(expanded) =>
updateCollapseState('preview', expanded)
}
collapseKey='preview'
>
{objectData?.file?._id ? (
<Card>
<FilePreview
file={objectData?.file}
style={{ width: '100%', height: '100%' }}
/>
</Card>
) : (
<MissingPlaceholder message={'No file.'} />
)}
</InfoCollapse>
</Flex> </Flex>
) )
}} }}

View File

@ -1,140 +0,0 @@
import { useRef, useState } from 'react'
import { useLocation } from 'react-router-dom'
import { Space, Flex, Card } from 'antd'
import loglevel from 'loglevel'
import config from '../../../../config.js'
import useCollapseState from '../../hooks/useCollapseState.jsx'
import NotesPanel from '../../common/NotesPanel.jsx'
import InfoCollapse from '../../common/InfoCollapse.jsx'
import ViewButton from '../../common/ViewButton.jsx'
import NoteIcon from '../../../Icons/NoteIcon.jsx'
import EyeIcon from '../../../Icons/EyeIcon.jsx'
import ObjectForm from '../../common/ObjectForm.jsx'
import LockIndicator from '../../common/LockIndicator.jsx'
import ObjectActions from '../../common/ObjectActions.jsx'
import ScrollBox from '../../common/ScrollBox.jsx'
import FilePreview from '../../common/FilePreview.jsx'
import MissingPlaceholder from '../../common/MissingPlaceholder.jsx'
import InfoCollapsePlaceholder from '../../common/InfoCollapsePlaceholder.jsx'
import DocumentPrintButton from '../../common/DocumentPrintButton.jsx'
import UserNotifierToggle from '../../common/UserNotifierToggle.jsx'
const log = loglevel.getLogger('GCodeFilePreview')
log.setLevel(config.logLevel)
const GCodeFilePreview = () => {
const location = useLocation()
const objectFormRef = useRef(null)
const gcodeFileId = new URLSearchParams(location.search).get('gcodeFileId')
const [collapseState, updateCollapseState] = useCollapseState(
'GCodeFilePreview',
{
preview: true,
notes: true
}
)
const [objectFormState, setEditFormState] = useState({
loading: false,
objectData: {},
lock: null
})
return (
<Flex
gap='large'
vertical='true'
style={{
maxHeight: '100%',
minHeight: 0
}}
>
<Flex justify={'space-between'}>
<Space size='middle'>
<Space size='small'>
<ObjectActions
type='gcodeFile'
id={gcodeFileId}
disabled={objectFormState.loading}
objectData={objectFormState.objectData}
visibleActions={{ edit: false }}
/>
<ViewButton
disabled={objectFormState.loading}
items={[
{ key: 'preview', label: 'GCode File Preview' },
{ key: 'notes', label: 'Notes' }
]}
visibleState={collapseState}
updateVisibleState={updateCollapseState}
/>
<UserNotifierToggle
type='gcodeFile'
objectData={objectFormState.objectData}
disabled={objectFormState.loading}
/>
<DocumentPrintButton
type='gcodeFile'
objectData={objectFormState.objectData}
disabled={objectFormState.loading}
/>
</Space>
<LockIndicator lock={objectFormState.lock} />
</Space>
</Flex>
<ScrollBox>
<Flex vertical gap={'large'}>
<ObjectForm
id={gcodeFileId}
type='gcodeFile'
style={{ height: '100%' }}
ref={objectFormRef}
onStateChange={(state) => {
setEditFormState((prev) => ({ ...prev, ...state }))
}}
>
{({ loading, objectData }) => (
<InfoCollapse
title='GCode File Preview'
icon={<EyeIcon />}
active={collapseState.preview}
onToggle={(expanded) =>
updateCollapseState('preview', expanded)
}
collapseKey='preview'
>
{loading ? (
<InfoCollapsePlaceholder />
) : objectData?.file?._id ? (
<Card>
<FilePreview
file={objectData?.file}
style={{ width: '100%', height: '72vh' }}
/>
</Card>
) : (
<MissingPlaceholder message={'No file.'} />
)}
</InfoCollapse>
)}
</ObjectForm>
<InfoCollapse
title='Notes'
icon={<NoteIcon />}
active={collapseState.notes}
onToggle={(expanded) => updateCollapseState('notes', expanded)}
collapseKey='notes'
>
<Card>
<NotesPanel _id={gcodeFileId} type='gcodeFile' />
</Card>
</InfoCollapse>
</Flex>
</ScrollBox>
</Flex>
)
}
export default GCodeFilePreview

View File

@ -18,7 +18,7 @@ const NewGCodeFile = ({ onOk, defaultValues }) => {
const steps = [ const steps = [
{ {
title: 'Upload', title: 'Upload',
key: 'upload', key: 'uplaod',
content: ( content: (
<ObjectInfo <ObjectInfo
type='gcodeFile' type='gcodeFile'
@ -27,7 +27,7 @@ const NewGCodeFile = ({ onOk, defaultValues }) => {
isEditing={true} isEditing={true}
required={true} required={true}
objectData={objectData} objectData={objectData}
visibleProperties={{ file: true }} visibleProperties={{ name: false, filament: false }}
showLabels={false} showLabels={false}
/> />
) )
@ -57,8 +57,6 @@ const NewGCodeFile = ({ onOk, defaultValues }) => {
bordered={false} bordered={false}
visibleProperties={{ visibleProperties={{
_id: false, _id: false,
_reference: false,
parts: false,
createdAt: false, createdAt: false,
updatedAt: false, updatedAt: false,
startedAt: false startedAt: false

View File

@ -54,6 +54,10 @@ const JobInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current.handleFetchObject()
return true
},
edit: () => { edit: () => {
objectFormRef?.current.startEditing() objectFormRef?.current.startEditing()
return false return false

View File

@ -85,6 +85,10 @@ const ControlPrinter = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current.handleFetchObject()
return true
},
edit: () => { edit: () => {
objectFormRef?.current.startEditing() objectFormRef?.current.startEditing()
return false return false

View File

@ -48,6 +48,10 @@ const PrinterInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current.handleFetchObject()
return true
},
edit: () => { edit: () => {
objectFormRef?.current.startEditing() objectFormRef?.current.startEditing()
return false return false

View File

@ -42,6 +42,10 @@ const SubJobInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current.handleFetchObject()
return true
},
edit: () => { edit: () => {
objectFormRef?.current.startEditing() objectFormRef?.current.startEditing()
return false return false

View File

@ -45,6 +45,10 @@ const ClientInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false

View File

@ -55,6 +55,10 @@ const ListingVarientInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false
@ -222,7 +226,7 @@ const ListingVarientInfo = () => {
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
onOk={() => { onOk={() => {
setPublishOpen(false) setPublishOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
/> />
</Modal> </Modal>
@ -238,7 +242,7 @@ const ListingVarientInfo = () => {
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
onOk={() => { onOk={() => {
setUnpublishOpen(false) setUnpublishOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
/> />
</Modal> </Modal>

View File

@ -55,6 +55,10 @@ const ListingInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false
@ -265,7 +269,7 @@ const ListingInfo = () => {
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
onOk={() => { onOk={() => {
setPublishListingOpen(false) setPublishListingOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
listingVarientsTableRef.current?.reload?.() listingVarientsTableRef.current?.reload?.()
}} }}
/> />
@ -282,7 +286,7 @@ const ListingInfo = () => {
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
onOk={() => { onOk={() => {
setUnpublishListingOpen(false) setUnpublishListingOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
listingVarientsTableRef.current?.reload?.() listingVarientsTableRef.current?.reload?.()
}} }}
/> />

View File

@ -112,6 +112,10 @@ const MarketplaceInfo = () => {
} }
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
return false return false
@ -291,7 +295,7 @@ const MarketplaceInfo = () => {
<SyncListings <SyncListings
onOk={() => { onOk={() => {
setSyncListingsOpen(false) setSyncListingsOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />
@ -307,7 +311,7 @@ const MarketplaceInfo = () => {
<SyncOrders <SyncOrders
onOk={() => { onOk={() => {
setSyncOrdersOpen(false) setSyncOrdersOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />

View File

@ -71,6 +71,10 @@ const SalesOrderInfo = () => {
}) })
const actions = { const actions = {
reload: () => {
objectFormRef?.current?.handleFetchObject?.()
return true
},
edit: () => { edit: () => {
orderItemsTableRef?.current?.startEditing?.() orderItemsTableRef?.current?.startEditing?.()
objectFormRef?.current?.startEditing?.() objectFormRef?.current?.startEditing?.()
@ -420,7 +424,7 @@ const SalesOrderInfo = () => {
<PostSalesOrder <PostSalesOrder
onOk={() => { onOk={() => {
setPostSalesOrderOpen(false) setPostSalesOrderOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />
@ -438,7 +442,7 @@ const SalesOrderInfo = () => {
<ConfirmSalesOrder <ConfirmSalesOrder
onOk={() => { onOk={() => {
setConfirmSalesOrderOpen(false) setConfirmSalesOrderOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />
@ -456,7 +460,7 @@ const SalesOrderInfo = () => {
<CancelSalesOrder <CancelSalesOrder
onOk={() => { onOk={() => {
setCancelSalesOrderOpen(false) setCancelSalesOrderOpen(false)
objectFormRef?.current.handleFetchObject() actions.reload()
}} }}
objectData={objectFormState.objectData} objectData={objectFormState.objectData}
/> />

View File

@ -12,12 +12,10 @@ const breadcrumbNameMap = {
developer: 'Developer', developer: 'Developer',
finance: 'Finance', finance: 'Finance',
sales: 'Sales', sales: 'Sales',
productcategories: 'Product Categories',
overview: 'Overview', overview: 'Overview',
info: 'Info', info: 'Info',
design: 'Design', design: 'Design',
control: 'Control', control: 'Control'
preview: 'Preview'
} }
const mainSections = ['production', 'inventory', 'management', 'developer'] const mainSections = ['production', 'inventory', 'management', 'developer']

View File

@ -23,7 +23,6 @@ const FileList = ({
showInfo = true, showInfo = true,
showDownload = true, showDownload = true,
defaultPreviewOpen = false, defaultPreviewOpen = false,
minimal = false,
card = true card = true
}) => { }) => {
const { fetchFileContent, flushFile } = useContext(ApiServerContext) const { fetchFileContent, flushFile } = useContext(ApiServerContext)
@ -79,7 +78,7 @@ const FileList = ({
<Tag>{file.extension}</Tag> <Tag>{file.extension}</Tag>
</Flex> </Flex>
<Flex gap={'small'} align='center'> <Flex gap={'small'} align='center'>
{showDownload && !minimal && ( {showDownload && (
<Button <Button
icon={<DownloadIcon />} icon={<DownloadIcon />}
size='small' size='small'
@ -87,7 +86,7 @@ const FileList = ({
onClick={() => handleDownload(file)} onClick={() => handleDownload(file)}
/> />
)} )}
{showPreview && !minimal && ( {showPreview && (
<Button <Button
icon={previewOpen ? <EyeSlashIcon /> : <EyeIcon />} icon={previewOpen ? <EyeSlashIcon /> : <EyeIcon />}
size='small' size='small'
@ -101,7 +100,7 @@ const FileList = ({
}} }}
/> />
)} )}
{showInfo && !minimal && ( {showInfo && (
<Button <Button
icon={<InfoCircleIcon />} icon={<InfoCircleIcon />}
size='small' size='small'
@ -111,7 +110,7 @@ const FileList = ({
}} }}
/> />
)} )}
{editing && !minimal && ( {editing && (
<Button <Button
icon={<BinIcon />} icon={<BinIcon />}
size='small' size='small'
@ -121,7 +120,7 @@ const FileList = ({
)} )}
</Flex> </Flex>
</Flex> </Flex>
{previewOpen && !minimal ? ( {previewOpen ? (
<> <>
<Divider style={{ marginTop: 0, marginBottom: card ? 0 : '4px' }} /> <Divider style={{ marginTop: 0, marginBottom: card ? 0 : '4px' }} />
<FilePreview file={file} style={{ width: '100%' }} /> <FilePreview file={file} style={{ width: '100%' }} />
@ -175,8 +174,7 @@ FileList.propTypes = {
showInfo: PropTypes.bool, showInfo: PropTypes.bool,
showDownload: PropTypes.bool, showDownload: PropTypes.bool,
defaultPreviewOpen: PropTypes.bool, defaultPreviewOpen: PropTypes.bool,
card: PropTypes.bool, card: PropTypes.bool
minimal: PropTypes.bool
} }
export default FileList export default FileList

View File

@ -2,14 +2,7 @@ import { Upload, Button, Flex, Typography, Space, Progress, Card } from 'antd'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { ApiServerContext } from '../context/ApiServerContext' import { ApiServerContext } from '../context/ApiServerContext'
import UploadIcon from '../../Icons/UploadIcon' import UploadIcon from '../../Icons/UploadIcon'
import { import { useContext, useState, useEffect } from 'react'
useCallback,
useContext,
useEffect,
useMemo,
useRef,
useState
} from 'react'
import ObjectSelect from './ObjectSelect' import ObjectSelect from './ObjectSelect'
import FileList from './FileList' import FileList from './FileList'
import PlusIcon from '../../Icons/PlusIcon' import PlusIcon from '../../Icons/PlusIcon'
@ -18,16 +11,6 @@ import FileIcon from '../../Icons/FileIcon'
const { Text } = Typography const { Text } = Typography
const getFileIdentity = (value, multiple) => {
if (multiple) {
return Array.isArray(value)
? value.map((file) => file?._id || file).join(',')
: ''
}
return value?._id || value || ''
}
const FileUpload = ({ const FileUpload = ({
value, value,
onChange, onChange,
@ -40,11 +23,6 @@ const FileUpload = ({
const { uploadFile } = useContext(ApiServerContext) const { uploadFile } = useContext(ApiServerContext)
const [uploading, setUploading] = useState(false) const [uploading, setUploading] = useState(false)
const [uploadProgress, setUploadProgress] = useState(0) const [uploadProgress, setUploadProgress] = useState(0)
const onChangeRef = useRef(onChange)
useEffect(() => {
onChangeRef.current = onChange
}, [onChange])
// Track current files using useState // Track current files using useState
const [currentFiles, setCurrentFiles] = useState(() => { const [currentFiles, setCurrentFiles] = useState(() => {
@ -57,34 +35,29 @@ const FileUpload = ({
// Update currentFiles when value prop changes // Update currentFiles when value prop changes
useEffect(() => { useEffect(() => {
setCurrentFiles((prev) => { if (multiple) {
if ( setCurrentFiles(Array.isArray(value) ? value : [])
getFileIdentity(prev, multiple) === getFileIdentity(value, multiple) } else {
) { setCurrentFiles(value || null)
return prev }
}
return multiple ? (Array.isArray(value) ? value : []) : value || null
})
}, [value, multiple]) }, [value, multiple])
// Track if there are no items in the list
const [hasNoItems, setHasNoItems] = useState(false)
// Track the selected file from ObjectSelect // Track the selected file from ObjectSelect
const [selectedFile, setSelectedFile] = useState(null) const [selectedFile, setSelectedFile] = useState(null)
const hasNoItems = useMemo( // Update hasNoItems when currentFiles changes
() => useEffect(() => {
multiple const noItems = multiple
? !currentFiles || ? !currentFiles ||
!Array.isArray(currentFiles) || !Array.isArray(currentFiles) ||
currentFiles.length === 0 currentFiles.length === 0
: !currentFiles, : !currentFiles
[currentFiles, multiple] setHasNoItems(noItems)
) onChange(currentFiles)
}, [currentFiles, multiple, onChange])
const updateCurrentFiles = useCallback((nextFiles) => {
setCurrentFiles(nextFiles)
onChangeRef.current?.(nextFiles)
}, [])
const handleFileUpload = async (file) => { const handleFileUpload = async (file) => {
try { try {
@ -97,10 +70,10 @@ const FileUpload = ({
if (multiple) { if (multiple) {
// For multiple files, add to existing array // For multiple files, add to existing array
const newFiles = [...currentFiles, uploadedFile] const newFiles = [...currentFiles, uploadedFile]
updateCurrentFiles(newFiles) setCurrentFiles(newFiles)
} else { } else {
// For single file, replace the value // For single file, replace the value
updateCurrentFiles(uploadedFile) setCurrentFiles(uploadedFile)
} }
} }
} catch (error) { } catch (error) {
@ -115,10 +88,10 @@ const FileUpload = ({
if (multiple) { if (multiple) {
// For multiple files, add to existing array // For multiple files, add to existing array
const newFiles = [...currentFiles, selectedFile] const newFiles = [...currentFiles, selectedFile]
updateCurrentFiles(newFiles) setCurrentFiles(newFiles)
} else { } else {
// For single file, replace the value // For single file, replace the value
updateCurrentFiles(selectedFile) setCurrentFiles(selectedFile)
} }
// Clear the selection // Clear the selection
setSelectedFile(null) setSelectedFile(null)
@ -137,7 +110,7 @@ const FileUpload = ({
return ( return (
<Flex gap={'small'} vertical> <Flex gap={'small'} vertical>
{hasNoItems && uploading == false ? ( {hasNoItems && uploading == false ? (
<Flex gap={'small'} align='center' wrap> <Flex gap={'small'} align='center'>
<Space.Compact style={{ flexGrow: 1 }}> <Space.Compact style={{ flexGrow: 1 }}>
<ObjectSelect <ObjectSelect
type={'file'} type={'file'}
@ -195,7 +168,7 @@ const FileUpload = ({
showPreview={showPreview} showPreview={showPreview}
defaultPreviewOpen={defaultPreviewOpen} defaultPreviewOpen={defaultPreviewOpen}
onChange={(updatedFiles) => { onChange={(updatedFiles) => {
updateCurrentFiles(updatedFiles) setCurrentFiles(updatedFiles)
}} }}
/> />
</Flex> </Flex>

View File

@ -1,6 +1,6 @@
import * as GCodePreview from 'gcode-preview' import * as GCodePreview from 'gcode-preview'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { useCallback, useEffect, useRef } from 'react' import { useCallback, useEffect, useRef, useState } from 'react'
import * as THREE from 'three' import * as THREE from 'three'
function GCodePreviewUI(props) { function GCodePreviewUI(props) {
@ -14,36 +14,33 @@ function GCodePreviewUI(props) {
style = {} style = {}
} = props } = props
const canvasRef = useRef(null) const canvasRef = useRef(null)
const previewRef = useRef(null) const [preview, setPreview] = useState()
const resizePreview = useCallback(() => { const resizePreview = useCallback(() => {
previewRef.current?.resize() preview?.resize()
}, []) }, [preview])
// Ex-ref methods removed; this component is now a regular functional component // Ex-ref methods removed; this component is now a regular functional component
useEffect(() => { useEffect(() => {
if (!canvasRef.current) return setPreview(
GCodePreview.init({
previewRef.current?.dispose?.() canvas: canvasRef.current,
previewRef.current = GCodePreview.init({ startLayer,
canvas: canvasRef.current, endLayer,
startLayer, lineWidth,
endLayer, topLayerColor: new THREE.Color(topLayerColor).getHex(),
lineWidth, lastSegmentColor: new THREE.Color(lastSegmentColor).getHex(),
topLayerColor: new THREE.Color(topLayerColor).getHex(), buildVolume: { x: 250, y: 220, z: 150 },
lastSegmentColor: new THREE.Color(lastSegmentColor).getHex(), initialCameraPosition: [0, 400, 450],
buildVolume: { x: 250, y: 220, z: 150 }, allowDragNDrop: false
initialCameraPosition: [0, 400, 450], })
allowDragNDrop: false )
})
window.addEventListener('resize', resizePreview) window.addEventListener('resize', resizePreview)
return () => { return () => {
window.removeEventListener('resize', resizePreview) window.removeEventListener('resize', resizePreview)
previewRef.current?.dispose?.()
previewRef.current = null
} }
}, [ }, [
endLayer, endLayer,
@ -55,27 +52,18 @@ function GCodePreviewUI(props) {
]) ])
useEffect(() => { useEffect(() => {
let cancelled = false
const loadFromSrc = async () => { const loadFromSrc = async () => {
const preview = previewRef.current
if (!src || !preview) return if (!src || !preview) return
try { try {
const response = await fetch(src) const response = await fetch(src)
const text = await response.text() const text = await response.text()
if (cancelled || previewRef.current !== preview) return
preview.processGCode(text) preview.processGCode(text)
} catch (e) { } catch (e) {
if (cancelled) return
console.error('Failed to load G-code from src', e) console.error('Failed to load G-code from src', e)
} }
} }
loadFromSrc() loadFromSrc()
}, [src, preview])
return () => {
cancelled = true
}
}, [endLayer, lastSegmentColor, lineWidth, src, startLayer, topLayerColor])
return <canvas ref={canvasRef} style={style}></canvas> return <canvas ref={canvasRef} style={style}></canvas>
} }

View File

@ -1,4 +1,4 @@
import { useState, useEffect, useContext, useCallback, useRef } from 'react' import { useState, useEffect, useContext, useCallback } from 'react'
import { Form } from 'antd' import { Form } from 'antd'
import { ApiServerContext } from '../context/ApiServerContext' import { ApiServerContext } from '../context/ApiServerContext'
import { useMessageContext } from '../context/MessageContext' import { useMessageContext } from '../context/MessageContext'
@ -38,35 +38,10 @@ const NewObjectForm = ({ type, style, defaultValues = {}, children }) => {
const [submitLoading, setSubmitLoading] = useState(false) const [submitLoading, setSubmitLoading] = useState(false)
const [formValid, setFormValid] = useState(false) const [formValid, setFormValid] = useState(false)
const [form] = Form.useForm() const [form] = Form.useForm()
const validationRunRef = useRef(0)
const formUpdateValues = Form.useWatch([], form) const formUpdateValues = Form.useWatch([], form)
const { showSuccess, showError: showMessageError } = useMessageContext() const { showSuccess, showError: showMessageError } = useMessageContext()
const { createObject, showError } = useContext(ApiServerContext) const { createObject, showError } = useContext(ApiServerContext)
const validateForm = useCallback(() => {
const validationRun = ++validationRunRef.current
let cancelled = false
const timeoutId = setTimeout(() => {
form
.validateFields({ validateOnly: true })
.then(() => {
if (!cancelled && validationRun === validationRunRef.current) {
setFormValid(true)
}
})
.catch(() => {
if (!cancelled && validationRun === validationRunRef.current) {
setFormValid(false)
}
})
}, 0)
return () => {
cancelled = true
clearTimeout(timeoutId)
}
}, [form])
// Get the model definition for this object type // Get the model definition for this object type
const model = getModelByName(type) const model = getModelByName(type)
@ -166,15 +141,21 @@ const NewObjectForm = ({ type, style, defaultValues = {}, children }) => {
const computedValuesObject = buildObjectFromEntries(computedEntries) const computedValuesObject = buildObjectFromEntries(computedEntries)
const initialFormData = merge({}, defaultValues, computedValuesObject) const initialFormData = merge({}, defaultValues, computedValuesObject)
form.setFieldsValue(initialFormData) form.setFieldsValue(initialFormData)
form
.validateFields({ validateOnly: true })
.then(() => setFormValid(true))
.catch(() => setFormValid(false))
setObjectData((prev) => merge({}, prev, initialFormData)) setObjectData((prev) => merge({}, prev, initialFormData))
return validateForm()
} }
}, [form, defaultValues, calculateComputedValues, model, validateForm]) }, [form, defaultValues, calculateComputedValues, model])
// Validate form on change // Validate form on change
useEffect(() => { useEffect(() => {
return validateForm() form
}, [validateForm, formUpdateValues]) .validateFields({ validateOnly: true })
.then(() => setFormValid(true))
.catch(() => setFormValid(false))
}, [form, formUpdateValues])
const handleSubmit = async () => { const handleSubmit = async () => {
try { try {
@ -236,7 +217,7 @@ const NewObjectForm = ({ type, style, defaultValues = {}, children }) => {
}} }}
> >
{children({ {children({
submitLoading, submitLoading: submitLoading,
handleSubmit, handleSubmit,
form, form,
formValid, formValid,

View File

@ -103,10 +103,11 @@ const NoteItem = ({
if (isExpanded == true) { if (isExpanded == true) {
subscribeToObjectTypeUpdatesRef.current = subscribeToObjectTypeUpdates( subscribeToObjectTypeUpdatesRef.current = subscribeToObjectTypeUpdates(
'note', 'note',
{ 'parent._id': note._id }, (noteData) => {
() => { if (noteData.parent._id == note._id) {
if (isExpanded == true) { if (isExpanded == true) {
handleNoteExpand() handleNoteExpand()
}
} }
} }
) )

View File

@ -95,8 +95,11 @@ const NotesPanel = ({ _id, type }) => {
if (connected == true && subscribeToObjectTypeUpdatesRef.current == null) { if (connected == true && subscribeToObjectTypeUpdatesRef.current == null) {
subscribeToObjectTypeUpdatesRef.current = subscribeToObjectTypeUpdates( subscribeToObjectTypeUpdatesRef.current = subscribeToObjectTypeUpdates(
'note', 'note',
{ 'parent._id': _id }, (noteData) => {
() => handleReloadData() if (noteData.parent._id == _id) {
handleReloadData()
}
}
) )
} }
return () => { return () => {

View File

@ -99,14 +99,6 @@ const ObjectProperty = ({
value = value(objectData) value = value(objectData)
} }
if (max && typeof max == 'function' && objectData) {
max = max(objectData)
}
if (min && typeof min == 'function' && objectData) {
min = min(objectData)
}
if (objectType && typeof objectType == 'function' && objectData) { if (objectType && typeof objectType == 'function' && objectData) {
objectType = objectType(objectData) objectType = objectType(objectData)
} }

View File

@ -17,8 +17,6 @@ import merge from 'lodash/merge'
import { getModelProperty } from '../../../database/ObjectModels' import { getModelProperty } from '../../../database/ObjectModels'
const { SHOW_CHILD } = TreeSelect const { SHOW_CHILD } = TreeSelect
const EMPTY_OBJECT = {}
// Helper to check if two values are equal (handling objects/ids) // Helper to check if two values are equal (handling objects/ids)
const areValuesEqual = (v1, v2) => { const areValuesEqual = (v1, v2) => {
const id1 = v1 && typeof v1 === 'object' && v1._id ? v1._id : v1 const id1 = v1 && typeof v1 === 'object' && v1._id ? v1._id : v1
@ -30,11 +28,10 @@ const ObjectSelect = ({
type = 'unknown', type = 'unknown',
showSearch = false, showSearch = false,
multiple = false, multiple = false,
treeSelectProps = EMPTY_OBJECT, treeSelectProps = {},
filter = EMPTY_OBJECT, filter = {},
masterFilter = EMPTY_OBJECT, masterFilter = {},
value, value,
onChange,
disabled = false, disabled = false,
...rest ...rest
}) => { }) => {
@ -58,6 +55,11 @@ const ObjectSelect = ({
const prevValueRef = useRef(value) const prevValueRef = useRef(value)
const isInternalChangeRef = useRef(false) const isInternalChangeRef = useRef(false)
useEffect(() => {
console.log('type', type)
console.log('value', value)
}, [value, type])
// Normalize a value to an identity string so we can detect in-place _id updates // Normalize a value to an identity string so we can detect in-place _id updates
const getValueIdentity = useCallback((val) => { const getValueIdentity = useCallback((val) => {
if (val && typeof val === 'object') { if (val && typeof val === 'object') {
@ -357,15 +359,15 @@ const ObjectSelect = ({
.filter(Boolean) .filter(Boolean)
} }
setTreeSelectValue(value) setTreeSelectValue(value)
onChange?.(selectedObjects) if (rest.onChange) rest.onChange(selectedObjects)
} else { } else {
// Single selection // Single selection
const selectedObject = objectList.find((obj) => obj._id === value) const selectedObject = objectList.find((obj) => obj._id === value)
setTreeSelectValue(value) setTreeSelectValue(value)
onChange?.(selectedObject) if (rest.onChange) rest.onChange(selectedObject)
} }
}, },
[multiple, objectList, onChange] [multiple, objectList, rest]
) )
// Update treeData when objectPropertiesTree changes // Update treeData when objectPropertiesTree changes

View File

@ -438,21 +438,9 @@ const ObjectTable = forwardRef(
// Store the latest updateEventHandler in a ref // Store the latest updateEventHandler in a ref
updateEventHandlerRef.current = updateEventHandler updateEventHandlerRef.current = updateEventHandler
const newEventHandler = useCallback( const newEventHandler = useCallback(() => {
(params) => { reload()
logger.debug('New event handler:', params) }, [reload])
reload()
},
[reload]
)
const subscriptionFilter = useMemo(() => {
const active = {}
Object.entries(sidebarFilter).forEach(([k, v]) => {
if (v !== '' && v !== undefined) active[k] = v
})
return { ...active, ...masterFilter }
}, [sidebarFilter, masterFilter])
// Subscribe to real-time updates for all items // Subscribe to real-time updates for all items
useEffect(() => { useEffect(() => {
@ -525,28 +513,16 @@ const ObjectTable = forwardRef(
}, [connected]) }, [connected])
useEffect(() => { useEffect(() => {
if (connected == true) { if (
const unsubscribe = subscribeToObjectTypeUpdates( connected == true &&
subscribeToObjectTypeUpdatesRef.current == null
) {
subscribeToObjectTypeUpdatesRef.current = subscribeToObjectTypeUpdates(
type, type,
subscriptionFilter,
newEventHandler newEventHandler
) )
subscribeToObjectTypeUpdatesRef.current = unsubscribe
return () => {
if (unsubscribe) unsubscribe()
if (subscribeToObjectTypeUpdatesRef.current === unsubscribe) {
subscribeToObjectTypeUpdatesRef.current = null
}
}
} }
}, [ }, [type, subscribeToObjectTypeUpdates, connected, newEventHandler])
type,
subscriptionFilter,
subscribeToObjectTypeUpdates,
connected,
newEventHandler
])
const updateData = useCallback( const updateData = useCallback(
(id, updatedData) => { (id, updatedData) => {
@ -683,13 +659,11 @@ const ObjectTable = forwardRef(
} }
}) })
console.log('filters--', filters)
setSidebarFilter(next) setSidebarFilter(next)
setPages([]) setPages([])
setLoading(true) setLoading(true)
loadPage(initialPage, getActiveFilter(next), { loadPage(initialPage, getActiveFilter(next), {
field: sorter.columnKey, field: sorter.field,
order: sorter.order order: sorter.order
}) })
} }
@ -880,42 +854,29 @@ const ObjectTable = forwardRef(
style={{ overflowY: 'auto', maxHeight: adjustedScrollHeight }} style={{ overflowY: 'auto', maxHeight: adjustedScrollHeight }}
ref={cardsContainerRef} ref={cardsContainerRef}
> >
{tableData.map((record) => { {tableData.map((record) => (
if (record?._id == undefined) { <Col xs={24} sm={12} md={12} lg={8} xl={6} xxl={6} key={record._id}>
return null <div style={{ width: '100%', overflow: 'hidden' }}>
} <RowForm
return ( record={record}
<Col isEditing={isEditing}
xs={24} onRegister={registerForm}
sm={12} >
md={12} <Flex align={'center'} vertical gap={'middle'}>
lg={8} <ObjectCard
xl={6} model={model}
xxl={6} modelProperties={modelProperties}
key={record._id} visibleColumns={visibleColumns}
> record={record}
<div style={{ width: '100%', overflow: 'hidden' }}> isEditing={isEditing}
<RowForm rowActions={rowActions}
record={record} renderActions={renderActions}
isEditing={isEditing} />
onRegister={registerForm} </Flex>
> </RowForm>
<Flex align={'center'} vertical gap={'middle'}> </div>
<ObjectCard </Col>
model={model} ))}
modelProperties={modelProperties}
visibleColumns={visibleColumns}
record={record}
isEditing={isEditing}
rowActions={rowActions}
renderActions={renderActions}
/>
</Flex>
</RowForm>
</div>
</Col>
)
})}
</Row> </Row>
) )
} }

View File

@ -136,10 +136,6 @@ const StateTag = ({ state, showBadge = true, style = {} }) => {
status = 'cyan' status = 'cyan'
text = 'Ordered' text = 'Ordered'
break break
case 'posted':
status = 'magenta'
text = 'Posted'
break
case 'received': case 'received':
status = 'success' status = 'success'
text = 'Received' text = 'Received'

View File

@ -17,7 +17,6 @@ import ExclamationOctagonIcon from '../../Icons/ExclamationOctagonIcon'
import ReloadIcon from '../../Icons/ReloadIcon' import ReloadIcon from '../../Icons/ReloadIcon'
import config from '../../../config' import config from '../../../config'
import loglevel from 'loglevel' import loglevel from 'loglevel'
import { getModelByName } from '../../../database/ObjectModels'
const logger = loglevel.getLogger('ApiServerContext') const logger = loglevel.getLogger('ApiServerContext')
logger.setLevel(config.logLevel) logger.setLevel(config.logLevel)
@ -26,35 +25,6 @@ const SPOTLIGHT_CACHE_TTL_MS = 10_000
const spotlightCache = new Map() const spotlightCache = new Map()
const runningSpotlightFetches = new Map() const runningSpotlightFetches = new Map()
const stableStringify = (value) => {
if (Array.isArray(value)) {
return `[${value.map(stableStringify).join(',')}]`
}
if (value && typeof value === 'object') {
return `{${Object.keys(value)
.sort()
.map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`)
.join(',')}}`
}
return JSON.stringify(value)
}
const getObjectTypeSubscriptionKey = (objectType, filter = {}) =>
`${objectType}:${stableStringify(filter || {})}`
const getObjectTypeSubscriptionArgs = (filterOrCallback, callback) => {
if (typeof filterOrCallback === 'function') {
return { filter: {}, callback: filterOrCallback }
}
return { filter: filterOrCallback || {}, callback }
}
const getObjectEndpoint = (type) =>
getModelByName(type)?.endpoint || `${type.toLowerCase()}s`
const ApiServerContext = createContext() const ApiServerContext = createContext()
const ApiServerProvider = ({ children }) => { const ApiServerProvider = ({ children }) => {
@ -346,16 +316,12 @@ const ApiServerProvider = ({ children }) => {
const handleObjectNew = async (data) => { const handleObjectNew = async (data) => {
logger.debug('Notifying object new:', data) logger.debug('Notifying object new:', data)
const objectType = data.objectType || 'unknown' const objectType = data.objectType || 'unknown'
const callbacksRefKey = getObjectTypeSubscriptionKey(
objectType,
data.filter || {}
)
if (objectType && subscribedCallbacksRef.current.has(callbacksRefKey)) { if (objectType && subscribedCallbacksRef.current.has(objectType)) {
const callbacks = subscribedCallbacksRef.current.get(callbacksRefKey) const callbacks = subscribedCallbacksRef.current.get(objectType)
logger.debug( logger.debug(
`Calling ${callbacks.length} callbacks for type:`, `Calling ${callbacks.length} callbacks for type:`,
callbacksRefKey objectType
) )
callbacks.forEach((callback) => { callbacks.forEach((callback) => {
try { try {
@ -366,7 +332,7 @@ const ApiServerProvider = ({ children }) => {
}) })
} else { } else {
logger.debug( logger.debug(
`No callbacks found for object: ${callbacksRefKey}, subscribed callbacks:`, `No callbacks found for object: ${objectType}, subscribed callbacks:`,
Array.from(subscribedCallbacksRef.current.keys()) Array.from(subscribedCallbacksRef.current.keys())
) )
} }
@ -375,16 +341,12 @@ const ApiServerProvider = ({ children }) => {
const handleObjectDelete = async (data) => { const handleObjectDelete = async (data) => {
logger.debug('Notifying object delete:', data) logger.debug('Notifying object delete:', data)
const objectType = data.objectType || 'unknown' const objectType = data.objectType || 'unknown'
const callbacksRefKey = getObjectTypeSubscriptionKey(
objectType,
data.filter || {}
)
if (objectType && subscribedCallbacksRef.current.has(callbacksRefKey)) { if (objectType && subscribedCallbacksRef.current.has(objectType)) {
const callbacks = subscribedCallbacksRef.current.get(callbacksRefKey) const callbacks = subscribedCallbacksRef.current.get(objectType)
logger.debug( logger.debug(
`Calling ${callbacks.length} callbacks for type:`, `Calling ${callbacks.length} callbacks for type:`,
callbacksRefKey objectType
) )
callbacks.forEach((callback) => { callbacks.forEach((callback) => {
try { try {
@ -395,7 +357,7 @@ const ApiServerProvider = ({ children }) => {
}) })
} else { } else {
logger.debug( logger.debug(
`No callbacks found for object: ${callbacksRefKey}, subscribed callbacks:`, `No callbacks found for object: ${objectType}, subscribed callbacks:`,
Array.from(subscribedCallbacksRef.current.keys()) Array.from(subscribedCallbacksRef.current.keys())
) )
} }
@ -427,29 +389,24 @@ const ApiServerProvider = ({ children }) => {
} }
}, []) }, [])
const offObjectTypeUpdatesEvent = useCallback( const offObjectTypeUpdatesEvent = useCallback((objectType, callback) => {
(objectType, filter, callback) => { if (socketRef.current && socketRef.current.connected == true) {
if (socketRef.current && socketRef.current.connected == true) { // Remove callback from the subscribed callbacks map
const callbacksRefKey = getObjectTypeSubscriptionKey(objectType, filter) if (subscribedCallbacksRef.current.has(objectType)) {
// Remove callback from the subscribed callbacks map const callbacks = subscribedCallbacksRef.current
if (subscribedCallbacksRef.current.has(callbacksRefKey)) { .get(objectType)
const callbacks = subscribedCallbacksRef.current .filter((cb) => cb !== callback)
.get(callbacksRefKey) if (callbacks.length === 0) {
.filter((cb) => cb !== callback) subscribedCallbacksRef.current.delete(objectType)
if (callbacks.length === 0) { socketRef.current.emit('unsubscribeObjectTypeUpdate', {
subscribedCallbacksRef.current.delete(callbacksRefKey) objectType: objectType
socketRef.current.emit('unsubscribeObjectTypeUpdate', { })
objectType: objectType, } else {
filter: filter subscribedCallbacksRef.current.set(objectType, callbacks)
})
} else {
subscribedCallbacksRef.current.set(callbacksRefKey, callbacks)
}
} }
} }
}, }
[] }, [])
)
const subscribeToObjectUpdates = useCallback( const subscribeToObjectUpdates = useCallback(
(id, objectType, callback) => { (id, objectType, callback) => {
@ -514,46 +471,31 @@ const ApiServerProvider = ({ children }) => {
}, [connected, userProfile?._id, subscribeToObjectUpdates, setUserProfile]) }, [connected, userProfile?._id, subscribeToObjectUpdates, setUserProfile])
const subscribeToObjectTypeUpdates = useCallback( const subscribeToObjectTypeUpdates = useCallback(
(objectType, filterOrCallback = {}, maybeCallback) => { (objectType, callback) => {
const { filter, callback } = getObjectTypeSubscriptionArgs( logger.debug('Subscribing to type updates:', objectType)
filterOrCallback,
maybeCallback
)
const callbacksRefKey = getObjectTypeSubscriptionKey(objectType, filter)
logger.debug('Subscribing to type updates:', objectType, filter)
if (socketRef.current && socketRef.current.connected == true) { if (socketRef.current && socketRef.current.connected == true) {
// Add callback to the subscribed callbacks map immediately // Add callback to the subscribed callbacks map immediately
if (!subscribedCallbacksRef.current.has(callbacksRefKey)) { if (!subscribedCallbacksRef.current.has(objectType)) {
subscribedCallbacksRef.current.set(callbacksRefKey, []) subscribedCallbacksRef.current.set(objectType, [])
} }
subscribedCallbacksRef.current.get(objectType).push(callback)
logger.debug(
`Added callback for type ${objectType}, total callbacks: ${subscribedCallbacksRef.current.get(objectType).length}`
)
const callbacksLength = socketRef.current.emit(
subscribedCallbacksRef.current.get(callbacksRefKey).length 'subscribeToObjectTypeUpdate',
{ objectType: objectType },
if (callbacksLength <= 0) { (result) => {
socketRef.current.emit( if (result.success) {
'subscribeToObjectTypeUpdate', logger.info('Subscribed to objectType:', objectType)
{ objectType: objectType, filter: filter },
(result) => {
if (result.success) {
logger.info('Subscribed to objectType:', objectType, filter)
}
} }
) }
}
subscribedCallbacksRef.current.get(callbacksRefKey).push(callback)
logger.debug(
`Added callback for type ${callbacksRefKey}, total callbacks: ${callbacksLength + 1}`
)
logger.debug(
'Registered type event listener for object:',
callbacksRefKey
) )
logger.debug('Registered type event listener for object:', objectType)
// Return cleanup function // Return cleanup function
return () => offObjectTypeUpdatesEvent(objectType, filter, callback) return () => offObjectTypeUpdatesEvent(objectType, callback)
} }
}, },
[offObjectTypeUpdatesEvent] [offObjectTypeUpdatesEvent]
@ -766,7 +708,7 @@ const ApiServerProvider = ({ children }) => {
// Generalized fetchObject function // Generalized fetchObject function
const fetchObject = async (id, type) => { const fetchObject = async (id, type) => {
const fetchUrl = `${config.backendUrl}/${getObjectEndpoint(type)}/${id}` const fetchUrl = `${config.backendUrl}/${type}s/${id}`
setFetchLoading(true) setFetchLoading(true)
logger.debug('Fetching from ' + fetchUrl) logger.debug('Fetching from ' + fetchUrl)
try { try {
@ -796,37 +738,21 @@ const ApiServerProvider = ({ children }) => {
sorter = {}, sorter = {},
onDataChange onDataChange
} = params } = params
let newFilter = { ...filter }
if (filter != null && Object.keys(filter).length > 0) {
const model = getModelByName(type)
for (const key of Object.keys(filter)) {
const property = model?.properties?.find((p) => p.name === key)
if (property && property.type === 'object') {
const value = filter[key]
newFilter[`${key}._id`] = value?._id ?? value
delete newFilter[key]
}
}
}
logger.debug('Fetching table data from:', type, { logger.debug('Fetching table data from:', type, {
page, page,
limit, limit,
newFilter, filter,
sorter sorter
}) })
try { try {
const response = await axios.get( const response = await axios.get(
`${config.backendUrl}/${getObjectEndpoint(type)}`, `${config.backendUrl}/${type.toLowerCase()}s`,
{ {
params: { params: {
page, page,
limit, limit,
...newFilter, ...filter,
sort: sorter.field, sort: sorter.field,
order: sorter.order order: sorter.order
}, },
@ -873,7 +799,7 @@ const ApiServerProvider = ({ children }) => {
try { try {
const response = await axios.get( const response = await axios.get(
`${config.backendUrl}/${getObjectEndpoint(type)}/properties`, `${config.backendUrl}/${type.toLowerCase()}s/properties`,
{ {
params: { params: {
...Object.keys(filter).reduce((acc, key) => { ...Object.keys(filter).reduce((acc, key) => {
@ -907,7 +833,7 @@ const ApiServerProvider = ({ children }) => {
// Update filament information // Update filament information
const updateObject = async (id, type, value) => { const updateObject = async (id, type, value) => {
const updateUrl = `${config.backendUrl}/${getObjectEndpoint(type)}/${id}` const updateUrl = `${config.backendUrl}/${type.toLowerCase()}s/${id}`
logger.debug('Updating info for ' + id) logger.debug('Updating info for ' + id)
try { try {
const response = await axios.put(updateUrl, value, { const response = await axios.put(updateUrl, value, {
@ -929,7 +855,7 @@ const ApiServerProvider = ({ children }) => {
// Update multiple objects // Update multiple objects
const updateMultipleObjects = async (type, objects) => { const updateMultipleObjects = async (type, objects) => {
const updateUrl = `${config.backendUrl}/${getObjectEndpoint(type)}` const updateUrl = `${config.backendUrl}/${type.toLowerCase()}s`
logger.debug('Updating multiple objects for ' + type) logger.debug('Updating multiple objects for ' + type)
try { try {
const response = await axios.put(updateUrl, objects, { const response = await axios.put(updateUrl, objects, {
@ -951,7 +877,7 @@ const ApiServerProvider = ({ children }) => {
// Update filament information // Update filament information
const deleteObject = async (id, type) => { const deleteObject = async (id, type) => {
const deleteUrl = `${config.backendUrl}/${getObjectEndpoint(type)}/${id}` const deleteUrl = `${config.backendUrl}/${type.toLowerCase()}s/${id}`
logger.debug('Deleting object ID: ' + id) logger.debug('Deleting object ID: ' + id)
try { try {
const response = await axios.delete(deleteUrl, { const response = await axios.delete(deleteUrl, {
@ -973,7 +899,7 @@ const ApiServerProvider = ({ children }) => {
// Update filament information // Update filament information
const createObject = async (type, value) => { const createObject = async (type, value) => {
const createUrl = `${config.backendUrl}/${getObjectEndpoint(type)}` const createUrl = `${config.backendUrl}/${type.toLowerCase()}s`
logger.debug('Creating object...') logger.debug('Creating object...')
try { try {
const response = await axios.post(createUrl, value, { const response = await axios.post(createUrl, value, {
@ -994,7 +920,7 @@ const ApiServerProvider = ({ children }) => {
// Call a function on an object // Call a function on an object
const sendObjectFunction = async (id, type, functionName, value = {}) => { const sendObjectFunction = async (id, type, functionName, value = {}) => {
const url = `${config.backendUrl}/${getObjectEndpoint(type)}/${id}/${functionName}` const url = `${config.backendUrl}/${type.toLowerCase()}s/${id}/${functionName}`
logger.debug(`Calling object function ${functionName} for ${id} at ${url}`) logger.debug(`Calling object function ${functionName} for ${id} at ${url}`)
try { try {
const response = await axios.post(url, value, { const response = await axios.post(url, value, {
@ -1014,7 +940,7 @@ const ApiServerProvider = ({ children }) => {
} }
const getObjectFunction = async (id, type, functionName, params = {}) => { const getObjectFunction = async (id, type, functionName, params = {}) => {
const url = `${config.backendUrl}/${getObjectEndpoint(type)}/${id}/${functionName}` const url = `${config.backendUrl}/${type.toLowerCase()}s/${id}/${functionName}`
logger.debug(`Fetching object function ${functionName} for ${id} at ${url}`) logger.debug(`Fetching object function ${functionName} for ${id} at ${url}`)
try { try {
const response = await axios.get(url, { const response = await axios.get(url, {
@ -1239,7 +1165,7 @@ const ApiServerProvider = ({ children }) => {
if (objectType === 'history') { if (objectType === 'history') {
statsUrl = `${config.backendUrl}/stats/history` statsUrl = `${config.backendUrl}/stats/history`
} else { } else {
statsUrl = `${config.backendUrl}/${getObjectEndpoint(objectType)}/stats` statsUrl = `${config.backendUrl}/${objectType.toLowerCase()}s/stats`
} }
const response = await axios.get(statsUrl, { const response = await axios.get(statsUrl, {
@ -1264,7 +1190,7 @@ const ApiServerProvider = ({ children }) => {
const encodedStartDate = encodeURIComponent(startDate.toISOString()) const encodedStartDate = encodeURIComponent(startDate.toISOString())
const encodedEndDate = encodeURIComponent(endDate.toISOString()) const encodedEndDate = encodeURIComponent(endDate.toISOString())
try { try {
const historyUrl = `${config.backendUrl}/${getObjectEndpoint(objectType)}/history?from=${encodedStartDate}&to=${encodedEndDate}` const historyUrl = `${config.backendUrl}/${objectType.toLowerCase()}s/history?from=${encodedStartDate}&to=${encodedEndDate}`
const response = await axios.get(historyUrl, { const response = await axios.get(historyUrl, {
headers: { headers: {

View File

@ -1,8 +0,0 @@
import Icon from '@ant-design/icons'
import CustomIconSvg from '../../../assets/icons/productcategoryicon.svg?react'
const ProductCategoryIcon = (props) => (
<Icon component={CustomIconSvg} {...props} />
)
export default ProductCategoryIcon

View File

@ -7,7 +7,6 @@ import { Spool } from './models/Spool'
import { GCodeFile } from './models/GCodeFile' import { GCodeFile } from './models/GCodeFile'
import { Job } from './models/Job' import { Job } from './models/Job'
import { Product } from './models/Product' import { Product } from './models/Product'
import { ProductCategory } from './models/ProductCategory'
import { ProductSku } from './models/ProductSku' import { ProductSku } from './models/ProductSku'
import { Part } from './models/Part.js' import { Part } from './models/Part.js'
import { PartSku } from './models/PartSku.js' import { PartSku } from './models/PartSku.js'
@ -57,7 +56,6 @@ export const objectModels = [
GCodeFile, GCodeFile,
Job, Job,
Product, Product,
ProductCategory,
ProductSku, ProductSku,
Part, Part,
PartSku, PartSku,
@ -108,7 +106,6 @@ export {
GCodeFile, GCodeFile,
Job, Job,
Product, Product,
ProductCategory,
ProductSku, ProductSku,
Part, Part,
PartSku, PartSku,

View File

@ -1,5 +1,6 @@
import AppPasswordIcon from '../../components/Icons/AppPasswordIcon' import AppPasswordIcon from '../../components/Icons/AppPasswordIcon'
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
@ -20,6 +21,13 @@ export const AppPassword = {
url: (_id) => url: (_id) =>
`/dashboard/management/apppasswords/info?appPasswordId=${_id}` `/dashboard/management/apppasswords/info?appPasswordId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/apppasswords/info?appPasswordId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',

View File

@ -3,6 +3,7 @@ import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import BinIcon from '../../components/Icons/BinIcon' import BinIcon from '../../components/Icons/BinIcon'
export const Client = { export const Client = {
@ -19,6 +20,13 @@ export const Client = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/sales/clients/info?clientId=${_id}` url: (_id) => `/dashboard/sales/clients/info?clientId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/sales/clients/info?clientId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -3,6 +3,7 @@ import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import BinIcon from '../../components/Icons/BinIcon' import BinIcon from '../../components/Icons/BinIcon'
export const Courier = { export const Courier = {
@ -19,6 +20,13 @@ export const Courier = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/management/couriers/info?courierId=${_id}` url: (_id) => `/dashboard/management/couriers/info?courierId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/couriers/info?courierId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -3,6 +3,7 @@ import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import BinIcon from '../../components/Icons/BinIcon' import BinIcon from '../../components/Icons/BinIcon'
export const CourierService = { export const CourierService = {
@ -20,6 +21,13 @@ export const CourierService = {
url: (_id) => url: (_id) =>
`/dashboard/management/courierservices/info?courierServiceId=${_id}` `/dashboard/management/courierservices/info?courierServiceId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/courierservices/info?courierServiceId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -1,4 +1,5 @@
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
@ -21,6 +22,13 @@ export const DocumentJob = {
`/dashboard/management/documentjobs/info?documentJobId=${_id}` `/dashboard/management/documentjobs/info?documentJobId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/documentjobs/info?documentJobId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -1,4 +1,5 @@
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import DocumentPrinterIcon from '../../components/Icons/DocumentPrinterIcon' import DocumentPrinterIcon from '../../components/Icons/DocumentPrinterIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
@ -20,6 +21,13 @@ export const DocumentPrinter = {
`/dashboard/management/documentprinters/info?documentPrinterId=${_id}` `/dashboard/management/documentprinters/info?documentPrinterId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/documentprinters/info?documentPrinterId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -1,4 +1,5 @@
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
@ -20,6 +21,13 @@ export const DocumentSize = {
`/dashboard/management/documentsizes/info?documentSizeId=${_id}` `/dashboard/management/documentsizes/info?documentSizeId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/documentsizes/info?documentSizeId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -1,4 +1,5 @@
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
@ -29,6 +30,13 @@ export const DocumentTemplate = {
`/dashboard/management/documenttemplates/info?documentTemplateId=${_id}` `/dashboard/management/documenttemplates/info?documentTemplateId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/documenttemplates/info?documentTemplateId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -1,6 +1,7 @@
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import FilamentIcon from '../../components/Icons/FilamentIcon' import FilamentIcon from '../../components/Icons/FilamentIcon'
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
import PlusIcon from '../../components/Icons/PlusIcon' import PlusIcon from '../../components/Icons/PlusIcon'
@ -20,6 +21,13 @@ export const Filament = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/management/filaments/info?filamentId=${_id}` url: (_id) => `/dashboard/management/filaments/info?filamentId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/filaments/info?filamentId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -4,6 +4,7 @@ import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
import BinIcon from '../../components/Icons/BinIcon' import BinIcon from '../../components/Icons/BinIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
export const FilamentSku = { export const FilamentSku = {
name: 'filamentSku', name: 'filamentSku',
@ -20,6 +21,13 @@ export const FilamentSku = {
url: (_id) => url: (_id) =>
`/dashboard/management/filamentskus/info?filamentSkuId=${_id}` `/dashboard/management/filamentskus/info?filamentSkuId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/filamentskus/info?filamentSkuId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',
@ -94,7 +102,6 @@ export const FilamentSku = {
'createdAt', 'createdAt',
'updatedAt' 'updatedAt'
], ],
group: ['filament'],
properties: [ properties: [
{ {
name: '_id', name: '_id',

View File

@ -22,15 +22,14 @@ export const FilamentStock = {
'state', 'state',
'currentWeight', 'currentWeight',
'startingWeight', 'startingWeight',
'filament',
'filamentSku', 'filamentSku',
'stockLocation', 'stockLocation',
'createdAt', 'createdAt',
'updatedAt' 'updatedAt'
], ],
filters: ['_id', 'filament', 'filament._id', 'filamentSku', 'filamentSku._id'], filters: ['_id'],
sorters: ['createdAt', 'updatedAt', 'filament', 'filamentSku'], sorters: ['createdAt', 'updatedAt'],
group: ['filament', 'filamentSku'], group: ['filamentSku'],
properties: [ properties: [
{ {
name: '_id', name: '_id',
@ -72,17 +71,6 @@ export const FilamentStock = {
readOnly: true, readOnly: true,
columnWidth: 175 columnWidth: 175
}, },
{
name: 'filament',
label: 'Filament',
type: 'object',
value: null,
objectType: 'filament',
required: true,
showHyperlink: true,
columnWidth: 200,
initial: true
},
{ {
name: 'filamentSku', name: 'filamentSku',
label: 'Filament SKU', label: 'Filament SKU',
@ -92,12 +80,7 @@ export const FilamentStock = {
initial: true, initial: true,
required: true, required: true,
showHyperlink: true, showHyperlink: true,
columnWidth: 200, columnWidth: 200
masterFilter: (objectData) => {
return {
filament: objectData?.filament?._id
}
}
}, },
{ {
name: 'stockLocation', name: 'stockLocation',

View File

@ -4,6 +4,7 @@ import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import BinIcon from '../../components/Icons/BinIcon' import BinIcon from '../../components/Icons/BinIcon'
export const File = { export const File = {
@ -20,6 +21,13 @@ export const File = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/management/files/info?fileId=${_id}` url: (_id) => `/dashboard/management/files/info?fileId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/files/info?fileId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',
@ -70,15 +78,7 @@ export const File = {
} }
], ],
url: (id) => `/dashboard/management/files/info?fileId=${id}`, url: (id) => `/dashboard/management/files/info?fileId=${id}`,
columns: [ columns: ['_reference', 'name', 'type', 'size', 'temp', 'createdAt'],
'_reference',
'name',
'type',
'size',
'temp',
'createdAt',
'updatedAt'
],
filters: ['name', '_id', 'type', 'temp'], filters: ['name', '_id', 'type', 'temp'],
sorters: ['name', 'type', 'size', 'createdAt', 'temp'], sorters: ['name', 'type', 'size', 'createdAt', 'temp'],
group: ['type'], group: ['type'],
@ -129,7 +129,7 @@ export const File = {
type: 'text', type: 'text',
readOnly: true, readOnly: true,
required: true, required: true,
columnWidth: 190 columnWidth: 120
}, },
{ {
name: 'size', name: 'size',

View File

@ -4,7 +4,7 @@ import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
import GCodeFileIcon from '../../components/Icons/GCodeFileIcon' import GCodeFileIcon from '../../components/Icons/GCodeFileIcon'
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import EyeIcon from '../../components/Icons/EyeIcon' import ReloadIcon from '../../components/Icons/ReloadIcon'
export const GCodeFile = { export const GCodeFile = {
name: 'gcodeFile', name: 'gcodeFile',
@ -12,14 +12,6 @@ export const GCodeFile = {
prefix: 'GCF', prefix: 'GCF',
icon: GCodeFileIcon, icon: GCodeFileIcon,
actions: [ actions: [
{
name: 'preview',
label: 'Preview',
row: true,
icon: EyeIcon,
url: (_id) =>
`/dashboard/production/gcodefiles/preview?gcodeFileId=${_id}`
},
{ {
name: 'info', name: 'info',
label: 'Info', label: 'Info',
@ -28,6 +20,13 @@ export const GCodeFile = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/production/gcodefiles/info?gcodeFileId=${_id}` url: (_id) => `/dashboard/production/gcodefiles/info?gcodeFileId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/production/gcodefiles/info?gcodeFileId=${_id}&action=reload`
},
{ {
name: 'download', name: 'download',
label: 'Download', label: 'Download',
@ -72,7 +71,6 @@ export const GCodeFile = {
columns: [ columns: [
'_reference', '_reference',
'name', 'name',
'filament',
'filamentSku', 'filamentSku',
'cost', 'cost',
'gcodeFileInfo.estimatedPrintingTimeNormalMode', 'gcodeFileInfo.estimatedPrintingTimeNormalMode',
@ -82,24 +80,9 @@ export const GCodeFile = {
'gcodeFileInfo.hotPlateTemp', 'gcodeFileInfo.hotPlateTemp',
'updatedAt' 'updatedAt'
], ],
filters: [ filters: ['_id', 'name', 'cost', 'updatedAt'],
'_id', sorters: ['name', 'cost', 'createdAt', 'updatedAt'],
'name', group: ['filamentSku'],
'filament',
'filament._id',
'filamentSku',
'cost',
'updatedAt'
],
sorters: [
'name',
'filament',
'filamentSku',
'cost',
'createdAt',
'updatedAt'
],
group: ['filament', 'filamentSku'],
properties: [ properties: [
{ {
name: '_id', name: '_id',
@ -156,16 +139,6 @@ export const GCodeFile = {
filter: ['.gcode', '.g'], filter: ['.gcode', '.g'],
columnWidth: 200 columnWidth: 200
}, },
{
name: 'filament',
label: 'Filament',
type: 'object',
value: null,
objectType: 'filament',
required: true,
showHyperlink: true,
columnWidth: 200
},
{ {
name: 'filamentSku', name: 'filamentSku',
label: 'Filament SKU', label: 'Filament SKU',
@ -174,12 +147,7 @@ export const GCodeFile = {
objectType: 'filamentSku', objectType: 'filamentSku',
required: true, required: true,
showHyperlink: true, showHyperlink: true,
columnWidth: 200, columnWidth: 200
masterFilter: (objectData) => {
return {
filament: objectData?.filament?._id
}
}
}, },
{ {
name: 'cost', name: 'cost',
@ -188,9 +156,9 @@ export const GCodeFile = {
roundNumber: 2, roundNumber: 2,
value: (objectData) => { value: (objectData) => {
const fs = objectData?.filamentSku const fs = objectData?.filamentSku
const costPerKg = fs?.overrideCost ? fs?.cost : fs?.filament?.cost const costPerKg =
if (!costPerKg || !objectData?.file?.metaData?.filamentUsedG) fs?.overrideCost ? fs?.cost : fs?.filament?.cost
return undefined if (!costPerKg || !objectData?.file?.metaData?.filamentUsedG) return undefined
return objectData.file.metaData.filamentUsedG * (costPerKg / 1000) return objectData.file.metaData.filamentUsedG * (costPerKg / 1000)
}, },
readOnly: true, readOnly: true,
@ -270,7 +238,6 @@ export const GCodeFile = {
label: 'Parts', label: 'Parts',
type: 'objectChildren', type: 'objectChildren',
objectType: 'part', objectType: 'part',
size: 'medium',
properties: [ properties: [
{ {
name: 'part', name: 'part',

View File

@ -1,9 +1,9 @@
import HostIcon from '../../components/Icons/HostIcon' import HostIcon from '../../components/Icons/HostIcon'
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
import BinIcon from '../../components/Icons/BinIcon'
import OTPIcon from '../../components/Icons/OTPIcon' import OTPIcon from '../../components/Icons/OTPIcon'
export const Host = { export const Host = {
@ -21,6 +21,13 @@ export const Host = {
url: (_id) => `/dashboard/management/hosts/info?hostId=${_id}` url: (_id) => `/dashboard/management/hosts/info?hostId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/hosts/info?hostId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',
@ -61,14 +68,6 @@ export const Host = {
icon: OTPIcon, icon: OTPIcon,
url: (_id) => url: (_id) =>
`/dashboard/management/hosts/info?hostId=${_id}&action=hostOTP` `/dashboard/management/hosts/info?hostId=${_id}&action=hostOTP`
},
{
name: 'delete',
label: 'Delete',
icon: BinIcon,
danger: true,
url: (_id) =>
`/dashboard/management/hosts/info?hostId=${_id}&action=delete`
} }
], ],
columns: ['_reference', 'name', 'state', 'tags', 'connectedAt'], columns: ['_reference', 'name', 'state', 'tags', 'connectedAt'],

View File

@ -1,5 +1,6 @@
import JobIcon from '../../components/Icons/JobIcon' import JobIcon from '../../components/Icons/JobIcon'
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import dayjs from 'dayjs' import dayjs from 'dayjs'
@ -29,6 +30,12 @@ export const Job = {
return objectData?.state?.type != 'draft' return objectData?.state?.type != 'draft'
} }
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) => `/dashboard/production/jobs/info?jobId=${_id}&action=reload`
}
], ],
columns: ['_reference', 'quantity', 'state', 'gcodeFile', 'createdAt'], columns: ['_reference', 'quantity', 'state', 'gcodeFile', 'createdAt'],
filters: ['state', '_id', 'gcodeFile', 'quantity'], filters: ['state', '_id', 'gcodeFile', 'quantity'],

View File

@ -3,6 +3,7 @@ import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import BinIcon from '../../components/Icons/BinIcon' import BinIcon from '../../components/Icons/BinIcon'
import PlusIcon from '../../components/Icons/PlusIcon' import PlusIcon from '../../components/Icons/PlusIcon'
@ -20,6 +21,13 @@ export const Listing = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/sales/listings/info?listingId=${_id}` url: (_id) => `/dashboard/sales/listings/info?listingId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/sales/listings/info?listingId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -3,6 +3,7 @@ import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import BinIcon from '../../components/Icons/BinIcon' import BinIcon from '../../components/Icons/BinIcon'
export const ListingVarient = { export const ListingVarient = {
@ -19,6 +20,13 @@ export const ListingVarient = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/sales/listingvarients/info?listingVarientId=${_id}` url: (_id) => `/dashboard/sales/listingvarients/info?listingVarientId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/sales/listingvarients/info?listingVarientId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -21,6 +21,13 @@ export const Marketplace = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/sales/marketplaces/info?marketplaceId=${_id}` url: (_id) => `/dashboard/sales/marketplaces/info?marketplaceId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/sales/marketplaces/info?marketplaceId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -3,6 +3,7 @@ import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import BinIcon from '../../components/Icons/BinIcon' import BinIcon from '../../components/Icons/BinIcon'
export const Material = { export const Material = {
@ -19,6 +20,13 @@ export const Material = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/management/materials/info?materialId=${_id}` url: (_id) => `/dashboard/management/materials/info?materialId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/materials/info?materialId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -1,5 +1,6 @@
import NoteTypeIcon from '../../components/Icons/NoteTypeIcon' import NoteTypeIcon from '../../components/Icons/NoteTypeIcon'
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
@ -18,6 +19,13 @@ export const NoteType = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/management/notetypes/info?noteTypeId=${_id}` url: (_id) => `/dashboard/management/notetypes/info?noteTypeId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/notetypes/info?noteTypeId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -230,7 +230,7 @@ export const OrderItem = {
}, },
{ {
name: 'sku', name: 'sku',
label: 'Item SKU', label: 'SKU',
type: 'object', type: 'object',
objectType: (objectData) => { objectType: (objectData) => {
if (objectData?.itemType === 'filament') return 'filamentSku' if (objectData?.itemType === 'filament') return 'filamentSku'
@ -238,9 +238,11 @@ export const OrderItem = {
if (objectData?.itemType === 'product') return 'productSku' if (objectData?.itemType === 'product') return 'productSku'
return undefined return undefined
}, },
required: true, required: false,
showHyperlink: true, showHyperlink: true,
columnWidth: 300, columnWidth: 300,
visible: (objectData) =>
['filament', 'part', 'product'].includes(objectData?.itemType),
masterFilter: (objectData) => { masterFilter: (objectData) => {
console.log(objectData) console.log(objectData)
if (objectData?.itemType === 'filament' && objectData?.item?._id) { if (objectData?.itemType === 'filament' && objectData?.item?._id) {

View File

@ -1,6 +1,7 @@
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import PartIcon from '../../components/Icons/PartIcon' import PartIcon from '../../components/Icons/PartIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
import PlusIcon from '../../components/Icons/PlusIcon' import PlusIcon from '../../components/Icons/PlusIcon'
@ -19,6 +20,13 @@ export const Part = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/management/parts/info?partId=${_id}` url: (_id) => `/dashboard/management/parts/info?partId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/parts/info?partId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -4,6 +4,7 @@ import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
import BinIcon from '../../components/Icons/BinIcon' import BinIcon from '../../components/Icons/BinIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
export const PartSku = { export const PartSku = {
name: 'partSku', name: 'partSku',
@ -19,6 +20,13 @@ export const PartSku = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/management/partskus/info?partSkuId=${_id}` url: (_id) => `/dashboard/management/partskus/info?partSkuId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/partskus/info?partSkuId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -26,6 +26,13 @@ export const Printer = {
url: (_id) => `/dashboard/production/printers/info?printerId=${_id}` url: (_id) => `/dashboard/production/printers/info?printerId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/production/printers/info?printerId=${_id}&action=reload`
},
{ {
name: 'control', name: 'control',
label: 'Control', label: 'Control',

View File

@ -1,5 +1,6 @@
import ProductIcon from '../../components/Icons/ProductIcon' import ProductIcon from '../../components/Icons/ProductIcon'
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
@ -19,6 +20,13 @@ export const Product = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/management/products/info?productId=${_id}` url: (_id) => `/dashboard/management/products/info?productId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/products/info?productId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',
@ -68,7 +76,6 @@ export const Product = {
columns: [ columns: [
'_reference', '_reference',
'name', 'name',
'productCategory',
'tags', 'tags',
'vendor', 'vendor',
'cost', 'cost',
@ -78,30 +85,8 @@ export const Product = {
'createdAt', 'createdAt',
'updatedAt' 'updatedAt'
], ],
filters: [ filters: ['_id', 'name', 'type', 'color', 'vendor', 'cost', 'costWithTax', 'price', 'priceWithTax'],
'_id', sorters: ['name', 'createdAt', 'type', 'vendor', 'cost', 'costWithTax', 'price', 'priceWithTax', 'updatedAt'],
'name',
'productCategory',
'type',
'color',
'vendor',
'cost',
'costWithTax',
'price',
'priceWithTax'
],
sorters: [
'name',
'productCategory',
'createdAt',
'type',
'vendor',
'cost',
'costWithTax',
'price',
'priceWithTax',
'updatedAt'
],
properties: [ properties: [
{ {
name: '_id', name: '_id',
@ -143,15 +128,6 @@ export const Product = {
readOnly: true, readOnly: true,
columnWidth: 175 columnWidth: 175
}, },
{
name: 'productCategory',
label: 'Product Category',
required: true,
type: 'object',
objectType: 'productCategory',
showHyperlink: true,
columnWidth: 200
},
{ {
name: 'vendor', name: 'vendor',
label: 'Vendor', label: 'Vendor',

View File

@ -1,113 +0,0 @@
import ProductCategoryIcon from '../../components/Icons/ProductCategoryIcon'
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon'
import BinIcon from '../../components/Icons/BinIcon'
export const ProductCategory = {
name: 'productCategory',
label: 'Product Category',
prefix: 'PCG',
endpoint: 'productcategories',
icon: ProductCategoryIcon,
actions: [
{
name: 'info',
label: 'Info',
default: true,
row: true,
icon: InfoCircleIcon,
url: (_id) =>
`/dashboard/management/productcategories/info?productCategoryId=${_id}`
},
{
name: 'edit',
label: 'Edit',
row: true,
icon: EditIcon,
url: (_id) =>
`/dashboard/management/productcategories/info?productCategoryId=${_id}&action=edit`,
visible: (objectData) => {
return !(objectData?._isEditing && objectData?._isEditing == true)
}
},
{
name: 'finishEdit',
label: 'Save Edits',
icon: CheckIcon,
url: (_id) =>
`/dashboard/management/productcategories/info?productCategoryId=${_id}&action=finishEdit`,
visible: (objectData) => {
return objectData?._isEditing && objectData?._isEditing == true
}
},
{
name: 'cancelEdit',
label: 'Cancel Edits',
icon: XMarkIcon,
url: (_id) =>
`/dashboard/management/productcategories/info?productCategoryId=${_id}&action=cancelEdit`,
visible: (objectData) => {
return objectData?._isEditing && objectData?._isEditing == true
}
},
{ type: 'divider' },
{
name: 'delete',
label: 'Delete',
icon: BinIcon,
danger: true,
url: (_id) =>
`/dashboard/management/productcategories/info?productCategoryId=${_id}&action=delete`
}
],
url: (id) =>
`/dashboard/management/productcategories/info?productCategoryId=${id}`,
columns: ['_reference', 'name', 'createdAt', 'updatedAt'],
filters: ['_id', 'name'],
sorters: ['name', 'createdAt', 'updatedAt', '_id'],
properties: [
{
name: '_id',
label: 'ID',
columnFixed: 'left',
type: 'id',
objectType: 'productCategory',
showCopy: true,
readOnly: true,
columnWidth: 140
},
{
name: 'createdAt',
label: 'Created At',
type: 'dateTime',
readOnly: true,
columnWidth: 175
},
{
name: '_reference',
label: 'Reference',
type: 'reference',
columnFixed: 'left',
objectType: 'productCategory',
showCopy: true,
readOnly: true
},
{
name: 'name',
label: 'Name',
columnFixed: 'left',
required: true,
type: 'text',
columnWidth: 200
},
{
name: 'updatedAt',
label: 'Updated At',
type: 'dateTime',
readOnly: true,
columnWidth: 175
}
]
}

View File

@ -4,6 +4,7 @@ import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
import BinIcon from '../../components/Icons/BinIcon' import BinIcon from '../../components/Icons/BinIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
export const ProductSku = { export const ProductSku = {
name: 'productSku', name: 'productSku',
@ -19,6 +20,13 @@ export const ProductSku = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/management/productskus/info?productSkuId=${_id}` url: (_id) => `/dashboard/management/productskus/info?productSkuId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/productskus/info?productSkuId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

View File

@ -172,26 +172,8 @@ export const PurchaseOrder = {
} }
], ],
group: ['vendor'], group: ['vendor'],
filters: [ filters: ['vendor'],
'vendor', sorters: ['createdAt', 'state', 'updatedAt'],
'totalAmount',
'totalAmountWithTax',
'totalTaxAmount',
'shippingAmount',
'shippingAmountWithTax',
'grandTotalAmount'
],
sorters: [
'createdAt',
'state',
'updatedAt',
'totalAmount',
'totalAmountWithTax',
'totalTaxAmount',
'shippingAmount',
'shippingAmountWithTax',
'grandTotalAmount'
],
columns: [ columns: [
'_reference', '_reference',
'state', 'state',
@ -278,7 +260,7 @@ export const PurchaseOrder = {
prefix: '£', prefix: '£',
roundNumber: 2, roundNumber: 2,
readOnly: true, readOnly: true,
columnWidth: 185 columnWidth: 175
}, },
{ {
name: 'completedAt', name: 'completedAt',
@ -293,7 +275,7 @@ export const PurchaseOrder = {
type: 'number', type: 'number',
prefix: '£', prefix: '£',
readOnly: true, readOnly: true,
columnWidth: 215, columnWidth: 175,
roundNumber: 2 roundNumber: 2
}, },
{ {
@ -303,7 +285,7 @@ export const PurchaseOrder = {
prefix: '£', prefix: '£',
roundNumber: 2, roundNumber: 2,
readOnly: true, readOnly: true,
columnWidth: 190 columnWidth: 150
}, },
{ {
name: 'shippingAmountWithTax', name: 'shippingAmountWithTax',
@ -312,7 +294,7 @@ export const PurchaseOrder = {
prefix: '£', prefix: '£',
readOnly: true, readOnly: true,
roundNumber: 2, roundNumber: 2,
columnWidth: 240 columnWidth: 200
}, },
{ {
name: 'totalAmount', name: 'totalAmount',
@ -321,7 +303,7 @@ export const PurchaseOrder = {
prefix: '£', prefix: '£',
roundNumber: 2, roundNumber: 2,
readOnly: true, readOnly: true,
columnWidth: 170 columnWidth: 150
}, },
{ {
name: 'grandTotalAmount', name: 'grandTotalAmount',
@ -329,7 +311,7 @@ export const PurchaseOrder = {
type: 'number', type: 'number',
prefix: '£', prefix: '£',
roundNumber: 2, roundNumber: 2,
columnWidth: 215, columnWidth: 175,
readOnly: true readOnly: true
} }
], ],

View File

@ -170,7 +170,7 @@ export const SalesOrder = {
} }
} }
], ],
group: ['client'], group: ['client', 'marketplace'],
filters: ['client', 'marketplace'], filters: ['client', 'marketplace'],
sorters: ['createdAt', 'state', 'updatedAt'], sorters: ['createdAt', 'state', 'updatedAt'],
columns: [ columns: [

View File

@ -85,9 +85,9 @@ export const StockTransfer = {
} }
], ],
url: (id) => `/dashboard/inventory/stocktransfers/info?stockTransferId=${id}`, url: (id) => `/dashboard/inventory/stocktransfers/info?stockTransferId=${id}`,
filters: ['_id', 'name', 'state'], filters: ['_id', 'state'],
sorters: ['name', 'createdAt', 'postedAt'], sorters: ['createdAt', 'postedAt'],
columns: ['_reference', 'name', 'state', 'postedAt', 'createdAt', 'updatedAt'], columns: ['_reference', 'state', 'postedAt', 'createdAt', 'updatedAt'],
properties: [ properties: [
{ {
name: '_id', name: '_id',
@ -114,14 +114,6 @@ export const StockTransfer = {
showCopy: true, showCopy: true,
readOnly: true readOnly: true
}, },
{
name: 'name',
label: 'Name',
type: 'text',
required: true,
columnWidth: 220,
columnFixed: 'left'
},
{ {
name: 'state', name: 'state',
label: 'State', label: 'State',
@ -185,38 +177,6 @@ export const StockTransfer = {
suffix: (row) => suffix: (row) =>
row?.fromStockType === 'filamentStock' ? 'g net' : null row?.fromStockType === 'filamentStock' ? 'g net' : null
}, },
{
name: 'available',
label: 'Available',
type: 'number',
readOnly: true,
columnWidth: 140,
value: (row) => {
if (row?.fromStockType === 'filamentStock') {
return row?.fromStock?.currentWeight?.net ?? 0
} else {
return row?.fromStock?.currentQuantity ?? 0
}
},
suffix: (row) =>
row?.fromStockType === 'filamentStock' ? 'g net' : null
},
{
name: 'remaining',
label: 'Remaining',
type: 'number',
readOnly: true,
columnWidth: 140,
value: (row) => {
const quantity = row?.quantity ?? 0
if (row?.fromStockType === 'filamentStock') {
return (row?.fromStock?.currentWeight?.net ?? 0) - quantity
}
return (row?.fromStock?.currentQuantity ?? 0) - quantity
},
suffix: (row) =>
row?.fromStockType === 'filamentStock' ? 'g net' : null
},
{ {
name: 'toStockLocation', name: 'toStockLocation',
label: 'To location', label: 'To location',

View File

@ -3,6 +3,7 @@ import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import EditIcon from '../../components/Icons/EditIcon' import EditIcon from '../../components/Icons/EditIcon'
import CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon' import XMarkIcon from '../../components/Icons/XMarkIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon'
import BinIcon from '../../components/Icons/BinIcon' import BinIcon from '../../components/Icons/BinIcon'
export const TaxRate = { export const TaxRate = {
@ -19,6 +20,13 @@ export const TaxRate = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/management/taxrates/info?taxRateId=${_id}` url: (_id) => `/dashboard/management/taxrates/info?taxRateId=${_id}`
}, },
{
name: 'reload',
label: 'Reload',
icon: ReloadIcon,
url: (_id) =>
`/dashboard/management/taxrates/info?taxRateId=${_id}&action=reload`
},
{ {
name: 'edit', name: 'edit',
label: 'Edit', label: 'Edit',

Some files were not shown because too many files have changed in this diff Show More