Skip to content

Commit 2a46a58

Browse files
committed
Add item subclip
1 parent 5ed97be commit 2a46a58

File tree

6 files changed

+262
-0
lines changed

6 files changed

+262
-0
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import Button from '@material-ui/core/Button';
2+
import Dialog from '@material-ui/core/Dialog';
3+
import DialogActions from '@material-ui/core/DialogActions';
4+
import DialogContent from '@material-ui/core/DialogContent';
5+
import DialogTitle from '@material-ui/core/DialogTitle';
6+
import Divider from '@material-ui/core/Divider';
7+
import { compose } from 'redux';
8+
9+
import * as formActions from '../../formactions/item';
10+
import withFormActions from '../../hoc/withFormActions';
11+
import withUI from '../../hoc/withUI';
12+
13+
import ItemSubclipCreateForm from './ItemSubclipCreateForm';
14+
15+
const ITEM_SUBCLIP_CREATE_FORM = 'ITEM_SUBCLIP_CREATE_FORM';
16+
17+
function ItemSubclipCreate({
18+
open,
19+
onClose,
20+
onSuccess,
21+
onFail,
22+
openSnackBar,
23+
submitForm,
24+
itemId,
25+
initialValues,
26+
form = ITEM_SUBCLIP_CREATE_FORM,
27+
}) {
28+
const onSubmitSuccess = (response, dispatch, props) => {
29+
const messageContent = 'Subclip Job Created';
30+
openSnackBar({ messageContent });
31+
if (onSuccess) {
32+
onSuccess(response, dispatch, props);
33+
}
34+
onClose();
35+
};
36+
const onSubmitFail = (error, dispatch, props) => {
37+
const messageContent = 'Error Creating Subclip';
38+
openSnackBar({ messageContent, messageColor: 'secondary' });
39+
if (onFail) {
40+
onFail(error, dispatch, props);
41+
}
42+
};
43+
return (
44+
<Dialog open={open} onClose={onClose} fullWidth maxWidth={false}>
45+
<DialogTitle>Create Sequence</DialogTitle>
46+
<DialogContent>
47+
<ItemSubclipCreateForm
48+
form={form}
49+
onSubmit={formActions.onCreateItemSubclip}
50+
onSubmitSuccess={onSubmitSuccess}
51+
onSubmitFail={onSubmitFail}
52+
onCancel={onClose}
53+
itemId={itemId}
54+
initialValues={{ itemId, ...initialValues }}
55+
/>
56+
</DialogContent>
57+
<Divider />
58+
<DialogActions>
59+
<Button color="secondary" onClick={onClose}>
60+
Close
61+
</Button>
62+
<Button variant="contained" color="primary" onClick={() => submitForm(form)}>
63+
Create
64+
</Button>
65+
</DialogActions>
66+
</Dialog>
67+
);
68+
}
69+
70+
export default compose(withUI, withFormActions)(ItemSubclipCreate);
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import FormControl from '@material-ui/core/FormControl';
2+
import FormControlLabel from '@material-ui/core/FormControlLabel';
3+
import FormHelperText from '@material-ui/core/FormHelperText';
4+
import InputLabel from '@material-ui/core/InputLabel';
5+
import MenuItem from '@material-ui/core/MenuItem';
6+
import Typography from '@material-ui/core/Typography';
7+
import { reduxForm } from 'redux-form';
8+
9+
import JobPriority from '../../const/JobPriority';
10+
import { required } from '../../utils/FieldValidation';
11+
import { TextField, Select } from '../form';
12+
import { loadShapeTagOptions } from '../shapetag/ShapeTagSelect';
13+
import { loadStorageOptions } from '../storage/StorageSelect';
14+
import BoolCheckbox from '../ui/BoolCheckbox';
15+
import Field from '../ui/Field';
16+
import FieldTypeArray from '../ui/FieldTypeArray';
17+
import FormSection from '../ui/FormSection';
18+
import { KeyValuePairType } from '../ui/FormType';
19+
import { StatefulAsyncSelect } from '../ui/Select';
20+
21+
const queryParams = () => (
22+
<>
23+
<Field
24+
name="sourceTag"
25+
label="sourceTag"
26+
helperText="Comma-separated list of shape tags. The first valid shape is selected as the source of the job. If non of the tags are valid, the original shape will be used"
27+
component={StatefulAsyncSelect}
28+
loadOptions={loadShapeTagOptions}
29+
cacheOptions
30+
isClearable
31+
fullWidth
32+
isMulti
33+
creatable
34+
/>
35+
<Field
36+
name="tag"
37+
label="tag"
38+
helperText="Comma-separated list of shape tags specifying the desired output formats. Currently, only a single tag can be specified for a sequence item"
39+
component={StatefulAsyncSelect}
40+
loadOptions={loadShapeTagOptions}
41+
cacheOptions
42+
isClearable
43+
fullWidth
44+
isMulti
45+
creatable
46+
/>
47+
<Field
48+
name="original"
49+
label="original"
50+
component={TextField}
51+
fullWidth
52+
helperText="If specified, should be one of the tags specified in the tag parameter. Specifies that the original shape tag will be reset to the shape created to this tag."
53+
/>
54+
<Field
55+
name="destinationItem"
56+
label="destinationItem"
57+
component={TextField}
58+
fullWidth
59+
helperText="An item id to which the new shape will be associated"
60+
validate={[required]}
61+
required
62+
/>
63+
<Field
64+
name="storageId"
65+
label="storageId"
66+
helperText="Where essence file is to be stored"
67+
component={StatefulAsyncSelect}
68+
loadOptions={loadStorageOptions}
69+
cacheOptions
70+
isClearable
71+
fullWidth
72+
creatable
73+
/>
74+
<FormControl required fullWidth>
75+
<InputLabel htmlFor="mode">mode</InputLabel>
76+
<Field name="mode" component={Select} validate={[required]}>
77+
<MenuItem value="Rendering">Rendering</MenuItem>
78+
</Field>
79+
<FormHelperText>Rendermode of the transcoder</FormHelperText>
80+
</FormControl>
81+
<Field
82+
name="start"
83+
label="start"
84+
component={TextField}
85+
fullWidth
86+
helperText="Start frame in the source of the subclip"
87+
/>
88+
<Field name="duration" component={TextField} fullWidth helperText="Duration of the subclip" />
89+
<Field
90+
name="startTimeCode"
91+
label="startTimeCode"
92+
component={TextField}
93+
fullWidth
94+
helperText="Start timecode of the new clip"
95+
/>
96+
<Field
97+
name="resourceId"
98+
label="resourceId"
99+
component={TextField}
100+
fullWidth
101+
helperText="The transcoder resource to use to execute the job"
102+
/>
103+
<Field
104+
name="resourceTag"
105+
label="resourceTag"
106+
component={TextField}
107+
fullWidth
108+
helperText="The resource tag criteria used to select transcoders for the job"
109+
/>
110+
<Field
111+
name="notification"
112+
label="notification"
113+
component={TextField}
114+
fullWidth
115+
helperText="The placeholder job notification to use for this job"
116+
/>
117+
<FieldTypeArray
118+
name="notificationData"
119+
label="notificationData"
120+
component={KeyValuePairType}
121+
arrayHeader
122+
withHeader={false}
123+
dense
124+
/>
125+
<FormControl fullWidth>
126+
<InputLabel htmlFor="priority">priority</InputLabel>
127+
<Field name="priority" component={Select}>
128+
{JobPriority.map((priority) => (
129+
<MenuItem key={priority} value={priority}>
130+
{priority}
131+
</MenuItem>
132+
))}
133+
</Field>
134+
<FormHelperText>The priority to assign to the job. Default is MEDIUM</FormHelperText>
135+
</FormControl>
136+
<FieldTypeArray
137+
name="jobmetadata"
138+
label="jobmetadata"
139+
component={KeyValuePairType}
140+
withHeader={false}
141+
arrayHeader
142+
dense
143+
/>
144+
<FormControl>
145+
<FormControlLabel
146+
control={<Field name="holdJob" component={BoolCheckbox} />}
147+
label="holdJob"
148+
fullWidth
149+
/>
150+
<FormHelperText>Created job in a HOLD state</FormHelperText>
151+
</FormControl>
152+
</>
153+
);
154+
155+
function ItemSubclipCreateForm({ itemId, error, handleSubmit }) {
156+
return (
157+
<form onSubmit={handleSubmit}>
158+
{error && <Typography color="error">{error}</Typography>}
159+
{itemId === undefined ? (
160+
<Field name="itemId" label="Item ID" component={TextField} fullWidth />
161+
) : null}
162+
<FormSection name="queryParams" component={queryParams} />
163+
<button type="submit" hidden />
164+
</form>
165+
);
166+
}
167+
168+
export default reduxForm()(ItemSubclipCreateForm);

