Enhance Job and SubJob models by adding 'edit', 'cancelEdit', 'finishEdit', and 'delete' actions with corresponding visibility and disabled conditions. Update JobInfo and SubJobInfo components to incorporate new edit logic and improve button state management. Add 'updatedAt' field to both models for better tracking of job and subjob modifications.
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good

This commit is contained in:
Tom Butcher 2026-07-18 15:19:02 +01:00
parent 51abe4ca67
commit 359fbae5c7
4 changed files with 101 additions and 31 deletions

View File

@ -24,6 +24,7 @@ import DocumentPrintButton from '../../common/DocumentPrintButton.jsx'
import UserNotifierToggle from '../../common/UserNotifierToggle.jsx' import UserNotifierToggle from '../../common/UserNotifierToggle.jsx'
import DeployJob from './DeployJob.jsx' import DeployJob from './DeployJob.jsx'
import ScrollBox from '../../common/ScrollBox.jsx' import ScrollBox from '../../common/ScrollBox.jsx'
import { getModelByName } from '../../../../database/ObjectModels.js'
const log = loglevel.getLogger('JobInfo') const log = loglevel.getLogger('JobInfo')
log.setLevel(config.logLevel) log.setLevel(config.logLevel)
@ -53,6 +54,11 @@ const JobInfo = () => {
} }
}) })
const editDisabled =
getModelByName('job')
?.actions?.find((action) => action.name === 'edit')
?.disabled(objectFormState.objectData) ?? false
const actions = { const actions = {
edit: () => { edit: () => {
objectFormRef?.current.startEditing() objectFormRef?.current.startEditing()
@ -129,7 +135,11 @@ const JobInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.lock?.locked || objectFormState.loading} disabled={
objectFormState.lock?.locked ||
objectFormState.loading ||
editDisabled
}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
</Space> </Space>

View File

@ -109,7 +109,7 @@ const SubJobInfo = () => {
}} }}
editLoading={objectFormState.editLoading} editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid} formValid={objectFormState.formValid}
disabled={objectFormState.lock?.locked || objectFormState.loading} disabled={true}
loading={objectFormState.editLoading} loading={objectFormState.editLoading}
/> />
</Space> </Space>

View File

