@pega/custom-dx-components 0.23.1 → 0.23.2

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 (43) hide show
  1. package/package.json +1 -1
  2. package/src/constants.js +3 -0
  3. package/src/tasks/create/templates/Constellation/Field/Boolean/config.json.mustache +1 -0
  4. package/src/tasks/create/templates/Constellation/Field/Date/config.json.mustache +1 -0
  5. package/src/tasks/create/templates/Constellation/Field/DateTime/config.json.mustache +1 -0
  6. package/src/tasks/create/templates/Constellation/Field/Decimal/config.json.mustache +1 -0
  7. package/src/tasks/create/templates/Constellation/Field/Decimal-Currency/config.json.mustache +1 -0
  8. package/src/tasks/create/templates/Constellation/Field/Decimal-Percentage/config.json.mustache +1 -0
  9. package/src/tasks/create/templates/Constellation/Field/Integer/config.json.mustache +1 -0
  10. package/src/tasks/create/templates/Constellation/Field/Picklist/config.json.mustache +1 -0
  11. package/src/tasks/create/templates/Constellation/Field/Text/config.json.mustache +1 -0
  12. package/src/tasks/create/templates/Constellation/Field/Text-Email/config.json.mustache +1 -0
  13. package/src/tasks/create/templates/Constellation/Field/Text-Input/config.json.mustache +1 -0
  14. package/src/tasks/create/templates/Constellation/Field/Text-Paragraph/config.json.mustache +1 -0
  15. package/src/tasks/create/templates/Constellation/Field/Text-Phone/config.json.mustache +1 -0
  16. package/src/tasks/create/templates/Constellation/Field/Text-URL/config.json.mustache +1 -0
  17. package/src/tasks/create/templates/Constellation/Field/TimeOfDay/config.json.mustache +1 -0
  18. package/src/tasks/create/templates/Constellation/Template/DETAILS/config.json.mustache +1 -0
  19. package/src/tasks/create/templates/Constellation/Template/DETAILS-region/config.json.mustache +1 -0
  20. package/src/tasks/create/templates/Constellation/Template/FORM/config.json.mustache +1 -0
  21. package/src/tasks/create/templates/Constellation/Template/FORM-region/config.json.mustache +1 -0
  22. package/src/tasks/create/templates/Constellation/Template/PAGE/config.json.mustache +1 -0
  23. package/src/tasks/create/templates/Constellation/Widget/CASE/config.json.mustache +1 -0
  24. package/src/tasks/create/templates/Constellation/Widget/PAGE/config.json.mustache +1 -0
  25. package/src/tasks/create/templates/Constellation/Widget/PAGE-CASE/config.json.mustache +1 -0
  26. package/src/tasks/generate-ai/aiPrompt.txt.mustache +13 -111
  27. package/src/tasks/generate-ai/aiPromptDavinci.txt.mustache +14 -0
  28. package/src/tasks/generate-ai/helper.js +252 -79
  29. package/src/tasks/generate-ai/index.js +5 -4
  30. package/src/tasks/init/template/package.json.mustache +1 -1
  31. package/src/tasks/init/template/src/components/_components.md +1 -0
  32. package/src/util.js +125 -0
  33. package/src/tasks/init/template/src/components/Organization_Library_MediaURL/MediaURL.stories.tsx +0 -19
  34. package/src/tasks/init/template/src/components/Organization_Library_MediaURL/MediaURL.styles.ts +0 -5
  35. package/src/tasks/init/template/src/components/Organization_Library_MediaURL/MediaURL.types.ts +0 -10
  36. package/src/tasks/init/template/src/components/Organization_Library_MediaURL/MediaURLDisplay.tsx +0 -25
  37. package/src/tasks/init/template/src/components/Organization_Library_MediaURL/MediaURLInput.tsx +0 -24
  38. package/src/tasks/init/template/src/components/Organization_Library_MediaURL/config.json +0 -13
  39. package/src/tasks/init/template/src/components/Organization_Library_MediaURL/index.ts +0 -2
  40. package/src/tasks/init/template/src/components/Organization_Library_VideoPlayer/config.json +0 -44
  41. package/src/tasks/init/template/src/components/Organization_Library_VideoPlayer/demo.stories.jsx +0 -40
  42. package/src/tasks/init/template/src/components/Organization_Library_VideoPlayer/index.jsx +0 -42
  43. package/src/tasks/init/template/src/components/Organization_Library_VideoPlayer/styles.js +0 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pega/custom-dx-components",
3
- "version": "0.23.1",
3
+ "version": "0.23.2",
4
4
  "description": "Utility for building custom UI components",
5
5
  "bin": "./bin/index.js",
