@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.
- package/package.json +1 -1
- package/src/constants.js +3 -0
- package/src/tasks/create/templates/Constellation/Field/Boolean/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Field/Date/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Field/DateTime/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Currency/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Field/Decimal-Percentage/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Field/Integer/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Field/Picklist/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Field/Text/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Email/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Input/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Paragraph/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Field/Text-Phone/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Field/Text-URL/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Field/TimeOfDay/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Template/DETAILS-region/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Template/FORM/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Template/FORM-region/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Template/PAGE/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Widget/CASE/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Widget/PAGE/config.json.mustache +1 -0
- package/src/tasks/create/templates/Constellation/Widget/PAGE-CASE/config.json.mustache +1 -0
- package/src/tasks/generate-ai/aiPrompt.txt.mustache +13 -111
- package/src/tasks/generate-ai/aiPromptDavinci.txt.mustache +14 -0
- package/src/tasks/generate-ai/helper.js +252 -79
- package/src/tasks/generate-ai/index.js +5 -4
- package/src/tasks/init/template/package.json.mustache +1 -1
- package/src/tasks/init/template/src/components/_components.md +1 -0
- package/src/util.js +125 -0
- package/src/tasks/init/template/src/components/Organization_Library_MediaURL/MediaURL.stories.tsx +0 -19
- package/src/tasks/init/template/src/components/Organization_Library_MediaURL/MediaURL.styles.ts +0 -5
- package/src/tasks/init/template/src/components/Organization_Library_MediaURL/MediaURL.types.ts +0 -10
- package/src/tasks/init/template/src/components/Organization_Library_MediaURL/MediaURLDisplay.tsx +0 -25
- package/src/tasks/init/template/src/components/Organization_Library_MediaURL/MediaURLInput.tsx +0 -24
- package/src/tasks/init/template/src/components/Organization_Library_MediaURL/config.json +0 -13
- package/src/tasks/init/template/src/components/Organization_Library_MediaURL/index.ts +0 -2
- package/src/tasks/init/template/src/components/Organization_Library_VideoPlayer/config.json +0 -44
- package/src/tasks/init/template/src/components/Organization_Library_VideoPlayer/demo.stories.jsx +0 -40
- package/src/tasks/init/template/src/components/Organization_Library_VideoPlayer/index.jsx +0 -42
- package/src/tasks/init/template/src/components/Organization_Library_VideoPlayer/styles.js +0 -5
package/package.json
CHANGED
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';
|
|
@@ -1,121 +1,23 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
4
|
+
Very important: The name of the component comes from component definition compName.
|
|
6
5
|
|
|
7
|
-
|
|
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
|
-
|
|
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
|
-
|
|
19
|
-
|
|
13
|
+
{{COMPONENT_ADDITIONAL}}
|
|
14
|
+
|
|
15
|
+
Build a component defined by subtype in component definition.
|
|
20
16
|
|
|
21
|
-
|
|
17
|
+
Should use the following design system components
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<DesignSystemComponent
|
|
26
|
-
input1 = {aNumber}
|
|
27
|
-
input2 = {aString}
|
|
28
|
-
input3 = {aBoolean}
|
|
29
|
-
/>
|
|
30
|
-
</StyledMyOrgMyLibMyPageWidgetWrapper>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
19
|
+
DesignSystemComponents:
|
|
20
|
+
{{COMPONENT_DSC}}
|
|
33
21
|
|
|
34
|
-
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
112
|
-
|
|
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
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
|
|
212
|
+
if (parseInt(theIndex) > lastIndex) {
|
|
213
|
+
lastIndex = parseInt(theIndex);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
127
216
|
|
|
128
|
-
|
|
217
|
+
lastIndex++;
|
|
129
218
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
|
|
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 =
|
|
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 (
|
|
147
|
-
lastIndex
|
|
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
|
-
|
|
154
|
-
|
|
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
|
-
|
|
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
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
+
};
|
package/src/tasks/init/template/src/components/Organization_Library_MediaURL/MediaURL.stories.tsx
DELETED
|
@@ -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
|
-
};
|
package/src/tasks/init/template/src/components/Organization_Library_MediaURL/MediaURL.types.ts
DELETED
|
@@ -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
|
-
}
|
package/src/tasks/init/template/src/components/Organization_Library_MediaURL/MediaURLDisplay.tsx
DELETED
|
@@ -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;
|
package/src/tasks/init/template/src/components/Organization_Library_MediaURL/MediaURLInput.tsx
DELETED
|
@@ -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,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
|
-
}
|
package/src/tasks/init/template/src/components/Organization_Library_VideoPlayer/demo.stories.jsx
DELETED
|
@@ -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;
|