@imposium-hub/components 1.42.4 → 1.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Entry.ts +5 -0
- package/components/data-table/DataTable.tsx +0 -1
- package/components/publish-wizard/PublishWizard.tsx +62 -8
- package/components/publish-wizard/publish/EmailWorkflow.tsx +236 -27
- package/components/select-field/SelectField.tsx +2 -3
- package/constants/copy.ts +3 -0
- package/dist/components.js +4 -4
- package/dist/components.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/styles.css.map +1 -1
- package/dist/styles.less +72 -0
- package/dist/styles.less.map +1 -1
- package/less/components/align-columns.less +66 -0
- package/less/components/publish-wizard.less +6 -0
- package/less/styles.less +1 -0
- package/package.json +1 -1
- package/redux/actions/active-batch.ts +110 -0
- package/redux/reducers/active-batch.ts +108 -0
package/Entry.ts
CHANGED
|
@@ -101,6 +101,8 @@ import assetTags from './redux/reducers/asset-tags';
|
|
|
101
101
|
import assetUploads from './redux/reducers/asset-uploads';
|
|
102
102
|
import selectedAssets from './redux/reducers/selected-assets';
|
|
103
103
|
import assetActions from './redux/actions/asset-list';
|
|
104
|
+
import activeBatch from './redux/reducers/active-batch';
|
|
105
|
+
import batchActions from './redux/actions/active-batch';
|
|
104
106
|
/*
|
|
105
107
|
Statics / Services
|
|
106
108
|
*/
|
|
@@ -222,6 +224,9 @@ export {
|
|
|
222
224
|
addAssetTagToList,
|
|
223
225
|
assetTags,
|
|
224
226
|
assetActions,
|
|
227
|
+
|
|
228
|
+
activeBatch,
|
|
229
|
+
batchActions,
|
|
225
230
|
|
|
226
231
|
AuthService,
|
|
227
232
|
IIdentity,
|
|
@@ -109,7 +109,6 @@ let doubleClickTimeout : number;
|
|
|
109
109
|
const DataTable : React.FC<IDataTableProps> = (props : IDataTableProps) => {
|
|
110
110
|
const wrapperRef = React.useRef(null);
|
|
111
111
|
const activeRowRef = React.useRef(null);
|
|
112
|
-
|
|
113
112
|
const [didMount, setDidMount] = React.useState(false);
|
|
114
113
|
const [data, setData] = React.useState([]);
|
|
115
114
|
const [columns, setColumns] = React.useState([]);
|
|
@@ -60,6 +60,9 @@ interface IPublishWizardState {
|
|
|
60
60
|
accessKey : string;
|
|
61
61
|
credentials : ICredential[];
|
|
62
62
|
done : boolean;
|
|
63
|
+
error : boolean;
|
|
64
|
+
next : boolean;
|
|
65
|
+
nextStep : boolean;
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
interface IBigButtonProps {
|
|
@@ -78,6 +81,7 @@ interface IBigLinkProps {
|
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
class PublishWizard extends React.PureComponent<IPublishWizardProps, IPublishWizardState> {
|
|
84
|
+
public emailWorkflow : any;
|
|
81
85
|
private readonly hiddenFileInputRef : any;
|
|
82
86
|
constructor(props) {
|
|
83
87
|
super(props);
|
|
@@ -92,7 +96,11 @@ class PublishWizard extends React.PureComponent<IPublishWizardProps, IPublishWiz
|
|
|
92
96
|
accessKey: null,
|
|
93
97
|
credentials: [],
|
|
94
98
|
done: false,
|
|
99
|
+
error: false,
|
|
100
|
+
next: false,
|
|
101
|
+
nextStep: false,
|
|
95
102
|
};
|
|
103
|
+
this.emailWorkflow = React.createRef();
|
|
96
104
|
this.hiddenFileInputRef = React.createRef();
|
|
97
105
|
}
|
|
98
106
|
|
|
@@ -216,8 +224,8 @@ class PublishWizard extends React.PureComponent<IPublishWizardProps, IPublishWiz
|
|
|
216
224
|
|
|
217
225
|
private renderLowerButtons() {
|
|
218
226
|
|
|
219
|
-
const {screenIndex, done} = this.state;
|
|
220
|
-
const {publishing} = this.props;
|
|
227
|
+
const { screenIndex, done, error, next } = this.state;
|
|
228
|
+
const { publishing } = this.props;
|
|
221
229
|
|
|
222
230
|
const lowerButtons = [];
|
|
223
231
|
|
|
@@ -246,26 +254,47 @@ class PublishWizard extends React.PureComponent<IPublishWizardProps, IPublishWiz
|
|
|
246
254
|
</Button>);
|
|
247
255
|
} else {
|
|
248
256
|
// display button when emailworkflow downloading state is true to close the modal
|
|
249
|
-
if (done) {
|
|
257
|
+
if (done || error) {
|
|
250
258
|
lowerButtons.push(<Button
|
|
251
|
-
tooltip = {copy.publish.btnFinished}
|
|
259
|
+
tooltip = { error ? copy.publish.btnCancel : copy.publish.btnFinished }
|
|
252
260
|
size={'large'}
|
|
253
261
|
key = 'btn-finish'
|
|
254
262
|
onClick={() => this.props.onClose()}
|
|
255
263
|
color = 'primary'>
|
|
256
|
-
{copy.publish.btnFinished}
|
|
264
|
+
{ error ? copy.publish.btnCancel : copy.publish.btnFinished }
|
|
257
265
|
</Button>);
|
|
258
266
|
}
|
|
267
|
+
|
|
259
268
|
const backIndex = (screenIndex === 1) ? 0 : 1;
|
|
269
|
+
|
|
260
270
|
// back button
|
|
261
271
|
lowerButtons.push(<Button
|
|
262
272
|
tooltip = {copy.publish.btnBack}
|
|
263
273
|
size={'large'}
|
|
264
274
|
key = 'btn-back'
|
|
265
|
-
onClick={() => this.setState({
|
|
275
|
+
onClick={() => this.setState({
|
|
276
|
+
screenIndex: backIndex,
|
|
277
|
+
next: false,
|
|
278
|
+
nextStep: false,
|
|
279
|
+
error: false,
|
|
280
|
+
done: false,
|
|
281
|
+
})}
|
|
266
282
|
color = 'primary'>
|
|
267
283
|
{copy.publish.btnBack}
|
|
268
284
|
</Button>);
|
|
285
|
+
|
|
286
|
+
// reimport after column align
|
|
287
|
+
if ( error ) {
|
|
288
|
+
lowerButtons.push(<Button
|
|
289
|
+
tooltip = {copy.publish.btnNext}
|
|
290
|
+
size={'large'}
|
|
291
|
+
key = 'btn-next'
|
|
292
|
+
color = 'primary'
|
|
293
|
+
disabled = {!next}
|
|
294
|
+
onClick={() => this.nextClickHandler()}>
|
|
295
|
+
{copy.publish.btnNext}
|
|
296
|
+
</Button>);
|
|
297
|
+
}
|
|
269
298
|
}
|
|
270
299
|
|
|
271
300
|
return lowerButtons;
|
|
@@ -362,13 +391,30 @@ class PublishWizard extends React.PureComponent<IPublishWizardProps, IPublishWiz
|
|
|
362
391
|
);
|
|
363
392
|
}
|
|
364
393
|
|
|
394
|
+
private nextClickHandler = () => {
|
|
395
|
+
this.setState({nextStep: true});
|
|
396
|
+
|
|
397
|
+
if (this.state.screenIndex === 7) {
|
|
398
|
+
this.emailWorkflow.current.getWrappedInstance().proceedWithExport();
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
365
402
|
private onDoneHandler = () => {
|
|
366
|
-
this.setState({done: true});
|
|
403
|
+
this.setState({ done: true, error: false });
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
private onErrorHandler = () => {
|
|
407
|
+
this.setState({error: !this.state.error});
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
private onNextHandler = (val : boolean) => {
|
|
411
|
+
this.setState({next: val});
|
|
367
412
|
}
|
|
368
413
|
|
|
369
414
|
public render() {
|
|
370
415
|
const {
|
|
371
416
|
story,
|
|
417
|
+
project,
|
|
372
418
|
api,
|
|
373
419
|
handleError,
|
|
374
420
|
createFreshBatch,
|
|
@@ -380,11 +426,13 @@ class PublishWizard extends React.PureComponent<IPublishWizardProps, IPublishWiz
|
|
|
380
426
|
batchJobs
|
|
381
427
|
} = this.props;
|
|
382
428
|
|
|
383
|
-
const {screenIndex, status, selectedComposition, compositions, accessKey} = this.state;
|
|
429
|
+
const {screenIndex, status, selectedComposition, compositions, accessKey, error, nextStep} = this.state;
|
|
384
430
|
const compName = compositions.find((comp) => {
|
|
385
431
|
return comp.id === selectedComposition;
|
|
386
432
|
})?.name || '';
|
|
387
433
|
|
|
434
|
+
const variables = (story) ? story.acts[project.actId].inventory : {};
|
|
435
|
+
|
|
388
436
|
return (
|
|
389
437
|
<div className='publish-wizard'>
|
|
390
438
|
<div className = 'publish-wizard-header'>
|
|
@@ -401,7 +449,11 @@ class PublishWizard extends React.PureComponent<IPublishWizardProps, IPublishWiz
|
|
|
401
449
|
isExport = {screenIndex === 7}
|
|
402
450
|
api={api}
|
|
403
451
|
story={story}
|
|
452
|
+
variables= {variables}
|
|
404
453
|
onDone={this.onDoneHandler}
|
|
454
|
+
onError={this.onErrorHandler}
|
|
455
|
+
onNext={this.onNextHandler}
|
|
456
|
+
error={error}
|
|
405
457
|
status={status}
|
|
406
458
|
renderBatch={renderBatch}
|
|
407
459
|
batchJobs={batchJobs}
|
|
@@ -413,6 +465,8 @@ class PublishWizard extends React.PureComponent<IPublishWizardProps, IPublishWiz
|
|
|
413
465
|
getBatches={getBatches}
|
|
414
466
|
getBatchExport={getBatchExport}
|
|
415
467
|
importBatchFromCsv={importBatchFromCsv}
|
|
468
|
+
next={nextStep}
|
|
469
|
+
ref={this.emailWorkflow}
|
|
416
470
|
/>}
|
|
417
471
|
{
|
|
418
472
|
screenIndex === 5 &&
|
|
@@ -7,9 +7,14 @@ import { ExportToCsv } from 'export-to-csv';
|
|
|
7
7
|
import { ICON_DOWNLOAD, ICON_UPLOAD } from '../../../constants/icons';
|
|
8
8
|
import * as moment from 'moment';
|
|
9
9
|
import { IImposiumAPI } from '../../../services/API';
|
|
10
|
+
import { bindActionCreators } from 'redux';
|
|
11
|
+
import { connect } from 'react-redux';
|
|
12
|
+
import SelectField from '../../select-field/SelectField';
|
|
13
|
+
import { updateAssociation, getBatch, setPage } from '../../../redux/actions/active-batch';
|
|
10
14
|
|
|
11
15
|
interface IEmailWorkflowProps {
|
|
12
16
|
story : any;
|
|
17
|
+
variables : any;
|
|
13
18
|
createFreshBatch : (e : string) => any;
|
|
14
19
|
getBatches : () => any;
|
|
15
20
|
getBatchExport : (batchId : string) => any;
|
|
@@ -20,10 +25,19 @@ interface IEmailWorkflowProps {
|
|
|
20
25
|
compositionId : string;
|
|
21
26
|
compositionName : string;
|
|
22
27
|
onDone : () => void;
|
|
28
|
+
onError : () => void;
|
|
29
|
+
error : boolean;
|
|
23
30
|
api : IImposiumAPI;
|
|
24
31
|
handleError : (e) => any;
|
|
25
32
|
batchJobs : any;
|
|
26
33
|
isExport ? : boolean;
|
|
34
|
+
updateAssociation : (api : IImposiumAPI, colIndex : number, newType : string, newAssociation : string) => any;
|
|
35
|
+
getBatch : (api : IImposiumAPI) => any;
|
|
36
|
+
activeBatch : any;
|
|
37
|
+
batchesList : any;
|
|
38
|
+
setPage : (page : number) => any;
|
|
39
|
+
onNext : ( val : boolean ) => void;
|
|
40
|
+
next : boolean;
|
|
27
41
|
}
|
|
28
42
|
|
|
29
43
|
interface IEmailWorkflowState {
|
|
@@ -32,6 +46,10 @@ interface IEmailWorkflowState {
|
|
|
32
46
|
uploading : boolean;
|
|
33
47
|
downloading : boolean;
|
|
34
48
|
renderedBatch : boolean;
|
|
49
|
+
inventory : any[];
|
|
50
|
+
inventoryKeys : string[];
|
|
51
|
+
missingColumns : string;
|
|
52
|
+
isMissing : boolean;
|
|
35
53
|
}
|
|
36
54
|
|
|
37
55
|
class EmailWorkflow extends React.PureComponent<IEmailWorkflowProps, IEmailWorkflowState> {
|
|
@@ -45,8 +63,9 @@ class EmailWorkflow extends React.PureComponent<IEmailWorkflowProps, IEmailWorkf
|
|
|
45
63
|
showTitle: false,
|
|
46
64
|
useTextFile: false,
|
|
47
65
|
useBom: false,
|
|
48
|
-
useKeysAsHeaders: true
|
|
66
|
+
useKeysAsHeaders: true
|
|
49
67
|
};
|
|
68
|
+
|
|
50
69
|
constructor(props) {
|
|
51
70
|
super(props);
|
|
52
71
|
this.state = {
|
|
@@ -55,14 +74,20 @@ class EmailWorkflow extends React.PureComponent<IEmailWorkflowProps, IEmailWorkf
|
|
|
55
74
|
downloading : false,
|
|
56
75
|
selectedBatchId: '',
|
|
57
76
|
renderedBatch: false,
|
|
77
|
+
inventory: [],
|
|
78
|
+
inventoryKeys: [],
|
|
79
|
+
missingColumns: '',
|
|
80
|
+
isMissing: false,
|
|
58
81
|
};
|
|
59
82
|
this.hiddenFileInputRef = React.createRef();
|
|
60
83
|
}
|
|
61
84
|
|
|
62
|
-
public
|
|
85
|
+
public componentDidMount() : void {
|
|
86
|
+
this.getInventory();
|
|
87
|
+
}
|
|
63
88
|
|
|
64
|
-
|
|
65
|
-
const {acts} = this.props.story;
|
|
89
|
+
private getInventory() {
|
|
90
|
+
const { acts } = this.props.story;
|
|
66
91
|
const actsKeys : string[] = Object.keys(acts);
|
|
67
92
|
let inventory : any = {};
|
|
68
93
|
|
|
@@ -71,6 +96,16 @@ class EmailWorkflow extends React.PureComponent<IEmailWorkflowProps, IEmailWorkf
|
|
|
71
96
|
});
|
|
72
97
|
|
|
73
98
|
const inventoryKeys : string[] = Object.keys(inventory).sort();
|
|
99
|
+
|
|
100
|
+
this.setState({inventory});
|
|
101
|
+
this.setState({inventoryKeys});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public downloadSampleCsv() {
|
|
105
|
+
|
|
106
|
+
const { name } = this.props.story;
|
|
107
|
+
const { inventory, inventoryKeys } = this.state;
|
|
108
|
+
|
|
74
109
|
const maskConfig : any[] = inventoryKeys.map((currKey : string) => ({
|
|
75
110
|
id: currKey,
|
|
76
111
|
name: inventory[currKey].name,
|
|
@@ -124,23 +159,48 @@ class EmailWorkflow extends React.PureComponent<IEmailWorkflowProps, IEmailWorkf
|
|
|
124
159
|
});
|
|
125
160
|
}
|
|
126
161
|
|
|
162
|
+
private getBatch = () => {
|
|
163
|
+
const { api } = this.props;
|
|
164
|
+
this.props.setPage(1);
|
|
165
|
+
this.props.getBatch(api);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
public proceedWithExport() {
|
|
169
|
+
const { renderBatch, activeBatch: { data: { id, name }} } = this.props;
|
|
170
|
+
renderBatch(id, name).then(() => {
|
|
171
|
+
this.setState({renderedBatch: true});
|
|
172
|
+
}).catch((e) => {
|
|
173
|
+
this.props.handleError(copy.publish.renderBatchFailed);
|
|
174
|
+
this.setState({renderedBatch: false});
|
|
175
|
+
throw e;
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
127
179
|
private importBatch({story_id, id, name, uploadEvt}) {
|
|
128
|
-
const {accessKey, compositionId, isExport,
|
|
180
|
+
const {accessKey, compositionId, isExport, onError} = this.props;
|
|
129
181
|
this.props.importBatchFromCsv(story_id, id, name, uploadEvt.target.files[0], accessKey, compositionId, !isExport, isExport)
|
|
130
182
|
.then(() => {
|
|
183
|
+
|
|
184
|
+
if (this.props.batchJobs.missing.length > 0 ) {
|
|
185
|
+
onError();
|
|
186
|
+
}
|
|
187
|
+
|
|
131
188
|
this.setState({uploadComplete: true, uploading: false});
|
|
132
|
-
|
|
189
|
+
this.getBatch();
|
|
190
|
+
|
|
191
|
+
if (isExport && Object.keys(this.props.batchJobs.missing).length === 0) {
|
|
133
192
|
this.renderBatch({id, name});
|
|
134
193
|
}
|
|
135
194
|
})
|
|
136
195
|
.catch((e) => {
|
|
137
|
-
const {status, data} = e.response;
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
196
|
+
// const {status, data} = e.response;
|
|
197
|
+
// if (status === 400) {
|
|
198
|
+
// handleError(copy.publish.missingColumns);
|
|
199
|
+
// this.setState({csvError: true});
|
|
200
|
+
// this.setState({csvErrorString: copy.publish.csvMissingColumns + data.error})
|
|
201
|
+
// // this.getBatch(id);
|
|
202
|
+
// this.hiddenFileInputRef.current.value = '';
|
|
203
|
+
// }
|
|
144
204
|
this.setState({uploadComplete: false, uploading: false});
|
|
145
205
|
throw e;
|
|
146
206
|
});
|
|
@@ -168,6 +228,7 @@ class EmailWorkflow extends React.PureComponent<IEmailWorkflowProps, IEmailWorkf
|
|
|
168
228
|
}
|
|
169
229
|
this.props.getBatchExport(selectedBatchId).then(() => {
|
|
170
230
|
this.props.onDone();
|
|
231
|
+
// this.props.onError();
|
|
171
232
|
this.setState({
|
|
172
233
|
downloading: false
|
|
173
234
|
});
|
|
@@ -176,9 +237,10 @@ class EmailWorkflow extends React.PureComponent<IEmailWorkflowProps, IEmailWorkf
|
|
|
176
237
|
}
|
|
177
238
|
|
|
178
239
|
public renderLabel() {
|
|
179
|
-
const {isExport, batchJobs} = this.props;
|
|
180
|
-
const {renderedBatch, selectedBatchId, uploading, uploadComplete} = this.state;
|
|
181
|
-
|
|
240
|
+
const { isExport, batchJobs } = this.props;
|
|
241
|
+
const { renderedBatch, selectedBatchId, uploading, uploadComplete } = this.state;
|
|
242
|
+
|
|
243
|
+
if (isExport && uploadComplete && !renderedBatch && Object.keys(this.props.batchJobs.missing).length === 0 ) {
|
|
182
244
|
return (
|
|
183
245
|
<div className={'progress-bar'}>
|
|
184
246
|
<progress
|
|
@@ -195,9 +257,134 @@ class EmailWorkflow extends React.PureComponent<IEmailWorkflowProps, IEmailWorkf
|
|
|
195
257
|
return <span>{ICON_UPLOAD} {copy.publish.uploadCsv}</span>;
|
|
196
258
|
}
|
|
197
259
|
|
|
260
|
+
private onAssociationChange(colIndex : any, e : any, stillMissingCols : boolean) {
|
|
261
|
+
|
|
262
|
+
const {activeBatch: {data : { columns }}} = this.props;
|
|
263
|
+
|
|
264
|
+
// Change the previous association back to static
|
|
265
|
+
const previousColumn = columns.findIndex((col) => {
|
|
266
|
+
return col.detail === e;
|
|
267
|
+
});
|
|
268
|
+
if (previousColumn !== -1) {
|
|
269
|
+
this.props.updateAssociation(this.props.api, previousColumn, 'Static', null);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Set the new association
|
|
273
|
+
this.props.updateAssociation(this.props.api, parseInt(colIndex, 10), 'UGC', e);
|
|
274
|
+
|
|
275
|
+
this.props.onNext(stillMissingCols);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
private renderColumnMap() {
|
|
279
|
+
|
|
280
|
+
const { activeBatch: {data : { columns }}, batchJobs: { missing }, variables } = this.props;
|
|
281
|
+
|
|
282
|
+
if (missing.length >= 0 && columns) {
|
|
283
|
+
|
|
284
|
+
const varArray = Object.keys(variables).map((key) => {
|
|
285
|
+
|
|
286
|
+
// disable options which are already aligned
|
|
287
|
+
const opt = {...variables[key]};
|
|
288
|
+
|
|
289
|
+
return opt;
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
const colArray = Object.keys(columns).map((i) => {
|
|
293
|
+
return columns[i];
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
const colOpts = colArray.filter((c : any) => {
|
|
297
|
+
if (c.from_import === 0 ) {
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return true;
|
|
302
|
+
}).map((c, i) => {
|
|
303
|
+
|
|
304
|
+
const opt : any = {
|
|
305
|
+
value: i,
|
|
306
|
+
label: c.name
|
|
307
|
+
};
|
|
308
|
+
const alignedColIdx = varArray.findIndex((v) => {
|
|
309
|
+
return c.detail === v.id;
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
if (alignedColIdx !== -1) {
|
|
313
|
+
opt.disabled = true;
|
|
314
|
+
}
|
|
315
|
+
return opt;
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// check to see if any required variables are missing
|
|
319
|
+
let stillMissingCols = false;
|
|
320
|
+
for (const v of varArray) {
|
|
321
|
+
if (!v.optional) {
|
|
322
|
+
const selectedCol = colArray.findIndex((c : any) => {
|
|
323
|
+
return c.detail === v.id;
|
|
324
|
+
});
|
|
325
|
+
if (selectedCol === -1) {
|
|
326
|
+
stillMissingCols = true;
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// add an empty option to the columns
|
|
333
|
+
colOpts.unshift('');
|
|
334
|
+
|
|
335
|
+
const missingColumn = Object.keys(missing).map((m) => missing[m]);
|
|
336
|
+
const showMissing = missingColumn.join();
|
|
337
|
+
|
|
338
|
+
if (colOpts.length < varArray.length) {
|
|
339
|
+
return (
|
|
340
|
+
<><HRule/><p className='missingColumns'>{`${copy.publish.csvMissingColumns} ${showMissing}`}</p></>
|
|
341
|
+
);
|
|
342
|
+
} else {
|
|
343
|
+
return (
|
|
344
|
+
<div className = 'align-columns' >
|
|
345
|
+
<HRule/>
|
|
346
|
+
<p className='match-columns'>{`${copy.publish.csvMatchColumns}`}</p>
|
|
347
|
+
|
|
348
|
+
<table>
|
|
349
|
+
<thead>
|
|
350
|
+
<tr>
|
|
351
|
+
<th>Variable</th>
|
|
352
|
+
<th>CSV Column</th>
|
|
353
|
+
</tr>
|
|
354
|
+
</thead>
|
|
355
|
+
<tbody>
|
|
356
|
+
{
|
|
357
|
+
varArray.map((v, i) => {
|
|
358
|
+
|
|
359
|
+
const selectedCol = colArray.findIndex((c : any) => {
|
|
360
|
+
return c.detail === v.id;
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
const selectedVal = (selectedCol !== undefined && selectedCol !== null) ? selectedCol : '';
|
|
364
|
+
const rClass = (!v.optional) ? 'required' : '';
|
|
365
|
+
|
|
366
|
+
return <tr key = {`var-${v.id}`} className = {`${rClass}`}>
|
|
367
|
+
<td className='variable'>
|
|
368
|
+
<p>{v.name} { (!v.optional) ? <span style={{ color: 'red' }}> * </span> : null }</p>
|
|
369
|
+
</td>
|
|
370
|
+
<td>
|
|
371
|
+
<SelectField options={colOpts} value={selectedVal} onChange={(c) => this.onAssociationChange(c, v.id, stillMissingCols)} />
|
|
372
|
+
</td>
|
|
373
|
+
</tr>;
|
|
374
|
+
})
|
|
375
|
+
}
|
|
376
|
+
</tbody>
|
|
377
|
+
</table>
|
|
378
|
+
</div>
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
198
385
|
public render() {
|
|
199
386
|
const {uploadComplete, uploading, downloading, renderedBatch, selectedBatchId} = this.state;
|
|
200
|
-
const {isExport} = this.props;
|
|
387
|
+
const { isExport, batchJobs: { missing, renders } } = this.props;
|
|
201
388
|
|
|
202
389
|
const emailOptions = [
|
|
203
390
|
{
|
|
@@ -214,16 +401,27 @@ class EmailWorkflow extends React.PureComponent<IEmailWorkflowProps, IEmailWorkf
|
|
|
214
401
|
];
|
|
215
402
|
const downloadCsvLabel = (downloading) ? <span><Spinner/> {copy.publish.exporting}</span> : <span>{ICON_DOWNLOAD} {copy.publish.btnDownload}</span>;
|
|
216
403
|
|
|
217
|
-
const
|
|
218
|
-
<
|
|
404
|
+
const reRenderLabel = <div className={'progress-bar'}>
|
|
405
|
+
<progress
|
|
406
|
+
max = {EmailWorkflow.PROGRESS_MAX_VALUE}
|
|
407
|
+
value = {renders[selectedBatchId]}
|
|
408
|
+
/>
|
|
409
|
+
</div>;
|
|
410
|
+
|
|
411
|
+
const downloadCSVDiv = <div>
|
|
219
412
|
<h2>{uploadComplete ? copy.publish.downloadLink : copy.publish.generatingLink}</h2>
|
|
220
413
|
<HRule/>
|
|
221
414
|
<p>{uploadComplete ? copy.publish.downloadDesc : copy.publish.generatingLinkDesc}</p>
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
</div
|
|
415
|
+
|
|
416
|
+
{ isExport && uploadComplete && !renderedBatch ?
|
|
417
|
+
<BigButton label={reRenderLabel} disabled={isExport}/> :
|
|
418
|
+
<BigButton label={downloadCsvLabel} disabled = {downloading} onClick={() => this.downloadCsv()}/>}
|
|
419
|
+
</div>;
|
|
420
|
+
|
|
421
|
+
const downloadCSV = (<>
|
|
422
|
+
{this.props.error ? ( this.props.next ? downloadCSVDiv : '' ) : downloadCSVDiv}
|
|
423
|
+
{this.renderColumnMap()}
|
|
424
|
+
</>
|
|
227
425
|
);
|
|
228
426
|
|
|
229
427
|
const uploadCSV = <div>
|
|
@@ -238,7 +436,6 @@ class EmailWorkflow extends React.PureComponent<IEmailWorkflowProps, IEmailWorkf
|
|
|
238
436
|
onChange={this.doUploadCsv}/>
|
|
239
437
|
<div className = 'link-wrapper'>
|
|
240
438
|
{emailOptions?.map((option, index) => {
|
|
241
|
-
|
|
242
439
|
return <BigButton
|
|
243
440
|
label={<span>{option.label}</span>}
|
|
244
441
|
onClick={option.onClick}
|
|
@@ -248,7 +445,7 @@ class EmailWorkflow extends React.PureComponent<IEmailWorkflowProps, IEmailWorkf
|
|
|
248
445
|
</div>
|
|
249
446
|
</div>;
|
|
250
447
|
|
|
251
|
-
return (isExport ? renderedBatch : uploadComplete) ? downloadCSV : uploadCSV;
|
|
448
|
+
return (( isExport && Object.keys(missing).length === 0 ) ? renderedBatch : uploadComplete) ? downloadCSV : uploadCSV;
|
|
252
449
|
}
|
|
253
450
|
}
|
|
254
451
|
|
|
@@ -256,4 +453,16 @@ const alphaNumeric = (str) => {
|
|
|
256
453
|
return str.replace(/\W/g, '');
|
|
257
454
|
};
|
|
258
455
|
|
|
259
|
-
|
|
456
|
+
const mapDispatchToProps = (dispatch) : any => {
|
|
457
|
+
return bindActionCreators({
|
|
458
|
+
updateAssociation, getBatch, setPage
|
|
459
|
+
}, dispatch);
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
const mapStateToProps = (state) : any => {
|
|
463
|
+
return {
|
|
464
|
+
activeBatch: state.activeBatch,
|
|
465
|
+
batchesList: state.batchesList,
|
|
466
|
+
};
|
|
467
|
+
};
|
|
468
|
+
export default connect(mapStateToProps, mapDispatchToProps, null, { withRef: true })(EmailWorkflow);
|
|
@@ -62,7 +62,7 @@ class SelectField extends React.PureComponent<ISelectFieldProps, {}> {
|
|
|
62
62
|
|
|
63
63
|
public render() {
|
|
64
64
|
|
|
65
|
-
const {label, showCopy,
|
|
65
|
+
const {label, showCopy, options, value, width, buttons, selectRef, disable, tooltip, info, labelPosition, disableFirst} = this.props;
|
|
66
66
|
let opts = [];
|
|
67
67
|
|
|
68
68
|
const selectValue = (value === null || value === undefined) ? '' : value;
|
|
@@ -91,8 +91,7 @@ class SelectField extends React.PureComponent<ISelectFieldProps, {}> {
|
|
|
91
91
|
|
|
92
92
|
if (options) {
|
|
93
93
|
opts = options.map((option , i) => {
|
|
94
|
-
|
|
95
|
-
const disabled = (i === 0 && disableFirst) ? true : false;
|
|
94
|
+
const disabled = (i === 0 && disableFirst || (option.disabled !== undefined && option.disabled)) ? true : false;
|
|
96
95
|
const optionValue = (option.value !== undefined) ? option.value : option;
|
|
97
96
|
const optionLabel = (option.label !== undefined) ? option.label : option;
|
|
98
97
|
return <option disabled = {disabled} key = {`option-${optionValue}`} value = {optionValue}>{optionLabel}</option>;
|
package/constants/copy.ts
CHANGED
|
@@ -138,6 +138,7 @@ export const publish = {
|
|
|
138
138
|
importingData: 'Importing Data... (please wait)',
|
|
139
139
|
downloadDesc: 'Your CSV data file is ready to download with an embed code you can import into your email platform to send out.',
|
|
140
140
|
csvMissingColumns: 'Warning: Some of your column names did not match up with the variables in the story. Please ensure these variables line up and then re-upload the csv: ',
|
|
141
|
+
csvMatchColumns: 'Please match the column(s) provided to the story variables:',
|
|
141
142
|
// export
|
|
142
143
|
exportBatchOfVideo: 'Export batch of videos',
|
|
143
144
|
|
|
@@ -159,6 +160,8 @@ export const publish = {
|
|
|
159
160
|
btnSkip: 'Skip',
|
|
160
161
|
btnBack: 'Back',
|
|
161
162
|
btnFinished: 'Done',
|
|
163
|
+
btnCancel: 'Cancel',
|
|
164
|
+
btnNext: 'Next',
|
|
162
165
|
noCompErrorTitle: 'No Compositions Found',
|
|
163
166
|
noCompErrorDesc: `You must have at least 1 composition on your story to render and distribute videos.`
|
|
164
167
|
};
|