src/components/item/ItemTitle.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ function ItemTitle({
5959
breadcrumbList,
6060
createShapeModal,
6161
createSequenceModal,
62+
createSubclipModal,
6263
analyzeModal,
6364
...props
6465
}) {
@@ -150,6 +151,9 @@ function ItemTitle({
150151
<MenuItem onClick={() => onOpen({ modalName: createSequenceModal })}>
151152
<Typography>Create Sequence</Typography>
152153
</MenuItem>
154+
<MenuItem onClick={() => onOpen({ modalName: createSubclipModal })}>
155+
<Typography>Create Subclip</Typography>
156+
</MenuItem>
153157
<MenuItem onClick={() => onOpen({ modalName: exportModal })}>
154158
<Typography>Export</Typography>
155159
</MenuItem>

src/const/routes.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ export default {
4242
metadataField: (params) => generatePath('/metadata-field/:fieldName/', params),
4343
fieldGroupList: (params) => generatePath('/field-group/', params),
4444
fieldGroup: (params) => generatePath('/field-group/:groupName/', params),
45+
job: (params) => generatePath('/job/:jobId', params),
4546
};

src/containers/Item.jsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import ItemImpImport from '../components/item/ItemImpImport';
1414
import ItemRelationDialog from '../components/item/ItemRelation';
1515
import ItemSequenceCreate from '../components/item/ItemSequenceCreate';
1616
import ItemShapeCreate from '../components/item/ItemShapeCreate';
17+
import ItemSubclipCreate from '../components/item/ItemSubclipCreate';
1718
import ItemThumbnailDialog from '../components/item/ItemThumbnail';
1819
import ItemTitle from '../components/item/ItemTitle';
1920
import ItemTranscode from '../components/item/ItemTranscode';
@@ -90,6 +91,7 @@ const ITEM_REMOVEALLSHAPES_DIALOG = 'ITEM_REMOVEALLSHAPES_DIALOG';
9091
const ITEM_IMPIMPORT_DIALOG = 'ITEM_IMPIMPORT_DIALOG';
9192
const ITEM_ANALYZE_DIALOG = 'ITEM_ANALYZE_DIALOG';
9293
const ITEM_SEQUENCE_CREATE_DIALOG = 'ITEM_SEQUENCE_CREATE_DIALOG';
94+
const ITEM_SUBCLIP_CREATE_DIALOG = 'ITEM_SUBCLIP_CREATE_DIALOG';
9395
const EXTERNALID_TAB = 'EXTERNALID_TAB';
9496

9597
const TAB_TITLE = [
@@ -334,6 +336,7 @@ class Item extends PureComponent {
334336
createShapeModal={ITEM_SHAPE_CREATE_DIALOG}
335337
analyzeModal={ITEM_ANALYZE_DIALOG}
336338
createSequenceModal={ITEM_SEQUENCE_CREATE_DIALOG}
339+
createSubclipModal={ITEM_SUBCLIP_CREATE_DIALOG}
337340
{...props}
338341
/>
339342
);
@@ -419,6 +422,11 @@ class Item extends PureComponent {
419422
}
420423
itemId={itemId}
421424
/>
425+
<ItemSubclipCreate
426+
dialogName={ITEM_SUBCLIP_CREATE_DIALOG}
427+
onSuccess={(response) => history.push(routes.job({ jobId: response.data.jobId }))}
428+
itemId={itemId}
429+
/>
422430
<CollectionEntityAdd
423431
dialogName={COLLECTION_ENTITY_ADD_DIALOG}
424432
entityId={itemId}

src/formactions/item.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,3 +312,14 @@ export const onSearchItemMetadataGroup = withSubmissionError((form) => {
312312
...response,
313313
}));
314314
});
315+
316+
export const onCreateItemSubclip = withSubmissionError((form, dispatch, props) => {
317+
const { queryParams } = form;
318+
const itemId = props.itemId || form.itemId;
319+
const path = `/API/item/${itemId}/subclip`;
320+
return ItemApi.createTranscode({
321+
itemId,
322+
queryParams,
323+
path,
324+
});
325+
});

0 commit comments

Comments
 (0)