@capillarytech/creatives-library 8.0.102-alpha.0 → 8.0.104

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/config/app.js CHANGED
@@ -17,16 +17,16 @@ const config = {
17
17
  accountConfig: (strs, accountId) => `${window.location.origin}/org/config/AccountAdd?q=a&channelId=2&accountId=${accountId}&edit=1`,
18
18
  },
19
19
  development: {
20
- api_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/arya/api/v1/creatives',
21
- campaigns_api_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/iris/v2/campaigns',
22
- campaigns_api_org_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/iris/v2/org/campaign',
23
- auth_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/arya/api/v1/auth',
24
- arya_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/arya/api/v1',
25
- subscription_api_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/arya/api/v1/org-settings/subscription',
26
- exports_api_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/arya/api/v1/export/data',
20
+ api_endpoint: 'https://devenv-crm.cc.capillarytech.com/arya/api/v1/creatives',
21
+ campaigns_api_endpoint: 'https://devenv-crm.cc.capillarytech.com/iris/v2/campaigns',
22
+ campaigns_api_org_endpoint: 'https://devenv-crm.cc.capillarytech.com/iris/v2/org/campaign',
23
+ auth_endpoint: 'https://devenv-crm.cc.capillarytech.com/arya/api/v1/auth',
24
+ arya_endpoint: 'https://devenv-crm.cc.capillarytech.com/arya/api/v1',
25
+ subscription_api_endpoint: 'https://devenv-crm.cc.capillarytech.com/arya/api/v1/org-settings/subscription',
26
+ exports_api_endpoint: 'https://devenv-crm.cc.capillarytech.com/arya/api/v1/export/data',
27
27
  login_url: '/auth/login',
28
28
  dashboard_url: '/sms',
29
- liquid_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/iris/v2/template',
29
+ liquid_endpoint: 'https://devenv-crm.cc.capillarytech.com/iris/v2/template',
30
30
  dashboard_url_v2: '/v2',
31
31
  },
32
32
  testing: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "8.0.102-alpha.0",
