@capillarytech/creatives-library 9.0.70-alpha.sprint-cap-213712.13 → 9.0.70

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.
Files changed (39) hide show
  1. package/package.json +1 -1
  2. package/v2Components/FormBuilder/Classic.js +3 -0
  3. package/v2Containers/CreativesContainer/SlideBoxContent.js +39 -30
  4. package/v2Containers/CreativesContainer/SlideBoxFooter.js +6 -2
  5. package/v2Containers/CreativesContainer/constants.js +1 -0
  6. package/v2Containers/CreativesContainer/index.js +26 -1
  7. package/v2Containers/CreativesContainer/messages.js +4 -0
  8. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +40 -12
  9. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +10 -0
  10. package/v2Containers/CreativesContainer/tests/switchToEditAfterCreate.test.js +152 -0
  11. package/v2Containers/Email/index.js +41 -6
  12. package/v2Containers/Email/tests/index.test.js +123 -0
  13. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +32 -12
  14. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +34 -0
  15. package/v2Containers/InApp/index.js +19 -23
  16. package/v2Containers/InApp/tests/index.test.js +52 -9
  17. package/v2Containers/InappAdvance/index.js +19 -24
  18. package/v2Containers/InappAdvance/tests/index.test.js +39 -15
  19. package/v2Containers/Line/Container/index.js +18 -8
  20. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +129 -108
  21. package/v2Containers/Line/Container/tests/index.test.js +68 -0
  22. package/v2Containers/MobilePush/Create/index.js +24 -5
  23. package/v2Containers/MobilePush/Create/test/stayOpenOnSave.test.js +80 -0
  24. package/v2Containers/MobilePush/Edit/index.js +15 -9
  25. package/v2Containers/MobilePush/Edit/test/stayOpenOnSave.test.js +60 -0
  26. package/v2Containers/MobilePushNew/index.js +41 -7
  27. package/v2Containers/MobilePushNew/tests/index.test.js +61 -0
  28. package/v2Containers/Sms/Create/index.js +32 -14
  29. package/v2Containers/Sms/Create/test/stayOpenOnSave.test.js +92 -0
  30. package/v2Containers/Sms/Edit/index.js +22 -14
  31. package/v2Containers/Sms/Edit/tests/index.test.js +66 -0
  32. package/v2Containers/Templates/index.js +17 -4
  33. package/v2Containers/Viber/index.js +15 -6
  34. package/v2Containers/Viber/tests/index.test.js +97 -28
  35. package/v2Containers/WebPush/Create/components/FormActions.js +1 -1
  36. package/v2Containers/WebPush/Create/components/FormActions.test.js +3 -3
  37. package/v2Containers/WebPush/Create/index.js +32 -6
  38. package/v2Containers/WebPush/Create/messages.js +0 -4
  39. package/v2Containers/WebPush/Create/tests/stayOpenOnSave.test.js +268 -0
@@ -6,6 +6,7 @@ import { createStructuredSelector } from 'reselect';
6
6
  import { injectIntl, FormattedMessage } from 'react-intl';
7
7
  import isEmpty from 'lodash/isEmpty';
8
8
  import get from 'lodash/get';
9
+ import isPlainObject from 'lodash/isPlainObject';
9
10
  import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
10
11
  import CapRow from '@capillarytech/cap-ui-library/CapRow';
11
12
  import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