6
6
  "scripts": {
package/src/constants.js CHANGED
@@ -7,6 +7,7 @@ export const TOKEN_PATH = 'node_modules/@pega/custom-dx-components/.access_token
7
7
  export const SERVICE_TOKEN_PATH = 'node_modules/@pega/custom-dx-components/.service_token';
8
8
  export const OOTB_COMPONENTS = 'node_modules/@pega/custom-dx-components/.ootb_components';
9
9
  export const AI_PROMPT_FILENAME = 'aiPrompt.txt.mustache';
10
+ export const AI_DAVINCI_PROMPT_FILENAME = 'aiPromptDavinci.txt.mustache';
10
11
 
11
12
  /* REST end points */
12
13
  export const PUBLISH_COMPONENT_SERVICE_REST_ENDPOINT = 'PRRestService/dev/v1/publish_component';
@@ -14,6 +15,8 @@ export const LIST_COMPONENT_SERVICE_REST_ENDPOINT = 'PRRestService/dev/v1/list_c
14
15
  export const OOTB_COMPONENT_SERVICE_REST_ENDPOINT = 'PRRestService/dev/v1/ootb_component';
15
16
  export const DELETE_COMPONENT_SERVICE_REST_ENDPOINT = 'PRRestService/dev/v1/delete_component';
16
17
  export const BOOTSTRAP_SERVICE_REST_ENDPOINT = "PRRestService/application/v2/data_views/D_pxBootstrapConfig";
18
+ export const DXCOMPGENAI_SERVICE_REST_ENDPOINT = "PRRestService/application/v2/data_views/D_DXCompAIGenList";
19
+
17
20
  export const SERVICES_AI_REST_ENDPOINT = 'generativeai';
18
21
  export const INF_TOKEN_URL_V1 = 'PRRestService/oauth2/v1/token';
19
22
  export const INF_AUTHORIZE_URL_V1 = 'PRRestService/oauth2/v1/authorize';
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "images/pz-checkbox-active.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "images/pz-date-time-active.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "images/pz-text-input-active.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "images/pz-decimal-active.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "images/pz-currency-active.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "images/pz-text-input-active.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  {{#IS_TEMPLATE}}
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "images/pz-dropdown-active.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  {{#IS_TEMPLATE}}
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "images/pz-email-active.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": "Text",
12
13
  "icon": "images/pz-text-input-active.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "images/pz-text-area-active.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "images/pz-phone-active.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "images/pz-url-active.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "images/pz-date-time-active.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "OneColumnDetails.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "TwoColumnDetails.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "DefaultForm.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "TwoColumn.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "OneColumnPage.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "OneColumnPage.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "OneColumnPage.svg",
@@ -7,6 +7,7 @@
7
7
  "library": "{{LIBRARY}}",
8
8
  "allowedApplications": {{{ALLOWEDAPPS}}},
9
9
  "componentKey": "{{COMPONENT_KEY}}",
10
+ "compName" : "{{COMPONENT_CLASS_NAME}}",
10
11
  "type": "{{TYPE}}",
11
12
  "subtype": {{{SUB_TYPE}}},
12
13
  "icon": "OneColumnPage.svg",
@@ -1,121 +1,23 @@
1
- Your task is to generate a custom DX component based on the Pega Constellation architecture. A custom DX component is a React functional component that uses hooks. Create the first iteration of this component using the code template below, delimited by the second set of triple backticks.
1
+ You are a Pega Digital Experience (DX) Component and React expert who only produces sample code with no additional narrative. A Pega React DX Component is a functional component that uses hooks, PropTypes and StyledComponents.
2
2
 
3
- Replace MyOrg, MyLib and MyComponent with the text specified in InputProperties called organization, library and name respectively that is provided in the in the json properties array delimited by the fourth set of triple backticks. Be aware that MyComponent should be derived from the last part of the componentKey text that is delimited by a '_'. Based on the example component definition delimited by the third set of three backticks, replace the component props and PropTypes with the properties defined in the properties json array delimited by the fourth set of backticks.
4
3
 
5
- DesignSystemComponents is an array of jsx React components. Replace the DesignSystemComponents import with the comma delimited list of imported components from '@pega/cosmos-react-core' with the text specified in DesignSystemComponents, delimited by the first set of triple backticks. Also add in the jsx components in the render function.
4
+ Very important: The name of the component comes from component definition compName.
6
5
 
7
- {{COMPONENT_ADDITIONAL}}
6
+ Very important: The type of component to be created comes from component definition subtype.
7
+
8
+ Very important: A DX component has all of it's data passed in via a single object that must always be called props. The object properties are then destructured in the component. There is always a function passed in called getPConnect() that is required. All event handlers are created in the same component and not passed in via the props object. Apart from getPConnect() all of the object properties are defined in an array called properties in a file called config.json (a.k.a the component definition).
8
9
 
9
- DesignSystemComponents:
10
- ```{{COMPONENT_DSC}}```
11
10
 
12
- Template:
13
- ```
14
- import PropTypes from 'prop-types';
15
- import { DesignSystemComponents } from '@pega/cosmos-react-core';
16
- import StyledMyOrgMyLibMyComponentWrapper from './styles';
11
+ Presentation components are imported from the Constellation Design System from the packages @pega/cosmos-react-core, @pega/cosmos-react-work, @pega/cosmos-react-social.
17
12
 
18
- export default function MyOrgMyLibMyComponent(props) {
19
- const { getPConnect, visibility, disabled, required, aNumber, aString, aBoolean } = props;
13
+ {{COMPONENT_ADDITIONAL}}
14
+
15
+ Build a component defined by subtype in component definition.
20
16
 
21
- const pConn = getPConnect();
17
+ Should use the following design system components
22
18
 
23
- return (
24
- <StyledMyOrgMyLibMyPageWidgetWrapper>
25
- <DesignSystemComponent
26
- input1 = {aNumber}
27
- input2 = {aString}
28
- input3 = {aBoolean}
29
- />
30
- </StyledMyOrgMyLibMyPageWidgetWrapper>
31
- );
32
- }
19
+ DesignSystemComponents:
20
+ {{COMPONENT_DSC}}
33
21
 
34
- MyOrgMyLibMyComponent.defaultProps = {
35
- aString: '',
36
- aNumber: 0,
37
- aBoolean: false,
38
- visibility: true,
39
- disabled: false,
40
- required: false
41
- }
42
- MyOrgMyLibMyComponent.propTypes = {
43
- aString: PropTypes.string,
44
- aNumber: PropTypes.number,
45
- aBoolean: PropTypes.bool,
46
- visibility: PropTypes.string.bool,
47
- disabled: PropTypes.string.bool,
48
- required: PropTypes.string.bool,
49
- getPConnect: PropTypes.func.isRequired
50
- }
51
- ```
52
- ExampleComponentDefinition:
53
- ```
54
- {
55
- "name": "MyOrg_MyLib_MyComponent",
56
- "label": "My Component",
57
- "description": "My Component",
58
- "organization": "MyOrg",
59
- "version": "01.01.01",
60
- "library": "MyLib",
61
- "allowedApplications": [],
62
- "componentKey": "MyOrg_MyLib_MyComponent",
63
- "type": "",
64
- "subtype": "",
65
- "properties": [
66
- {
67
- "name": "aString",
68
- "label": "aString value",
69
- "format": "TEXT"
70
- },
71
- {
72
- "name": "aBoolean",
73
- "label": "aBoolean value",
74
- "format": "BOOLEAN"
75
- },
76
- {
77
- "name": "aNumber",
78
- "label": "aNumber value",
79
- "format": "NUMBER",
80
- "defaultValue": "0"
81
- },
82
- {
83
- "name": "visibility",
84
- "label": "Visible",
85
- "format": "VISIBILITY"
86
- },
87
- {
88
- "name": "disabled",
89
- "label": "Disabled",
90
- "format": "DISABLED",
91
- "visibility": "(!$this.readOnly = true)"
92
- },
93
- {
94
- "name": "required",
95
- "label": "Required",
96
- "format": "REQUIRED",
97
- "visibility": "(!$this.readOnly = true)"
98
- },
99
- {
100
- "label": "Advanced",
101
- "format": "GROUP",
102
- "collapsible": true,
103
- "properties": [
104
- {
105
- "name": "testId",
106
- "label": "Test ID",
107
- "format": "TEXT",
108
- "ignorePattern": "[^-_\\p{N}\\p{L}]",
109
- "includeAnnotations": false
110
- }
111
- ]
112
- }
113
- ],
114
- "defaultConfig": {
115
- }
116
- }
117
- ```
118
- InputProperties:
119
- ```
22
+ Here is the component definition
120
23
  {{COMPONENT_CONFIG}}
121
- ```
@@ -0,0 +1,14 @@
1
+ You are a Pega Digital Experience (DX) Component and React expert who only produces sample code with no additional narrative. A Pega React DX Component is a functional component that uses hooks, PropTypes and StyledComponents.
2
+
3
+
4
+ Very important: The name of the component comes from component definition compName.
5
+
6
+ Very important: A DX component has all of it's data passed in via a single object that must always be called props. The object properties are then destructured in the component. There is always a function passed in called getPConnect() that is required. All event handlers are created in the same component and not passed in via the props object. Apart from getPConnect() all of the object properties are defined in an array called properties in a file called config.json (a.k.a the component definition).
7
+
8
+
9
+ Presentation components are imported from the Constellation Design System from the packages @pega/cosmos-react-core, @pega/cosmos-react-work, @pega/cosmos-react-social.
10
+
11
+ {{COMPONENT_ADDITIONAL}}
12
+
13
+ Here is the component definition
14
+ {{COMPONENT_CONFIG}}
@@ -6,68 +6,124 @@ import { URL, fileURLToPath } from 'url';
6
6
  import { join } from 'path';
7
7
  import fs from 'fs';
8
8
 
9
- import { AI_PROMPT_FILENAME } from '../../constants.js';
9
+ import {
10
+ AI_PROMPT_FILENAME,
11
+ AI_DAVINCI_PROMPT_FILENAME
12
+ } from '../../constants.js';
10
13
 
11
14
  import _ from 'lodash';
12
15
 
13
16
 
14
17
  import {
15
18
  getComponents,
19
+ getComponentsOfType,
16
20
  getPegaConfig,
17
21
  getAIPromptData,
18
22
  getDirectoryFiles,
19
23
  getAIComponent,
24
+ getInfinityAIComponent,
20
25
  getComponentDirectoryPath,
21
26
  compileMustacheTemplate,
22
- getComponentConfigJson
27
+ getComponentConfigJson,
28
+ getComponentConfigType
23
29
  } from '../../util.js';
24
30
  import { str } from 'ajv';
25
31
 
26
32
 
33
+ export const getSelectAComponent = async() => {
34
+ //let localComponents = await getComponents();
35
+ const localComponents = await getComponentsOfType("Widget,Template");
36
+
37
+ let answers;
38
+
39
+ if (localComponents.length > 0) {
40
+ answers = await inquirer.prompt([
41
+ {
42
+ name: 'componentKey',
43
+ type: 'rawlist',
44
+ message: 'Select component to generateAI',
45
+ choices: localComponents
46
+ }]);
47
+ }
48
+
49
+ return answers;
50
+ }
27
51
 
52
+ export const determineAndGenerateAI = async (enteredKey) => {
28
53
 
54
+ if (!enteredKey) {
55
+ let answer = await getSelectAComponent();
56
+ if (answer) {
57
+ enteredKey = answer.componentKey;
58
+ }
59
+ else {
60
+ console.log(chalk.bold.redBright(`No custom components to generate AI. Please create a Widget or Template component first.`));
61
+ process.exit(1);
62
+ }
63
+
64
+ }
65
+
66
+ const targetDirectory = await getComponentDirectoryPath(enteredKey);
67
+ const configType = await getComponentConfigType(targetDirectory);
68
+
69
+ switch (configType.toLowerCase()) {
70
+ case "widget":
71
+ case "template":
72
+ await getWidgetTemplateAndGenerateAI(enteredKey);
73
+ break;
74
+ case "field":
75
+ await getFieldAndGenerateAI(enteredKey);
76
+ break;
77
+ }
29
78
 
30
- export const getComponentAndGenerateAI = async (enteredKey) => {
79
+
80
+ }
81
+
82
+ export const getWidgetTemplateAndGenerateAI = async (enteredKey) => {
31
83
  const localComponents = await getComponents();
32
84
 
33
85
  let answers;
34
86
 
35
87
  if (localComponents.length > 0) {
36
88
 
37
- if (enteredKey && enteredKey != "") {
38
- answers = await inquirer.prompt([
39
- {
40
- name: 'designSystemComponents',
41
- message: 'Enter comma delimited string of Design system components (ie. Input, TextArea, etc.)'
42
- },
43
- {
44
- name: 'additionalPromptInfo',
45
- message: 'Enter any additional generation information',
46
- }
89
+ answers = await inquirer.prompt([
47
90
 
91
+ {
92
+ name: 'additionalPromptInfo',
93
+ message: 'Enter what you would like this component to do? ',
94
+ }
48
95
 
49
- ]);
50
- }
51
- else {
52
- answers = await inquirer.prompt([
53
- {
54
- name: 'componentKey',
55
- type: 'rawlist',
56
- message: 'Select component to generateAI',
57
- choices: localComponents,
58
- },
59
- {
60
- name: 'designSystemComponents',
61
- message: 'Enter comma delimited string of Design system components (ie. Input, TextArea, etc.)'
62
- },
63
- {
64
- name: 'additionalPromptInfo',
65
- message: 'Enter any additional generation information',
66
- }
67
96
 
97
+ ]);
68
98
 
69
- ]);
70
- }
99
+ console.log("Generating component...");
100
+
101
+ await generateInfinityAIComponent(enteredKey, answers.additionalPromptInfo);
102
+
103
+ } else {
104
+ console.log(chalk.bold.redBright(`No custom components in ${sourceOfComponents}`));
105
+ }
106
+ };
107
+
108
+
109
+ export const getFieldAndGenerateAI = async (enteredKey) => {
110
+ const localComponents = await getComponents();
111
+
112
+ let answers;
113
+
114
+ if (localComponents.length > 0) {
115
+
116
+ answers = await inquirer.prompt([
117
+ {
118
+ name: 'designSystemComponents',
119
+ message: 'Enter comma delimited string of Design system components (ie. Input, TextArea, etc.)'
120
+ },
121
+ {
122
+ name: 'additionalPromptInfo',
123
+ message: 'Enter any additional generation information',
124
+ }
125
+
126
+ ]);
71
127
 
72
128
 
73
129
  console.log("Generating component...");
@@ -95,90 +151,207 @@ export const generateAIComponent = async (componentKey, designSystemComponents,
95
151
  // get config file
96
152
  //
97
153
  const targetDirectory = await getComponentDirectoryPath(componentKey);
98
- const configFile = await getComponentConfigJson(targetDirectory);
154
+ let configFileData = await getComponentConfigJson(targetDirectory);
155
+
156
+ // let data = JSON.parse(configFileData);
157
+ // data.properties = [];
158
+ // configFileData = JSON.stringify(data);
159
+
99
160
 
100
161
  let strPrompt = compileMustacheTemplate(fileURLToPath(new URL(fileName, import.meta.url)), {
101
- COMPONENT_CONFIG: configFile,
162
+ COMPONENT_CONFIG: configFileData,
102
163
  COMPONENT_DSC: designSystemComponents,
103
164
  COMPONENT_ADDITIONAL: additionalPromptInfo
104
165
  });
105
166
 
167
+ strPrompt = strPrompt.replaceAll("$", "//$");
168
+
106
169
  strPrompt = _.unescape(strPrompt);
107
170
 
171
+
108
172
  //let strPrompt = await getAIPromptData(fileURLToPath(new URL(fileName, import.meta.url)));
109
- let aiComponent = await getAIComponent(strPrompt);
173
+ //let aiComponent = await getAIComponent(strPrompt);
174
+ let aiComponent = await getInfinityAIComponent(strPrompt);
110
175
 
111
- //console.log(aiData);
112
- const indexFile = join(targetDirectory, "index.jsx");
176
+ if (aiComponent) {
177
+ //console.log(aiData);
178
+ const indexFile = join(targetDirectory, "index.jsx");
179
+
180
+ // remove enclosed ``` and "Answer:"
181
+ aiComponent = aiComponent.substring(aiComponent.indexOf("import"));
182
+ aiComponent = aiComponent.substring(0, aiComponent.lastIndexOf("```"));
183
+
184
+
185
+
186
+ // get directory list
187
+ // check for index-template.jsx.old
188
+ // if not there, copy index.jsx to index-template.jsx.old and then copy aiComponent to index.jsx
189
+ // if there, check if have index-genai-1.jsx.old, if not, then copy index.jsx, to index-genai-1.jsx.old
190
+ // otherwise, find all index-genai-X and find biggest number and add one, and save index.jsx to that and then create index.jsx
113
191
 
114
- // remove enclosed ``` and "Answer:"
115
- aiComponent = aiComponent.substring(aiComponent.indexOf("import"));
116
- aiComponent = aiComponent.substring(0, aiComponent.lastIndexOf("```"));
192
+ const dirList = await getDirectoryFiles(targetDirectory);
117
193
 
194
+ if (dirList.includes("index-template.jsx.old")) {
118
195
 
196
+ const genList = dirList.map( (el) => {
197
+ if (el.indexOf("index-genai") >= 0) {
198
+ return el;
199
+ }
200
+ else {
201
+ return "";
202
+ }
203
+ });
204
+
205
+ if (genList.length > 0) {
206
+ let lastIndex = 0;
119
207
 
120
- // get directory list
121
- // check for index-template.jsx.old
122
- // if not there, copy index.jsx to index-template.jsx.old and then copy aiComponent to index.jsx
123
- // if there, check if have index-genai-1.jsx.old, if not, then copy index.jsx, to index-genai-1.jsx.old
124
- // otherwise, find all index-genai-X and find biggest number and add one, and save index.jsx to that and then create index.jsx
208
+ genList.forEach((el) => {
209
+ const theName = el.split(".")[0];
210
+ const theIndex = theName.split("-")[2];
125
211
 
126
- const dirList = await getDirectoryFiles(targetDirectory);
212
+ if (parseInt(theIndex) > lastIndex) {
213
+ lastIndex = parseInt(theIndex);
214
+ }
215
+ });
127
216
 
128
- if (dirList.includes("index-template.jsx.old")) {
217
+ lastIndex++;
129
218
 
130
- const genList = dirList.map( (el) => {
131
- if (el.indexOf("index-genai") >= 0) {
132
- return el;
219
+ const oldGenFileName = join(targetDirectory, "index.jsx");
220
+ const newGenFileName = join(targetDirectory, "index-genai-" + lastIndex + ".jsx.old");
221
+
222
+ renameFile(oldGenFileName, newGenFileName);
133
223
  }
134
224
  else {
135
- return "";
225
+ const oldGenFileName = join(targetDirectory, "index.jsx");
226
+ const newGenFileName = join(targetDirectory, "index-genai-1.jsx.old");
227
+
228
+ renameFile(oldGenFileName, newGenFileName);
229
+ }
230
+ }
231
+ else {
232
+ // so only index.jsx, so rename index.jsx to index-template.jsx.old
233
+ // and create a new index.jsx
234
+ const oldFileName = join(targetDirectory, "index.jsx");
235
+ const newFileName = join(targetDirectory, "index-template.jsx.old");
236
+
237
+ renameFile(oldFileName, newFileName);
238
+ }
239
+
240
+ // creae new index.jsx
241
+ fs.writeFileSync(indexFile, aiComponent, err => {
242
+ if (err) {
243
+ Promise.reject(`${chalk.bold.red(err)}`);
136
244
  }
137
245
  });
138
246
 
247
+ console.log(`Updated file ${chalk.green('index.jsx')} in directory ${chalk.green(componentKey)} with AI generated code.`);
248
+ }
249
+
250
+
251
+
252
+
253
+ }
254
+
255
+ export const generateInfinityAIComponent = async (componentKey, additionalPromptInfo) => {
256
+
257
+ const fileName = "." + path.sep + AI_DAVINCI_PROMPT_FILENAME;
258
+
259
+ // get config file
260
+ //
261
+ const targetDirectory = await getComponentDirectoryPath(componentKey);
262
+ let configFileData = await getComponentConfigJson(targetDirectory);
263
+
264
+ // need to escape $
265
+ configFileData = configFileData.replaceAll("$", "\\$");
266
+
267
+ let strPrompt = compileMustacheTemplate(fileURLToPath(new URL(fileName, import.meta.url)), {
268
+ COMPONENT_CONFIG: configFileData,
269
+ COMPONENT_ADDITIONAL: additionalPromptInfo
270
+ });
271
+
272
+ strPrompt = _.unescape(strPrompt);
273
+
274
+ //let strPrompt = await getAIPromptData(fileURLToPath(new URL(fileName, import.meta.url)));
275
+ let aiComponent = await getInfinityAIComponent(strPrompt);
276
+
277
+ //console.log(aiData);
278
+
279
+ if (aiComponent) {
280
+ const indexFile = join(targetDirectory, "index-genai.jsx.tmp");
281
+
282
+ // remove enclosed ``` and "Answer:"
283
+ if (aiComponent.indexOf("```") >= 0) {
284
+ aiComponent = aiComponent.substring(aiComponent.indexOf("```"));
285
+ aiComponent = aiComponent.substring(0, aiComponent.lastIndexOf("```"));
286
+ }
287
+ else if (aiComponent.indexOf("'") == 0) {
288
+ aiComponent = aiComponent.substring(aiComponent.indexOf("'"));
289
+ aiComponent = aiComponent.substring(0, aiComponent.lastIndexOf("'"));
290
+ }
291
+
292
+
293
+
294
+
295
+ // get directory list
296
+ // check for index-template.jsx.old
297
+ // if not there, copy index.jsx to index-template.jsx.old and then copy aiComponent to index.jsx
298
+ // if there, check if have index-genai-1.jsx.old, if not, then copy index.jsx, to index-genai-1.jsx.old
299
+ // otherwise, find all index-genai-X and find biggest number and add one, and save index.jsx to that and then create index.jsx
300
+
301
+ const dirList = await getDirectoryFiles(targetDirectory);
302
+
303
+
304
+
305
+ const genList = dirList.map( (el) => {
306
+ if (el.indexOf("index-genai") >= 0) {
307
+ return el;
308
+ }
309
+ else {
310
+ return "";
311
+ }
312
+ });
313
+
139
314
  if (genList.length > 0) {
140
- let lastIndex = 0;
315
+ let lastIndex = -1;
141
316
 
142
317
  genList.forEach((el) => {
143
318
  const theName = el.split(".")[0];
144
- const theIndex = theName.split("-")[2];
145
319
 
146
- if (parseInt(theIndex) > lastIndex) {
147
- lastIndex = parseInt(theIndex);
320
+ if (theName.indexOf("index-genai") >=0) {
321
+ if (lastIndex === -1) {
322
+ lastIndex = 0;
323
+ }
324
+ const theIndex = theName.split("-")[2];
325
+
326
+ if (parseInt(theIndex) > lastIndex) {
327
+ lastIndex = parseInt(theIndex);
328
+ }
148
329
  }
330
+
149
331
  });
150
332
 
151
333
  lastIndex++;
152
334
 
153
- const oldGenFileName = join(targetDirectory, "index.jsx");
154
- const newGenFileName = join(targetDirectory, "index-genai-" + lastIndex + ".jsx.old");
335
+ if (lastIndex > 0) {
336
+ const oldGenFileName = join(targetDirectory, "index-genai.jsx.tmp");
337
+ const newGenFileName = join(targetDirectory, "index-genai-" + lastIndex + ".jsx.tmp");
155
338
 
156
- renameFile(oldGenFileName, newGenFileName);
157
- }
158
- else {
159
- const oldGenFileName = join(targetDirectory, "index.jsx");
160
- const newGenFileName = join(targetDirectory, "index-genai-1.jsx.old");
339
+ renameFile(oldGenFileName, newGenFileName);
340
+ }
161
341
 
162
- renameFile(oldGenFileName, newGenFileName);
163
342
  }
164
- }
165
- else {
166
- // so only index.jsx, so rename index.jsx to index-template.jsx.old
167
- // and create a new index.jsx
168
- const oldFileName = join(targetDirectory, "index.jsx");
169
- const newFileName = join(targetDirectory, "index-template.jsx.old");
170
343
 
171
- renameFile(oldFileName, newFileName);
172
- }
173
344
 
174
- // creae new index.jsx
175
- fs.writeFileSync(indexFile, aiComponent, err => {
176
- if (err) {
177
- Promise.reject(`${chalk.bold.red(err)}`);
178
- }
179
- });
345
+ // creae new index.jsx
346
+ fs.writeFileSync(indexFile, aiComponent, err => {
347
+ if (err) {
348
+ Promise.reject(`${chalk.bold.red(err)}`);
349
+ }
350
+ });
351
+
352
+ console.log(`Updated file ${chalk.green('index-genai.jsx.tmp')} in directory ${chalk.green(componentKey)} with AI generated code.`);
353
+ }
180
354
 
181
- console.log(`Updated file ${chalk.green('index.jsx')} in directory ${chalk.green(componentKey)} with AI generated code.`);
182
355
 
183
356
 
184
357
  }
@@ -3,8 +3,7 @@ import ora from 'ora';
3
3
  import chalk from 'chalk';
4
4
 
5
5
  import {
6
- getComponentAndGenerateAI,
7
- generateAIComponent
6
+ determineAndGenerateAI
8
7
  } from './helper.js';
9
8
 
10
9
  import { showVersion } from '../../util.js';
@@ -19,11 +18,13 @@ export default async options => {
19
18
  const sourceOfComponents = options.params[3];
20
19
 
21
20
  //await generateAIComponent(sourceOfComponents);
22
- await getComponentAndGenerateAI(sourceOfComponents);
21
+ //await getComponentAndGenerateAI(sourceOfComponents);
22
+ await determineAndGenerateAI(sourceOfComponents);
23
23
  }
24
24
  else {
25
25
 
26
- await getComponentAndGenerateAI();
26
+ //await getComponentAndGenerateAI();
27
+ await determineAndGenerateAI();
27
28
  }
28
29
 
29
30
 
@@ -57,7 +57,7 @@
57
57
  },
58
58
  "devDependencies": {
59
59
  "@pega/configs": "^0.5.3",
60
- "@pega/custom-dx-components": "^0.23.1",
60
+ "@pega/custom-dx-components": "^0.23.2",
61
61
  "@pega/eslint-config": "^0.3.2",
62
62
  "@storybook/addon-actions": "^6.5.12",
63
63
  "@storybook/addon-essentials": "^6.5.12",
@@ -0,0 +1 @@
1
+ # directory for components #
package/src/util.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import fs from 'fs';
2
+ import path from 'path';
2
3
  import { join } from 'path';
3
4
  import { promisify } from 'util';
4
5
  import https from 'https';
@@ -21,6 +22,7 @@ import {
21
22
  OOTB_COMPONENTS,
22
23
  SERVICES_AI_REST_ENDPOINT,
23
24
  BOOTSTRAP_SERVICE_REST_ENDPOINT,
25
+ DXCOMPGENAI_SERVICE_REST_ENDPOINT,
24
26
  SERVICE_TOKEN_PATH
25
27
  } from './constants.js';
26
28
 
@@ -142,6 +144,46 @@ export const getComponents = async () => {
142
144
  .map(dirent => dirent.name);
143
145
  };
144
146
 
147
+ export const getComponentsOfType = async (componentType) => {
148
+ const componentList = await getComponents();
149
+ let filteredList = Array();
150
+ if (componentList.length > 0) {
151
+
152
+ const currentDirectory = process.cwd();
153
+ const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
154
+
155
+ await checkPathAccess(pegaConfigJsonPath);
156
+
157
+ let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
158
+ data = JSON.parse(data);
159
+
160
+ if (!data[COMPONENTS_DIRECTORY_PATH]) {
161
+ console.error(
162
+ `${chalk.red.bold('ERROR')} Could not able find components directory path in config.json`
163
+ );
164
+ process.exit(1);
165
+ }
166
+
167
+ const directory = join(currentDirectory, data[COMPONENTS_DIRECTORY_PATH]);
168
+ const arTypes = componentType.split(",");
169
+
170
+ for (let index in componentList) {
171
+ let compDir = directory + path.sep + componentList[index];
172
+ let type = await getComponentConfigType(compDir);
173
+ if (arTypes.includes(type)) {
174
+ filteredList.push( componentList[index]);
175
+ }
176
+ }
177
+
178
+
179
+
180
+ return filteredList;
181
+ }
182
+ else {
183
+ return componentList;
184
+ }
185
+ };
186
+
145
187
 
146
188
 
147
189
 
@@ -219,6 +261,15 @@ export const getComponentConfigJson = async (componentDirectory) => {
219
261
  return data;
220
262
  }
221
263
 
264
+ export const getComponentConfigType = async (componentDirectory) => {
265
+ const configData = await getComponentConfigJson(componentDirectory);
266
+
267
+ let data = JSON.parse(configData);
268
+
269
+ return data.type;
270
+
271
+ }
272
+
222
273
  export const getPegaServerConfig = async () => {
223
274
  const config = await getPegaConfig();
224
275
  return config['server-config'];
@@ -516,3 +567,77 @@ export const getAIComponent = async (prompt) => {
516
567
 
517
568
  return returnCode;
518
569
  };
570
+
571
+
572
+ export const getInfinityAIComponent = async (prompt) => {
573
+ const { server } = await getPegaServerConfig();
574
+ const dataPageUrl = constructCompleteUrl(server, DXCOMPGENAI_SERVICE_REST_ENDPOINT);
575
+
576
+ const jsonBody = { "dataViewParameters" : { "Prompt" : prompt } };
577
+
578
+
579
+
580
+ let returnCode = "";
581
+
582
+ try {
583
+ const OauthData = fs.readFileSync(TOKEN_PATH, 'utf8');
584
+
585
+ if (OauthData) {
586
+ let {
587
+ access_token: accessToken,
588
+ token_type: tokenType,
589
+ refresh_token: refreshToken
590
+ } = JSON.parse(OauthData);
591
+
592
+ // services needs Bearer with a big "B"
593
+ //tokenType = convertIntoPascalCase(tokenType);
594
+
595
+ await fetch(dataPageUrl, {
596
+ method: 'POST',
597
+ agent: new https.Agent({ rejectUnauthorized: false }),
598
+ headers: {
599
+ Authorization: `${tokenType} ${accessToken}`
600
+ },
601
+ body: JSON.stringify(jsonBody),
602
+ })
603
+ .then(response => response.text())
604
+ .then(data => {
605
+
606
+ try {
607
+ const returnData = JSON.parse(data);
608
+
609
+ if (returnData != null && returnData.data) {
610
+ returnCode = returnData.data[0].pyValue;
611
+ }
612
+ else if (returnData != null && returnData.errors) {
613
+ if (returnData.errors[0].message.indexOf("token") >= 0) {
614
+ Promise.reject(`${chalk.bold.red("ERROR: Need to authenticate or reauthenticate.")}`);
615
+ }
616
+ }
617
+ else {
618
+ returnCode = "";
619
+ Promise.reject(`Error in AI generation: \n ${chalk.bold.red(data)}`);
620
+ }
621
+ }
622
+ catch {
623
+ Promise.reject(`Error in AI generation: \n ${chalk.bold.red(data)}`);
624
+ //throw new Error('Error occurred in validation', data);
625
+ }
626
+
627
+
628
+ })
629
+ .catch(e => Promise.reject(`Error in AI generation: \n ${chalk.bold.red(e)}`));
630
+ }
631
+ }
632
+ catch (error) {
633
+ if (error.code === 'ENOENT') {
634
+ Promise.reject(`${chalk.bold.red("ERROR: Need to authenticate or reauthenticate.")}`);
635
+ }
636
+ else {
637
+ throw new Error('Error occurred in validation', error);
638
+ }
639
+
640
+ }
641
+
642
+ return returnCode;
643
+ };
@@ -1,19 +0,0 @@
1
- import type { Meta, Story } from '@storybook/react';
2
-
3
- import MediaURLInput from './MediaURLInput';
4
- import MediaURLDisplay from './MediaURLDisplay';
5
-
6
- export default {
7
- title: 'MediaURL',
8
- parameters: {
9
- layout: 'centered'
10
- }
11
- } as Meta;
12
-
13
- export const InputMode: Story = () => {
14
- return <MediaURLInput label='Media src url' />;
15
- };
16
-
17
- export const DisplayMode: Story = () => {
18
- return <MediaURLDisplay value='https://youtu.be/BxogmCLpy0w' />;
19
- };
@@ -1,5 +0,0 @@
1
- import styled, { css } from 'styled-components';
2
-
3
- export default styled.div(() => {
4
- return css``;
5
- });
@@ -1,10 +0,0 @@
1
- import type { FormControlProps, OmitStrict, URLDisplayProps } from '@pega/cosmos-react-core';
2
-
3
- export interface MediaURLInputProps extends OmitStrict<FormControlProps, 'defaultValue'> {
4
- testId?: string;
5
- }
6
-
7
- export interface MediaURLDisplayProps extends OmitStrict<URLDisplayProps, 'variant' | 'ref'> {
8
- variant?: 'player' | URLDisplayProps['variant'];
9
- testId?: string;
10
- }
@@ -1,25 +0,0 @@
1
- import type { FunctionComponent } from 'react';
2
- import { URLDisplay } from '@pega/cosmos-react-core';
3
- import ReactPlayer from 'react-player';
4
-
5
- import StyledMediaURLDisplay from './MediaURL.styles';
6
- import type { MediaURLDisplayProps } from './MediaURL.types';
7
-
8
- const MediaURLDisplay: FunctionComponent<MediaURLDisplayProps> = ({
9
- value,
10
- variant = 'player',
11
- testId,
12
- ...restProps
13
- }) => {
14
- if ((!value && variant !== 'player') || variant !== 'player') {
15
- return <URLDisplay value={value} variant={variant} {...restProps} />;
16
- }
17
-
18
- return (
19
- <StyledMediaURLDisplay data-testid={testId}>
20
- <ReactPlayer url={value} />
21
- </StyledMediaURLDisplay>
22
- );
23
- };
24
-
25
- export default MediaURLDisplay;
@@ -1,24 +0,0 @@
1
- import { ChangeEvent, FunctionComponent, useState } from 'react';
2
- import { Input } from '@pega/cosmos-react-core';
3
-
4
- import type { MediaURLInputProps } from './MediaURL.types';
5
-
6
- const MediaURLInput: FunctionComponent<MediaURLInputProps> = ({
7
- value,
8
- ...restProps
9
- }: MediaURLInputProps) => {
10
- const [url, setURL] = useState(value);
11
-
12
- return (
13
- <Input
14
- {...restProps}
15
- type='url'
16
- value={url}
17
- onChange={(e: ChangeEvent<HTMLInputElement>) => {
18
- setURL(e.target.value);
19
- }}
20
- />
21
- );
22
- };
23
-
24
- export default MediaURLInput;
@@ -1,13 +0,0 @@
1
- {
2
- "name": "Organization_Library_MediaURL",
3
- "label": "MediaURL",
4
- "description": "A pair of components for taking input and displaying teh value of a video or audio url.",
5
- "organization": "TBD",
6
- "version": "0.0.1",
7
- "library": "TBD",
8
- "componentKey": "Organization_Library_MediaURL",
9
- "type": "Field",
10
- "subtype": "Text",
11
- "icon": "TBD",
12
- "properties": ["TBD"]
13
- }
@@ -1,2 +0,0 @@
1
- export { default as MediaURLInput } from './MediaURLInput';
2
- export { default as MediaURLDisplay } from './MediaURLDisplay';
@@ -1,44 +0,0 @@
1
- {
2
- "name": "Organization_Library_VideoPlayer",
3
- "label": "Video Player",
4
- "description": "video player",
5
- "organization": "apple",
6
- "version": "0.0.1",
7
- "library": "basic",
8
- "componentKey": "Organization_Library_VideoPlayer",
9
- "type": "Field",
10
- "subtype": "Text",
11
- "icon": "images/pz-text-input-active.svg",
12
- "properties": [
13
- {
14
- "name": "value",
15
- "label": "Property",
16
- "format": "PROPERTY"
17
- },
18
- {
19
- "name": "label",
20
- "label": "Label value",
21
- "format": "TEXT"
22
- },
23
- {
24
- "name": "placeholder",
25
- "label": "Placeholder",
26
- "format": "TEXT"
27
- },
28
- {
29
- "name": "visibility",
30
- "label": "Visible",
31
- "format": "VISIBILITY"
32
- },
33
- {
34
- "name": "disabled",
35
- "label": "Disabled",
36
- "format": "DISABLED"
37
- },
38
- {
39
- "name": "required",
40
- "label": "Required",
41
- "format": "REQUIRED"
42
- }
43
- ]
44
- }
@@ -1,40 +0,0 @@
1
- import React, { useState } from 'react';
2
- import { withKnobs, text, boolean } from '@storybook/addon-knobs';
3
-
4
- import VideoPlayer from './index';
5
-
6
- export default {
7
- title: 'VideoPlayer',
8
- decorators: [withKnobs],
9
- component: VideoPlayer
10
- };
11
-
12
- export const baseVideoPlayer = () => {
13
- const [value, setValue] = useState('test value');
14
-
15
- const props = {
16
- getPConnect: () => {
17
- return {
18
- getActionsApi: () => {
19
- return {
20
- updateFieldValue: (propName, value) => {
21
- setValue(value);
22
- }
23
- };
24
- },
25
- getStateProps: () => {
26
- return { value: '.name' };
27
- }
28
- };
29
- },
30
- value: text('src', 'https://www.youtube.com/watch?v=EtG5IuNGYSk'),
31
- placeholder: text('Placeholder', 'Test placeholder'),
32
- disabled: boolean('Disabled', false),
33
- readOnly: boolean('Disabled', false),
34
- required: boolean('Disabled', false),
35
- label: text('Label', 'Video player label'),
36
- testId: text('Test id', 'video-12344566')
37
- };
38
-
39
- return <VideoPlayer {...props} />;
40
- };
@@ -1,42 +0,0 @@
1
- import PropTypes from 'prop-types';
2
- import React from 'react';
3
- import { Label } from '@pega/cosmos-react-core';
4
- import ReactPlayer from 'react-player';
5
-
6
- import StyledVideoPlayerWrapper from './styles';
7
-
8
- const VideoPlayer = props => {
9
- const { getPConnect, value, placeholder, disabled, readOnly, required, label } = props;
10
-
11
- const pConn = getPConnect();
12
- const actions = pConn.getActionsApi();
13
- const propName = pConn?.getStateProps()?.value;
14
-
15
- return (
16
- <StyledVideoPlayerWrapper>
17
- <Label>{label}</Label>
18
- <ReactPlayer url={value} />
19
- </StyledVideoPlayerWrapper>
20
- );
21
- };
22
-
23
- VideoPlayer.defaultProps = {
24
- value: '',
25
- placeholder: '',
26
- disabled: false,
27
- readOnly: false,
28
- required: false,
29
- testId: null
30
- };
31
- VideoPlayer.propTypes = {
32
- label: PropTypes.string,
33
- value: PropTypes.string.isRequired,
34
- placeholder: PropTypes.string,
35
- getPConnect: PropTypes.func.isRequired,
36
- disabled: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
37
- readOnly: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
38
- required: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
39
- testId: PropTypes.string
40
- };
41
-
42
- export default VideoPlayer;
@@ -1,5 +0,0 @@
1
- import styled, { css } from 'styled-components';
2
-
3
- export default styled.div(() => {
4
- return css``;
5
- });