@pega/dx-component-builder-sdk 8.23.12 → 8.23.13

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 (24) hide show
  1. package/package.json +1 -1
  2. package/src/tasks/build/helper.js +1 -0
  3. package/src/tasks/build/index.js +5 -3
  4. package/src/tasks/build-all/helper.js +1 -0
  5. package/src/tasks/build-all/index.js +17 -17
  6. package/src/tasks/bundle/builder/webpack.config.js +2 -1
  7. package/src/tasks/create/templates/SDK-React/field/Boolean/index.tsx.mustache +3 -3
  8. package/src/tasks/create/templates/SDK-React/field/DateTime/index.tsx.mustache +6 -7
  9. package/src/tasks/create/templates/SDK-React/field/Decimal/demo.stories.jsx.mustache +3 -0
  10. package/src/tasks/create/templates/SDK-React/field/Decimal/index.tsx.mustache +76 -26
  11. package/src/tasks/create/templates/SDK-React/field/Picklist/demo.stories.jsx.mustache +13 -0
  12. package/src/tasks/create/templates/SDK-React/field/Picklist/index.tsx.mustache +28 -8
  13. package/src/tasks/create/templates/SDK-React/field/Text-Phone/index.tsx.mustache +2 -1
  14. package/src/tasks/create/templates/SDK-React/field/Text-URL/index.tsx.mustache +11 -0
  15. package/src/tasks/create/templates/SDK-React/field/TimeOfDay/index.tsx.mustache +12 -1
  16. package/src/tasks/create/templates/SDK-React/template/FORM/index.tsx.mustache +30 -20
  17. package/src/tasks/create/templates/SDK-React/widget/CASE/index.tsx.mustache +4 -3
  18. package/src/tasks/create/templates/SDK-React/widget/PAGE-CASE/demo.stories.jsx.mustache +2 -10
  19. package/src/tasks/create/templates/SDK-React/widget/PAGE-CASE/index.tsx.mustache +22 -28
  20. package/src/tasks/create/templates/SDK-React/widget/PAGE-CASE/mock.stories.js.mustache +1 -1
  21. package/src/tasks/publish/helper.js +5 -4
  22. package/src/tasks/publish/index.js +10 -8
  23. package/src/tasks/publish-all/helper.js +5 -4
  24. package/src/tasks/publish-all/index.js +19 -19
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pega/dx-component-builder-sdk",
3
- "version": "8.23.12",
3
+ "version": "8.23.13",
4
4
  "description": "Utility for building custom UI components",
5
5
  "bin": "./bin/index.js",
6
6
  "scripts": {
@@ -73,6 +73,7 @@ export const getBuildComponentQuestions = async (category) => {
73
73
  },
74
74
  {
75
75
  name: 'devBuild',
76
+ type: 'confirm',
76
77
  message: 'Generate development build ?',
77
78
  default: defaultPegaConfig.devBuild
78
79
  }
@@ -30,6 +30,8 @@ export default async options => {
30
30
  ...answers
31
31
  };
32
32
 
33
+ const sDevBuild = devBuild ? '(dev build)' : '';
34
+
33
35
  const customTasks = new Listr(
34
36
  [
35
37
  {
@@ -47,7 +49,7 @@ export default async options => {
47
49
  }
48
50
  },
49
51
  {
50
- title: 'Bundle component',
52
+ title: `Bundle component ${sDevBuild}`,
51
53
  task: async () => await bundleComponent(componentKey, sourceMap, devBuild, category),
52
54
  },
53
55
  {
@@ -59,7 +61,7 @@ export default async options => {
59
61
  }
60
62
  },
61
63
  {
62
- title: 'Bundle associated component',
64
+ title: `Bundle associated component ${sDevBuild}`,
63
65
  task: async () => await bundleComponent(componentKey, sourceMap, devBuild, "constellation")
64
66
  }
65
67
  ],
@@ -85,7 +87,7 @@ export default async options => {
85
87
  }
86
88
  },
87
89
  {
88
- title: 'Bundle Component',
90
+ title: `Bundle Component ${sDevBuild}`,
89
91
  task: async () => await bundleComponent(componentKey, sourceMap, devBuild, category),
90
92
  }
91
93
  ],