@@ -133,7 +134,6 @@ export const Viber = (props) => {
133
134
  metaEntities,
134
135
  globalActions: globalActionsProps,
135
136
  handleClose,
136
- onCreateComplete,
137
137
  params,
138
138
  templateData = EMPTY_TEMPLATE_DATA,
139
139
  actions,
@@ -158,6 +158,8 @@ export const Viber = (props) => {
158
158
  const [errorMessageTextarea, updateErrorMessageTextArea] = useState(false);
159
159
  const [isEditLoading, updateEditLoading] = useState(false);
160
160
  const [isEditFlow, checkEditFlow] = useState(false);
161
+ // Full mode: id of the template created in this session — the form stays as is and later saves update it
162
+ const [savedTemplateId, setSavedTemplateId] = useState('');
161
163
  const [messageTitle, updateTextMessageTitle] = useState("");
162
164
  const [errorMessageTitle, updateErrorMessageTitle] = useState(false);
163
165
  const [buttonURLErrorMessage, updateButtonURLErrorMessage] = useState(false);
@@ -1432,13 +1434,19 @@ export const Viber = (props) => {
1432
1434
  }
1433
1435
  };
1434
1436
 
1437
+ // Full mode stays open; a create continues in place as an edit.
1435
1438
  const onCreateViber = () => {
1436
1439
  actions.createTemplate(
1437
1440
  formatSubmitPayload(),
1438
1441
  (resp, errorMessage) => {
1439
1442
  createCallback({resp, errorMessage});
1440
1443
  if (!errorMessage) {
1441
- onCreateComplete();
1444
+ const savedResponse = resp?.templateId;
1445
+ const newTemplateId = (isPlainObject(savedResponse) ? savedResponse._id : savedResponse) || '';
1446
+ setSavedTemplateId(newTemplateId);
1447
+ getFormSubscriptionData({
1448
+ _id: newTemplateId, validity: true, keepSlideBoxOpen: true, continuedAsEdit: true,
1449
+ });
1442
1450
  }
1443
1451
  }
1444
1452
  );
@@ -1448,12 +1456,12 @@ export const Viber = (props) => {
1448
1456
  actions.editTemplate(
1449
1457
  {
1450
1458
  ...formatSubmitPayload(),
1451
- _id: params.id,
1459
+ _id: params?.id || savedTemplateId,
1452
1460
  },
1453
1461
  (resp, errorMessage) => {
1454
1462
  createCallback({resp, errorMessage}, true);
1455
1463
  if (!errorMessage) {
1456
- onCreateComplete();
1464
+ getFormSubscriptionData({ validity: true, keepSlideBoxOpen: true });
1457
1465
  }
1458
1466
  }
1459
1467
  );
@@ -1461,7 +1469,7 @@ export const Viber = (props) => {
1461
1469
 
1462
1470
  const onDoneCallback = () => {
1463
1471
  if (isFullMode) {
1464
- if (isEditFlow) {
1472
+ if (isEditFlow || savedTemplateId) {
1465
1473
  return onEditViber;
1466
1474
  }
1467
1475
  return onCreateViber;
@@ -1574,7 +1582,8 @@ export const Viber = (props) => {
1574
1582
  disabled={isDisableDone()}
1575
1583
  className="create-msg viber-create-msg"
1576
1584
  >
1577
- <FormattedMessage {...messages.doneButtonLabel} />
1585
+ {/* Full mode saves without closing, so the button reads "Save" for create and edit */}
1586
+ <FormattedMessage {...(isFullMode ? messages.save : messages.doneButtonLabel)} />
1578
1587
  </CapButton>
1579
1588
  <CapButton
1580
1589
  onClick={handleTestAndPreview}
@@ -44,6 +44,21 @@ const renderComponent = (props) =>
44
44
  </Provider>,
45
45
  );
46
46
 
47
+ // Full mode labels the main Viber button "Save" (same text as the CTA / carousel-button "Save"),
48
+ // so tell them apart by the main button's class.
49
+ const MAIN_BUTTON_CLASS = 'viber-create-msg';
50
+ const isMainButton = (btn) => btn.classList.contains(MAIN_BUTTON_CLASS);
51
+ const getMainButton = () => screen.getAllByRole('button', { name: /^(save|done)$/i }).find(isMainButton);
52
+ const findMainButton = async () => {
53
+ await screen.findAllByRole('button', { name: /^(save|done)$/i });
54
+ return getMainButton();
55
+ };
56
+ const getOtherSaveButton = () => screen.getAllByRole('button', { name: /^save$/i }).find((btn) => !isMainButton(btn));
57
+ const findOtherSaveButton = async () => {
58
+ await waitFor(() => expect(getOtherSaveButton()).toBeTruthy());
59
+ return getOtherSaveButton();
60
+ };
61
+
47
62
  describe('Test Viber container', () => {
48
63
  it('test case for Viber template creation flow', async () => {
49
64
  renderComponent({
@@ -110,18 +125,14 @@ describe('Test Viber container', () => {
110
125
  fireEvent.change(ctaBtnUrl2, { target: { value: 'not url' } });
111
126
  ctaBtnUrl2 = screen.getByPlaceholderText('Enter button url');
112
127
  fireEvent.change(ctaBtnUrl2, { target: { value: 'https://www.test.com' } });
113
- const saveBtn = await screen.findByRole('button', {
114
- name: /save/i,
115
- });
128
+ const saveBtn = await findOtherSaveButton();
116
129
  await waitFor(() => expect(saveBtn).toBeEnabled());
117
130
  fireEvent.click(saveBtn);
118
131
  const editCta = await screen.findByLabelText(/edit-cta-icon/i);
119
132
  fireEvent.click(editCta);
120
133
  const cancelBtn = screen.getAllByRole('button', {name: /cancel/i});
121
134
  fireEvent.click(cancelBtn[0]);
122
- const doneBtn = await screen.findByRole('button', {
123
- name: /done/i,
124
- });
135
+ const doneBtn = await findMainButton();
125
136
  await waitFor(() => expect(doneBtn).toBeEnabled());
126
137
  fireEvent.click(doneBtn);
127
138
  expect(mockActions.createTemplate).toHaveBeenCalled();
@@ -148,9 +159,7 @@ describe('Test Viber container', () => {
148
159
  params: { id: 'test'},
149
160
  handleClose: jest.fn(),
150
161
  });
151
- const doneBtn = screen.getByRole('button', {
152
- name: /done/i,
153
- });
162
+ const doneBtn = getMainButton();
154
163
  expect(doneBtn).toBeEnabled();
155
164
  fireEvent.click(doneBtn);
156
165
  expect(mockActions.editTemplate).toHaveBeenCalled();
@@ -181,9 +190,7 @@ describe('Test Viber container', () => {
181
190
  name: /reupload/i,
182
191
  });
183
192
  fireEvent.click(reupload);
184
- const doneBtn = screen.getByRole('button', {
185
- name: /done/i,
186
- });
193
+ const doneBtn = getMainButton();
187
194
  expect(doneBtn).toBeDisabled();
188
195
  });
189
196
  it('test case for Viber template creation flow for video media type', async () => {
@@ -211,9 +218,7 @@ describe('Test Viber container', () => {
211
218
  getDefaultTags,
212
219
  injectedTags,
213
220
  });
214
- const doneBtn = screen.getByRole('button', {
215
- name: /done/i,
216
- });
221
+ const doneBtn = getMainButton();
217
222
  expect(doneBtn).toBeEnabled();
218
223
  fireEvent.click(doneBtn);
219
224
  expect(mockActions.editTemplate).toHaveBeenCalled();
@@ -243,9 +248,7 @@ describe('Test Viber container', () => {
243
248
  getDefaultTags,
244
249
  injectedTags,
245
250
  });
246
- const doneBtn = screen.getByRole('button', {
247
- name: /done/i,
248
- });
251
+ const doneBtn = getMainButton();
249
252
  expect(doneBtn).toBeEnabled();
250
253
  fireEvent.click(doneBtn);
251
254
  expect(mockActions.editTemplate).toHaveBeenCalled();
@@ -278,9 +281,7 @@ describe('Test Viber container', () => {
278
281
  name: /re upload/i,
279
282
  });
280
283
  fireEvent.click(reupload);
281
- const doneBtn = screen.getByRole('button', {
282
- name: /done/i,
283
- });
284
+ const doneBtn = getMainButton();
284
285
  expect(doneBtn).toBeDisabled();
285
286
  });
286
287
  it('test case for Viber template for error cases', async () => {
@@ -304,9 +305,7 @@ describe('Test Viber container', () => {
304
305
  params: { id: 'test'},
305
306
  handleClose: jest.fn(),
306
307
  });
307
- const doneBtn = screen.getByRole('button', {
308
- name: /done/i,
309
- });
308
+ const doneBtn = getMainButton();
310
309
  expect(doneBtn).toBeDisabled();
311
310
  });
312
311
 
@@ -334,7 +333,7 @@ describe('Test Viber container', () => {
334
333
  getDefaultTags,
335
334
  injectedTags,
336
335
  });
337
- const doneBtn = screen.getByRole('button', { name: /done/i });
336
+ const doneBtn = getMainButton();
338
337
  expect(doneBtn).toBeDisabled();
339
338
  });
340
339
 
@@ -358,7 +357,7 @@ describe('Test Viber container', () => {
358
357
  params: { id: 'test' },
359
358
  handleClose: jest.fn(),
360
359
  });
361
- const doneBtn = screen.getByRole('button', { name: /done/i });
360
+ const doneBtn = getMainButton();
362
361
  expect(doneBtn).toBeDisabled();
363
362
  });
364
363
 
@@ -386,7 +385,7 @@ describe('Test Viber container', () => {
386
385
  getDefaultTags,
387
386
  injectedTags,
388
387
  });
389
- const doneBtn = screen.getByRole('button', { name: /done/i });
388
+ const doneBtn = getMainButton();
390
389
  expect(doneBtn).toBeEnabled();
391
390
  });
392
391
 
@@ -465,7 +464,7 @@ describe('Test Viber container', () => {
465
464
 
466
465
  fireEvent.click(screen.getByRole('radio', { name: /carousel/i }));
467
466
  await screen.findByPlaceholderText('https://example.com/action');
468
- fireEvent.click(screen.getByRole('button', { name: /save/i }));
467
+ fireEvent.click(getOtherSaveButton());
469
468
 
470
469
  expect(await screen.findByText("URL can't be empty")).toBeInTheDocument();
471
470
  });
@@ -573,3 +572,73 @@ describe('Test Viber container', () => {
573
572
  });
574
573
  });
575
574
  });
575
+
576
+ describe('Viber — full mode keeps the slidebox open after saving', () => {
577
+ const buildProps = (overrides = {}) => ({
578
+ actions: {
579
+ ...mockActions,
580
+ createTemplate: jest.fn(),
581
+ editTemplate: jest.fn(),
582
+ clearCreateResponse: jest.fn(),
583
+ clearEditResponse: jest.fn(),
584
+ },
585
+ globalActions: mockGlobalActions,
586
+ templateData: { mode: 'create' },
587
+ viber: { uploadedAssetData: {}, createTemplateInProgress: false },
588
+ location: { pathname: '/viber/create', query: { type: false, module: 'default' }, search: '' },
589
+ isFullMode: true,
590
+ handleClose: jest.fn(),
591
+ onCreateComplete: jest.fn(),
592
+ getFormSubscriptionData: jest.fn(),
593
+ metaEntities,
594
+ getDefaultTags,
595
+ injectedTags,
596
+ ...overrides,
597
+ });
598
+
599
+ it('labels the main button "Save" in full mode and "Done" in library mode', async () => {
600
+ const { unmount } = renderComponent(buildProps());
601
+ expect((await findMainButton()).textContent).toMatch(/^save$/i);
602
+ unmount();
603
+ renderComponent(buildProps({ isFullMode: false }));
604
+ expect((await findMainButton()).textContent).toMatch(/^done$/i);
605
+ });
606
+
607
+ it('create: stays open (header switches) and the next save updates the created template', async () => {
608
+ const props = buildProps();
609
+ renderComponent(props);
610
+ fireEvent.change((await screen.findAllByPlaceholderText('Enter template name'))[0], { target: { value: 'Promo' } });
611
+ fireEvent.change(screen.getAllByPlaceholderText(/Enter message/i)[0], { target: { value: 'Hello there' } });
612
+
613
+ fireEvent.click(getMainButton());
614
+ expect(props.actions.createTemplate).toHaveBeenCalledTimes(1);
615
+ props.actions.createTemplate.mock.calls[0][1]({ templateId: { _id: 'vb-1' } });
616
+
617
+ expect(props.getFormSubscriptionData).toHaveBeenCalledWith({
618
+ _id: 'vb-1', validity: true, keepSlideBoxOpen: true, continuedAsEdit: true,
619
+ });
620
+ expect(props.onCreateComplete).not.toHaveBeenCalled();
621
+ expect(props.handleClose).not.toHaveBeenCalled();
622
+
623
+ await waitFor(() => expect(getMainButton()).toBeEnabled());
624
+ fireEvent.click(getMainButton());
625
+ expect(props.actions.createTemplate).toHaveBeenCalledTimes(1);
626
+ expect(props.actions.editTemplate).toHaveBeenCalledTimes(1);
627
+ expect(props.actions.editTemplate.mock.calls[0][0]._id).toBe('vb-1');
628
+ });
629
+
630
+ it('edit: stays open after a successful update', async () => {
631
+ const props = buildProps({
632
+ params: { id: 'vb-9' },
633
+ viber: { uploadedAssetData: {}, createTemplateInProgress: false, templateDetails: templateDetailsText },
634
+ });
635
+ renderComponent(props);
636
+
637
+ fireEvent.click(await findMainButton());
638
+ expect(props.actions.editTemplate.mock.calls[0][0]._id).toBe('vb-9');
639
+ props.actions.editTemplate.mock.calls[0][1]({ templateId: { _id: 'vb-9' } });
640
+
641
+ expect(props.getFormSubscriptionData).toHaveBeenCalledWith({ validity: true, keepSlideBoxOpen: true });
642
+ expect(props.onCreateComplete).not.toHaveBeenCalled();
643
+ });
644
+ });
@@ -18,7 +18,7 @@ export const FormActions = ({
18
18
  <>
19
19
  <CapRow useLegacy className="creatives-webpush-actions">
20
20
  <CapButton type="primary" onClick={onSave} disabled={isSaveDisabled}>
21
- {formatMessage(messages.saveTemplate)}
21
+ {formatMessage(messages.saveButton)}
22
22
  </CapButton>
23
23
  </CapRow>
24
24
  {errorText && (
@@ -10,8 +10,8 @@ describe('FormActions', () => {
10
10
  const mockOnSave = jest.fn();
11
11
 
12
12
  const mockMessages = {
13
- saveTemplate: {
14
- defaultMessage: 'Save Template',
13
+ saveButton: {
14
+ defaultMessage: 'Save',
15
15
  },
16
16
  };
17
17
 
@@ -46,7 +46,7 @@ describe('FormActions', () => {
46
46
  const wrapper = mountWithIntl(<FormActions {...defaultProps} />);
47
47
  const saveButton = wrapper.find(CapButton);
48
48
  expect(saveButton.exists()).toBe(true);
49
- expect(mockFormatMessage).toHaveBeenCalledWith(mockMessages.saveTemplate);
49
+ expect(mockFormatMessage).toHaveBeenCalledWith(mockMessages.saveButton);
50
50
  });
51
51
 
52
52
  it('should disable save button when isSaveDisabled is true', () => {
@@ -32,6 +32,7 @@ import { useImageUpload } from './hooks/useImageUpload';
32
32
  import { useTagManagement } from './hooks/useTagManagement';
33
33
  import isEmpty from 'lodash/isEmpty';
34
34
  import get from 'lodash/get';
35
+ import isPlainObject from 'lodash/isPlainObject';
35
36
  import * as templateActions from '../../Templates/actions';
36
37
  import { makeSelectTemplates } from '../../Templates/selectors';
37
38
 
@@ -165,8 +166,13 @@ const WebPushCreate = ({
165
166
  Templates,
166
167
  restrictPersonalization = false,
167
168
  onContentValidityChange,
169
+ canStayOpenAfterCreate = false,
170
+ onCreateContinuedAsEdit,
168
171
  }) => {
169
172
  const { formatMessage } = intl;
173
+ // Full mode stays open after saving; creates only with edit permission.
174
+ const stayOpenAfterSave = !!isFullMode;
175
+ const stayOpenAfterCreate = !!isFullMode && !!canStayOpenAfterCreate;
170
176
  const aiContentBotDisabled = isAiContentBotDisabled();
171
177
 
172
178
  // Form state - kept in main component for now
@@ -189,6 +195,8 @@ const WebPushCreate = ({
189
195
  const [activeUploadField, setActiveUploadField] = useState(null);
190
196
  const [templateIdError, setTemplateIdError] = useState('');
191
197
  const [showTestAndPreviewSlidebox, setShowTestAndPreviewSlidebox] = useState(false);
198
+ // Full mode: id of the template created in this session — the form stays as is and later saves update it
199
+ const [savedTemplateId, setSavedTemplateId] = useState('');
192
200
 
193
201
  // Refs
194
202
  const titleCountRef = useRef(null);
@@ -708,10 +716,10 @@ const WebPushCreate = ({
708
716
  return;
709
717
  }
710
718
 
711
- // Full mode: proceed with API calls
712
- if (isEditMode) {
713
- // Get template ID from params or templateData
714
- const templateId = params?.id || templateData?._id;
719
+ // Full mode: proceed with API calls. A template created earlier in this session is updated too.
720
+ if (isEditMode || savedTemplateId) {
721
+ // Get template ID from params or templateData (or the in-session created template)
722
+ const templateId = params?.id || templateData?._id || savedTemplateId;
715
723
  if (templateId) {
716
724
  // Clear any previous template ID error
717
725
  setTemplateIdError('');
@@ -725,6 +733,10 @@ const WebPushCreate = ({
725
733
  // Clear flag before calling callbacks to prevent double-invocation
726
734
  // from the editResponse useEffect
727
735
  saveInitiatedRef.current = false;
736
+ // Stays open (host shows the toast and refreshes its list from the edit response)
737
+ if (stayOpenAfterSave) {
738
+ return;
739
+ }
728
740
  if (onCreateComplete) {
729
741
  onCreateComplete(true);
730
742
  }
@@ -769,6 +781,15 @@ const WebPushCreate = ({
769
781
  ) {
770
782
  // Reset flag after handling response
771
783
  saveInitiatedRef.current = false;
784
+ if (stayOpenAfterCreate) {
785
+ // Stay open: next save updates this template.
786
+ const savedResponse = response.templateId || response._id;
787
+ setSavedTemplateId((isPlainObject(savedResponse) ? savedResponse._id : savedResponse) || '');
788
+ if (onCreateContinuedAsEdit) {
789
+ onCreateContinuedAsEdit(); // host switches the header to the edit title
790
+ }
791
+ return;
792
+ }
772
793
  if (onCreateComplete) {
773
794
  onCreateComplete(true);
774
795
  }
@@ -776,7 +797,7 @@ const WebPushCreate = ({
776
797
  handleClose();
777
798
  }
778
799
  }
779
- }, [webPush?.response, onCreateComplete, handleClose, isEditMode]);
800
+ }, [webPush?.response, onCreateComplete, handleClose, isEditMode, stayOpenAfterCreate, onCreateContinuedAsEdit]);
780
801
 
781
802
  // Handle edit response
782
803
  useEffect(() => {
@@ -789,6 +810,9 @@ const WebPushCreate = ({
789
810
  ) {
790
811
  // Reset flag after handling response
791
812
  saveInitiatedRef.current = false;
813
+ if (stayOpenAfterSave) {
814
+ return;
815
+ }
792
816
  if (onCreateComplete) {
793
817
  onCreateComplete(true);
794
818
  }
@@ -796,7 +820,7 @@ const WebPushCreate = ({
796
820
  handleClose();
797
821
  }
798
822
  }
799
- }, [webPush?.editResponse, onCreateComplete, handleClose, isEditMode]);
823
+ }, [webPush?.editResponse, onCreateComplete, handleClose, isEditMode, stayOpenAfterSave]);
800
824
 
801
825
  // Handle getFormData request from parent (library mode)
802
826
  useEffect(() => {
@@ -1194,6 +1218,8 @@ WebPushCreate.propTypes = {
1194
1218
  templateActions: PropTypes.object,
1195
1219
  restrictPersonalization: PropTypes.bool,
1196
1220
  onContentValidityChange: PropTypes.func,
1221
+ canStayOpenAfterCreate: PropTypes.bool,
1222
+ onCreateContinuedAsEdit: PropTypes.func,
1197
1223
  };
1198
1224
 
1199
1225
  WebPushCreate.defaultProps = {
@@ -43,10 +43,6 @@ export default defineMessages({
43
43
  id: `${scope}.messageRequired`,
44
44
  defaultMessage: 'Message is required',
45
45
  },
46
- saveTemplate: {
47
- id: `${scope}.saveTemplate`,
48
- defaultMessage: 'Save Template',
49
- },
50
46
  accountRequired: {
51
47
  id: `${scope}.accountRequired`,
52
48
  defaultMessage: 'Select an account to create a template',