4
+ "version": "8.0.104",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -740,10 +740,7 @@ export class Creatives extends React.Component {
740
740
  forEach(androidContent.custom, (customKeyValue) => {
741
741
  custom[customKeyValue.key] = customKeyValue.value;
742
742
  });
743
- //skipping it for MPUSH as custom key is already in the reqd format for hydra sdk
744
- if (channel !== constants.MOBILE_PUSH) {
745
- androidContent.custom = custom;
746
- }
743
+ androidContent.custom = custom;
747
744
  templateData.androidContent = androidContent;
748
745
  templateData.androidContent.type = get(channelTemplate, 'definition.mode', '').toUpperCase();
749
746
  templateData.androidContent.deviceType = 'ANDROID';
@@ -759,10 +756,7 @@ export class Creatives extends React.Component {
759
756
  forEach(iosContent.custom, (customKeyValue) => {
760
757
  custom[customKeyValue.key] = customKeyValue.value;
761
758
  });
762
- //skipping it for MPUSH as custom key is already in the reqd format for hydra sdk
763
- if (channel !== constants.MOBILE_PUSH) {
764
- iosContent.custom = custom;
765
- }
759
+ iosContent.custom = custom;
766
760
  templateData.iosContent = iosContent;
767
761
  templateData.iosContent.type = get(channelTemplate, 'definition.mode').toUpperCase();
768
762
  templateData.iosContent.deviceType = IOS.toUpperCase();
@@ -2,12 +2,19 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { FormattedMessage } from 'react-intl';
4
4
  import styled from 'styled-components';
5
- import _ from 'lodash';
6
- import { CapRadioCard, CapInput, CapUploader, CapSpin, CapButton, CapError } from '@capillarytech/cap-ui-library';
5
+ import isEmpty from 'lodash/isEmpty';
6
+ import get from 'lodash/get';
7
+ import CapRadioCard from '@capillarytech/cap-ui-library/CapRadioCard';
8
+ import CapInput from '@capillarytech/cap-ui-library/CapInput';
9
+ import CapUploader from '@capillarytech/cap-ui-library/CapUploader';
10
+ import CapSpin from '@capillarytech/cap-ui-library/CapSpin';
11
+ import CapButton from '@capillarytech/cap-ui-library/CapButton';
12
+ import CapError from '@capillarytech/cap-ui-library/CapError';
7
13
  import ComponentWithLabelHOC from '@capillarytech/cap-ui-library/assets/HOCs/ComponentWithLabelHOC';
8
14
  import Email from '../../Email';
9
15
  import CmsTemplatesComponent from '../../../v2Components/CmsTemplatesComponent';
10
16
  import messages from '../messages';
17
+ import { EMAIL_CREATE_MODES, STEPS } from '../constants';
11
18
 
12
19
  const CapRadioCardWithLabel = ComponentWithLabelHOC(CapRadioCard);
13
20
 
@@ -36,7 +43,7 @@ const ModeSelectionUI = ({
36
43
  useFileUpload,
37
44
  uploadButtonLabel,
38
45
  }) => (
39
- <div>
46
+ <>
40
47
  {isFullMode && (
41
48
  <CapInput
42
49
  label={<FormattedMessage {...messages.creativeName} />}
@@ -55,8 +62,8 @@ const ModeSelectionUI = ({
55
62
  label={<FormattedMessage {...messages.createMode} />}
56
63
  />
57
64
  </CardContainer>
58
- <div>
59
- {emailCreateMode === "upload" && (
65
+ <>
66
+ {emailCreateMode === EMAIL_CREATE_MODES.UPLOAD && (
60
67
  <div style={{ marginLeft: '8px' }}>
61
68
  <CapUploader onChange={useFileUpload} accept=".zip, .html, .htm" showUploadList={false}>
62
69
  {(isFullMode && isTemplateNameEmpty) && (
@@ -68,13 +75,13 @@ const ModeSelectionUI = ({
68
75
  {uploadButtonLabel}
69
76
  </CapButton>
70
77
  </CapUploader>
71
- {!_.isEmpty(EmailLayout) && (
72
- <div>{_.get(modeContent, "file.name")}</div>
78
+ {!isEmpty(EmailLayout) && (
79
+ <>{get(modeContent, "file.name")}</>
73
80
  )}
74
81
  </div>
75
82
  )}
76
- </div>
77
- </div>
83
+ </>
84
+ </>
78
85
  );
79
86
 
80
87
  ModeSelectionUI.propTypes = {
@@ -97,13 +104,13 @@ const ContentCreationUI = ({
97
104
  emailProps,
98
105
  cmsTemplatesProps,
99
106
  }) => (
100
- <div>
107
+ <>
101
108
  {isShowEmailCreate ? (
102
109
  <Email {...emailProps} />
103
110
  ) : (
104
111
  <CmsTemplatesComponent {...cmsTemplatesProps} />
105
112
  )}
106
- </div>
113
+ </>
107
114
  );
108
115
 
109
116
  ContentCreationUI.propTypes = {
@@ -131,11 +138,12 @@ const EmailWrapperView = ({
131
138
  emailProps,
132
139
  cmsTemplatesProps,
133
140
  }) => {
134
- const isShowTemplateSelection = step === "modeSelection" || (step === "templateSelection" && emailCreateMode === "upload");
141
+ console.log("EmailLayout", step, emailCreateMode);
142
+ const isShowTemplateSelection = step === STEPS.MODE_SELECTION || (step === STEPS.TEMPLATE_SELECTION && emailCreateMode === EMAIL_CREATE_MODES.UPLOAD);
135
143
 
136
144
  return (
137
- <div>
138
- <CapSpin spinning={emailCreateMode === "upload" ? isUploading : false}>
145
+ <>
146
+ <CapSpin spinning={emailCreateMode === EMAIL_CREATE_MODES.UPLOAD ? isUploading : false}>
139
147
  {isShowTemplateSelection ? (
140
148
  <ModeSelectionUI
141
149
  isFullMode={isFullMode}
@@ -158,7 +166,7 @@ const EmailWrapperView = ({
158
166
  />
159
167
  )}
160
168
  </CapSpin>
161
- </div>
169
+ </>
162
170
  );
163
171
  };
164
172
 
@@ -172,7 +180,7 @@ EmailWrapperView.propTypes = {
172
180
  isTemplateNameEmpty: PropTypes.bool,
173
181
  modes: PropTypes.array.isRequired,
174
182
  onChange: PropTypes.func.isRequired,
175
- EmailLayout: PropTypes.object,
183
+ EmailLayout: PropTypes.string,
176
184
  modeContent: PropTypes.object,
177
185
  useFileUpload: PropTypes.func.isRequired,
178
186
  uploadButtonLabel: PropTypes.node.isRequired,
@@ -4,4 +4,14 @@
4
4
  *
5
5
  */
6
6
 
7
- export const DEFAULT_ACTION = 'app/EmailWrapper/DEFAULT_ACTION';
7
+ export const DEFAULT_ACTION = "app/EmailWrapper/DEFAULT_ACTION";
8
+ export const EMAIL_CREATE_MODES = {
9
+ UPLOAD: "upload",
10
+ EDITOR: "editor",
11
+ };
12
+
13
+ export const STEPS = {
14
+ MODE_SELECTION: "modeSelection",
15
+ TEMPLATE_SELECTION: "templateSelection",
16
+ CREATE_TEMPLATE_CONTENT: "createTemplateContent",
17
+ };
@@ -1,19 +1,20 @@
1
1
  import { useState, useEffect, useMemo, useCallback } from 'react';
2
- import _ from 'lodash';
2
+ import isEmpty from 'lodash/isEmpty';
3
+ import get from 'lodash/get';
3
4
  import { GA } from '@capillarytech/cap-ui-utils';
4
- import { CapNotification } from '@capillarytech/cap-ui-library';
5
+ import CapNotification from '@capillarytech/cap-ui-library/CapNotification';
5
6
  import { CHANNEL_CREATE_TRACK_MAPPING } from '../../App/constants';
6
7
  import { gtmPush } from '../../../utils/gtmTrackers';
7
8
  import { EMAIL } from '../../CreativesContainer/constants';
8
9
  import messages from '../messages';
9
-
10
- const { timeTracker } = GA;
10
+ import { STEPS } from '../constants';
11
+ import { EMAIL_CREATE_MODES } from '../constants';
11
12
 
12
13
  /**
13
14
  * Custom hook to handle EmailWrapper component business logic
14
15
  */
15
16
  const useEmailWrapper = ({
16
- intl,
17
+ intl: { formatMessage },
17
18
  onEmailModeChange,
18
19
  emailCreateMode,
19
20
  step,
@@ -67,33 +68,6 @@ const useEmailWrapper = ({
67
68
  };
68
69
  }, [onResetStep, templatesActions]);
69
70
 
70
- // Main logic effect
71
- useEffect(() => {
72
- if (step === "modeSelection" && !selectedCreateMode && emailCreateMode === 'upload' && !EmailLayout) {
73
- //document.getElementById('upload-email-template').click();
74
- } else if (step === "templateSelection" && !selectedCreateMode) {
75
- if (emailCreateMode === "editor" && !CmsTemplates && !getCmsTemplatesInProgress) {
76
- templatesActions.getDefaultBeeTemplates();
77
- }
78
- } else if (step === "createTemplateContent" && !selectedCreateMode) {
79
- if (emailCreateMode === 'upload' && !_.isEmpty(EmailLayout)) {
80
- setSelectedCreateMode('upload');
81
- } else if (emailCreateMode === "editor" && _.isEmpty(SelectedEdmDefaultTemplate)) {
82
- handleEdmDefaultTemplateSelection(modeContent.id);
83
- }
84
- }
85
- }, [
86
- step,
87
- selectedCreateMode,
88
- emailCreateMode,
89
- EmailLayout,
90
- CmsTemplates,
91
- getCmsTemplatesInProgress,
92
- modeContent.id,
93
- SelectedEdmDefaultTemplate,
94
- templatesActions
95
- ]);
96
-
97
71
  // Event handlers
98
72
  const onTemplateNameChange = useCallback(({target: {value}}) => {
99
73
  const isEmptyTemplateName = !value?.trim();
@@ -114,14 +88,14 @@ const useEmailWrapper = ({
114
88
  const handleZipUploadError = useCallback(() => {
115
89
  const message = {
116
90
  key: "email-upload-error",
117
- message: intl.formatMessage(messages.invalidUploadFileError2),
118
- description: intl.formatMessage(messages.invalidUploadFileErrorDesc2),
91
+ message: formatMessage(messages.invalidUploadFileError2),
92
+ description: formatMessage(messages.invalidUploadFileErrorDesc2),
119
93
  };
120
94
  CapNotification.error(message);
121
- }, [intl]);
95
+ }, [formatMessage]);
122
96
 
123
97
  const stopTimerGA = useCallback(() => {
124
- const timeTaken = timeTracker.stopTimer(CHANNEL_CREATE_TRACK_MAPPING.email, {
98
+ const timeTaken = GA.timeTracker.stopTimer(CHANNEL_CREATE_TRACK_MAPPING.email, {
125
99
  category: 'Creatives',
126
100
  action: 'Create',
127
101
  label: 'uploadZip',
@@ -131,54 +105,85 @@ const useEmailWrapper = ({
131
105
  timeTaken,
132
106
  mode: 'uploadZip',
133
107
  });
134
- }, []);
108
+ }, [formatMessage]);
135
109
 
136
110
  const handleFileUpload = useCallback((file = {}) => {
137
111
  if (!isUploading) {
138
- const fileExtension = file.name.split('.').pop();
112
+ // Validate file object
113
+ if (!file || !file.name) {
114
+ const message = {
115
+ key: "email-upload-error",
116
+ message: formatMessage(messages.invalidUploadFileError),
117
+ description: formatMessage(messages.invalidUploadFileErrorDesc3),
118
+ };
119
+ CapNotification.error(message);
120
+ return;
121
+ }
122
+
123
+ const fileExtension = (file.name || '').split('.').pop().toLowerCase();
139
124
  const supportedZipFormats = ['zip'];
140
125
 
141
- // Converted file size to MB
142
- const fileSize = file && (file.size / (1024 * 1024));
126
+ // Converted file size to MB - added defensive check
127
+ const fileSize = file && file.size ? (file.size / (1024 * 1024)) : 0;
143
128
 
144
129
  // Here fileSize is in MB
145
130
  if (fileSize > 5) {
146
131
  const message = {
147
132
  key: "email-upload-error",
148
- message: intl.formatMessage(messages.invalidUploadFileError),
149
- description: intl.formatMessage(messages.invalidUploadFileErrorDesc3),
133
+ message: formatMessage(messages.invalidUploadFileError),
134
+ description: formatMessage(messages.invalidUploadFileErrorDesc3),
150
135
  };
151
136
  CapNotification.error(message);
152
- } else if (supportedZipFormats.indexOf(fileExtension.toLowerCase()) !== -1) {
137
+ } else if (supportedZipFormats.includes(fileExtension)) {
138
+ // Verify originFileObj exists
139
+ if (!file.originFileObj) {
140
+ handleZipUploadError();
141
+ return;
142
+ }
143
+
153
144
  templatesActions.handleZipUpload(file.originFileObj, () => { // Handle upload success
154
145
  stopTimerGA();
155
146
  setModeContent({ file });
156
147
  showNextStep();
157
148
  }, handleZipUploadError);
158
149
  } else if (fileExtension === 'html' || fileExtension === 'htm') {
150
+ // Verify originFileObj exists
151
+ if (!file.originFileObj) {
152
+ handleZipUploadError();
153
+ return;
154
+ }
155
+
159
156
  const reader = new FileReader();
160
157
  reader.onload = () => {
161
158
  const text = reader.result;
159
+ // Add defensive check for empty or invalid content
160
+ if (!text || typeof text !== 'string') {
161
+ handleZipUploadError();
162
+ return;
163
+ }
162
164
  setModeContent({ file });
163
165
  templatesActions.handleHtmlUpload(text);
164
166
  };
167
+ reader.onerror = () => {
168
+ handleZipUploadError();
169
+ };
165
170
  reader.readAsText(file.originFileObj);
166
171
  } else {
167
172
  const message = {
168
173
  key: "email-upload-error",
169
- message: intl.formatMessage(messages.invalidUploadFileError),
170
- description: intl.formatMessage(messages.invalidUploadFileErrorDesc),
174
+ message: formatMessage(messages.invalidUploadFileError),
175
+ description: formatMessage(messages.invalidUploadFileErrorDesc),
171
176
  };
172
177
  CapNotification.error(message);
173
178
  }
174
179
  }
175
- }, [isUploading, intl, templatesActions, stopTimerGA, handleZipUploadError, showNextStep]);
180
+ }, [isUploading, formatMessage, templatesActions, stopTimerGA, handleZipUploadError, showNextStep]);
176
181
 
177
182
  const handleEdmDefaultTemplateSelection = useCallback((id) => {
178
- const data = _.find(CmsTemplates, { _id: id });
183
+ const data = find(CmsTemplates, { _id: id });
179
184
  templatesActions.setEdmTemplate(data);
180
185
  templatesActions.setBEETemplate(data);
181
- setSelectedCreateMode('editor');
186
+ setSelectedCreateMode(EMAIL_CREATE_MODES.EDITOR);
182
187
  }, [CmsTemplates, templatesActions]);
183
188
 
184
189
  const useFileUpload = useCallback(({ file }) => {
@@ -191,22 +196,70 @@ const useEmailWrapper = ({
191
196
  showNextStep();
192
197
  }, [showNextStep]);
193
198
 
199
+ // Main logic effect - MOVED AFTER function declarations
200
+ useEffect(() => {
201
+ // Skip if user has already made a selection
202
+ if (selectedCreateMode) return;
203
+
204
+ // Handle different steps
205
+ switch (step) {
206
+ case STEPS.MODE_SELECTION:
207
+ if (emailCreateMode === EMAIL_CREATE_MODES.UPLOAD && !EmailLayout) {
208
+ // Commented out: document.getElementById('upload-email-template').click();
209
+ }
210
+ break;
211
+
212
+ case STEPS.TEMPLATE_SELECTION:
213
+ const needsTemplates = emailCreateMode === EMAIL_CREATE_MODES.EDITOR
214
+ && !CmsTemplates
215
+ && !getCmsTemplatesInProgress;
216
+
217
+ if (needsTemplates) {
218
+ templatesActions.getDefaultBeeTemplates();
219
+ }
220
+ break;
221
+
222
+ case STEPS.CREATE_TEMPLATE_CONTENT:
223
+ if (emailCreateMode === EMAIL_CREATE_MODES.UPLOAD && !isEmpty(EmailLayout)) {
224
+ setSelectedCreateMode(EMAIL_CREATE_MODES.UPLOAD);
225
+ } else if (emailCreateMode === EMAIL_CREATE_MODES.EDITOR && isEmpty(SelectedEdmDefaultTemplate)) {
226
+ handleEdmDefaultTemplateSelection(modeContent.id);
227
+ }
228
+ break;
229
+
230
+ default:
231
+ // No operation for other steps
232
+ break;
233
+ }
234
+ }, [
235
+ step,
236
+ selectedCreateMode,
237
+ emailCreateMode,
238
+ EmailLayout,
239
+ CmsTemplates,
240
+ getCmsTemplatesInProgress,
241
+ modeContent.id,
242
+ SelectedEdmDefaultTemplate,
243
+ templatesActions,
244
+ handleEdmDefaultTemplateSelection
245
+ ]);
246
+
194
247
  // Derived state
195
- const isShowEmailCreate = !_.isEmpty(selectedCreateMode) && (!_.isEmpty(EmailLayout) || SelectedEdmDefaultTemplate);
248
+ const isShowEmailCreate = !isEmpty(selectedCreateMode) && (!isEmpty(EmailLayout) || SelectedEdmDefaultTemplate);
196
249
 
197
250
  // Memoize static data
198
251
  const modes = useMemo(() => [
199
252
  {
200
- title: intl.formatMessage(messages.zipUpload),
201
- content: intl.formatMessage(messages.zipUploadDesc),
202
- value: 'upload',
253
+ title: formatMessage(messages.zipUpload),
254
+ content: formatMessage(messages.zipUploadDesc),
255
+ value: EMAIL_CREATE_MODES.UPLOAD,
203
256
  },
204
257
  {
205
- title: intl.formatMessage(messages.useEditor),
206
- content: intl.formatMessage(messages.useEditorDesc),
207
- value: 'editor',
258
+ title: formatMessage(messages.useEditor),
259
+ content: formatMessage(messages.useEditorDesc),
260
+ value: EMAIL_CREATE_MODES.EDITOR,
208
261
  },
209
- ], [intl]);
262
+ ], [formatMessage]);
210
263
 
211
264
  // Prepare props for Email component
212
265
  const emailProps = useMemo(() => ({
@@ -264,7 +317,7 @@ const useEmailWrapper = ({
264
317
  }), [CmsTemplates, useEditor, cmsTemplatesLoader, currentOrgDetails, cap]);
265
318
 
266
319
  // Upload button label
267
- const uploadButtonLabel = intl.formatMessage(messages.upload);
320
+ const uploadButtonLabel = formatMessage(messages.upload);
268
321
 
269
322
  return {
270
323
  // State
@@ -23,7 +23,41 @@ import EmailWrapperView from './components/EmailWrapperView';
23
23
  import useEmailWrapper from './hooks/useEmailWrapper';
24
24
 
25
25
  const EmailWrapper = (props) => {
26
- // Pass all props to the custom hook
26
+ // Destructure props for clarity before passing to hook
27
+ const {
28
+ emailCreateMode,
29
+ step,
30
+ isFullMode,
31
+ EmailLayout,
32
+ isUploading,
33
+ onEmailModeChange,
34
+ isGetFormData,
35
+ type,
36
+ templatesActions,
37
+ CmsTemplates,
38
+ SelectedEdmDefaultTemplate,
39
+ showNextStep,
40
+ getFormdata,
41
+ intl,
42
+ cap,
43
+ onResetStep,
44
+ setIsLoadingContent,
45
+ showTemplateName,
46
+ showLiquidErrorInFooter,
47
+ onValidationFail,
48
+ forwardedTags,
49
+ selectedOfferDetails,
50
+ getCmsTemplatesInProgress,
51
+ currentOrgDetails,
52
+ moduleType,
53
+ onEnterTemplateName,
54
+ onRemoveTemplateName,
55
+ eventContextTags,
56
+ isLoyaltyModule,
57
+ cmsTemplatesLoader
58
+ } = props;
59
+
60
+ // Pass destructured props to the custom hook
27
61
  const {
28
62
  templateName,
29
63
  isTemplateNameEmpty,
@@ -36,21 +70,52 @@ const EmailWrapper = (props) => {
36
70
  onTemplateNameChange,
37
71
  onChange,
38
72
  useFileUpload,
39
- } = useEmailWrapper(props);
73
+ } = useEmailWrapper({
74
+ emailCreateMode,
75
+ step,
76
+ isFullMode,
77
+ EmailLayout,
78
+ isUploading,
79
+ onEmailModeChange,
80
+ isGetFormData,
81
+ type,
82
+ templatesActions,
83
+ CmsTemplates,
84
+ SelectedEdmDefaultTemplate,
85
+ showNextStep,
86
+ getFormdata,
87
+ intl,
88
+ cap,
89
+ onResetStep,
90
+ setIsLoadingContent,
91
+ showTemplateName,
92
+ showLiquidErrorInFooter,
93
+ onValidationFail,
94
+ forwardedTags,
95
+ selectedOfferDetails,
96
+ getCmsTemplatesInProgress,
97
+ currentOrgDetails,
98
+ moduleType,
99
+ onEnterTemplateName,
100
+ onRemoveTemplateName,
101
+ eventContextTags,
102
+ isLoyaltyModule,
103
+ cmsTemplatesLoader
104
+ });
40
105
 
41
106
  // Render using the presentation component with data from the hook
42
107
  return (
43
108
  <EmailWrapperView
44
- isUploading={props.isUploading}
45
- emailCreateMode={props.emailCreateMode}
46
- step={props.step}
47
- isFullMode={props.isFullMode}
109
+ isUploading={isUploading}
110
+ emailCreateMode={emailCreateMode}
111
+ step={step}
112
+ isFullMode={isFullMode}
48
113
  templateName={templateName}
49
114
  onTemplateNameChange={onTemplateNameChange}
50
115
  isTemplateNameEmpty={isTemplateNameEmpty}
51
116
  modes={modes}
52
117
  onChange={onChange}
53
- EmailLayout={props.EmailLayout}
118
+ EmailLayout={EmailLayout}
54
119
  modeContent={modeContent}
55
120
  useFileUpload={useFileUpload}
56
121
  uploadButtonLabel={uploadButtonLabel}