@ -1,6 +1,9 @@
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 CheckIcon from '../../components/Icons/CheckIcon' import CheckIcon from '../../components/Icons/CheckIcon'
import XMarkIcon from '../../components/Icons/XMarkIcon'
import EditIcon from '../../components/Icons/EditIcon'
import BinIcon from '../../components/Icons/BinIcon'
import dayjs from 'dayjs' import dayjs from 'dayjs'
export const Job = { export const Job = {
@ -19,6 +22,57 @@ export const Job = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/production/jobs/info?jobId=${_id}` url: (_id) => `/dashboard/production/jobs/info?jobId=${_id}`
}, },
{
name: 'edit',
label: 'Edit',
type: 'button',
icon: EditIcon,
url: (_id) => `/dashboard/production/jobs/info?jobId=${_id}&action=edit`,
visible: (objectData) => {
return !(objectData?._isEditing && objectData?._isEditing == true)
},
disabled: (objectData) => {
return objectData?.state?.type != 'draft'
}
},
{
name: 'cancelEdit',
label: 'Cancel Edit',
type: 'button',
icon: XMarkIcon,
url: (_id) =>
`/dashboard/production/jobs/info?jobId=${_id}&action=cancelEdit`,
visible: (objectData) => {
return objectData?._isEditing && objectData?._isEditing == true
}
},
{
name: 'finishEdit',
label: 'Finish Edit',
type: 'button',
icon: CheckIcon,
url: (_id) =>
`/dashboard/production/jobs/info?jobId=${_id}&action=finishEdit`,
visible: (objectData) => {
return objectData?._isEditing && objectData?._isEditing == true
}
},
{
name: 'delete',
label: 'Delete',
type: 'button',
icon: BinIcon,
danger: true,
url: (_id) =>
`/dashboard/production/jobs/info?jobId=${_id}&action=delete`,
visible: (objectData) => {
return !(objectData?._isEditing && objectData?._isEditing == true)
},
disabled: (objectData) => {
return objectData?.state?.type != 'draft'
}
},
{ type: 'divider' },
{ {
name: 'deploy', name: 'deploy',
label: 'Deploy', label: 'Deploy',
@ -30,7 +84,7 @@ export const Job = {
disabled: (objectData) => { disabled: (objectData) => {
return objectData?.state?.type != 'draft' return objectData?.state?.type != 'draft'
} }
}, }
], ],
columns: ['_reference', 'quantity', 'state', 'gcodeFile', 'createdAt'], columns: ['_reference', 'quantity', 'state', 'gcodeFile', 'createdAt'],
filters: ['state', '_id', 'gcodeFile', 'quantity'], filters: ['state', '_id', 'gcodeFile', 'quantity'],
@ -62,6 +116,13 @@ export const Job = {
readOnly: true, readOnly: true,
columnWidth: 180 columnWidth: 180
}, },
{
name: 'updatedAt',
label: 'Updated At',
type: 'dateTime',
readOnly: true,
columnWidth: 175
},
{ {
name: 'state', name: 'state',
label: 'State', label: 'State',
@ -75,8 +136,8 @@ export const Job = {
readOnly: true readOnly: true
}, },
{ {
name: 'updatedAt', name: 'startedAt',
label: 'Updated At', label: 'Started At',
type: 'dateTime', type: 'dateTime',
readOnly: true, readOnly: true,
columnWidth: 175 columnWidth: 175
@ -89,21 +150,6 @@ export const Job = {
columnWidth: 125, columnWidth: 125,
required: true required: true
}, },
{
name: 'startedAt',
label: 'Started At',
type: 'dateTime',
readOnly: true,
columnWidth: 175
},
{
name: 'printers',
label: 'Printers',
type: 'objectList',
objectType: 'printer',
required: true,
columnWidth: 200
},
{ {
name: 'finishedAt', name: 'finishedAt',
label: 'Finished At', label: 'Finished At',
@ -111,6 +157,7 @@ export const Job = {
readOnly: true, readOnly: true,
columnWidth: 175 columnWidth: 175
}, },
{ {
name: 'gcodeFile', name: 'gcodeFile',
label: 'GCode File', label: 'GCode File',
@ -120,6 +167,7 @@ export const Job = {
required: true, required: true,
showHyperlink: true showHyperlink: true
}, },
{ {
name: 'totalTime', name: 'totalTime',
label: 'Total Time', label: 'Total Time',
@ -147,6 +195,14 @@ export const Job = {
return parts.join(' ') return parts.join(' ')
} }
},
{
name: 'printers',
label: 'Printers',
type: 'objectList',
objectType: 'printer',
required: true,
columnWidth: 200
} }
], ],
stats: [ stats: [

View File

@ -62,6 +62,13 @@ export const SubJob = {
readOnly: true, readOnly: true,
columnWidth: 180 columnWidth: 180
}, },
{
name: 'updatedAt',
label: 'Updated At',
type: 'dateTime',
readOnly: true,
columnWidth: 175
},
{ {
name: 'state', name: 'state',
label: 'State', label: 'State',
@ -75,12 +82,13 @@ export const SubJob = {
readOnly: true readOnly: true
}, },
{ {
name: 'updatedAt', name: 'startedAt',
label: 'Updated At', label: 'Started At',
type: 'dateTime', type: 'dateTime',
readOnly: true, readOnly: true,
columnWidth: 175 columnWidth: 175
}, },
{ {
name: 'moonrakerJobId', name: 'moonrakerJobId',
label: 'Moonraker Job ID', label: 'Moonraker Job ID',
@ -88,13 +96,15 @@ export const SubJob = {
columnWidth: 140, columnWidth: 140,
showCopy: true showCopy: true
}, },
{ {
name: 'startedAt', name: 'finishedAt',
label: 'Started At', label: 'Finished At',
type: 'dateTime', type: 'dateTime',
readOnly: true, readOnly: true,
columnWidth: 175 columnWidth: 175
}, },
{ {
name: 'job', name: 'job',
label: 'Job', label: 'Job',
@ -103,13 +113,7 @@ export const SubJob = {
showHyperlink: true, showHyperlink: true,
columnWidth: 200 columnWidth: 200
}, },
{
name: 'finishedAt',
label: 'Finished At',
type: 'dateTime',
readOnly: true,
columnWidth: 175
},
{ {
name: 'printer', name: 'printer',
label: 'Printer', label: 'Printer',