-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #29 from pegasystems/feature/RatingInput
Add new RatingInput component
- Loading branch information
Showing
14 changed files
with
1,556 additions
and
1,054 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { Meta, Primary, Controls, Story } from '@storybook/blocks'; | ||
import * as DemoStories from './demo.stories'; | ||
|
||
<Meta of={DemoStories} /> | ||
|
||
# Overview | ||
|
||
The RatingLayout component is a template component that let you enter a set of numeric values between 1 and 5 - Each set of fields is grouped by tabs representing different categories. | ||
|
||
This template can be used inside an form view by adding the values of the embedded page that will contain all the ratings | ||
|
||
<Primary /> | ||
|
||
## Props | ||
|
||
<Controls /> | ||
|
||
## Example | ||
|
||
Assuming that you have an embedded object called 'Ratings'. This object contains 3 fields: Category, Label and Value. To use this component, create a new subview inside your step, select the RatingLayout template, | ||
add the following 3 fields in the picker in this order: [Ratings.Category, Ratings.Label, Ratings.Value] - These 3 values must be passed in this exact order to be correctly used at runtime. | ||
|
||
 | ||
|
||
 | ||
|
||
 | ||
|
||
Here is how the component looks at runtime: | ||
 |
60 changes: 60 additions & 0 deletions
60
src/components/Pega_Extensions_RatingLayout/RatingElem.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { useState, useMemo } from 'react'; | ||
import { Slider, type SliderProps } from '@pega/cosmos-react-core'; | ||
|
||
type RatingElemProps = { | ||
value: number; | ||
label: string; | ||
propIndex: number; | ||
path: string; | ||
getPConnect?: any; | ||
}; | ||
|
||
const tickValues = ['N/A', 'Low', 'Medium', 'High', 'Severe']; | ||
const RatingElem = (props: RatingElemProps) => { | ||
const { getPConnect, label, value, path, propIndex } = props; | ||
const [inputValue, setInputValue] = useState(value); | ||
const ticksObject: SliderProps['ticks'] = {}; | ||
const numTicks = 5; | ||
Array(numTicks) | ||
.fill(0) | ||
.map((_, index) => index) | ||
.forEach(tick => { | ||
ticksObject![tick + 1] = tickValues[tick]; | ||
}); | ||
|
||
/* When calling updateFieldValue, we need to be in the context of the object in the array | ||
Using useMemo to cache the actionsApi object to only create it once and not when changing tabs | ||
path should be set to the embedded object name like '.Ratings' */ | ||
const actionsApi: any = useMemo(() => { | ||
const messageConfig = { | ||
meta: props, | ||
options: { | ||
context: getPConnect().getContextName(), | ||
pageReference: `caseInfo.content${path}[${propIndex}]`, | ||
target: getPConnect().getTarget() | ||
} | ||
}; | ||
const c11nEnv = (window as any).PCore.createPConnect(messageConfig); | ||
return c11nEnv.getPConnect().getActionsApi(); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [getPConnect]); | ||
|
||
const onChangeValue = (changeValue: number) => { | ||
setInputValue(changeValue); | ||
actionsApi?.updateFieldValue('.Value', changeValue); | ||
}; | ||
|
||
return ( | ||
<Slider | ||
step={1} | ||
min={1} | ||
max={5} | ||
ticks={ticksObject} | ||
showInput={false} | ||
label={label} | ||
value={inputValue} | ||
onChange={onChangeValue} | ||
/> | ||
); | ||
}; | ||
export default RatingElem; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"name": "Pega_Extensions_RatingLayout", | ||
"label": "Rating Layout", | ||
"description": "Rating Layout", | ||
"organization": "Pega", | ||
"version": "1.0.0", | ||
"library": "Extensions", | ||
"allowedApplications": [], | ||
"componentKey": "Pega_Extensions_RatingLayout", | ||
"type": "Template", | ||
"subtype": "DETAILS", | ||
"properties": [ | ||
{ | ||
"name": "minWidth", | ||
"label": "Slider min width", | ||
"format": "TEXT", | ||
"defaultValue": "40ch" | ||
}, | ||
{ | ||
"name": "A", | ||
"label": "Region A", | ||
"format": "CONTENTPICKER", | ||
"addTypeList": ["Fields"] | ||
} | ||
], | ||
"defaultConfig": { | ||
"minWidth": "40ch" | ||
} | ||
} |
169 changes: 169 additions & 0 deletions
169
src/components/Pega_Extensions_RatingLayout/demo.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
import type { StoryObj } from '@storybook/react'; | ||
import PegaExtensionsRatingLayout from './index'; | ||
|
||
type configInfo = { | ||
values?: Array<any>; | ||
value?: string; | ||
componentType?: string; | ||
label?: string; | ||
heading?: string; | ||
}; | ||
|
||
type info = { | ||
config: configInfo; | ||
type: string; | ||
children?: Array<info>; | ||
}; | ||
|
||
export default { | ||
title: 'Templates/Rating Layout', | ||
argTypes: { | ||
getPConnect: { | ||
table: { | ||
disable: true | ||
} | ||
} | ||
}, | ||
component: PegaExtensionsRatingLayout | ||
}; | ||
|
||
const genComponent = (config: any) => { | ||
return config.config.text; | ||
}; | ||
|
||
const setPCore = () => { | ||
(window as any).PCore = { | ||
createPConnect: () => ({ | ||
getPConnect: () => ({ | ||
getActionsApi: () => ({ updateFieldValue: () => {} }) | ||
}) | ||
}) | ||
}; | ||
}; | ||
|
||
const genResponse = (numCategories?: number, numRatings?: number) => { | ||
const demoView = { | ||
name: 'demoView', | ||
type: 'View', | ||
config: { | ||
template: 'Pega_Extensions_RatingLayout', | ||
ruleClass: 'Work-', | ||
inheritedProps: [] | ||
}, | ||
children: [ | ||
{ | ||
name: 'A', | ||
type: 'Region', | ||
children: [] as Array<info>, | ||
getPConnect: () => {} | ||
} | ||
], | ||
classID: 'Work-MyComponents' | ||
}; | ||
const objects_categories = []; | ||
const objects_labels = []; | ||
const objects_values = []; | ||
if (numCategories && numRatings) { | ||
for (let i = 1; i <= numCategories; i += 1) { | ||
for (let j = 1; j <= numRatings; j += 1) { | ||
objects_categories.push(`Category #${i}`); | ||
objects_labels.push(`Category #${i} - label #${j}`); | ||
objects_values.push(Math.floor(Math.random() * 5) + 1); | ||
} | ||
} | ||
} | ||
demoView.children[0].children = [ | ||
{ | ||
config: { | ||
values: objects_categories, | ||
value: '@FILTERED_LIST .Ratings[].Category' | ||
}, | ||
type: 'ScalarList' | ||
}, | ||
{ | ||
config: { | ||
values: objects_labels, | ||
value: '@FILTERED_LIST .Ratings[].Label' | ||
}, | ||
type: 'ScalarList' | ||
}, | ||
{ | ||
config: { | ||
values: objects_values, | ||
value: '@FILTERED_LIST .Ratings[].Value' | ||
}, | ||
type: 'ScalarList' | ||
} | ||
]; | ||
|
||
demoView.children[0].getPConnect = () => { | ||
return { | ||
getRawMetadata: () => { | ||
return demoView.children[0]; | ||
} | ||
}; | ||
}; | ||
return demoView; | ||
}; | ||
|
||
type Story = StoryObj<typeof PegaExtensionsRatingLayout>; | ||
export const Default: Story = { | ||
render: args => { | ||
const response = genResponse(args.numCategories, args.numRatings); | ||
setPCore(); | ||
const props = { | ||
template: 'RatingLayout', | ||
...args, | ||
getPConnect: () => { | ||
return { | ||
getListActions: () => { | ||
return { | ||
update: () => {} | ||
}; | ||
}, | ||
getActionsApi: () => { | ||
return { | ||
updateFieldValue: (prop: string, value: string) => { | ||
// eslint-disable-next-line no-console | ||
//console.log(`Updating property ${prop} with value: ${value}`); | ||
} | ||
}; | ||
}, | ||
getChildren: () => { | ||
return response.children; | ||
}, | ||
getRawMetadata: () => { | ||
return response; | ||
}, | ||
getInheritedProps: () => { | ||
return response.config.inheritedProps; | ||
}, | ||
getContextName: () => { | ||
return 'primary'; | ||
}, | ||
getTarget: () => { | ||
return 'caseInfo'; | ||
}, | ||
createComponent: (config: any) => { | ||
return genComponent(config); | ||
}, | ||
setInheritedProp: () => { | ||
/* nothing */ | ||
}, | ||
setValue: () => { | ||
/* nothing */ | ||
}, | ||
resolveConfigProps: (f: any) => { | ||
return { value: f.values }; | ||
} | ||
}; | ||
} | ||
}; | ||
return <PegaExtensionsRatingLayout {...props}></PegaExtensionsRatingLayout>; | ||
}, | ||
args: { | ||
minWidth: '40ch', | ||
numCategories: 3, | ||
numRatings: 3 | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { render, screen } from '@testing-library/react'; | ||
import { composeStories } from '@storybook/react'; | ||
import * as DemoStories from './demo.stories'; | ||
|
||
const { Default } = composeStories(DemoStories); | ||
|
||
test('renders RatingLayout component with default args', async () => { | ||
render(<Default />); | ||
expect(await screen.findByText('Category #1')).toBeVisible(); | ||
expect(await screen.findByText('Category #2')).toBeVisible(); | ||
expect(await screen.findByText('Category #3')).toBeVisible(); | ||
expect(await screen.findByText('Category #1 - label #1')).toBeVisible(); | ||
}); |
Oops, something went wrong.