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 DeployJob from './DeployJob.jsx'
import ScrollBox from '../../common/ScrollBox.jsx'
import { getModelByName } from '../../../../database/ObjectModels.js'
const log = loglevel.getLogger('JobInfo')
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 = {
edit: () => {
objectFormRef?.current.startEditing()
@ -129,7 +135,11 @@ const JobInfo = () => {
}}
editLoading={objectFormState.editLoading}
formValid={objectFormState.formValid}
disabled={objectFormState.lock?.locked || objectFormState.loading}
disabled={
objectFormState.lock?.locked ||
objectFormState.loading ||
editDisabled
}
loading={objectFormState.editLoading}
/>
</Space>

View File

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

View File

@ -1,6 +1,9 @@
import JobIcon from '../../components/Icons/JobIcon'
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
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'
export const Job = {
@ -19,6 +22,57 @@ export const Job = {
icon: InfoCircleIcon,
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',
label: 'Deploy',
@ -30,7 +84,7 @@ export const Job = {
disabled: (objectData) => {
return objectData?.state?.type != 'draft'
}
},
}
],
columns: ['_reference', 'quantity', 'state', 'gcodeFile', 'createdAt'],
filters: ['state', '_id', 'gcodeFile', 'quantity'],
@ -62,6 +116,13 @@ export const Job = {
readOnly: true,
columnWidth: 180
},
{
name: 'updatedAt',
label: 'Updated At',
type: 'dateTime',
readOnly: true,
columnWidth: 175
},
{
name: 'state',
label: 'State',
@ -75,8 +136,8 @@ export const Job = {
readOnly: true
},
{
name: 'updatedAt',
label: 'Updated At',
name: 'startedAt',
label: 'Started At',
type: 'dateTime',
readOnly: true,
columnWidth: 175
@ -89,21 +150,6 @@ export const Job = {
columnWidth: 125,
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',
label: 'Finished At',
@ -111,6 +157,7 @@ export const Job = {
readOnly: true,
columnWidth: 175
},
{
name: 'gcodeFile',
label: 'GCode File',
@ -120,6 +167,7 @@ export const Job = {
required: true,
showHyperlink: true
},
{
name: 'totalTime',
label: 'Total Time',
@ -147,6 +195,14 @@ export const Job = {
return parts.join(' ')
}
},
{
name: 'printers',
label: 'Printers',
type: 'objectList',
objectType: 'printer',
required: true,
columnWidth: 200
}
],
stats: [

View File

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