Merge branch 'release' into 'master'
Release See merge request theappsmith/internal-tools-client!383
This commit is contained in:
commit
393f7fb33f
3
app/client/.gitignore
vendored
3
app/client/.gitignore
vendored
|
|
@ -29,4 +29,5 @@ yarn-error.log*
|
|||
.idea
|
||||
.storybook-out/
|
||||
cypress/videos
|
||||
results/
|
||||
cypress/screenshots
|
||||
results/
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ cypress-test:
|
|||
- echo "127.0.0.1 dev.appsmith.com" >> /etc/hosts
|
||||
- yarn test
|
||||
artifacts:
|
||||
when: on_failure
|
||||
expire_in: 1 week
|
||||
paths:
|
||||
- build/
|
||||
|
|
@ -61,7 +62,7 @@ cypress-test:
|
|||
docker-package-release:
|
||||
image: docker:dind
|
||||
services:
|
||||
- docker:dind
|
||||
- docker:dind
|
||||
stage: package
|
||||
script:
|
||||
- docker build --build-arg REACT_APP_ENVIRONMENT=STAGING --build-arg GIT_SHA=$CI_COMMIT_SHORT_SHA -t appsmith/appsmith-editor:release .
|
||||
|
|
@ -75,7 +76,7 @@ docker-package-prod:
|
|||
services:
|
||||
- docker:dind
|
||||
stage: package
|
||||
script:
|
||||
script:
|
||||
- docker build --build-arg REACT_APP_ENVIRONMENT=PRODUCTION --build-arg GIT_SHA=$CI_COMMIT_SHORT_SHA -t appsmith/appsmith-editor:latest .
|
||||
- docker login -u $DOCKER_HUB_USERNAME -p $DOCKER_HUB_ACCESS_TOKEN
|
||||
- docker push appsmith/appsmith-editor:latest
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
"flow-bin": "^0.91.0",
|
||||
"fontfaceobserver": "^2.1.0",
|
||||
"fuse.js": "^3.4.5",
|
||||
"fusioncharts": "^3.15.0-sr.1",
|
||||
"history": "^4.10.1",
|
||||
"husky": "^3.0.5",
|
||||
"interweave": "^12.1.1",
|
||||
|
|
@ -67,6 +68,7 @@
|
|||
"react-dnd-html5-backend": "^9.3.4",
|
||||
"react-dnd-touch-backend": "^9.4.0",
|
||||
"react-dom": "^16.7.0",
|
||||
"react-fusioncharts": "^3.1.2",
|
||||
"react-helmet": "^5.2.1",
|
||||
"react-redux": "^7.1.3",
|
||||
"react-router": "^5.1.2",
|
||||
|
|
@ -157,8 +159,7 @@
|
|||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged",
|
||||
"pre-push": "yarn run test"
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,12 +62,12 @@ export interface RestAction {
|
|||
cacheResponse?: string;
|
||||
}
|
||||
|
||||
export type PaginationField = "PREV" | "NEXT" | undefined;
|
||||
export type PaginationField = "PREV" | "NEXT";
|
||||
|
||||
export interface ExecuteActionRequest extends APIRequest {
|
||||
action: Pick<RestAction, "id"> | Omit<RestAction, "id">;
|
||||
params?: Property[];
|
||||
paginationField: PaginationField;
|
||||
paginationField?: PaginationField;
|
||||
}
|
||||
|
||||
export interface ExecuteActionResponse extends ApiResponse {
|
||||
|
|
@ -80,7 +80,7 @@ export interface ActionApiResponse {
|
|||
data: {
|
||||
body: object;
|
||||
headers: Record<string, string[]>;
|
||||
statusCode: string | number;
|
||||
statusCode: string;
|
||||
};
|
||||
clientMeta: {
|
||||
duration: string;
|
||||
|
|
@ -91,7 +91,7 @@ export interface ActionApiResponse {
|
|||
export interface ActionResponse {
|
||||
body: object;
|
||||
headers: Record<string, string[]>;
|
||||
statusCode: string | number;
|
||||
statusCode: string;
|
||||
duration: string;
|
||||
size: string;
|
||||
}
|
||||
|
|
|
|||
3
app/client/src/assets/icons/widget/chart.svg
Normal file
3
app/client/src/assets/icons/widget/chart.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16.7494 13.8508L13.069 10.0279L4.21712 19.024L3 17.8274L13.0818 7.58082L16.798 11.4404L23.1909 5.31898L21.3593 3.48817H26.1416V8.26875L24.3978 6.52586L16.7494 13.8508ZM7.23518 26.3199H12.9965V18.2114H7.23518V26.3199ZM16.237 26.3199H20.9982V15.6509H16.237V26.3199ZM24.2387 10.3164V26.3199H29V10.3164H24.2387Z" fill="#F1F7FC"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 439 B |
|
|
@ -0,0 +1,83 @@
|
|||
import React from "react";
|
||||
import ReactFC from "react-fusioncharts";
|
||||
import FusionCharts from "fusioncharts";
|
||||
import Column2D from "fusioncharts/fusioncharts.charts";
|
||||
import FusionTheme from "fusioncharts/themes/fusioncharts.theme.fusion";
|
||||
import { ChartType, ChartData } from "widgets/ChartWidget";
|
||||
import styled from "styled-components";
|
||||
import { invisible } from "constants/DefaultTheme";
|
||||
|
||||
ReactFC.fcRoot(FusionCharts, Column2D, FusionTheme);
|
||||
|
||||
export interface ChartComponentProps {
|
||||
chartType: ChartType;
|
||||
chartData: ChartData[];
|
||||
xAxisName: string;
|
||||
yAxisName: string;
|
||||
chartName: string;
|
||||
componentWidth: number;
|
||||
componentHeight: number;
|
||||
isVisible?: boolean;
|
||||
}
|
||||
|
||||
const CanvasContainer = styled.div<ChartComponentProps>`
|
||||
border: none;
|
||||
border-radius: ${props => `${props.theme.radii[1]}px`};
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: white;
|
||||
box-shadow: 0 1px 1px 0 rgba(60,75,100,.14),0 2px 1px -1px rgba(60,75,100,.12),0 1px 3px 0 rgba(60,75,100,.2);
|
||||
position: relative;
|
||||
${props => (!props.isVisible ? invisible : "")};
|
||||
}`;
|
||||
|
||||
/* eslint-disable react/display-name */
|
||||
const ChartComponent = (props: ChartComponentProps) => {
|
||||
const getChartType = (chartType: ChartType) => {
|
||||
switch (chartType) {
|
||||
case "LINE_CHART":
|
||||
return "line";
|
||||
case "BAR_CHART":
|
||||
return "bar2d";
|
||||
case "PIE_CHART":
|
||||
return "pie2d";
|
||||
case "COLUMN_CHART":
|
||||
return "column2d";
|
||||
case "AREA_CHART":
|
||||
return "area2d";
|
||||
default:
|
||||
return "column2d";
|
||||
}
|
||||
};
|
||||
|
||||
const getChartData = (chartData: ChartData[]) => {
|
||||
return chartData.map(item => {
|
||||
return {
|
||||
label: item.x,
|
||||
value: item.y,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<CanvasContainer {...props}>
|
||||
<ReactFC
|
||||
type={getChartType(props.chartType)}
|
||||
width={props.componentWidth.toString()}
|
||||
height={props.componentHeight.toString()}
|
||||
dataForma="json"
|
||||
dataSource={{
|
||||
chart: {
|
||||
xAxisName: props.xAxisName,
|
||||
yAxisName: props.yAxisName,
|
||||
theme: "fusion",
|
||||
caption: props.chartName,
|
||||
},
|
||||
data: getChartData(props.chartData),
|
||||
}}
|
||||
/>
|
||||
</CanvasContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChartComponent;
|
||||
|
|
@ -32,7 +32,7 @@ class FilePickerComponent extends React.Component<
|
|||
<BaseButton
|
||||
accent="primary"
|
||||
filled
|
||||
className={this.props.isLoading ? "bp3-skeleton" : ""}
|
||||
loading={this.props.isLoading}
|
||||
text={label}
|
||||
onClick={this.openModal}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -26,22 +26,22 @@ class CheckboxComponent extends React.Component<CheckboxComponentProps> {
|
|||
className={
|
||||
this.props.isLoading ? "bp3-skeleton" : Classes.RUNNING_TEXT
|
||||
}
|
||||
defaultChecked={this.props.defaultCheckedState}
|
||||
onChange={this.onCheckChange}
|
||||
disabled={this.props.isDisabled}
|
||||
checked={this.props.isChecked}
|
||||
/>
|
||||
</CheckboxContainer>
|
||||
);
|
||||
}
|
||||
|
||||
onCheckChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
this.props.onCheckChange(event.target.value === "true");
|
||||
onCheckChange = () => {
|
||||
this.props.onCheckChange(!this.props.isChecked);
|
||||
};
|
||||
}
|
||||
|
||||
export interface CheckboxComponentProps extends ComponentProps {
|
||||
label: string;
|
||||
defaultCheckedState: boolean;
|
||||
isChecked: boolean;
|
||||
onCheckChange: (isChecked: boolean) => void;
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,15 +8,39 @@ import moment from "moment-timezone";
|
|||
import "../../../../node_modules/@blueprintjs/datetime/lib/css/blueprint-datetime.css";
|
||||
import { DatePickerType } from "widgets/DatePickerWidget";
|
||||
import { WIDGET_PADDING } from "constants/WidgetConstants";
|
||||
import { Colors } from "constants/Colors";
|
||||
|
||||
const StyledControlGroup = styled(ControlGroup)`
|
||||
&&& {
|
||||
.${Classes.INPUT} {
|
||||
box-shadow: none;
|
||||
border: 1px solid;
|
||||
border-color: ${Colors.GEYSER_LIGHT};
|
||||
border-radius: ${props => props.theme.radii[1]}px;
|
||||
width: 100%;
|
||||
height: inherit;
|
||||
align-items: center;
|
||||
&:active {
|
||||
border-color: ${Colors.HIT_GRAY};
|
||||
}
|
||||
&:focus {
|
||||
border-color: ${Colors.MYSTIC};
|
||||
}
|
||||
}
|
||||
.${Classes.INPUT_GROUP} {
|
||||
display: block;
|
||||
margin: 0;
|
||||
}
|
||||
.${Classes.CONTROL_GROUP} {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
label {
|
||||
${labelStyle}
|
||||
flex: 0 1 30%;
|
||||
margin: 7px ${WIDGET_PADDING * 2}px 0 0;
|
||||
text-align: right;
|
||||
margin: 0 ${WIDGET_PADDING * 2}px 0 0;
|
||||
align-self: center;
|
||||
align-self: flex-start;
|
||||
max-width: calc(30% - ${WIDGET_PADDING}px);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
|
@ -47,14 +71,14 @@ class DatePickerComponent extends React.Component<DatePickerComponentProps> {
|
|||
this.props.enableTimePicker
|
||||
? {
|
||||
useAmPm: true,
|
||||
value: this.props.selectedDate || this.props.defaultDate,
|
||||
value: this.props.selectedDate,
|
||||
showArrowButtons: true,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
closeOnSelection={true}
|
||||
onChange={this.onDateSelected}
|
||||
value={this.props.selectedDate || this.props.defaultDate}
|
||||
value={this.props.selectedDate}
|
||||
/>
|
||||
) : (
|
||||
<DateRangeInput
|
||||
|
|
@ -97,7 +121,6 @@ class DatePickerComponent extends React.Component<DatePickerComponentProps> {
|
|||
|
||||
export interface DatePickerComponentProps extends ComponentProps {
|
||||
label: string;
|
||||
defaultDate?: Date;
|
||||
dateFormat: string;
|
||||
enableTimePicker?: boolean;
|
||||
selectedDate?: Date;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import _ from "lodash";
|
|||
import { WIDGET_PADDING } from "constants/WidgetConstants";
|
||||
import "../../../../node_modules/@blueprintjs/select/lib/css/blueprint-select.css";
|
||||
import styled, {
|
||||
createGlobalStyle,
|
||||
labelStyle,
|
||||
BlueprintCSSTransform,
|
||||
BlueprintInputTransform,
|
||||
|
|
@ -79,53 +80,61 @@ const StyledControlGroup = styled(ControlGroup)<{ haslabel: string }>`
|
|||
}
|
||||
`;
|
||||
|
||||
const DropdownContainer = styled.div`
|
||||
${BlueprintCSSTransform}
|
||||
&&&& .${Classes.MENU_ITEM} {
|
||||
border-radius: ${props => props.theme.radii[1]}px;
|
||||
&:hover{
|
||||
background: ${Colors.POLAR};
|
||||
}
|
||||
&.${Classes.ACTIVE} {
|
||||
background: ${Colors.POLAR};
|
||||
color: ${props => props.theme.colors.textDefault};
|
||||
position:relative;
|
||||
&.single-select{
|
||||
&:before{
|
||||
left: 0;
|
||||
top: -2px;
|
||||
position: absolute;
|
||||
content: "";
|
||||
background: ${props => props.theme.colors.primary};
|
||||
border-radius: 4px 0 0 4px;
|
||||
width: 4px;
|
||||
height:100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&& .${Classes.POPOVER} {
|
||||
const DropdownStyles = createGlobalStyle`
|
||||
.select-popover-wrapper {
|
||||
width: 100%;
|
||||
border-radius: ${props => props.theme.radii[1]}px;
|
||||
box-shadow: 0px 2px 4px rgba(67, 70, 74, 0.14);
|
||||
padding: ${props => props.theme.spaces[3]}px;
|
||||
background: white;
|
||||
}
|
||||
|
||||
&& .${Classes.POPOVER_WRAPPER} {
|
||||
position:relative;
|
||||
.${Classes.OVERLAY} {
|
||||
position: absolute;
|
||||
.${Classes.TRANSITION_CONTAINER} {
|
||||
width: 100%;
|
||||
&& .${Classes.MENU} {
|
||||
max-width: 100%;
|
||||
max-height: auto;
|
||||
}
|
||||
&&&& .${Classes.MENU_ITEM} {
|
||||
border-radius: ${props => props.theme.radii[1]}px;
|
||||
&:hover{
|
||||
background: ${Colors.POLAR};
|
||||
}
|
||||
&.${Classes.ACTIVE} {
|
||||
background: ${Colors.POLAR};
|
||||
color: ${props => props.theme.colors.textDefault};
|
||||
position:relative;
|
||||
&.single-select{
|
||||
&:before{
|
||||
left: 0;
|
||||
top: -2px;
|
||||
position: absolute;
|
||||
content: "";
|
||||
background: ${props => props.theme.colors.primary};
|
||||
border-radius: 4px 0 0 4px;
|
||||
width: 4px;
|
||||
height:100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.${Classes.CONTROL} .${Classes.CONTROL_INDICATOR} {
|
||||
background: white;
|
||||
box-shadow: none;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
border-color: ${Colors.GEYSER};
|
||||
&::before {
|
||||
width: auto;
|
||||
height: 1em;
|
||||
}&
|
||||
}
|
||||
.${Classes.CONTROL} input:checked ~ .${Classes.CONTROL_INDICATOR} {
|
||||
background: ${props => props.theme.colors.primary};
|
||||
color: ${props => props.theme.colors.textOnDarkBG};
|
||||
border-color: ${props => props.theme.colors.primary};
|
||||
}
|
||||
}
|
||||
}
|
||||
&& .${Classes.MENU} {
|
||||
max-width: 100%;
|
||||
max-height: auto;
|
||||
}
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const DropdownContainer = styled.div`
|
||||
${BlueprintCSSTransform}
|
||||
`;
|
||||
|
||||
const StyledMultiDropDown = styled(MultiDropDown)`
|
||||
|
|
@ -169,24 +178,6 @@ const StyledMultiDropDown = styled(MultiDropDown)`
|
|||
}
|
||||
}
|
||||
}
|
||||
&&&& {
|
||||
.${Classes.CONTROL} .${Classes.CONTROL_INDICATOR} {
|
||||
background: white;
|
||||
box-shadow: none;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
border-color: ${Colors.GEYSER};
|
||||
&::before {
|
||||
width: auto;
|
||||
height: 1em;
|
||||
}
|
||||
}
|
||||
.${Classes.CONTROL} input:checked ~ .${Classes.CONTROL_INDICATOR} {
|
||||
background: ${props => props.theme.colors.primary};
|
||||
color: ${props => props.theme.colors.textOnDarkBG};
|
||||
border-color: ${props => props.theme.colors.primary};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledCheckbox = styled(Checkbox)`
|
||||
|
|
@ -204,6 +195,7 @@ class DropDownComponent extends React.Component<DropDownComponentProps> {
|
|||
: [];
|
||||
return (
|
||||
<DropdownContainer>
|
||||
<DropdownStyles />
|
||||
<StyledControlGroup
|
||||
fill
|
||||
haslabel={!!this.props.label ? "true" : "false"}
|
||||
|
|
@ -228,14 +220,16 @@ class DropDownComponent extends React.Component<DropDownComponentProps> {
|
|||
onItemSelect={this.onItemSelect}
|
||||
popoverProps={{
|
||||
minimal: true,
|
||||
usePortal: false,
|
||||
usePortal: true,
|
||||
popoverClassName: "select-popover-wrapper",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
rightIcon={IconNames.CHEVRON_DOWN}
|
||||
text={
|
||||
!_.isEmpty(this.props.options) &&
|
||||
this.props.selectedIndex !== undefined
|
||||
this.props.selectedIndex !== undefined &&
|
||||
this.props.selectedIndex > -1
|
||||
? this.props.options[this.props.selectedIndex].label
|
||||
: "-- Empty --"
|
||||
}
|
||||
|
|
@ -258,9 +252,10 @@ class DropDownComponent extends React.Component<DropDownComponentProps> {
|
|||
onItemSelect={this.onItemSelect}
|
||||
popoverProps={{
|
||||
minimal: true,
|
||||
usePortal: false,
|
||||
usePortal: true,
|
||||
popoverClassName: "select-popover-wrapper",
|
||||
}}
|
||||
></StyledMultiDropDown>
|
||||
/>
|
||||
)}
|
||||
</StyledControlGroup>
|
||||
</DropdownContainer>
|
||||
|
|
|
|||
|
|
@ -27,8 +27,9 @@ import { INPUT_WIDGET_DEFAULT_VALIDATION_ERROR } from "constants/messages";
|
|||
*/
|
||||
|
||||
const InputComponentWrapper = styled(props => (
|
||||
<ControlGroup {..._.omit(props, ["hasError"])} />
|
||||
<ControlGroup {..._.omit(props, ["hasError", "numeric"])} />
|
||||
))<{
|
||||
numeric: boolean;
|
||||
multiline: string;
|
||||
hasError: boolean;
|
||||
}>`
|
||||
|
|
@ -41,6 +42,13 @@ const InputComponentWrapper = styled(props => (
|
|||
border-radius: ${props => props.theme.radii[1]}px;
|
||||
height: ${props => (props.multiline === "true" ? "100%" : "inherit")};
|
||||
width: 100%;
|
||||
${props =>
|
||||
props.numeric &&
|
||||
`
|
||||
border-top-right-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
border-right-width: 0px;
|
||||
`}
|
||||
&:active {
|
||||
border-color: ${({ hasError }) =>
|
||||
hasError ? IntentColors.danger : Colors.HIT_GRAY};
|
||||
|
|
@ -138,7 +146,6 @@ class InputComponent extends React.Component<
|
|||
disabled={this.props.disabled}
|
||||
intent={this.props.intent}
|
||||
className={this.props.isLoading ? "bp3-skeleton" : Classes.FILL}
|
||||
defaultValue={this.props.defaultValue}
|
||||
onValueChange={this.onNumberChange}
|
||||
leftIcon={
|
||||
this.props.inputType === "PHONE_NUMBER" ? "phone" : this.props.leftIcon
|
||||
|
|
@ -150,7 +157,7 @@ class InputComponent extends React.Component<
|
|||
onBlur={() => this.setFocusState(false)}
|
||||
/>
|
||||
);
|
||||
private textAreaInputComponent = (
|
||||
private textAreaInputComponent = () => (
|
||||
<TextArea
|
||||
value={this.props.value}
|
||||
placeholder={this.props.placeholder}
|
||||
|
|
@ -158,7 +165,6 @@ class InputComponent extends React.Component<
|
|||
maxLength={this.props.maxChars}
|
||||
intent={this.props.intent}
|
||||
onChange={this.onTextChange}
|
||||
defaultValue={this.props.defaultValue}
|
||||
className={this.props.isLoading ? "bp3-skeleton" : ""}
|
||||
growVertically={false}
|
||||
onFocus={() => this.setFocusState(true)}
|
||||
|
|
@ -168,7 +174,7 @@ class InputComponent extends React.Component<
|
|||
|
||||
private textInputComponent = (isTextArea: boolean) =>
|
||||
isTextArea ? (
|
||||
this.textAreaInputComponent
|
||||
this.textAreaInputComponent()
|
||||
) : (
|
||||
<InputGroup
|
||||
value={this.props.value}
|
||||
|
|
@ -177,7 +183,6 @@ class InputComponent extends React.Component<
|
|||
maxLength={this.props.maxChars}
|
||||
intent={this.props.intent}
|
||||
onChange={this.onTextChange}
|
||||
defaultValue={this.props.defaultValue}
|
||||
className={this.props.isLoading ? "bp3-skeleton" : ""}
|
||||
rightElement={
|
||||
this.props.inputType === "PASSWORD" ? (
|
||||
|
|
@ -207,6 +212,7 @@ class InputComponent extends React.Component<
|
|||
<InputComponentWrapper
|
||||
fill
|
||||
multiline={this.props.multiline.toString()}
|
||||
numeric={this.isNumberInputType(this.props.inputType)}
|
||||
hasError={this.props.isInvalid}
|
||||
>
|
||||
{this.props.label && (
|
||||
|
|
|
|||
|
|
@ -17,15 +17,19 @@ const StyledControlGroup = styled(ControlGroup)`
|
|||
& > label {
|
||||
${labelStyle}
|
||||
flex: 0 1 30%;
|
||||
align-self: flex-start;
|
||||
margin: 7px ${WIDGET_PADDING * 2}px 0 0;
|
||||
text-align: right;
|
||||
margin: 0 ${WIDGET_PADDING * 2}px 0 0;
|
||||
align-self: flex-start;
|
||||
max-width: calc(30% - ${WIDGET_PADDING}px);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledRadioGroup = styled(RadioGroup)`
|
||||
${BlueprintControlTransform};
|
||||
label {
|
||||
margin: 7px ${WIDGET_PADDING * 2}px 0 0;
|
||||
}
|
||||
`;
|
||||
|
||||
class RadioGroupComponent extends React.Component<RadioGroupComponentProps> {
|
||||
|
|
@ -44,11 +48,7 @@ class RadioGroupComponent extends React.Component<RadioGroupComponentProps> {
|
|||
</Label>
|
||||
)}
|
||||
<StyledRadioGroup
|
||||
selectedValue={
|
||||
this.props.selectedOptionValue === undefined
|
||||
? this.props.defaultOptionValue
|
||||
: this.props.selectedOptionValue
|
||||
}
|
||||
selectedValue={this.props.selectedOptionValue}
|
||||
onChange={this.onRadioSelectionChange}
|
||||
>
|
||||
{this.props.options.map(option => {
|
||||
|
|
@ -77,7 +77,6 @@ export interface RadioGroupComponentProps extends ComponentProps {
|
|||
onRadioSelectionChange: (updatedOptionValue: string) => void;
|
||||
selectedOptionValue: string;
|
||||
isLoading: boolean;
|
||||
defaultOptionValue: string;
|
||||
}
|
||||
|
||||
export default RadioGroupComponent;
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ class DynamicActionCreator extends React.Component<Props & ReduxStateProps> {
|
|||
) => void,
|
||||
) => {
|
||||
return (
|
||||
<div style={{ paddingLeft: 5 }}>
|
||||
<div>
|
||||
{selectedOption.arguments.map(arg => {
|
||||
switch (arg.field) {
|
||||
case "ACTION_SELECTOR_FIELD":
|
||||
|
|
@ -328,6 +328,7 @@ class DynamicActionCreator extends React.Component<Props & ReduxStateProps> {
|
|||
<StyledDropdown
|
||||
options={allOptions}
|
||||
selectedValue={arg.getSelectedValue(value, false)}
|
||||
defaultText={"Select Action"}
|
||||
onSelect={value =>
|
||||
handleUpdate(value, arg.valueChangeHandler)
|
||||
}
|
||||
|
|
@ -347,6 +348,7 @@ class DynamicActionCreator extends React.Component<Props & ReduxStateProps> {
|
|||
<StyledDropdown
|
||||
options={this.props.pageNameDropdown}
|
||||
selectedValue={arg.getSelectedValue(value, false)}
|
||||
defaultText={"Select Page"}
|
||||
onSelect={value =>
|
||||
handleUpdate(value, arg.valueChangeHandler)
|
||||
}
|
||||
|
|
@ -355,14 +357,15 @@ class DynamicActionCreator extends React.Component<Props & ReduxStateProps> {
|
|||
);
|
||||
case "TEXT_FIELD":
|
||||
return (
|
||||
<React.Fragment key={arg.label}>
|
||||
<ControlWrapper key={arg.label}>
|
||||
<label>{arg.label}</label>
|
||||
<InputText
|
||||
label={arg.label}
|
||||
value={arg.getSelectedValue(value, false)}
|
||||
onChange={e => handleUpdate(e, arg.valueChangeHandler)}
|
||||
isValid={true}
|
||||
/>
|
||||
</React.Fragment>
|
||||
</ControlWrapper>
|
||||
);
|
||||
case "ALERT_TYPE_SELECTOR_FIELD":
|
||||
return (
|
||||
|
|
@ -370,6 +373,7 @@ class DynamicActionCreator extends React.Component<Props & ReduxStateProps> {
|
|||
<label>{arg.label}</label>
|
||||
<StyledDropdown
|
||||
options={ALERT_STYLE_OPTIONS}
|
||||
defaultText={"Select type"}
|
||||
selectedValue={arg.getSelectedValue(value, false)}
|
||||
onSelect={value =>
|
||||
handleUpdate(value, arg.valueChangeHandler)
|
||||
|
|
@ -421,6 +425,7 @@ class DynamicActionCreator extends React.Component<Props & ReduxStateProps> {
|
|||
<StyledDropdown
|
||||
options={actionOptions}
|
||||
selectedValue={topLevelFuncValue}
|
||||
defaultText={"Select"}
|
||||
onSelect={value =>
|
||||
this.handleValueUpdate(value, handleTopLevelFuncUpdate)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,27 @@
|
|||
import React from "react";
|
||||
import { Popover } from "@blueprintjs/core";
|
||||
import styled from "styled-components";
|
||||
import styled, { createGlobalStyle } from "styled-components";
|
||||
import { Colors } from "constants/Colors";
|
||||
|
||||
const TooltipStyles = createGlobalStyle`
|
||||
.error-tooltip{
|
||||
.bp3-popover {
|
||||
.bp3-popover-arrow {
|
||||
display: block;
|
||||
}
|
||||
.bp3-popover-content {
|
||||
padding: 8px;
|
||||
color: ${Colors.RED};
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
text-transform: initial;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const Wrapper = styled.div`
|
||||
position: relative;
|
||||
|
|
@ -10,21 +31,6 @@ const Wrapper = styled.div`
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.bp3-popover {
|
||||
.bp3-popover-arrow {
|
||||
display: block;
|
||||
}
|
||||
.bp3-popover-content {
|
||||
padding: 8px;
|
||||
color: ${props => props.theme.colors.error};
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
text-transform: initial;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
|
|
@ -36,16 +42,15 @@ interface Props {
|
|||
const ErrorTooltip = (props: Props) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
<TooltipStyles />
|
||||
<Popover
|
||||
autoFocus={true}
|
||||
canEscapeKeyClose={true}
|
||||
content={props.message}
|
||||
position="bottom"
|
||||
isOpen={props.isOpen && !!props.message}
|
||||
usePortal={false}
|
||||
modifiers={{
|
||||
offset: { offset: "0,0,-11px" },
|
||||
}}
|
||||
usePortal
|
||||
portalClassName="error-tooltip"
|
||||
>
|
||||
{props.children}
|
||||
</Popover>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import { IconNames } from "@blueprintjs/icons";
|
|||
type ActionTypeDropdownProps = {
|
||||
options: DropdownOption[];
|
||||
selectedValue: string;
|
||||
defaultText: string;
|
||||
onSelect: (value: string) => void;
|
||||
};
|
||||
|
||||
|
|
@ -55,7 +56,9 @@ class StyledDropdown extends React.Component<ActionTypeDropdownProps> {
|
|||
|
||||
render() {
|
||||
const { selectedValue } = this.props;
|
||||
let selectedOption = this.props.options[0];
|
||||
let selectedOption = {
|
||||
label: this.props.defaultText,
|
||||
};
|
||||
this.props.options.forEach(o => {
|
||||
if (o.value === selectedValue) {
|
||||
selectedOption = o;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ export interface ControlData {
|
|||
id: string;
|
||||
label: string;
|
||||
propertyName: string;
|
||||
isJSConvertible?: boolean;
|
||||
controlType: ControlType;
|
||||
propertyValue?: any;
|
||||
isValid: boolean;
|
||||
|
|
|
|||
|
|
@ -11,8 +11,9 @@ export function InputText(props: {
|
|||
onChange: (event: React.ChangeEvent<HTMLTextAreaElement> | string) => void;
|
||||
isValid: boolean;
|
||||
validationMessage?: string;
|
||||
placeholder?: string;
|
||||
}) {
|
||||
const { validationMessage, value, isValid, onChange } = props;
|
||||
const { validationMessage, value, isValid, onChange, placeholder } = props;
|
||||
return (
|
||||
<StyledDynamicInput>
|
||||
<DynamicAutocompleteInput
|
||||
|
|
@ -26,6 +27,7 @@ export function InputText(props: {
|
|||
}}
|
||||
theme={"DARK"}
|
||||
singleLine={false}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
</StyledDynamicInput>
|
||||
);
|
||||
|
|
@ -33,7 +35,13 @@ export function InputText(props: {
|
|||
|
||||
class InputTextControl extends BaseControl<InputControlProps> {
|
||||
render() {
|
||||
const { validationMessage, propertyValue, isValid, label } = this.props;
|
||||
const {
|
||||
validationMessage,
|
||||
propertyValue,
|
||||
isValid,
|
||||
label,
|
||||
placeholderText,
|
||||
} = this.props;
|
||||
return (
|
||||
<InputText
|
||||
label={label}
|
||||
|
|
@ -41,6 +49,7 @@ class InputTextControl extends BaseControl<InputControlProps> {
|
|||
onChange={this.onTextChange}
|
||||
isValid={isValid}
|
||||
validationMessage={validationMessage}
|
||||
placeholder={placeholderText}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,10 @@ const StyledOptionControlWrapper = styled(ControlWrapper)`
|
|||
|
||||
class OptionControl extends BaseControl<ControlProps> {
|
||||
render() {
|
||||
const options: DropdownOption[] = this.props.propertyValue || [{}];
|
||||
const { propertyValue } = this.props;
|
||||
const options: DropdownOption[] = Array.isArray(propertyValue)
|
||||
? propertyValue
|
||||
: [{}];
|
||||
return (
|
||||
<React.Fragment>
|
||||
{options.map((option, index) => {
|
||||
|
|
@ -77,13 +80,19 @@ class OptionControl extends BaseControl<ControlProps> {
|
|||
}
|
||||
|
||||
deleteOption = (index: number) => {
|
||||
const options: DropdownOption[] = this.props.propertyValue.slice();
|
||||
options.splice(index, 1);
|
||||
this.updateProperty("options", options);
|
||||
const { propertyValue } = this.props;
|
||||
const options: DropdownOption[] = Array.isArray(propertyValue)
|
||||
? propertyValue
|
||||
: [{}];
|
||||
const newOptions = options.filter((o, i) => i !== index);
|
||||
this.updateProperty("options", newOptions);
|
||||
};
|
||||
|
||||
updateOptionLabel = (index: number, updatedLabel: string) => {
|
||||
const options: DropdownOption[] = this.props.propertyValue;
|
||||
const { propertyValue } = this.props;
|
||||
const options: DropdownOption[] = Array.isArray(propertyValue)
|
||||
? propertyValue
|
||||
: [{}];
|
||||
this.updateProperty(
|
||||
"options",
|
||||
options.map((option, optionIndex) => {
|
||||
|
|
@ -99,7 +108,10 @@ class OptionControl extends BaseControl<ControlProps> {
|
|||
};
|
||||
|
||||
updateOptionValue = (index: number, updatedValue: string) => {
|
||||
const options: DropdownOption[] = this.props.propertyValue;
|
||||
const { propertyValue } = this.props;
|
||||
const options: DropdownOption[] = Array.isArray(propertyValue)
|
||||
? propertyValue
|
||||
: [{}];
|
||||
this.updateProperty(
|
||||
"options",
|
||||
options.map((option, optionIndex) => {
|
||||
|
|
@ -115,9 +127,10 @@ class OptionControl extends BaseControl<ControlProps> {
|
|||
};
|
||||
|
||||
addOption = () => {
|
||||
const options: DropdownOption[] = this.props.propertyValue
|
||||
? this.props.propertyValue.slice()
|
||||
: [];
|
||||
const { propertyValue } = this.props;
|
||||
const options: DropdownOption[] = Array.isArray(propertyValue)
|
||||
? propertyValue
|
||||
: [{}];
|
||||
options.push({ label: "", value: "" });
|
||||
this.updateProperty("options", options);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,10 +19,3 @@ export type ControlType =
|
|||
| "TIME_ZONE"
|
||||
| "CODE_EDITOR"
|
||||
| "COLUMN_ACTION_SELECTOR";
|
||||
|
||||
export const CONVERTIBLE_CONTROLS = [
|
||||
"SWITCH",
|
||||
"OPTION_INPUT",
|
||||
"ACTION_SELECTOR",
|
||||
"DATE_PICKER",
|
||||
];
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ export type WidgetType =
|
|||
| "RADIO_GROUP_WIDGET"
|
||||
| "FILE_PICKER_WIDGET"
|
||||
| "INPUT_WIDGET"
|
||||
| "CHART_WIDGET"
|
||||
| "SWITCH_WIDGET"
|
||||
| "FORM_WIDGET"
|
||||
| "FORM_BUTTON_WIDGET";
|
||||
|
|
@ -28,6 +29,7 @@ export const WidgetTypes: { [id: string]: WidgetType } = {
|
|||
DROP_DOWN_WIDGET: "DROP_DOWN_WIDGET",
|
||||
CHECKBOX_WIDGET: "CHECKBOX_WIDGET",
|
||||
RADIO_GROUP_WIDGET: "RADIO_GROUP_WIDGET",
|
||||
CHART_WIDGET: "CHART_WIDGET",
|
||||
FORM_WIDGET: "FORM_WIDGET",
|
||||
FORM_BUTTON_WIDGET: "FORM_BUTTON_WIDGET",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ export const VALIDATION_TYPES = {
|
|||
TABLE_DATA: "TABLE_DATA",
|
||||
OPTIONS_DATA: "OPTIONS_DATA",
|
||||
DATE: "DATE",
|
||||
CHART_DATA: "CHART_DATA",
|
||||
};
|
||||
|
||||
export type ValidationResponse = {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { ReactComponent as SwitchIcon } from "assets/icons/widget/switch.svg";
|
|||
import { ReactComponent as TextIcon } from "assets/icons/widget/text.svg";
|
||||
import { ReactComponent as ImageIcon } from "assets/icons/widget/image.svg";
|
||||
import { ReactComponent as FilePickerIcon } from "assets/icons/widget/filepicker.svg";
|
||||
import { ReactComponent as ChartIcon } from "assets/icons/widget/chart.svg";
|
||||
import { ReactComponent as FormIcon } from "assets/icons/widget/form.svg";
|
||||
|
||||
/* eslint-disable react/display-name */
|
||||
|
|
@ -91,6 +92,11 @@ export const WidgetIcons: {
|
|||
<FilePickerIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
CHART_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<ChartIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
FORM_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<FormIcon />
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ export default class RealmExecutor implements JSExecutor {
|
|||
triggers,
|
||||
};
|
||||
} catch (e) {
|
||||
console.error(`Error: "${e.message}" when evaluating {{${sourceText}}}`);
|
||||
// console.error(`Error: "${e.message}" when evaluating {{${sourceText}}}`);
|
||||
return { result: undefined, triggers: [] };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -885,6 +885,67 @@ const PropertyPaneConfigResponse = {
|
|||
],
|
||||
},
|
||||
],
|
||||
CHART_WIDGET: [
|
||||
{
|
||||
sectionName: "General",
|
||||
id: "21",
|
||||
children: [
|
||||
{
|
||||
id: "21.1",
|
||||
propertyName: "chartType",
|
||||
label: "Chart Type",
|
||||
controlType: "DROP_DOWN",
|
||||
options: [
|
||||
{
|
||||
label: "Line Chart",
|
||||
value: "LINE_CHART",
|
||||
},
|
||||
{
|
||||
label: "Bar Chart",
|
||||
value: "BAR_CHART",
|
||||
},
|
||||
{
|
||||
label: "Pie Chart",
|
||||
value: "PIE_CHART",
|
||||
},
|
||||
{
|
||||
label: "Column Chart",
|
||||
value: "COLUMN_CHART",
|
||||
},
|
||||
{
|
||||
label: "Area Chart",
|
||||
value: "AREA_CHART",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "21.2",
|
||||
propertyName: "chartName",
|
||||
label: "Chart Name",
|
||||
controlType: "INPUT_TEXT",
|
||||
},
|
||||
{
|
||||
id: "21.3",
|
||||
propertyName: "xAxisName",
|
||||
label: "X-axis Label",
|
||||
controlType: "INPUT_TEXT",
|
||||
},
|
||||
{
|
||||
id: "21.4",
|
||||
propertyName: "yAxisName",
|
||||
label: "Y-axis Label",
|
||||
controlType: "INPUT_TEXT",
|
||||
},
|
||||
{
|
||||
id: "21.5",
|
||||
propertyName: "chartData",
|
||||
label: "Chart Data",
|
||||
controlType: "INPUT_TEXT",
|
||||
inputType: "ARRAY",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
name: "propertyPane",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
|||
rows: 1,
|
||||
columns: 8,
|
||||
widgetName: "Input",
|
||||
text: "",
|
||||
},
|
||||
SWITCH_WIDGET: {
|
||||
isOn: false,
|
||||
|
|
@ -119,7 +118,6 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
|||
{ label: "Option 5", value: "5" },
|
||||
],
|
||||
widgetName: "Dropdown",
|
||||
selectedIndex: 0,
|
||||
},
|
||||
CHECKBOX_WIDGET: {
|
||||
rows: 1,
|
||||
|
|
@ -156,6 +154,45 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
|||
widgetName: "FilePicker",
|
||||
isDefaultClickDisabled: true,
|
||||
},
|
||||
CHART_WIDGET: {
|
||||
rows: 8,
|
||||
columns: 6,
|
||||
widgetName: "Chart",
|
||||
chartType: "LINE_CHART",
|
||||
chartName: "Sales on working days",
|
||||
chartData: [
|
||||
{
|
||||
x: "Mon",
|
||||
y: 10000,
|
||||
},
|
||||
{
|
||||
x: "Tue",
|
||||
y: 12000,
|
||||
},
|
||||
{
|
||||
x: "Wed",
|
||||
y: 32000,
|
||||
},
|
||||
{
|
||||
x: "Thu",
|
||||
y: 28000,
|
||||
},
|
||||
{
|
||||
x: "Fri",
|
||||
y: 14000,
|
||||
},
|
||||
{
|
||||
x: "Sat",
|
||||
y: 19000,
|
||||
},
|
||||
{
|
||||
x: "Sun",
|
||||
y: 36000,
|
||||
},
|
||||
],
|
||||
xAxisName: "Last Week",
|
||||
yAxisName: "Total Order Revenue $",
|
||||
},
|
||||
FORM_BUTTON_WIDGET: {
|
||||
rows: 1,
|
||||
columns: 3,
|
||||
|
|
|
|||
|
|
@ -96,6 +96,11 @@ const WidgetSidebarResponse: {
|
|||
widgetCardName: "Table",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
{
|
||||
type: "CHART_WIDGET",
|
||||
widgetCardName: "Chart",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
],
|
||||
["Layout widgets"]: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ interface ReduxStateProps {
|
|||
interface ReduxActionProps {
|
||||
submitForm: (name: string) => void;
|
||||
createAction: (values: RestAction) => void;
|
||||
runAction: (id: string, paginationField: PaginationField) => void;
|
||||
runAction: (id: string, paginationField?: PaginationField) => void;
|
||||
deleteAction: (id: string, name: string) => void;
|
||||
updateAction: (data: RestAction) => void;
|
||||
}
|
||||
|
|
@ -158,7 +158,7 @@ const mapStateToProps = (state: AppState): ReduxStateProps => ({
|
|||
const mapDispatchToProps = (dispatch: any): ReduxActionProps => ({
|
||||
submitForm: (name: string) => dispatch(submit(name)),
|
||||
createAction: (action: RestAction) => dispatch(createActionRequest(action)),
|
||||
runAction: (id: string, paginationField: PaginationField) =>
|
||||
runAction: (id: string, paginationField?: PaginationField) =>
|
||||
dispatch(runApiAction(id, paginationField)),
|
||||
deleteAction: (id: string, name: string) =>
|
||||
dispatch(deleteAction({ id, name })),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import React from "react";
|
||||
import _ from "lodash";
|
||||
import { CONVERTIBLE_CONTROLS } from "constants/PropertyControlConstants";
|
||||
import {
|
||||
ControlPropertyLabelContainer,
|
||||
ControlWrapper,
|
||||
|
|
@ -54,7 +53,7 @@ const PropertyControl = (props: Props) => {
|
|||
["dynamicProperties", propertyName],
|
||||
false,
|
||||
);
|
||||
const isConvertible = CONVERTIBLE_CONTROLS.indexOf(config.controlType) > -1;
|
||||
const isConvertible = !!propertyConfig.isJSConvertible;
|
||||
const className = propertyConfig.label
|
||||
.split(" ")
|
||||
.join("")
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@ import { ImageWidgetProps } from "widgets/ImageWidget";
|
|||
import { InputWidgetProps } from "widgets/InputWidget";
|
||||
import { SwitchWidgetProps } from "widgets/SwitchWidget";
|
||||
import { SpinnerWidgetProps } from "widgets/SpinnerWidget";
|
||||
import { DatePickerWidgetProps } from "widgets/DatePickerWidget";
|
||||
import { TableWidgetProps } from "widgets/TableWidget";
|
||||
import { DropdownWidgetProps } from "widgets/DropdownWidget";
|
||||
import { CheckboxWidgetProps } from "widgets/CheckboxWidget";
|
||||
import { RadioGroupWidgetProps } from "widgets/RadioGroupWidget";
|
||||
import { AlertWidgetProps } from "widgets/AlertWidget";
|
||||
import { FilePickerWidgetProps } from "widgets/FilepickerWidget";
|
||||
import { DatePickerWidgetProps } from "../../widgets/DatePickerWidget";
|
||||
import { TableWidgetProps } from "../../widgets/TableWidget";
|
||||
import { DropdownWidgetProps } from "../../widgets/DropdownWidget";
|
||||
import { CheckboxWidgetProps } from "../../widgets/CheckboxWidget";
|
||||
import { RadioGroupWidgetProps } from "../../widgets/RadioGroupWidget";
|
||||
import { AlertWidgetProps } from "../../widgets/AlertWidget";
|
||||
import { FilePickerWidgetProps } from "../../widgets/FilepickerWidget";
|
||||
import { ChartWidgetProps } from "../../widgets/ChartWidget";
|
||||
import { FormWidgetProps } from "widgets/FormWidget";
|
||||
import { FormButtonWidgetProps } from "widgets/FormButtonWidget";
|
||||
|
||||
|
|
@ -53,6 +54,7 @@ export interface WidgetConfigReducerState {
|
|||
RADIO_GROUP_WIDGET: Partial<RadioGroupWidgetProps> & WidgetConfigProps;
|
||||
ALERT_WIDGET: Partial<AlertWidgetProps> & WidgetConfigProps;
|
||||
FILE_PICKER_WIDGET: Partial<FilePickerWidgetProps> & WidgetConfigProps;
|
||||
CHART_WIDGET: Partial<ChartWidgetProps> & WidgetConfigProps;
|
||||
FORM_WIDGET: Partial<FormWidgetProps> & WidgetConfigProps;
|
||||
FORM_BUTTON_WIDGET: Partial<FormButtonWidgetProps> & WidgetConfigProps;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -38,12 +38,12 @@ import {
|
|||
deleteActionSuccess,
|
||||
executeApiActionRequest,
|
||||
executeApiActionSuccess,
|
||||
fetchActionsForPageSuccess,
|
||||
FetchActionsPayload,
|
||||
moveActionError,
|
||||
moveActionSuccess,
|
||||
runApiAction,
|
||||
updateActionSuccess,
|
||||
fetchActionsForPageSuccess,
|
||||
} from "actions/actionActions";
|
||||
import {
|
||||
getDynamicBindings,
|
||||
|
|
@ -82,11 +82,20 @@ export const getAction = (
|
|||
return action ? action.config : undefined;
|
||||
};
|
||||
|
||||
const createActionResponse = (response: ActionApiResponse): ActionResponse => ({
|
||||
const createActionSuccessResponse = (
|
||||
response: ActionApiResponse,
|
||||
): ActionResponse => ({
|
||||
...response.data,
|
||||
...response.clientMeta,
|
||||
});
|
||||
|
||||
const isErrorResponse = (response: ActionApiResponse) => {
|
||||
return (
|
||||
(response.responseMeta && response.responseMeta.error) ||
|
||||
!/2\d\d/.test(response.data.statusCode)
|
||||
);
|
||||
};
|
||||
|
||||
function getCurrentPageNameByActionId(
|
||||
state: AppState,
|
||||
actionId: string,
|
||||
|
|
@ -102,8 +111,7 @@ function getPageNameByPageId(state: AppState, pageId: string): string {
|
|||
const page = state.entities.pageList.pages.find(
|
||||
page => page.pageId === pageId,
|
||||
);
|
||||
const pageName = page ? page.pageName : "";
|
||||
return pageName;
|
||||
return page ? page.pageName : "";
|
||||
}
|
||||
|
||||
const createActionErrorResponse = (
|
||||
|
|
@ -111,7 +119,7 @@ const createActionErrorResponse = (
|
|||
): ActionResponse => ({
|
||||
body: response.responseMeta.error || { error: "Error" },
|
||||
statusCode: response.responseMeta.error
|
||||
? response.responseMeta.error.code
|
||||
? response.responseMeta.error.code.toString()
|
||||
: "Error",
|
||||
headers: {},
|
||||
duration: "0",
|
||||
|
|
@ -157,7 +165,7 @@ export function* getActionParams(jsonPathKeys: string[] | undefined) {
|
|||
// });
|
||||
// }
|
||||
|
||||
export function* executeAPIQueryActionSaga(
|
||||
export function* executeActionSaga(
|
||||
apiAction: RunActionPayload,
|
||||
event: ExecuteActionPayloadEvent,
|
||||
) {
|
||||
|
|
@ -180,9 +188,8 @@ export function* executeAPIQueryActionSaga(
|
|||
const response: ActionApiResponse = yield ActionAPI.executeAction(
|
||||
executeActionRequest,
|
||||
);
|
||||
let payload = createActionResponse(response);
|
||||
if (response.responseMeta && response.responseMeta.error) {
|
||||
payload = createActionErrorResponse(response);
|
||||
if (isErrorResponse(response)) {
|
||||
const payload = createActionErrorResponse(response);
|
||||
if (onError) {
|
||||
yield put(
|
||||
executeAction({
|
||||
|
|
@ -206,6 +213,7 @@ export function* executeAPIQueryActionSaga(
|
|||
}),
|
||||
);
|
||||
} else {
|
||||
const payload = createActionSuccessResponse(response);
|
||||
yield put(
|
||||
executeApiActionSuccess({
|
||||
id: apiAction.actionId,
|
||||
|
|
@ -281,7 +289,7 @@ export function* executeActionTriggers(
|
|||
) {
|
||||
switch (trigger.type) {
|
||||
case "RUN_ACTION":
|
||||
yield call(executeAPIQueryActionSaga, trigger.payload, event);
|
||||
yield call(executeActionSaga, trigger.payload, event);
|
||||
break;
|
||||
case "NAVIGATE_TO":
|
||||
AnalyticsUtil.logEvent("NAVIGATE", {
|
||||
|
|
@ -513,7 +521,7 @@ export function* runApiActionSaga(
|
|||
params,
|
||||
paginationField,
|
||||
});
|
||||
let payload = createActionResponse(response);
|
||||
let payload = createActionSuccessResponse(response);
|
||||
if (response.responseMeta && response.responseMeta.error) {
|
||||
payload = createActionErrorResponse(response);
|
||||
}
|
||||
|
|
@ -541,27 +549,44 @@ export function* runApiActionSaga(
|
|||
}
|
||||
}
|
||||
|
||||
function* executePageLoadAction(pageAction: PageAction) {
|
||||
yield put(executeApiActionRequest({ id: pageAction.id }));
|
||||
const params: Property[] = yield call(
|
||||
getActionParams,
|
||||
pageAction.jsonPathKeys,
|
||||
);
|
||||
const executeActionRequest: ExecuteActionRequest = {
|
||||
action: { id: pageAction.id },
|
||||
params,
|
||||
};
|
||||
const response: ActionApiResponse = yield ActionAPI.executeAction(
|
||||
executeActionRequest,
|
||||
);
|
||||
|
||||
if (isErrorResponse(response)) {
|
||||
yield put(
|
||||
executeActionError({
|
||||
actionId: pageAction.id,
|
||||
error: response.responseMeta.error,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
const payload = createActionSuccessResponse(response);
|
||||
yield put(
|
||||
executeApiActionSuccess({
|
||||
id: pageAction.id,
|
||||
response: payload,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function* executePageLoadActionsSaga(action: ReduxAction<PageAction[][]>) {
|
||||
const pageActions = action.payload;
|
||||
const actionPayloads: RunActionPayload[][] = pageActions.map(actionSet =>
|
||||
actionSet.map(action => ({
|
||||
actionId: action.id,
|
||||
onSuccess: "",
|
||||
onError: "",
|
||||
})),
|
||||
);
|
||||
for (const actionSet of actionPayloads) {
|
||||
for (const actionSet of pageActions) {
|
||||
const apiResponses = yield select(getActionResponses);
|
||||
const filteredSet = actionSet.filter(
|
||||
action => !apiResponses[action.actionId],
|
||||
);
|
||||
yield* yield all(
|
||||
filteredSet.map(a =>
|
||||
call(executeAPIQueryActionSaga, a, {
|
||||
type: EventType.ON_PAGE_LOAD,
|
||||
}),
|
||||
),
|
||||
);
|
||||
const filteredSet = actionSet.filter(action => !apiResponses[action.id]);
|
||||
yield* yield all(filteredSet.map(a => call(executePageLoadAction, a)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import {
|
|||
takeLatest,
|
||||
all,
|
||||
} from "redux-saga/effects";
|
||||
import { getNextEntityName } from "utils/AppsmithUtils";
|
||||
import { convertToString, getNextEntityName } from "utils/AppsmithUtils";
|
||||
import {
|
||||
SetWidgetDynamicPropertyPayload,
|
||||
updateWidgetProperty,
|
||||
|
|
@ -262,7 +262,8 @@ function* setWidgetDynamicPropertySaga(
|
|||
};
|
||||
if (isDynamic) {
|
||||
dynamicProperties[propertyName] = true;
|
||||
yield put(updateWidgetProperty(widgetId, propertyName, "{{}}"));
|
||||
const value = convertToString(widget[propertyName]);
|
||||
yield put(updateWidgetProperty(widgetId, propertyName, value));
|
||||
} else {
|
||||
delete dynamicProperties[propertyName];
|
||||
yield put(updateWidgetProperty(widgetId, propertyName, undefined));
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ReduxAction } from "../constants/ReduxActionConstants";
|
||||
import { ReduxAction } from "constants/ReduxActionConstants";
|
||||
import { getAppsmithConfigs } from "configs";
|
||||
import * as Sentry from "@sentry/browser";
|
||||
import AnalyticsUtil from "./AnalyticsUtil";
|
||||
|
|
@ -77,3 +77,14 @@ export const getNextEntityName = (prefix: string, existingNames: string[]) => {
|
|||
export const noop = () => {
|
||||
console.log("noop");
|
||||
};
|
||||
|
||||
export const convertToString = (value: any): string => {
|
||||
if (_.isUndefined(value)) {
|
||||
return "";
|
||||
}
|
||||
if (_.isObject(value)) {
|
||||
return JSON.stringify(value, null, 2);
|
||||
}
|
||||
if (_.isString(value)) return value;
|
||||
return value.toString();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,12 +1,18 @@
|
|||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import WidgetFactory from "./WidgetFactory";
|
||||
import {
|
||||
VALIDATION_TYPES,
|
||||
ValidationResponse,
|
||||
ValidationType,
|
||||
Validator,
|
||||
} from "constants/WidgetValidation";
|
||||
|
||||
// TODO: need to be strict about what the key can be
|
||||
export const BASE_WIDGET_VALIDATION = {
|
||||
isLoading: VALIDATION_TYPES.BOOLEAN,
|
||||
isVisible: VALIDATION_TYPES.BOOLEAN,
|
||||
isDisabled: VALIDATION_TYPES.BOOLEAN,
|
||||
};
|
||||
|
||||
export type WidgetPropertyValidationType = Record<string, ValidationType>;
|
||||
|
||||
class ValidationFactory {
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ import { WIDGET_TYPE_VALIDATION_ERROR } from "constants/messages";
|
|||
export const VALIDATORS: Record<ValidationType, Validator> = {
|
||||
[VALIDATION_TYPES.TEXT]: (value: any): ValidationResponse => {
|
||||
let parsed = value;
|
||||
if (_.isUndefined(value)) {
|
||||
if (_.isUndefined(value) || value === null) {
|
||||
return {
|
||||
isValid: false,
|
||||
parsed: "",
|
||||
message: `${WIDGET_TYPE_VALIDATION_ERROR}: text`,
|
||||
isValid: true,
|
||||
parsed: value,
|
||||
message: "",
|
||||
};
|
||||
}
|
||||
if (_.isObject(value)) {
|
||||
|
|
@ -84,20 +84,16 @@ export const VALIDATORS: Record<ValidationType, Validator> = {
|
|||
message: `${WIDGET_TYPE_VALIDATION_ERROR}: boolean`,
|
||||
};
|
||||
}
|
||||
let isValid = _.isBoolean(value);
|
||||
const isBoolean = _.isBoolean(value);
|
||||
const isStringTrueFalse = value === "true" || value === "false";
|
||||
const isValid = isBoolean || isStringTrueFalse;
|
||||
if (isStringTrueFalse) parsed = value !== "false";
|
||||
if (!isValid) {
|
||||
try {
|
||||
parsed = !!value;
|
||||
isValid = true;
|
||||
} catch (e) {
|
||||
console.error(`Error when parsing ${value} to boolean`);
|
||||
console.error(e);
|
||||
return {
|
||||
isValid: false,
|
||||
parsed: false,
|
||||
message: `${WIDGET_TYPE_VALIDATION_ERROR}: boolean`,
|
||||
};
|
||||
}
|
||||
return {
|
||||
isValid: isValid,
|
||||
parsed: parsed,
|
||||
message: `${WIDGET_TYPE_VALIDATION_ERROR}: boolean`,
|
||||
};
|
||||
}
|
||||
return { isValid, parsed };
|
||||
},
|
||||
|
|
@ -174,6 +170,23 @@ export const VALIDATORS: Record<ValidationType, Validator> = {
|
|||
}
|
||||
return { isValid, parsed };
|
||||
},
|
||||
[VALIDATION_TYPES.CHART_DATA]: (value: any): ValidationResponse => {
|
||||
const { isValid, parsed } = VALIDATORS[VALIDATION_TYPES.ARRAY](value);
|
||||
if (!isValid) {
|
||||
return {
|
||||
isValid,
|
||||
parsed,
|
||||
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Chart Data`,
|
||||
};
|
||||
} else if (!_.every(parsed, datum => _.isObject(datum))) {
|
||||
return {
|
||||
isValid: false,
|
||||
parsed: [],
|
||||
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Chart Data`,
|
||||
};
|
||||
}
|
||||
return { isValid, parsed };
|
||||
},
|
||||
[VALIDATION_TYPES.OPTIONS_DATA]: (value: any): ValidationResponse => {
|
||||
const { isValid, parsed } = VALIDATORS[VALIDATION_TYPES.ARRAY](value);
|
||||
if (!isValid) {
|
||||
|
|
@ -200,6 +213,15 @@ export const VALIDATORS: Record<ValidationType, Validator> = {
|
|||
return { isValid, parsed };
|
||||
},
|
||||
[VALIDATION_TYPES.DATE]: (value: any): ValidationResponse => {
|
||||
if (value === undefined) {
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0);
|
||||
return {
|
||||
isValid: false,
|
||||
parsed: today,
|
||||
message: `${WIDGET_TYPE_VALIDATION_ERROR}: Date`,
|
||||
};
|
||||
}
|
||||
const isValid = moment(value).isValid();
|
||||
const parsed = isValid ? moment(value).toDate() : new Date();
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,10 @@ import {
|
|||
WidgetProps,
|
||||
WidgetDataProps,
|
||||
} from "widgets/BaseWidget";
|
||||
import { WidgetPropertyValidationType } from "./ValidationFactory";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "./ValidationFactory";
|
||||
import React from "react";
|
||||
|
||||
type WidgetDerivedPropertyType = any;
|
||||
|
|
@ -78,7 +81,7 @@ class WidgetFactory {
|
|||
const map = this.widgetPropValidationMap.get(widgetType);
|
||||
if (!map) {
|
||||
console.error("Widget type validation is not defined");
|
||||
return {};
|
||||
return BASE_WIDGET_VALIDATION;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import ButtonWidget, { ButtonWidgetProps } from "widgets/ButtonWidget";
|
|||
import DropdownWidget, { DropdownWidgetProps } from "widgets/DropdownWidget";
|
||||
import ImageWidget, { ImageWidgetProps } from "widgets/ImageWidget";
|
||||
import TableWidget, { TableWidgetProps } from "widgets/TableWidget";
|
||||
import ChartWidget, { ChartWidgetProps } from "widgets/ChartWidget";
|
||||
|
||||
import FilePickerWidget, {
|
||||
FilePickerWidgetProps,
|
||||
|
|
@ -169,7 +170,17 @@ class WidgetBuilderRegistry {
|
|||
DatePickerWidget.getDerivedPropertiesMap(),
|
||||
DatePickerWidget.getTriggerPropertyMap(),
|
||||
);
|
||||
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
"CHART_WIDGET",
|
||||
{
|
||||
buildWidget(widgetData: ChartWidgetProps): JSX.Element {
|
||||
return <ChartWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
ChartWidget.getPropertyValidationMap(),
|
||||
ChartWidget.getDerivedPropertiesMap(),
|
||||
ChartWidget.getTriggerPropertyMap(),
|
||||
);
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
"FORM_WIDGET",
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,7 +27,10 @@ import { EditorContext } from "components/editorComponents/EditorContextProvider
|
|||
import { PositionTypes } from "constants/WidgetConstants";
|
||||
|
||||
import ErrorBoundary from "components/editorComponents/ErrorBoundry";
|
||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
||||
import {
|
||||
BASE_WIDGET_VALIDATION,
|
||||
WidgetPropertyValidationType,
|
||||
} from "utils/ValidationFactory";
|
||||
import {
|
||||
DerivedPropertiesMap,
|
||||
TriggerPropertiesMap,
|
||||
|
|
@ -66,7 +69,7 @@ abstract class BaseWidget<
|
|||
// Needed to send a default no validation option. In case a widget needs
|
||||
// validation implement this in the widget class again
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {};
|
||||
return BASE_WIDGET_VALIDATION;
|
||||
}
|
||||
|
||||
static getDerivedPropertiesMap(): DerivedPropertiesMap {
|
||||
|
|
@ -166,7 +169,14 @@ abstract class BaseWidget<
|
|||
}
|
||||
|
||||
render() {
|
||||
return this.getWidgetView();
|
||||
let isValid = true;
|
||||
if (this.props.invalidProps) {
|
||||
isValid = _.keys(this.props.invalidProps).length === 0;
|
||||
}
|
||||
if (this.props.isLoading) isValid = true;
|
||||
return (
|
||||
<ErrorBoundary isValid={isValid}>{this.getWidgetView()}</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
private getWidgetView(): JSX.Element {
|
||||
|
|
@ -202,7 +212,7 @@ abstract class BaseWidget<
|
|||
this.props.widgetId === "0"
|
||||
}
|
||||
>
|
||||
<ErrorBoundary isValid>{this.getPageView()}</ErrorBoundary>
|
||||
{this.getPageView()}
|
||||
</PositionedContainer>
|
||||
);
|
||||
}
|
||||
|
|
@ -215,14 +225,7 @@ abstract class BaseWidget<
|
|||
abstract getPageView(): JSX.Element;
|
||||
|
||||
getCanvasView(): JSX.Element {
|
||||
let isValid = true;
|
||||
if (this.props.invalidProps) {
|
||||
isValid = _.keys(this.props.invalidProps).length === 0;
|
||||
}
|
||||
if (this.props.isLoading) isValid = true;
|
||||
return (
|
||||
<ErrorBoundary isValid={isValid}>{this.getPageView()}</ErrorBoundary>
|
||||
);
|
||||
return this.getPageView();
|
||||
}
|
||||
|
||||
// TODO(Nikhil): Revisit the inclusion of another library for shallowEqual.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ import ButtonComponent, {
|
|||
ButtonType,
|
||||
} from "components/designSystems/blueprint/ButtonComponent";
|
||||
import { EventType } from "constants/ActionConstants";
|
||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/ValidationFactory";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
||||
|
||||
|
|
@ -30,9 +33,8 @@ class ButtonWidget extends BaseWidget<
|
|||
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
text: VALIDATION_TYPES.TEXT,
|
||||
isDisabled: VALIDATION_TYPES.BOOLEAN,
|
||||
isVisible: VALIDATION_TYPES.BOOLEAN,
|
||||
buttonStyle: VALIDATION_TYPES.TEXT,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
63
app/client/src/widgets/ChartWidget.tsx
Normal file
63
app/client/src/widgets/ChartWidget.tsx
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import React from "react";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import ChartComponent from "components/designSystems/appsmith/ChartComponent";
|
||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
|
||||
class ChartWidget extends BaseWidget<ChartWidgetProps, WidgetState> {
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
chartData: VALIDATION_TYPES.CHART_DATA,
|
||||
xAxisName: VALIDATION_TYPES.TEXT,
|
||||
yAxisName: VALIDATION_TYPES.TEXT,
|
||||
chartName: VALIDATION_TYPES.TEXT,
|
||||
};
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
return (
|
||||
<ChartComponent
|
||||
key={this.props.widgetId}
|
||||
isVisible={this.props.isVisible}
|
||||
chartType={this.props.chartType}
|
||||
xAxisName={this.props.xAxisName}
|
||||
yAxisName={this.props.yAxisName}
|
||||
chartName={this.props.chartName}
|
||||
componentWidth={this.state.componentWidth - 10}
|
||||
componentHeight={this.state.componentHeight - 10}
|
||||
chartData={this.props.chartData}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
getWidgetType(): WidgetType {
|
||||
return "CHART_WIDGET";
|
||||
}
|
||||
}
|
||||
|
||||
export type ChartType =
|
||||
| "LINE_CHART"
|
||||
| "BAR_CHART"
|
||||
| "PIE_CHART"
|
||||
| "COLUMN_CHART"
|
||||
| "AREA_CHART"
|
||||
| "SCATTER_CHART";
|
||||
|
||||
export interface ChartData {
|
||||
x: any;
|
||||
y: any;
|
||||
}
|
||||
|
||||
export interface ChartWidgetProps extends WidgetProps {
|
||||
chartType: ChartType;
|
||||
chartData: ChartData[];
|
||||
xAxisName: string;
|
||||
yAxisName: string;
|
||||
chartName: string;
|
||||
componentWidth: number;
|
||||
componentHeight: number;
|
||||
isVisible?: boolean;
|
||||
}
|
||||
|
||||
export default ChartWidget;
|
||||
|
|
@ -4,16 +4,18 @@ import { WidgetType } from "constants/WidgetConstants";
|
|||
import CheckboxComponent from "components/designSystems/blueprint/CheckboxComponent";
|
||||
import { EventType } from "constants/ActionConstants";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/ValidationFactory";
|
||||
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
||||
|
||||
class CheckboxWidget extends BaseWidget<CheckboxWidgetProps, WidgetState> {
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
isDisabled: VALIDATION_TYPES.BOOLEAN,
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
label: VALIDATION_TYPES.TEXT,
|
||||
defaultCheckedState: VALIDATION_TYPES.BOOLEAN,
|
||||
isChecked: VALIDATION_TYPES.BOOLEAN,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -23,10 +25,35 @@ class CheckboxWidget extends BaseWidget<CheckboxWidgetProps, WidgetState> {
|
|||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
super.componentDidMount();
|
||||
if (this.props.defaultCheckedState) {
|
||||
this.updateWidgetMetaProperty(
|
||||
"isChecked",
|
||||
this.props.defaultCheckedState,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: CheckboxWidgetProps) {
|
||||
super.componentDidUpdate(prevProps);
|
||||
if (
|
||||
(this.props.isChecked !== prevProps.isChecked &&
|
||||
this.props.isChecked === undefined) ||
|
||||
this.props.defaultCheckedState.toString() !==
|
||||
prevProps.defaultCheckedState.toString()
|
||||
) {
|
||||
this.updateWidgetMetaProperty(
|
||||
"isChecked",
|
||||
this.props.defaultCheckedState,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
return (
|
||||
<CheckboxComponent
|
||||
defaultCheckedState={this.props.defaultCheckedState}
|
||||
isChecked={!!this.props.isChecked}
|
||||
label={this.props.label}
|
||||
widgetId={this.props.widgetId}
|
||||
key={this.props.widgetId}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import {
|
|||
CONTAINER_GRID_PADDING,
|
||||
WIDGET_PADDING,
|
||||
MAIN_CONTAINER_WIDGET_ID,
|
||||
RenderModes,
|
||||
} from "constants/WidgetConstants";
|
||||
|
||||
import ResizeBoundsContainerComponent from "components/editorComponents/ResizeBoundsContainerComponent";
|
||||
|
|
@ -64,12 +63,8 @@ class ContainerWidget extends BaseWidget<
|
|||
return _.map(
|
||||
// sort by row so stacking context is correct
|
||||
// TODO(abhinav): This is hacky. The stacking context should increase for widgets rendered top to bottom, always.
|
||||
// Figure out a way in which the stacking context is consitent.
|
||||
_.sortBy(this.props.children, child => {
|
||||
return this.props.renderMode === RenderModes.CANVAS
|
||||
? child.topRow
|
||||
: -child.topRow;
|
||||
}),
|
||||
// Figure out a way in which the stacking context is consistent.
|
||||
_.sortBy(this.props.children, child => child.topRow),
|
||||
this.renderChildWidget,
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
|||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import { EventType } from "constants/ActionConstants";
|
||||
import DatePickerComponent from "components/designSystems/blueprint/DatePickerComponent";
|
||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/ValidationFactory";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import {
|
||||
DerivedPropertiesMap,
|
||||
|
|
@ -13,8 +16,8 @@ import {
|
|||
class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
defaultDate: VALIDATION_TYPES.DATE,
|
||||
selectedDate: VALIDATION_TYPES.DATE,
|
||||
timezone: VALIDATION_TYPES.TEXT,
|
||||
enableTimePicker: VALIDATION_TYPES.BOOLEAN,
|
||||
dateFormat: VALIDATION_TYPES.TEXT,
|
||||
|
|
@ -37,6 +40,21 @@ class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
|||
onDateSelected: true,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: DatePickerWidgetProps) {
|
||||
super.componentDidUpdate(prevProps);
|
||||
if (this.props.defaultDate) {
|
||||
if (
|
||||
(this.props.selectedDate !== prevProps.selectedDate &&
|
||||
this.props.selectedDate === undefined) ||
|
||||
this.props.defaultDate.toDateString() !==
|
||||
prevProps.defaultDate.toDateString()
|
||||
) {
|
||||
this.updateWidgetMetaProperty("selectedDate", this.props.defaultDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
return (
|
||||
<DatePickerComponent
|
||||
|
|
@ -45,7 +63,6 @@ class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
|||
widgetId={this.props.widgetId}
|
||||
timezone={this.props.timezone}
|
||||
enableTimePicker={this.props.enableTimePicker}
|
||||
defaultDate={this.props.defaultDate}
|
||||
datePickerType={"DATE_PICKER"}
|
||||
onDateSelected={this.onDateSelected}
|
||||
selectedDate={this.props.selectedDate}
|
||||
|
|
@ -74,7 +91,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
|||
export type DatePickerType = "DATE_PICKER" | "DATE_RANGE_PICKER";
|
||||
|
||||
export interface DatePickerWidgetProps extends WidgetProps {
|
||||
defaultDate?: Date;
|
||||
defaultDate: Date;
|
||||
selectedDate: Date;
|
||||
timezone?: string;
|
||||
enableTimePicker: boolean;
|
||||
|
|
|
|||
|
|
@ -4,18 +4,21 @@ import { WidgetType } from "constants/WidgetConstants";
|
|||
import { EventType } from "constants/ActionConstants";
|
||||
import DropDownComponent from "components/designSystems/blueprint/DropdownComponent";
|
||||
import _ from "lodash";
|
||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/ValidationFactory";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
||||
|
||||
class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
placeholderText: VALIDATION_TYPES.TEXT,
|
||||
label: VALIDATION_TYPES.TEXT,
|
||||
options: VALIDATION_TYPES.OPTIONS_DATA,
|
||||
selectionType: VALIDATION_TYPES.TEXT,
|
||||
selectedIndex: VALIDATION_TYPES.NUMBER,
|
||||
selectedIndexArr: VALIDATION_TYPES.ARRAY,
|
||||
isRequired: VALIDATION_TYPES.BOOLEAN,
|
||||
};
|
||||
|
|
@ -44,6 +47,16 @@ class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
|
|||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
super.componentDidMount();
|
||||
if (this.props.defaultOptionValue) {
|
||||
const selectedIndex = _.findIndex(this.props.options, option => {
|
||||
return option.value === this.props.defaultOptionValue;
|
||||
});
|
||||
this.updateWidgetMetaProperty("selectedIndex", selectedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: DropdownWidgetProps) {
|
||||
super.componentDidUpdate(prevProps);
|
||||
if (
|
||||
|
|
@ -51,22 +64,26 @@ class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
|
|||
) {
|
||||
this.updateWidgetMetaProperty("selectedIndex", undefined);
|
||||
this.updateWidgetMetaProperty("selectedIndexArr", []);
|
||||
} else if (
|
||||
(this.props.selectedIndex !== prevProps.selectedIndex &&
|
||||
this.props.selectedIndex === undefined) ||
|
||||
this.props.defaultOptionValue !== prevProps.defaultOptionValue
|
||||
) {
|
||||
const selectedIndex = _.findIndex(this.props.options, option => {
|
||||
return option.value === this.props.defaultOptionValue;
|
||||
});
|
||||
if (selectedIndex > -1) {
|
||||
this.updateWidgetMetaProperty("selectedIndex", selectedIndex);
|
||||
} else {
|
||||
this.updateWidgetMetaProperty("selectedIndex", undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
getPageView() {
|
||||
const options = this.props.options || [];
|
||||
let selectedIndex: number | undefined = undefined;
|
||||
if (
|
||||
this.props.selectedIndex !== undefined &&
|
||||
this.props.selectedIndex < options.length &&
|
||||
this.props.selectedIndex >= 0
|
||||
) {
|
||||
selectedIndex = this.props.selectedIndex;
|
||||
}
|
||||
|
||||
const selectedIndexArr = this.props.selectedIndexArr || [];
|
||||
let computedSelectedIndexArr = selectedIndexArr.slice();
|
||||
selectedIndexArr.forEach((selectedIndex, index) => {
|
||||
selectedIndexArr.forEach(selectedIndex => {
|
||||
if (options[selectedIndex] === undefined) {
|
||||
computedSelectedIndexArr = [];
|
||||
}
|
||||
|
|
@ -80,7 +97,7 @@ class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
|
|||
placeholder={this.props.placeholderText}
|
||||
options={options}
|
||||
selectionType={this.props.selectionType}
|
||||
selectedIndex={selectedIndex}
|
||||
selectedIndex={this.props.selectedIndex}
|
||||
selectedIndexArr={computedSelectedIndexArr}
|
||||
label={`${this.props.label}${this.props.isRequired ? " *" : ""}`}
|
||||
isLoading={this.props.isLoading}
|
||||
|
|
@ -156,6 +173,7 @@ export interface DropdownWidgetProps extends WidgetProps {
|
|||
selectionType: SelectionType;
|
||||
options?: DropdownOption[];
|
||||
onOptionChange?: string;
|
||||
defaultOptionValue?: string;
|
||||
isRequired: boolean;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,12 @@ import Webcam from "@uppy/webcam";
|
|||
import Url from "@uppy/url";
|
||||
import OneDrive from "@uppy/onedrive";
|
||||
import FilePickerComponent from "components/designSystems/appsmith/FilePickerComponent";
|
||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/ValidationFactory";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { EventType } from "constants/ActionConstants";
|
||||
import { EventType, ExecutionResult } from "constants/ActionConstants";
|
||||
import {
|
||||
DerivedPropertiesMap,
|
||||
TriggerPropertiesMap,
|
||||
|
|
@ -28,9 +31,11 @@ class FilePickerWidget extends BaseWidget<FilePickerWidgetProps, WidgetState> {
|
|||
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
label: VALIDATION_TYPES.TEXT,
|
||||
maxNumFiles: VALIDATION_TYPES.NUMBER,
|
||||
allowedFileTypes: VALIDATION_TYPES.ARRAY,
|
||||
files: VALIDATION_TYPES.ARRAY,
|
||||
isRequired: VALIDATION_TYPES.BOOLEAN,
|
||||
};
|
||||
}
|
||||
|
|
@ -96,13 +101,15 @@ class FilePickerWidget extends BaseWidget<FilePickerWidgetProps, WidgetState> {
|
|||
locale: {},
|
||||
});
|
||||
this.uppy.on("file-removed", (file: any) => {
|
||||
const updatedFiles = this.props.files.filter(dslFile => {
|
||||
return file.id !== dslFile.id;
|
||||
});
|
||||
const updatedFiles = this.props.files
|
||||
? this.props.files.filter(dslFile => {
|
||||
return file.id !== dslFile.id;
|
||||
})
|
||||
: [];
|
||||
this.updateWidgetMetaProperty("files", updatedFiles);
|
||||
});
|
||||
this.uppy.on("file-added", (file: any) => {
|
||||
const dslFiles = this.props.files;
|
||||
const dslFiles = this.props.files || [];
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file.data);
|
||||
reader.onloadend = () => {
|
||||
|
|
@ -133,14 +140,30 @@ class FilePickerWidget extends BaseWidget<FilePickerWidgetProps, WidgetState> {
|
|||
dynamicString: this.props.onFilesSelected,
|
||||
event: {
|
||||
type: EventType.ON_FILES_SELECTED,
|
||||
callback: this.handleFileUploaded,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleFileUploaded = (result: ExecutionResult) => {
|
||||
if (result.success) {
|
||||
this.updateWidgetMetaProperty(
|
||||
"uploadedFileData",
|
||||
this.props.uploadedFileUrls,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps: FilePickerWidgetProps) {
|
||||
super.componentDidUpdate(prevProps);
|
||||
if (
|
||||
prevProps.files &&
|
||||
prevProps.files.length > 0 &&
|
||||
this.props.files === undefined
|
||||
) {
|
||||
this.uppy.reset();
|
||||
} else if (
|
||||
!shallowequal(prevProps.allowedFileTypes, this.props.allowedFileTypes) ||
|
||||
prevProps.maxNumFiles !== this.props.maxNumFiles ||
|
||||
prevProps.maxFileSize !== this.props.maxFileSize
|
||||
|
|
@ -165,7 +188,7 @@ class FilePickerWidget extends BaseWidget<FilePickerWidgetProps, WidgetState> {
|
|||
widgetId={this.props.widgetId}
|
||||
key={this.props.widgetId}
|
||||
label={this.props.label}
|
||||
files={this.props.files}
|
||||
files={this.props.files || []}
|
||||
isLoading={this.props.isLoading}
|
||||
/>
|
||||
);
|
||||
|
|
@ -180,10 +203,11 @@ export interface FilePickerWidgetProps extends WidgetProps {
|
|||
label: string;
|
||||
maxNumFiles?: number;
|
||||
maxFileSize?: number;
|
||||
files: any[];
|
||||
files?: any[];
|
||||
allowedFileTypes: string[];
|
||||
onFilesSelected?: string;
|
||||
isRequired?: boolean;
|
||||
uploadedFileUrls?: string;
|
||||
}
|
||||
|
||||
export default FilePickerWidget;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ import ButtonComponent, {
|
|||
ButtonType,
|
||||
} from "components/designSystems/blueprint/ButtonComponent";
|
||||
import { EventType, ExecutionResult } from "constants/ActionConstants";
|
||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
||||
import {
|
||||
BASE_WIDGET_VALIDATION,
|
||||
WidgetPropertyValidationType,
|
||||
} from "utils/ValidationFactory";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
||||
|
||||
|
|
@ -30,10 +33,11 @@ class FormButtonWidget extends BaseWidget<
|
|||
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
text: VALIDATION_TYPES.TEXT,
|
||||
disabledWhenInvalid: VALIDATION_TYPES.BOOLEAN,
|
||||
isVisible: VALIDATION_TYPES.BOOLEAN,
|
||||
buttonStyle: VALIDATION_TYPES.TEXT,
|
||||
buttonType: VALIDATION_TYPES.TEXT,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -55,6 +59,8 @@ class FormButtonWidget extends BaseWidget<
|
|||
callback: this.handleActionResult,
|
||||
},
|
||||
});
|
||||
} else if (this.props.resetFormOnClick && this.props.onReset) {
|
||||
this.props.onReset();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -84,7 +90,7 @@ class FormButtonWidget extends BaseWidget<
|
|||
disabled={disabled}
|
||||
onClick={this.onButtonClickBound}
|
||||
isLoading={this.props.isLoading || this.state.isLoading}
|
||||
type={ButtonType.SUBMIT}
|
||||
type={this.props.buttonType || ButtonType.BUTTON}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -105,6 +111,7 @@ export interface FormButtonWidgetProps extends WidgetProps {
|
|||
buttonStyle?: ButtonStyle;
|
||||
onClick?: string;
|
||||
isVisible?: boolean;
|
||||
buttonType: ButtonType;
|
||||
isFormValid?: boolean;
|
||||
resetFormOnClick?: boolean;
|
||||
onReset?: () => void;
|
||||
|
|
|
|||
|
|
@ -2,12 +2,16 @@ import * as React from "react";
|
|||
import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import ImageComponent from "components/designSystems/appsmith/ImageComponent";
|
||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/ValidationFactory";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
|
||||
class ImageWidget extends BaseWidget<ImageWidgetProps, WidgetState> {
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
image: VALIDATION_TYPES.TEXT,
|
||||
imageShape: VALIDATION_TYPES.TEXT,
|
||||
defaultImage: VALIDATION_TYPES.TEXT,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ import InputComponent, {
|
|||
InputComponentProps,
|
||||
} from "components/designSystems/blueprint/InputComponent";
|
||||
import { EventType } from "constants/ActionConstants";
|
||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/ValidationFactory";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { FIELD_REQUIRED_ERROR } from "constants/messages";
|
||||
import {
|
||||
|
|
@ -16,6 +19,7 @@ import {
|
|||
class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
inputType: VALIDATION_TYPES.TEXT,
|
||||
defaultText: VALIDATION_TYPES.TEXT,
|
||||
isDisabled: VALIDATION_TYPES.BOOLEAN,
|
||||
|
|
@ -30,7 +34,9 @@ class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
|||
inputValidators: VALIDATION_TYPES.ARRAY,
|
||||
focusIndex: VALIDATION_TYPES.NUMBER,
|
||||
isAutoFocusEnabled: VALIDATION_TYPES.BOOLEAN,
|
||||
onTextChanged: VALIDATION_TYPES.TEXT,
|
||||
isRequired: VALIDATION_TYPES.BOOLEAN,
|
||||
isValid: VALIDATION_TYPES.BOOLEAN,
|
||||
};
|
||||
}
|
||||
static getTriggerPropertyMap(): TriggerPropertiesMap {
|
||||
|
|
@ -64,6 +70,16 @@ class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
|||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: InputWidgetProps) {
|
||||
super.componentDidUpdate(prevProps);
|
||||
if (
|
||||
(this.props.text !== prevProps.text && this.props.text === undefined) ||
|
||||
this.props.defaultText !== prevProps.defaultText
|
||||
) {
|
||||
this.updateWidgetMetaProperty("text", this.props.defaultText);
|
||||
}
|
||||
}
|
||||
|
||||
onValueChange = (value: string) => {
|
||||
this.updateWidgetMetaProperty("text", value);
|
||||
if (!this.props.isDirty) {
|
||||
|
|
@ -96,7 +112,6 @@ class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
|||
if (this.props.maxNum) conditionalProps.maxNum = this.props.maxNum;
|
||||
if (this.props.minNum) conditionalProps.minNum = this.props.minNum;
|
||||
if (this.props.isRequired) conditionalProps.label = `${this.props.label} *`;
|
||||
|
||||
return (
|
||||
<InputComponent
|
||||
value={value}
|
||||
|
|
|
|||
|
|
@ -3,16 +3,22 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
|||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import RadioGroupComponent from "components/designSystems/blueprint/RadioGroupComponent";
|
||||
import { EventType } from "constants/ActionConstants";
|
||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/ValidationFactory";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
||||
|
||||
class RadioGroupWidget extends BaseWidget<RadioGroupWidgetProps, WidgetState> {
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
label: VALIDATION_TYPES.TEXT,
|
||||
options: VALIDATION_TYPES.OPTIONS_DATA,
|
||||
selectedOptionValue: VALIDATION_TYPES.TEXT,
|
||||
onSelectionChange: VALIDATION_TYPES.TEXT,
|
||||
defaultOptionValue: VALIDATION_TYPES.TEXT,
|
||||
isRequired: VALIDATION_TYPES.BOOLEAN,
|
||||
};
|
||||
}
|
||||
|
|
@ -28,6 +34,30 @@ class RadioGroupWidget extends BaseWidget<RadioGroupWidgetProps, WidgetState> {
|
|||
onSelectionChange: true,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
super.componentDidMount();
|
||||
if (this.props.defaultOptionValue) {
|
||||
this.updateWidgetMetaProperty(
|
||||
"selectedOptionValue",
|
||||
this.props.defaultOptionValue,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: RadioGroupWidgetProps) {
|
||||
super.componentDidUpdate(prevProps);
|
||||
if (
|
||||
(this.props.selectedOptionValue !== prevProps.selectedOptionValue &&
|
||||
this.props.selectedOptionValue === undefined) ||
|
||||
this.props.defaultOptionValue !== prevProps.defaultOptionValue
|
||||
) {
|
||||
this.updateWidgetMetaProperty(
|
||||
"selectedOptionValue",
|
||||
this.props.defaultOptionValue,
|
||||
);
|
||||
}
|
||||
}
|
||||
getPageView() {
|
||||
return (
|
||||
<RadioGroupComponent
|
||||
|
|
@ -35,7 +65,6 @@ class RadioGroupWidget extends BaseWidget<RadioGroupWidgetProps, WidgetState> {
|
|||
onRadioSelectionChange={this.onRadioSelectionChange}
|
||||
key={this.props.widgetId}
|
||||
label={`${this.props.label}${this.props.isRequired ? " *" : ""}`}
|
||||
defaultOptionValue={this.props.defaultOptionValue}
|
||||
selectedOptionValue={this.props.selectedOptionValue}
|
||||
options={this.props.options}
|
||||
isLoading={this.props.isLoading}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,16 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
|||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import { Intent } from "@blueprintjs/core";
|
||||
import SpinnerComponent from "components/designSystems/blueprint/SpinnerComponent";
|
||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/ValidationFactory";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
|
||||
class SpinnerWidget extends BaseWidget<SpinnerWidgetProps, WidgetState> {
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
size: VALIDATION_TYPES.NUMBER,
|
||||
value: VALIDATION_TYPES.NUMBER,
|
||||
ellipsize: VALIDATION_TYPES.BOOLEAN,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@ import { forIn } from "lodash";
|
|||
import TableComponent from "components/designSystems/syncfusion/TableComponent";
|
||||
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/ValidationFactory";
|
||||
import { ColumnModel } from "@syncfusion/ej2-grids";
|
||||
import { ColumnDirTypecast } from "@syncfusion/ej2-react-grids";
|
||||
import { ColumnAction } from "components/propertyControls/ColumnActionSelectorControl";
|
||||
|
|
@ -30,6 +33,7 @@ function constructColumns(data: object[]): ColumnModel[] | ColumnDirTypecast[] {
|
|||
class TableWidget extends BaseWidget<TableWidgetProps, WidgetState> {
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
tableData: VALIDATION_TYPES.TABLE_DATA,
|
||||
nextPageKey: VALIDATION_TYPES.TEXT,
|
||||
prevPageKey: VALIDATION_TYPES.TEXT,
|
||||
|
|
@ -156,11 +160,6 @@ class TableWidget extends BaseWidget<TableWidgetProps, WidgetState> {
|
|||
}
|
||||
}
|
||||
|
||||
type RowData = {
|
||||
rowIndex: number;
|
||||
};
|
||||
type SelectedRow = object & RowData;
|
||||
|
||||
export interface TableWidgetProps extends WidgetProps {
|
||||
nextPageKey?: string;
|
||||
prevPageKey?: string;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
|||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import TextComponent from "components/designSystems/blueprint/TextComponent";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/ValidationFactory";
|
||||
|
||||
const LINE_HEIGHTS: { [key in TextStyle]: number } = {
|
||||
// The following values are arrived at by multiplying line-height with font-size
|
||||
|
|
@ -16,9 +19,10 @@ const LINE_HEIGHTS: { [key in TextStyle]: number } = {
|
|||
class TextWidget extends BaseWidget<TextWidgetProps, WidgetState> {
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
text: VALIDATION_TYPES.TEXT,
|
||||
textStyle: VALIDATION_TYPES.TEXT,
|
||||
isVisible: VALIDATION_TYPES.BOOLEAN,
|
||||
shouldScroll: VALIDATION_TYPES.BOOLEAN,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
2250
app/client/yarn.lock
2250
app/client/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user