@@ -54,6 +54,7 @@ export const getBuildComponentQuestions = async (category) => {
54
54
  return [
55
55
  {
56
56
  name: 'devBuild',
57
+ type: 'confirm',
57
58
  message: 'Generate development build ?',
58
59
  default: defaultPegaConfig.devBuild
59
60
  }
@@ -13,7 +13,8 @@ import { CATEGORY_CUSTOM } from '../../constants.js';
13
13
 
14
14
  export function getCustomTasks(componentKey, category, sourceMap, devBuild, content, options) {
15
15
 
16
- const customTasks = new Listr(
16
+ const sDevBuild = devBuild ? '(dev build)' : '';
17
+ return new Listr(
17
18
  [
18
19
  {
19
20
  title: 'Validate config schema',
@@ -30,7 +31,7 @@ export function getCustomTasks(componentKey, category, sourceMap, devBuild, cont
30
31
  }
31
32
  },
32
33
  {
33
- title: 'Bundle component',
34
+ title: `Bundle component ${sDevBuild}`,
34
35
  task: async () => await bundleComponent(componentKey, sourceMap, devBuild, category),
35
36
  },
36
37
  {
@@ -42,7 +43,7 @@ export function getCustomTasks(componentKey, category, sourceMap, devBuild, cont
42
43
  }
43
44
  },
44
45
  {
45
- title: 'Bundle associated component',
46
+ title: `Bundle associated component ${sDevBuild}`,
46
47
  task: async () => await bundleComponent(componentKey, sourceMap, devBuild, "constellation")
47
48
  }
48
49
  ],
@@ -51,13 +52,12 @@ export function getCustomTasks(componentKey, category, sourceMap, devBuild, cont
51
52
  }
52
53
  );
53
54
 
54
- return customTasks;
55
55
  }
56
56
 
57
57
 
58
58
  export function getOverrideTasks(componentKey, category, sourceMap, devBuild, content, options) {
59
-
60
- const overrideTasks = new Listr(
59
+ const sDevBuild = devBuild ? '(dev build)' : '';
60
+ return new Listr(
61
61
  [
62
62
  {
63
63
  title: 'Validate config schema',
@@ -74,7 +74,7 @@ export function getOverrideTasks(componentKey, category, sourceMap, devBuild, co
74
74
  }
75
75
  },
76
76
  {
77
- title: 'Bundle Component',
77
+ title: `Bundle Component ${sDevBuild}`,
78
78
  task: async () => await bundleComponent(componentKey, sourceMap, devBuild, category),
79
79
  }
80
80
  ],
@@ -83,7 +83,6 @@ export function getOverrideTasks(componentKey, category, sourceMap, devBuild, co
83
83
  }
84
84
  );
85
85
 
86
- return overrideTasks;
87
86
  }
88
87
 
89
88
  export default async options => {
@@ -106,13 +105,13 @@ export default async options => {
106
105
  ...answers
107
106
  };
108
107
 
109
- var componentKey;
110
108
 
111
109
 
112
110
  if (category === CATEGORY_CUSTOM) {
113
- for (var index in components) {
114
- componentKey = components[index].value;
115
- console.log(chalk.bold.green("Building: " + components[index].name));
111
+ for (const component of components) {
112
+ const componentKey = component.value;
113
+ const componentKeyName = component.name;
114
+ console.log(chalk.bold.green(`Building: ${componentKeyName}`));
116
115
 
117
116
  let myCustomTasks = getCustomTasks(componentKey, category, sourceMap, devBuild, content, options);
118
117
 
@@ -122,19 +121,20 @@ export default async options => {
122
121
  }
123
122
  }
124
123
  else {
125
- for (var index in components) {
126
- componentKey = components[index].value;
127
- console.log(chalk.bold.green("Building: " + components[index].name));
124
+ for (const component of components) {
125
+ const componentKey = component.value;
126
+ const componentKeyName = component.name;
127
+ console.log(chalk.bold.green(`Building: ${componentKeyName}`));
128
128
 
129
129
  let myOverrideTasks = getOverrideTasks(componentKey, category, sourceMap, devBuild, content, options);
130
130
 
131
- await mOverrideTasks.run().catch(err => {
131
+ await myOverrideTasks.run().catch(err => {
132
132
  console.log(chalk.bold.red(err.toString()));
133
133
  });
134
134
  }
135
135
  }
136
136
 
137
- cleanUp();
137
+ await cleanUp();
138
138
 
139
139
  return true;
140
140
  };
@@ -125,7 +125,8 @@ export default (
125
125
  name: componentKey,
126
126
  type: 'umd',
127
127
  export: 'default'
128
- }
128
+ },
129
+ publicPath: ''
129
130
  },
130
131
  optimization: {
131
132
  minimize: isEnvProduction,
@@ -25,6 +25,7 @@ export default function {{COMPONENT_CLASS_NAME}}(props: any) {
25
25
  readOnly,
26
26
  testId,
27
27
  required,
28
+ disabled,
28
29
  status,
29
30
  helperText,
30
31
  validatemessage,
@@ -61,15 +62,14 @@ export default function {{COMPONENT_CLASS_NAME}}(props: any) {
61
62
  thePConn.getValidationApi().validate(event.target.checked);
62
63
  };
63
64
 
64
- let theCheckbox = <Checkbox color='primary' />;
65
+ let theCheckbox = <Checkbox color='primary' disabled={disabled} />;
65
66
 
66
67
  if (readOnly) {
67
68
  // Workaround for lack of InputProps readOnly from https://github.com/mui-org/material-ui/issues/17043
68
69
  // Also note that we need to turn off the onChange call in the FormControlLabel wrapper, too. See below!
69
- theCheckbox = <Checkbox value={value || false} onChange={handleChange} readOnly={readOnly} />;
70
+ theCheckbox = <Checkbox value={value || false} readOnly={readOnly} />;
70
71
  }
71
72
 
72
-
73
73
  return (
74
74
  <Styled{{COMPONENT_CLASS_NAME}}Wrapper>
75
75
  <FormControl required={required} error={status === 'error'}>
@@ -47,19 +47,18 @@ export default function {{COMPONENT_CLASS_NAME}}(props: any) {
47
47
 
48
48
 
49
49
  if (displayMode === 'LABELS_LEFT') {
50
- const formattedDate = format(props.value, 'datetime', { format: `${dateFormatInfo.dateFormatString} hh:mm a` });
51
- return <FieldValueList name={hideLabel ? '' : label} value={formattedDate} />;
50
+ const formattedDateTime = format(props.value, 'datetime', { format: `${dateFormatInfo.dateFormatString} hh:mm a` });
51
+ return <FieldValueList name={hideLabel ? '' : label} value={formattedDateTime} />;
52
52
  }
53
53
 
54
54
  if (displayMode === 'STACKED_LARGE_VAL') {
55
- const formattedDate = format(props.value, 'datetime', { format: `${dateFormatInfo.dateFormatString} hh:mm a` });
56
- return <FieldValueList name={hideLabel ? '' : label} value={formattedDate} variant='stacked' />;
55
+ const formattedDateTime = format(props.value, 'datetime', { format: `${dateFormatInfo.dateFormatString} hh:mm a` });
56
+ return <FieldValueList name={hideLabel ? '' : label} value={formattedDateTime} variant='stacked' />;
57
57
  }
58
58
 
59
59
  if (readOnly) {
60
- const formattedDate = format(props.value, 'datetime');
61
- props.value = formattedDate;
62
- return <TextInput {...props} />;
60
+ const formattedDateTime = format(props.value, 'datetime');
61
+ return <TextInput {...props} value={formattedDateTime} />;
63
62
  }
64
63
 
65
64
  const handleChange = date => {
@@ -31,6 +31,9 @@ export const Base{{COMPONENT_CLASS_NAME}} = () => {
31
31
  },
32
32
  getStateProps: () => {
33
33
  return { value: '.name' };
34
+ },
35
+ getComponentName: () => {
36
+ return 'Decimal';
34
37
  }
35
38
  };
36
39
  },
@@ -1,13 +1,16 @@
1
-
2
- import React from 'react';
3
- import { TextField } from '@material-ui/core';
4
- import TextInput from '@pega/react-sdk-components/lib/components/field/TextInput';
1
+ /* eslint-disable react/no-unused-prop-types */
2
+ import React, { useState, useEffect } from 'react';
3
+ import CurrencyTextField from '@unicef/material-ui-currency-textfield';
5
4
  import FieldValueList from '@pega/react-sdk-components/lib/components/designSystemExtension/FieldValueList';
5
+ import { getCurrencyCharacters, getCurrencyOptions } from '@pega/react-sdk-components/lib/components/field/Currency/currency-utils.js';
6
+ import handleEvent from '@pega/react-sdk-components/lib/components/helpers/event-utils';
7
+ import { format } from "@pega/react-sdk-components/lib/components/helpers/formatters";
6
8
  import PropTypes from 'prop-types';
7
9
 
8
10
 
9
11
  import Styled{{COMPONENT_CLASS_NAME}}Wrapper from './styles';
10
12
 
13
+ // Using control from: https://github.com/unicef/material-ui-currency-textfield
11
14
 
12
15
  // Duplicated runtime code from React SDK
13
16
 
@@ -15,55 +18,102 @@ import Styled{{COMPONENT_CLASS_NAME}}Wrapper from './styles';
15
18
  // any default values in config.pros should be set in defaultProps at bottom of this file
16
19
  export default function {{COMPONENT_CLASS_NAME}}(props: any) {
17
20
  const {
21
+ getPConnect,
18
22
  label,
19
23
  required,
20
24
  disabled,
21
25
  value = '',
22
26
  validatemessage,
23
27
  status,
24
- onChange,
25
- onBlur,
28
+ /* onChange, onBlur, */
26
29
  readOnly,
27
30
  helperText,
28
31
  displayMode,
29
- hideLabel
32
+ hideLabel,
33
+ currencyISOCode = "USD",
34
+ decimalPrecision = 2,
35
+ showGroupSeparators = true,
36
+ testId
30
37
  } = props;
38
+
39
+ const pConn = getPConnect();
40
+ const actions = pConn.getActionsApi();
41
+ const propName = pConn.getStateProps().value;
31
42
  const helperTextToDisplay = validatemessage || helperText;
32
43
 
44
+ const [decValue, setDecimalvalue] = useState();
45
+ const [theCurrDec, setCurrDec] = useState(".");
46
+ const [theCurrSep, setCurrSep] = useState(",");
47
+
48
+ useEffect(() => {
49
+ const theSymbols = getCurrencyCharacters(currencyISOCode);
50
+ setCurrDec(theSymbols.theDecimalIndicator);
51
+ setCurrSep(theSymbols.theDigitGroupSeparator);
52
+ }, [currencyISOCode]);
53
+
54
+ useEffect(() => {
55
+ setDecimalvalue(value.toString());
56
+ }, [value]);
57
+
58
+ const theCurrencyOptions = getCurrencyOptions(currencyISOCode);
59
+ const formattedValue = format(value, pConn.getComponentName().toLowerCase(), theCurrencyOptions);
60
+
33
61
  if (displayMode === 'LABELS_LEFT') {
34
- return <FieldValueList name={hideLabel ? '' : label} value={value} />;
62
+ return <FieldValueList name={hideLabel ? '' : label} value={formattedValue} />;
35
63
  }
36
64
 
37
65
  if (displayMode === 'STACKED_LARGE_VAL') {
38
- return <FieldValueList name={hideLabel ? '' : label} value={value} variant='stacked' />;
66
+ return <FieldValueList name={hideLabel ? '' : label} value={formattedValue} variant='stacked' />;
39
67
  }
40
68
 
69
+ let readOnlyProp = {}; // Note: empty if NOT ReadOnly
70
+
41
71
  if (readOnly) {
42
- return <TextInput {...props} />;
72
+ readOnlyProp = { readOnly: true };
73
+ }
74
+
75
+ let testProp = {};
76
+
77
+ testProp = {
78
+ 'data-test-id': testId
79
+ };
80
+
81
+ function decimalOnChange(event) {
82
+ // update internal value
83
+ setDecimalvalue(event?.target?.value);
43
84
  }
44
85
 
86
+ function decimalOnBlur(event, inValue) {
87
+ handleEvent(actions, 'changeNblur', propName, inValue !== '' ? Number(inValue) : inValue);
88
+ }
45
89
 
46
90
  return (
47
91
  <Styled{{COMPONENT_CLASS_NAME}}Wrapper>
48
- <TextField
49
- fullWidth
50
- variant={readOnly ? 'standard' : 'outlined'}
51
- helperText={helperTextToDisplay}
52
- placeholder=''
53
- size='small'
54
- required={required}
55
- disabled={disabled}
56
- onChange={onChange}
57
- onBlur={!readOnly ? onBlur : undefined}
58
- error={status === 'error'}
59
- label={label}
60
- value={value}
61
- type='text'
92
+ <CurrencyTextField
93
+ fullWidth
94
+ variant={readOnly ? 'standard' : 'outlined'}
95
+ helperText={helperTextToDisplay}
96
+ placeholder=''
97
+ size='small'
98
+ required={required}
99
+ disabled={disabled}
100
+ onChange={decimalOnChange}
101
+ onBlur={!readOnly ? decimalOnBlur : undefined}
102
+ error={status === 'error'}
103
+ label={label}
104
+ value={decValue}
105
+ type='text'
106
+ outputFormat='number'
107
+ textAlign='left'
62
108
  {{! pick new delimiteres for mustache }}
63
109
  {{=<% %>=}}
64
- inputProps={{ inputMode: 'decimal', pattern: '[0-9]*' }}
110
+ InputProps={{ ...readOnlyProp, inputProps: { ...testProp, value: decValue } }}
65
111
  <%={{ }}=%> {{! revert delimiteres for mustache }}
66
- />
112
+ currencySymbol=''
113
+ decimalCharacter={theCurrDec}
114
+ digitGroupSeparator={showGroupSeparators ? theCurrSep : ''}
115
+ decimalPlaces={decimalPrecision}
116
+ />
67
117
  </Styled{{COMPONENT_CLASS_NAME}}Wrapper>
68
118
  );
69
119
  }
@@ -39,6 +39,19 @@ export const Base{{COMPONENT_CLASS_NAME}} = () => {
39
39
  return undefined;
40
40
  }
41
41
  };
42
+ },
43
+ getCaseInfo: () => {
44
+ return {
45
+ getClassName: () => {
46
+ return undefined;
47
+ }
48
+ };
49
+ },
50
+ getLocalizedValue: val => {
51
+ return val;
52
+ },
53
+ getLocaleRuleNameFromKeys: () => {
54
+ return undefined;
42
55
  }
43
56
  };
44
57
  }
@@ -24,7 +24,6 @@ export default function {{COMPONENT_CLASS_NAME}}(props: any) {
24
24
  label,
25
25
  required,
26
26
  disabled,
27
- placeholder,
28
27
  value = '',
29
28
  datasource = [],
30
29
  validatemessage,
@@ -34,21 +33,38 @@ export default function {{COMPONENT_CLASS_NAME}}(props: any) {
34
33
  helperText,
35
34
  displayMode,
36
35
  hideLabel,
37
- onRecordChange
36
+ onRecordChange,
37
+ fieldMetadata
38
38
  } = props;
39
+ let { placeholder } = props;
40
+ placeholder = placeholder || 'Select...';
39
41
  const [options, setOptions] = useState<Array<IOption>>([]);
40
42
  const helperTextToDisplay = validatemessage || helperText;
41
43
 
42
44
  const thePConn = getPConnect();
43
45
  const actionsApi = thePConn.getActionsApi();
44
46
  const propName = thePConn.getStateProps().value;
47
+ const className = thePConn.getCaseInfo().getClassName();
48
+ const refName = propName?.slice(propName.lastIndexOf('.') + 1);
45
49
 
46
50
  useEffect(() => {
47
- const optionsList = Utils.getOptionList(props, getPConnect().getDataObject());
48
- optionsList.unshift({ key: 'Select', value: 'Select...' });
51
+ const list = Utils.getOptionList(props, getPConnect().getDataObject());
52
+ const optionsList = [...list];
53
+ optionsList.unshift({ key: placeholder, value: placeholder });
49
54
  setOptions(optionsList);
50
55
  }, [datasource]);
51
56
 
57
+ const metaData = Array.isArray(fieldMetadata)
58
+ ? fieldMetadata.filter((field) => field?.classID === className)[0]
59
+ : fieldMetadata;
60
+
61
+ let displayName = metaData?.datasource?.propertyForDisplayText;
62
+ displayName = displayName?.slice(displayName.lastIndexOf('.') + 1);
63
+ const localeContext = metaData?.datasource?.tableType === 'DataPage' ? 'datapage' : 'associated';
64
+ const localeClass = localeContext === 'datapage' ? '@baseclass' : className;
65
+ const localeName = localeContext === 'datapage' ? metaData?.datasource?.name : refName;
66
+ const localePath = localeContext === 'datapage' ? displayName : '';
67
+
52
68
  let readOnlyProp = {};
53
69
 
54
70
  if (displayMode === 'LABELS_LEFT') {
@@ -70,7 +86,7 @@ export default function {{COMPONENT_CLASS_NAME}}(props: any) {
70
86
  };
71
87
 
72
88
  const handleChange = evt => {
73
- const selectedValue = evt.target.value === 'Select' ? '' : evt.target.value;
89
+ const selectedValue = evt.target.value === placeholder ? '' : evt.target.value;
74
90
  handleEvent(actionsApi, 'changeNblur', propName, selectedValue);
75
91
  if (onRecordChange) {
76
92
  onRecordChange(evt);
@@ -85,14 +101,14 @@ export default function {{COMPONENT_CLASS_NAME}}(props: any) {
85
101
  fullWidth
86
102
  variant={readOnly ? 'standard' : 'outlined'}
87
103
  helperText={helperTextToDisplay}
88
- placeholder={placeholder}
104
+ placeholder={thePConn.getLocalizedValue(placeholder)}
89
105
  size='small'
90
106
  required={required}
91
107
  disabled={disabled}
92
108
  onChange={!readOnly ? handleChange : undefined}
93
109
  error={status === 'error'}
94
110
  label={label}
95
- value={value === '' && !readOnly ? 'Select' : value}
111
+ value={value === '' && !readOnly ? placeholder : value}
96
112
  select
97
113
  {{! pick new delimiteres for mustache }}
98
114
  {{=<% %>=}}
@@ -101,7 +117,11 @@ export default function {{COMPONENT_CLASS_NAME}}(props: any) {
101
117
  >
102
118
  {options.map((option: any) => (
103
119
  <MenuItem key={option.key} value={option.key}>
104
- {option.value}
120
+ {thePConn.getLocalizedValue(
121
+ option.value,
122
+ localePath,
123
+ thePConn.getLocaleRuleNameFromKeys(localeClass, localeContext, localeName)
124
+ )}
105
125
  </MenuItem>
106
126
  ))}
107
127
  </TextField>
@@ -63,7 +63,8 @@ export default function {{COMPONENT_CLASS_NAME}}(props: any) {
63
63
  {{! pick new delimiteres for mustache }}
64
64
  {{=<% %>=}}
65
65
  InputProps={{
66
- readOnly: true
66
+ readOnly: true,
67
+ inputProps: { ...testProp }
67
68
  }}
68
69
  <%={{ }}=%> {{! revert delimiteres for mustache }}
69
70
  disableDropdown={disableDropdown}
@@ -24,6 +24,7 @@ export default function {{COMPONENT_CLASS_NAME}}(props: any) {
24
24
  onChange,
25
25
  onBlur,
26
26
  readOnly,
27
+ testId,
27
28
  helperText,
28
29
  displayMode,
29
30
  hideLabel
@@ -42,6 +43,12 @@ export default function {{COMPONENT_CLASS_NAME}}(props: any) {
42
43
  return <TextInput {...props} />;
43
44
  }
44
45
 
46
+ let testProp = {};
47
+
48
+ testProp = {
49
+ 'data-test-id': testId
50
+ };
51
+
45
52
  return (
46
53
  <Styled{{COMPONENT_CLASS_NAME}}Wrapper>
47
54
  <TextField
@@ -58,6 +65,10 @@ export default function {{COMPONENT_CLASS_NAME}}(props: any) {
58
65
  error={status === 'error'}
59
66
  label={label}
60
67
  value={value}
68
+ {{! pick new delimiteres for mustache }}
69
+ {{=<% %>=}}
70
+ InputProps={{ inputProps: { ...testProp } }}
71
+ <%={{ }}=%> {{! revert delimiteres for mustache }}
61
72
  />
62
73
  </Styled{{COMPONENT_CLASS_NAME}}Wrapper>
63
74
  );
@@ -26,7 +26,8 @@ export default function {{COMPONENT_CLASS_NAME}}(props: any) {
26
26
  readOnly,
27
27
  helperText,
28
28
  displayMode,
29
- hideLabel
29
+ hideLabel,
30
+ testId
30
31
  } = props;
31
32
  const helperTextToDisplay = validatemessage || helperText;
32
33
 
@@ -42,6 +43,12 @@ export default function {{COMPONENT_CLASS_NAME}}(props: any) {
42
43
  return <TextInput {...props} />;
43
44
  }
44
45
 
46
+ let testProp = {};
47
+
48
+ testProp = {
49
+ 'data-test-id': testId
50
+ };
51
+
45
52
  const handleChange = date => {
46
53
  const theValue = date && date.isValid() ? date.format('HH:mm') : null;
47
54
  onChange({ value: theValue });
@@ -79,6 +86,10 @@ export default function {{COMPONENT_CLASS_NAME}}(props: any) {
79
86
  format='hh:mm a'
80
87
  value={timeValue}
81
88
  onChange={handleChange}
89
+ {{! pick new delimiteres for mustache }}
90
+ {{=<% %>=}}
91
+ InputProps={{ inputProps: { ...testProp } }}
92
+ <%={{ }}=%> {{! revert delimiteres for mustache }}
82
93
  />
83
94
  </MuiPickersUtilsProvider>
84
95
  </Styled{{COMPONENT_CLASS_NAME}}Wrapper>
@@ -1,10 +1,10 @@
1
- /* eslint-disable react/no-array-index-key */
2
- import React, { createElement } from "react";
3
- import PropTypes from "prop-types";
1
+ /* eslint-disable react/no-danger */
2
+ import React, { createElement } from 'react';
3
+ import PropTypes from 'prop-types';
4
4
 
5
- import { getInstructions } from "./utils";
6
- import createPConnectComponent from "@pega/react-sdk-components/lib/bridge/react_pconnect";
7
- import "./DefaultForm.css";
5
+ import { getInstructions } from './utils';
6
+ import createPConnectComponent from '@pega/react-sdk-components/lib/bridge/react_pconnect';
7
+ import './DefaultForm.css';
8
8
 
9
9
  import Styled{{COMPONENT_CLASS_NAME}}Wrapper from "./styles";
10
10
 
@@ -15,23 +15,22 @@ import Styled{{COMPONENT_CLASS_NAME}}Wrapper from "./styles";
15
15
  export default function {{COMPONENT_CLASS_NAME}}(props) {
16
16
  const { getPConnect, NumCols } = props;
17
17
  const instructions = getInstructions(getPConnect(), props.instructions);
18
- const instructionText = instructions?.replace(/<\/?[^>]+(>|$)/g, "");
19
18
 
20
19
  let divClass: string;
21
20
 
22
- const numCols = NumCols || "1";
21
+ const numCols = NumCols || '1';
23
22
  switch (numCols) {
24
- case "1":
25
- divClass = "psdk-default-form-one-column";
23
+ case '1':
24
+ divClass = 'psdk-default-form-one-column';
26
25
  break;
27
- case "2":
28
- divClass = "psdk-default-form-two-column";
26
+ case '2':
27
+ divClass = 'psdk-default-form-two-column';
29
28
  break;
30
- case "3":
31
- divClass = "psdk-default-form-three-column";
29
+ case '3':
30
+ divClass = 'psdk-default-form-three-column';
32
31
  break;
33
32
  default:
34
- divClass = "psdk-default-form-one-column";
33
+ divClass = 'psdk-default-form-one-column';
35
34
  break;
36
35
  }
37
36
 
@@ -40,21 +39,32 @@ export default function {{COMPONENT_CLASS_NAME}}(props) {
40
39
  // defaultForm kids
41
40
  const arChildren = getPConnect().getChildren()[0].getPConnect().getChildren();
42
41
  const dfChildren = arChildren.map((kid, idx) =>
42
+ // eslint-disable-next-line react/no-array-index-key
43
43
  createElement(createPConnectComponent(), { ...kid, key: idx })
44
44
  );
45
45
 
46
46
  return (
47
47
  <Styled{{COMPONENT_CLASS_NAME}}Wrapper>
48
- <div className={divClass}>
49
- <div>{instructionText}</div>
50
- {dfChildren}
51
- </div>
48
+ <>
49
+ {instructions && (
50
+ <div className='psdk-default-form-instruction-text'>
51
+ {/* server performs sanitization method for instructions html content */}
52
+ <div key="instructions"
53
+ {{! pick new delimiteres for mustache }}
54
+ {{=<% %>=}}
55
+ dangerouslySetInnerHTML={{ __html: instructions }}
56
+ <%={{ }}=%> {{! revert delimiteres for mustache }}
57
+ />
58
+ </div>
59
+ )}
60
+ <div className={divClass}>{dfChildren}</div>
61
+ </>
52
62
  </Styled{{COMPONENT_CLASS_NAME}}Wrapper>
53
63
  );
54
64
  }
55
65
 
56
66
  {{COMPONENT_CLASS_NAME}}.defaultProps = {
57
- NumCols: "1",
67
+ NumCols: '1',
58
68
  };
59
69
 
60
70
  {{COMPONENT_CLASS_NAME}}.propTypes = {
@@ -45,9 +45,9 @@ export default function {{COMPONENT_CLASS_NAME}}(props) {
45
45
  // let waitingForData = true;
46
46
 
47
47
  const displayedColumns = [
48
- { label: "Date", type: "DateTime", fieldName: "pxTimeCreated" },
49
- { label: "Description", type: "TextInput", fieldName: "pyMessageKey" },
50
- { label: "User", type: "TextInput", fieldName: "pyPerformer" }
48
+ { label: thePConn.getLocalizedValue('Date'), type: "DateTime", fieldName: "pxTimeCreated" },
49
+ { label: thePConn.getLocalizedValue('Description'), type: "TextInput", fieldName: "pyMessageKey" },
50
+ { label: thePConn.getLocalizedValue('Performed by'), type: "TextInput", fieldName: "pyPerformer" }
51
51
  ];
52
52
 
53
53
  const rowData: any = useRef([]);
@@ -59,6 +59,7 @@ export default function {{COMPONENT_CLASS_NAME}}(props) {
59
59
  const dataViewName = "D_pyWorkHistory";
60
60
  const context = thePConn.getContextName();
61
61
 
62
+
62
63
  function computeRowData(rows: Array<Object>): void {
63
64
  const theRowData: Array<Object> = [];
64
65
 
@@ -1,6 +1,6 @@
1
1
  import { withKnobs } from '@storybook/addon-knobs';
2
2
 
3
- import { configProps, operatorDetails } from './mock.stories';
3
+ import { caseOpConfig, operatorDetails } from './mock.stories';
4
4
 
5
5
  import {{COMPONENT_CLASS_NAME}} from './index.tsx';
6
6
 
@@ -27,15 +27,7 @@ window.PCore.getUserApi = () => {
27
27
  export const Base{{COMPONENT_CLASS_NAME}} = () => {
28
28
 
29
29
  const props = {
30
- label: configProps.label,
31
- createLabel: configProps.createLabel,
32
- updateLabel: configProps.updateLabel,
33
- createOperator: configProps.createOperator,
34
- updateOperator: configProps.updateOperator,
35
- createDateTime: configProps.createDateTime,
36
- updateDateTime: configProps.updateDateTime,
37
- hideLabel: configProps.hideLabel,
38
-
30
+ caseOpConfig,
39
31
  getPConnect: () => {
40
32
  return {
41
33
  getActionsApi: () => {
@@ -32,33 +32,25 @@ const useStyles = makeStyles((theme) => ({
32
32
  // any default values in config.pros should be set in defaultProps at bottom of this file
33
33
  export default function {{COMPONENT_CLASS_NAME}}(props) {
34
34
  // const componentName = "Operator";
35
- const {
36
- label,
37
- createLabel,
38
- updateLabel,
39
- createOperator,
40
- updateOperator,
41
- createDateTime,
42
- updateDateTime
43
- } = props;
35
+ const { caseOpConfig } = props;
44
36
  const classes = useStyles();
45
37
 
46
- const fieldLabel = label.toLowerCase();
38
+ const fieldLabel = caseOpConfig.label.toLowerCase();
47
39
  let caseOpLabel = "---";
48
40
  let caseOpName = "---";
49
41
  let caseOpId = "";
50
42
  let caseTime = null;
51
43
 
52
44
  if (fieldLabel === "create operator") {
53
- caseOpLabel = createLabel;
54
- caseOpName = createOperator.userName;
55
- caseTime = createDateTime;
56
- caseOpId = createOperator.userId;
45
+ caseOpLabel = caseOpConfig.createLabel;
46
+ caseOpName = caseOpConfig.createOperator.userName;
47
+ caseTime = caseOpConfig.createDateTime;
48
+ caseOpId = caseOpConfig.createOperator.userId;
57
49
  } else if (fieldLabel === "update operator") {
58
- caseOpLabel = updateLabel;
59
- caseOpName = updateOperator.userName;
60
- caseTime = updateDateTime;
61
- caseOpId = updateOperator.userId;
50
+ caseOpLabel = caseOpConfig.updateLabel;
51
+ caseOpName = caseOpConfig.updateOperator.userName;
52
+ caseTime = caseOpConfig.updateDateTime;
53
+ caseOpId = caseOpConfig.updateOperator.userId;
62
54
  }
63
55
 
64
56
  // Popover-related
@@ -75,6 +67,8 @@ export default function {{COMPONENT_CLASS_NAME}}(props) {
75
67
  function showOperatorDetails(event) {
76
68
 
77
69
  const operatorPreviewPromise = PCore.getUserApi().getOperatorDetails(caseOpId);
70
+ const localizedVal = PCore.getLocaleUtils().getLocaleValue;
71
+ const localeCategory = 'Operator';
78
72
 
79
73
  operatorPreviewPromise.then((res) => {
80
74
  const fillerString = "---";
@@ -87,27 +81,27 @@ export default function {{COMPONENT_CLASS_NAME}}(props) {
87
81
  fields = [
88
82
  {
89
83
  id: "pyPosition",
90
- name: "Position",
84
+ name: localizedVal("Position", localeCategory),
91
85
  value: res.data.pyOperatorInfo.pyPosition ? res.data.pyOperatorInfo.pyPosition : fillerString
92
86
  },
93
87
  {
94
88
  id: "pyOrganization",
95
- name: "Organization",
89
+ name: localizedVal("Organization", localeCategory),
96
90
  value: res.data.pyOperatorInfo.pyOrganization ? res.data.pyOperatorInfo.pyOrganization : fillerString
97
91
  },
98
92
  {
99
93
  id: "ReportToUserName",
100
- name: "Reports to",
94
+ name: localizedVal('Reports to', localeCategory),
101
95
  value: res.data.pyOperatorInfo.pyReportToUserName ? res.data.pyOperatorInfo.pyReportToUserName : fillerString
102
96
  },
103
97
  {
104
98
  id: "pyTelephone",
105
- name: "Telephone",
99
+ name: localizedVal('Telephone', localeCategory),
106
100
  value: res.data.pyOperatorInfo.pyTelephone ? <a href={`tel:${res.data.pyOperatorInfo.pyTelephone}`}>{res.data.pyOperatorInfo.pyTelephone}</a> : fillerString
107
101
  },
108
102
  {
109
103
  id: "pyEmailAddress",
110
- name: "Email address",
104
+ name: localizedVal('Email address', localeCategory),
111
105
  value: res.data.pyOperatorInfo.pyEmailAddress ? <a href={`mailto:${res.data.pyOperatorInfo.pyEmailAddress}`}>{res.data.pyOperatorInfo.pyEmailAddress}</a> : fillerString
112
106
  }
113
107
  ];
@@ -117,27 +111,27 @@ export default function {{COMPONENT_CLASS_NAME}}(props) {
117
111
  fields = [
118
112
  {
119
113
  id: "pyPosition",
120
- name: "Position",
114
+ name: localizedVal("Position", localeCategory),
121
115
  value: fillerString
122
116
  },
123
117
  {
124
118
  id: "pyOrganization",
125
- name: "Organization",
119
+ name: localizedVal("Organization", localeCategory),
126
120
  value: fillerString
127
121
  },
128
122
  {
129
123
  id: "ReportToUserName",
130
- name: "Reports to",
124
+ name: localizedVal('Reports to', localeCategory),
131
125
  value: fillerString
132
126
  },
133
127
  {
134
128
  id: "pyTelephone",
135
- name: "Telephone",
129
+ name: localizedVal('Telephone', localeCategory),
136
130
  value: fillerString
137
131
  },
138
132
  {
139
133
  id: "pyEmailAddress",
140
- name: "Email address",
134
+ name: localizedVal('Email address', localeCategory),
141
135
  value: fillerString
142
136
  }
143
137
  ];
@@ -1,5 +1,5 @@
1
1
 
2
- export const configProps = {
2
+ export const caseOpConfig = {
3
3
  label: 'Create operator',
4
4
  createLabel: 'Created',
5
5
  updateLabel: 'Updated',
@@ -15,10 +15,10 @@ import {
15
15
  getOptionsCategory
16
16
  } from '../../util.js';
17
17
 
18
- import { PUBLISH_COMPONENT_SERVICE_REST_ENDPOINT,
19
- TOKEN_PATH,
20
- COMPONENT_SCHEMA,
21
- CATEGORY_CONSTELLATION,
18
+ import { PUBLISH_COMPONENT_SERVICE_REST_ENDPOINT,
19
+ TOKEN_PATH,
20
+ COMPONENT_SCHEMA,
21
+ CATEGORY_CONSTELLATION,
22
22
  CATEGORY_CUSTOM } from '../../constants.js';
23
23
 
24
24
 
@@ -95,6 +95,7 @@ export const getPublishComponentQuestions = async (category) => {
95
95
  },
96
96
  {
97
97
  name: 'devBuild',
98
+ type: 'confirm',
98
99
  message: 'Generate development build ?',
99
100
  default: defaultPegaConfig.devBuild
100
101
  }
@@ -10,11 +10,11 @@ import { lintComponent } from '../linter/index.js';
10
10
  import { CATEGORY_CONSTELLATION, CATEGORY_CUSTOM } from '../../constants.js';
11
11
 
12
12
 
13
- import { getPublishComponentQuestions,
14
- publishComponentToServer,
15
- zipComponent,
16
- getBuildCategory,
17
- mapConfigJsonToCompanion,
13
+ import { getPublishComponentQuestions,
14
+ publishComponentToServer,
15
+ zipComponent,
16
+ getBuildCategory,
17
+ mapConfigJsonToCompanion,
18
18
  removeCompanionConfigJson} from './helper.js';
19
19
 
20
20
 
@@ -37,6 +37,8 @@ export default async options => {
37
37
  ...answers
38
38
  };
39
39
 
40
+ const sDevBuild = devBuild ? '(dev build)' : '';
41
+
40
42
  const customTasks = new Listr(
41
43
  [
42
44
 
@@ -55,7 +57,7 @@ export default async options => {
55
57
  }
56
58
  },
57
59
  {
58
- title: 'Bundle component',
60
+ title: `Bundle component ${sDevBuild}`,
59
61
  task: async () => await bundleComponent(componentKey, sourceMap, devBuild, category),
60
62
  skip: () => (options.skipBundle ? 'Skipped bundling component' : undefined)
61
63
  },
@@ -80,7 +82,7 @@ export default async options => {
80
82
  }
81
83
  },
82
84
  {
83
- title: 'Bundle associated component',
85
+ title: `Bundle associated component ${sDevBuild}`,
84
86
  task: async () => await bundleComponent(componentKey, sourceMap, devBuild, CATEGORY_CONSTELLATION),
85
87
  skip: () => (options.skipBundle ? 'Skipped bundling component' : undefined)
86
88
  },
@@ -126,7 +128,7 @@ export default async options => {
126
128
  }
127
129
  },
128
130
  {
129
- title: 'Bundle component',
131
+ title: `Bundle component ${sDevBuild}`,
130
132
  task: async () => await bundleComponent(componentKey, sourceMap, devBuild, category),
131
133
  skip: () => (options.skipBundle ? 'Skipped bundling component' : undefined)
132
134
  },
@@ -15,10 +15,10 @@ import {
15
15
  getOptionsCategory
16
16
  } from '../../util.js';
17
17
 
18
- import { PUBLISH_COMPONENT_SERVICE_REST_ENDPOINT,
19
- TOKEN_PATH,
20
- COMPONENT_SCHEMA,
21
- CATEGORY_CONSTELLATION,
18
+ import { PUBLISH_COMPONENT_SERVICE_REST_ENDPOINT,
19
+ TOKEN_PATH,
20
+ COMPONENT_SCHEMA,
21
+ CATEGORY_CONSTELLATION,
22
22
  CATEGORY_CUSTOM } from '../../constants.js';
23
23
 
24
24
 
@@ -89,6 +89,7 @@ export const getPublishComponentQuestions = async () => {
89
89
  },
90
90
  {
91
91
  name: 'devBuild',
92
+ type: 'confirm',
92
93
  message: 'Generate development build ?',
93
94
  default: defaultPegaConfig.devBuild
94
95
  }
@@ -10,10 +10,10 @@ import { lintComponent } from '../linter/index.js';
10
10
  import { CATEGORY_CONSTELLATION, CATEGORY_CUSTOM } from '../../constants.js';
11
11
 
12
12
 
13
- import { getPublishComponentQuestions,
14
- publishComponentToServer,
15
- zipComponent,
16
- getBuildCategory,
13
+ import { getPublishComponentQuestions,
14
+ publishComponentToServer,
15
+ zipComponent,
16
+ getBuildCategory,
17
17
  mapConfigJsonToCompanion,
18
18
  removeCompanionConfigJson,
19
19
  cleanUp
@@ -21,7 +21,8 @@ import { getPublishComponentQuestions,
21
21
 
22
22
 
23
23
  export function getCustomTasks(componentKey, category, sourceMap, devBuild, content, options) {
24
- const customTasks = new Listr(
24
+ const sDevBuild = devBuild ? '(dev build)' : '';
25
+ return new Listr(
25
26
  [
26
27
 
27
28
  {
@@ -59,7 +60,7 @@ export function getCustomTasks(componentKey, category, sourceMap, devBuild, cont
59
60
  }
60
61
  },
61
62
  {
62
- title: 'Bundle associated component',
63
+ title: `Bundle associated component ${sDevBuild}`,
63
64
  task: async () => await bundleComponent(componentKey, sourceMap, devBuild, CATEGORY_CONSTELLATION),
64
65
  skip: () => (options.skipBundle ? 'Skipped bundling component' : undefined)
65
66
  },
@@ -88,12 +89,11 @@ export function getCustomTasks(componentKey, category, sourceMap, devBuild, cont
88
89
  }
89
90
  );
90
91
 
91
- return customTasks;
92
92
  }
93
93
 
94
94
  export function getOverrideTasks(componentKey, category, sourceMap, devBuild, content, options) {
95
-
96
- const overrideTasks = new Listr(
95
+ const sDevBuild = devBuild ? '(dev build)' : '';
96
+ return new Listr(
97
97
  [
98
98
  {
99
99
  title: 'Validate config schema',
@@ -110,7 +110,7 @@ export function getOverrideTasks(componentKey, category, sourceMap, devBuild, co
110
110
  }
111
111
  },
112
112
  {
113
- title: 'Bundle component',
113
+ title: `Bundle component ${sDevBuild}`,
114
114
  task: async () => await bundleComponent(componentKey, sourceMap, devBuild, category),
115
115
  skip: () => (options.skipBundle ? 'Skipped bundling component' : undefined)
116
116
  },
@@ -139,7 +139,6 @@ export function getOverrideTasks(componentKey, category, sourceMap, devBuild, co
139
139
  }
140
140
  );
141
141
 
142
- return overrideTasks;
143
142
  }
144
143
 
145
144
 
@@ -163,14 +162,14 @@ export default async options => {
163
162
  ...answers
164
163
  };
165
164
 
166
- var componentKey;
167
165
 
168
166
 
169
167
  if (category === CATEGORY_CUSTOM) {
170
168
 
171
- for (var index in components) {
172
- componentKey = components[index].value;
173
- console.log(chalk.bold.green("Publishing: " + components[index].name));
169
+ for (const component of components) {
170
+ const componentKey = component.value;
171
+ const componentKeyName = component.name;
172
+ console.log(chalk.bold.green(`Publishing: ${componentKeyName}`));
174
173
 
175
174
  let myCustomTasks = getCustomTasks(componentKey, category, sourceMap, devBuild, content, options);
176
175
 
@@ -181,9 +180,10 @@ export default async options => {
181
180
 
182
181
  }
183
182
  else {
184
- for (var index in components) {
185
- componentKey = components[index].value;
186
- console.log(chalk.bold.green("Publishing: " + components[index].name));
183
+ for (const component of components) {
184
+ const componentKey = component.value;
185
+ const componentKeyName = component.name;
186
+ console.log(chalk.bold.green(`Publishing: ${componentKeyName}`));
187
187
 
188
188
  let myOverrideTasks = getOverrideTasks(componentKey, category, sourceMap, devBuild, content, options);
189
189
 
@@ -196,7 +196,7 @@ export default async options => {
196
196
 
197
197
 
198
198
  // once done, remove leftover directories
199
- cleanUp();
199
+ await cleanUp();
200
200
 
201
201
 
202
202
  return true;