From d606053af36415bcf6273684380948a7eaad7fd4 Mon Sep 17 00:00:00 2001 From: Alex Jennings Date: Tue, 16 Sep 2025 12:44:39 -0700 Subject: [PATCH 1/6] Bump to 25.3.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e1139fb..edca5f1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@vidispine/admin-tool", - "version": "25.3.0", + "version": "25.3.1", "private": true, "dependencies": { "@devbookhq/splitter": "^1.3.2", From 1e5d3f7001e952b807e6eaf6d4f48dcca0a10034 Mon Sep 17 00:00:00 2001 From: Alex Jennings Date: Mon, 10 Nov 2025 11:27:59 +0000 Subject: [PATCH 2/6] Fixes missing notification form and display --- .../notification/NotificationTrigger.jsx | 20 ++- .../notification/NotificationTriggerForm.jsx | 119 +++++++++++------- 2 files changed, 91 insertions(+), 48 deletions(-) diff --git a/src/components/notification/NotificationTrigger.jsx b/src/components/notification/NotificationTrigger.jsx index f785d60..bdca8b6 100644 --- a/src/components/notification/NotificationTrigger.jsx +++ b/src/components/notification/NotificationTrigger.jsx @@ -153,6 +153,8 @@ function StorageTriggerType({ trigger: { storage } }) { triggerAction = 'create'; } else if ('delete' in storage) { triggerAction = 'delete'; + } else if ('modify' in storage) { + triggerAction = 'modify'; } return ; } @@ -169,6 +171,8 @@ function FileTriggerType({ trigger: { file } }) { triggerAction = 'close'; } else if ('delete' in file) { triggerAction = 'delete'; + } else if ('lost' in file) { + triggerAction = 'lost'; } return ; } @@ -227,8 +231,22 @@ function DocumentTriggerType({ trigger: { document } }) { triggerAction = 'create'; } else if ('delete' in document) { triggerAction = 'delete'; + } else if ('modify' in document) { + triggerAction = 'modify'; } - return ; + return ( + <> + + {triggerAction === 'modify' && ( + <> + + + + + + )} + + ); } function DeletionLockTriggerType({ trigger: { deletionLock } }) { diff --git a/src/components/notification/NotificationTriggerForm.jsx b/src/components/notification/NotificationTriggerForm.jsx index 4db805f..82b7963 100644 --- a/src/components/notification/NotificationTriggerForm.jsx +++ b/src/components/notification/NotificationTriggerForm.jsx @@ -11,6 +11,17 @@ import StatefulSelect from '../ui/StatefulSelect'; import { getTriggerEntity, getJobAction } from './NotificationTrigger'; +function NotificationTriggerMetadataModifyType() { + return ( + <> + + + + + + ); +} + function NotificationTriggerItemType(props) { const { initialValues = {}, valueSelector, dirty } = props; const name = props?.id || 'notificationDocument.trigger.item'; @@ -62,13 +73,13 @@ function NotificationTriggerStorageType(props) { const name = props?.id || 'notificationDocument.trigger.storage'; let initialvalue; if (dirty) { - const item = valueSelector(name); - initialvalue = item && Object.keys(item)[0]; + const storage = valueSelector(name); + initialvalue = storage && Object.keys(storage)[0]; } else { const { notificationDocument = {} } = initialValues; const { trigger = {} } = notificationDocument; - const { item } = trigger; - initialvalue = item && Object.keys(item)[0]; + const { storage } = trigger; + initialvalue = storage && Object.keys(storage)[0]; } const onChange = (event, newValue, previousValue) => { const prevState = valueSelector(name); @@ -96,10 +107,12 @@ function NotificationTriggerStorageType(props) { > Create Delete + Modify Filename + ); @@ -110,13 +123,13 @@ function NotificationTriggerFileType(props) { const name = props?.id || 'notificationDocument.trigger.file'; let initialvalue; if (dirty) { - const item = valueSelector(name); - initialvalue = item && Object.keys(item)[0]; + const file = valueSelector(name); + initialvalue = file && Object.keys(file)[0]; } else { const { notificationDocument = {} } = initialValues; const { trigger = {} } = notificationDocument; - const { item } = trigger; - initialvalue = item && Object.keys(item)[0]; + const { file } = trigger; + initialvalue = file && Object.keys(file)[0]; } const onChange = (event, newValue, previousValue) => { const prevState = valueSelector(name); @@ -147,12 +160,14 @@ function NotificationTriggerFileType(props) { Hash Close Delete + Lost + ); } @@ -162,13 +177,13 @@ function NotificationTriggerGroupType(props) { const name = props?.id || 'notificationDocument.trigger.group'; let initialvalue; if (dirty) { - const item = valueSelector(name); - initialvalue = item && Object.keys(item)[0]; + const group = valueSelector(name); + initialvalue = group && Object.keys(group)[0]; } else { const { notificationDocument = {} } = initialValues; const { trigger = {} } = notificationDocument; - const { item } = trigger; - initialvalue = item && Object.keys(item)[0]; + const { group } = trigger; + initialvalue = group && Object.keys(group)[0]; } const onChange = (event, newValue, previousValue) => { const prevState = valueSelector(name); @@ -210,13 +225,13 @@ function NotificationTriggerShapeType(props) { const name = props?.id || 'notificationDocument.trigger.shape'; let initialvalue; if (dirty) { - const item = valueSelector(name); - initialvalue = item && Object.keys(item)[0]; + const shape = valueSelector(name); + initialvalue = shape && Object.keys(shape)[0]; } else { const { notificationDocument = {} } = initialValues; const { trigger = {} } = notificationDocument; - const { item } = trigger; - initialvalue = item && Object.keys(item)[0]; + const { shape } = trigger; + initialvalue = shape && Object.keys(shape)[0]; } const onChange = (event, newValue, previousValue) => { const prevState = valueSelector(name); @@ -258,13 +273,13 @@ function NotificationTriggerAccessType(props) { const name = props?.id || 'notificationDocument.trigger.access'; let initialvalue; if (dirty) { - const item = valueSelector(name); - initialvalue = item && Object.keys(item)[0]; + const access = valueSelector(name); + initialvalue = access && Object.keys(access)[0]; } else { const { notificationDocument = {} } = initialValues; const { trigger = {} } = notificationDocument; - const { item } = trigger; - initialvalue = item && Object.keys(item)[0]; + const { access } = trigger; + initialvalue = access && Object.keys(access)[0]; } const onChange = (event, newValue, previousValue) => { const prevState = valueSelector(name); @@ -306,13 +321,13 @@ function NotificationTriggerQuotaType(props) { const name = props?.id || 'notificationDocument.trigger.quota'; let initialvalue; if (dirty) { - const item = valueSelector(name); - initialvalue = item && Object.keys(item)[0]; + const quota = valueSelector(name); + initialvalue = quota && Object.keys(quota)[0]; } else { const { notificationDocument = {} } = initialValues; const { trigger = {} } = notificationDocument; - const { item } = trigger; - initialvalue = item && Object.keys(item)[0]; + const { quota } = trigger; + initialvalue = quota && Object.keys(quota)[0]; } const onChange = (event, newValue, previousValue) => { const prevState = valueSelector(name); @@ -354,17 +369,17 @@ function NotificationTriggerDocumentType(props) { const name = props?.id || 'notificationDocument.trigger.document'; let initialvalue; if (dirty) { - const item = valueSelector(name); - initialvalue = item && Object.keys(item)[0]; + const document = valueSelector(name); + initialvalue = document && Object.keys(document)[0]; } else { const { notificationDocument = {} } = initialValues; const { trigger = {} } = notificationDocument; - const { item } = trigger; - initialvalue = item && Object.keys(item)[0]; + const { document } = trigger; + initialvalue = document && Object.keys(document)[0]; } const onChange = (event, newValue, previousValue) => { const prevState = valueSelector(name); - const setValue = ''; + const setValue = newValue === 'modify' ? {} : ''; if (prevState) { const newState = update(prevState, { [newValue]: { @@ -377,6 +392,23 @@ function NotificationTriggerDocumentType(props) { props?.change(name, { [newValue]: setValue }); } }; + // TODO Refactor as standalone component + // eslint-disable-next-line react/no-unstable-nested-components + function ValueComponent(value) { + switch (value) { + case 'modify': + return ( + + ); + default: + return null; + } + } return ( <> Create Delete + Modify + ); } @@ -400,13 +436,13 @@ function NotificationTriggerDeletionLockType(props) { const name = props?.id || 'notificationDocument.trigger.deletionLock'; let initialvalue; if (dirty) { - const item = valueSelector(name); - initialvalue = item && Object.keys(item)[0]; + const deletionLock = valueSelector(name); + initialvalue = deletionLock && Object.keys(deletionLock)[0]; } else { const { notificationDocument = {} } = initialValues; const { trigger = {} } = notificationDocument; - const { item } = trigger; - initialvalue = item && Object.keys(item)[0]; + const { deletionLock } = trigger; + initialvalue = deletionLock && Object.keys(deletionLock)[0]; } const onChange = (event, newValue, previousValue) => { const prevState = valueSelector(name); @@ -447,17 +483,6 @@ function NotificationTriggerDeletionLockType(props) { ); } -function NotificationTriggerMetadataModifyType() { - return ( - <> - - - - - - ); -} - function NotificationTriggerMetadataType(props) { const { initialValues = {}, valueSelector, dirty } = props; const name = props?.id || 'notificationDocument.trigger.metadata'; @@ -536,8 +561,8 @@ function NotificationTriggerCollectionType(props) { const name = props?.id || 'notificationDocument.trigger.collection'; let initialvalue; if (dirty) { - const item = valueSelector(name); - initialvalue = item && Object.keys(item)[0]; + const collection = valueSelector(name); + initialvalue = collection && Object.keys(collection)[0]; } else { const { notificationDocument = {} } = initialValues; const { trigger = {} } = notificationDocument; @@ -667,7 +692,7 @@ function NotificationJobTriggerType(props) { Update Create Stop - Finish + Finished Fail From 5ed97bee585e7226ecf0d7cf970a71ba6311bde9 Mon Sep 17 00:00:00 2001 From: Alex Jennings Date: Mon, 10 Nov 2025 11:34:00 +0000 Subject: [PATCH 3/6] add priority to autoimport --- .../autoimport/AutoImportRuleDisplay.jsx | 1 + src/components/autoimport/AutoImportRuleForm.jsx | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/components/autoimport/AutoImportRuleDisplay.jsx b/src/components/autoimport/AutoImportRuleDisplay.jsx index 305f503..2211c1f 100644 --- a/src/components/autoimport/AutoImportRuleDisplay.jsx +++ b/src/components/autoimport/AutoImportRuleDisplay.jsx @@ -19,6 +19,7 @@ export function AutoImportRuleType({ rule }) { <> + } label="Enabled" /> + + Priority + + {JobPriority.map((priority) => ( + + {priority} + + ))} + + } label="File Name As Title" From 2a46a58168c1942b47af084da3bf957d02d3021a Mon Sep 17 00:00:00 2001 From: Alex Jennings Date: Mon, 10 Nov 2025 12:07:26 +0000 Subject: [PATCH 4/6] Add item subclip --- src/components/item/ItemSubclipCreate.jsx | 70 ++++++++ src/components/item/ItemSubclipCreateForm.jsx | 168 ++++++++++++++++++ src/components/item/ItemTitle.jsx | 4 + src/const/routes.js | 1 + src/containers/Item.jsx | 8 + src/formactions/item.js | 11 ++ 6 files changed, 262 insertions(+) create mode 100644 src/components/item/ItemSubclipCreate.jsx create mode 100644 src/components/item/ItemSubclipCreateForm.jsx diff --git a/src/components/item/ItemSubclipCreate.jsx b/src/components/item/ItemSubclipCreate.jsx new file mode 100644 index 0000000..93f6423 --- /dev/null +++ b/src/components/item/ItemSubclipCreate.jsx @@ -0,0 +1,70 @@ +import Button from '@material-ui/core/Button'; +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import Divider from '@material-ui/core/Divider'; +import { compose } from 'redux'; + +import * as formActions from '../../formactions/item'; +import withFormActions from '../../hoc/withFormActions'; +import withUI from '../../hoc/withUI'; + +import ItemSubclipCreateForm from './ItemSubclipCreateForm'; + +const ITEM_SUBCLIP_CREATE_FORM = 'ITEM_SUBCLIP_CREATE_FORM'; + +function ItemSubclipCreate({ + open, + onClose, + onSuccess, + onFail, + openSnackBar, + submitForm, + itemId, + initialValues, + form = ITEM_SUBCLIP_CREATE_FORM, +}) { + const onSubmitSuccess = (response, dispatch, props) => { + const messageContent = 'Subclip Job Created'; + openSnackBar({ messageContent }); + if (onSuccess) { + onSuccess(response, dispatch, props); + } + onClose(); + }; + const onSubmitFail = (error, dispatch, props) => { + const messageContent = 'Error Creating Subclip'; + openSnackBar({ messageContent, messageColor: 'secondary' }); + if (onFail) { + onFail(error, dispatch, props); + } + }; + return ( + + Create Sequence + + + + + + + + + + ); +} + +export default compose(withUI, withFormActions)(ItemSubclipCreate); diff --git a/src/components/item/ItemSubclipCreateForm.jsx b/src/components/item/ItemSubclipCreateForm.jsx new file mode 100644 index 0000000..46c452f --- /dev/null +++ b/src/components/item/ItemSubclipCreateForm.jsx @@ -0,0 +1,168 @@ +import FormControl from '@material-ui/core/FormControl'; +import FormControlLabel from '@material-ui/core/FormControlLabel'; +import FormHelperText from '@material-ui/core/FormHelperText'; +import InputLabel from '@material-ui/core/InputLabel'; +import MenuItem from '@material-ui/core/MenuItem'; +import Typography from '@material-ui/core/Typography'; +import { reduxForm } from 'redux-form'; + +import JobPriority from '../../const/JobPriority'; +import { required } from '../../utils/FieldValidation'; +import { TextField, Select } from '../form'; +import { loadShapeTagOptions } from '../shapetag/ShapeTagSelect'; +import { loadStorageOptions } from '../storage/StorageSelect'; +import BoolCheckbox from '../ui/BoolCheckbox'; +import Field from '../ui/Field'; +import FieldTypeArray from '../ui/FieldTypeArray'; +import FormSection from '../ui/FormSection'; +import { KeyValuePairType } from '../ui/FormType'; +import { StatefulAsyncSelect } from '../ui/Select'; + +const queryParams = () => ( + <> + + + + + + + mode + + Rendering + + Rendermode of the transcoder + + + + + + + + + + priority + + {JobPriority.map((priority) => ( + + {priority} + + ))} + + The priority to assign to the job. Default is MEDIUM + + + + } + label="holdJob" + fullWidth + /> + Created job in a HOLD state + + +); + +function ItemSubclipCreateForm({ itemId, error, handleSubmit }) { + return ( +
+ {error && {error}} + {itemId === undefined ? ( + + ) : null} + +