Merge branch 'release' of gitlab.com:theappsmith/internal-tools-client into fix/chart-component-title-align
This commit is contained in:
commit
9021e6edb1
|
|
@ -1,5 +1,4 @@
|
||||||
.git
|
.git
|
||||||
.idea
|
.idea
|
||||||
node_modules
|
node_modules
|
||||||
build
|
|
||||||
build.tgz
|
build.tgz
|
||||||
1
app/client/.gitignore
vendored
1
app/client/.gitignore
vendored
|
|
@ -29,4 +29,5 @@ yarn-error.log*
|
||||||
.idea
|
.idea
|
||||||
.storybook-out/
|
.storybook-out/
|
||||||
cypress/videos
|
cypress/videos
|
||||||
|
cypress/screenshots
|
||||||
results/
|
results/
|
||||||
|
|
@ -4,6 +4,17 @@
|
||||||
- master
|
- master
|
||||||
- merge_requests
|
- merge_requests
|
||||||
|
|
||||||
|
.set_env_variables: &set_env_variables
|
||||||
|
- |
|
||||||
|
if [ "$CI_COMMIT_BRANCH" == "master" ]; then
|
||||||
|
REACT_APP_ENVIRONMENT="PRODUCTION"
|
||||||
|
elif [ "$CI_COMMIT_BRANCH" == "release" ]; then
|
||||||
|
REACT_APP_ENVIRONMENT="STAGING"
|
||||||
|
REACT_APP_BASE_URL="https://release-api.appsmith.com"
|
||||||
|
else
|
||||||
|
REACT_APP_ENVIRONMENT="DEVELOPMENT"
|
||||||
|
REACT_APP_BASE_URL="https://release-api.appsmith.com"
|
||||||
|
fi
|
||||||
image: cypress/base:10.16.3
|
image: cypress/base:10.16.3
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
|
|
@ -25,32 +36,38 @@ stages:
|
||||||
- package
|
- package
|
||||||
- deploy
|
- deploy
|
||||||
|
|
||||||
react-build:
|
react-build-release:
|
||||||
stage: build
|
stage: build
|
||||||
script:
|
script:
|
||||||
|
- *set_env_variables
|
||||||
- yarn install
|
- yarn install
|
||||||
# show where the Cypress test runner binaries are cached
|
# show where the Cypress test runner binaries are cached
|
||||||
- $(npm bin)/cypress cache path
|
- $(npm bin)/cypress cache path
|
||||||
# show all installed versions of Cypress binary
|
# show all installed versions of Cypress binary
|
||||||
- $(npm bin)/cypress cache list
|
- $(npm bin)/cypress cache list
|
||||||
- $(npm bin)/cypress verify
|
- $(npm bin)/cypress verify
|
||||||
|
- REACT_APP_ENVIRONMENT=$REACT_APP_ENVIRONMENT REACT_APP_BASE_URL=$REACT_APP_BASE_URL GIT_SHA=$CI_COMMIT_SHORT_SHA yarn build
|
||||||
|
artifacts:
|
||||||
|
expire_in: 1 week
|
||||||
|
paths:
|
||||||
|
- build/
|
||||||
only:
|
only:
|
||||||
- release
|
- release
|
||||||
- merge_requests
|
- merge_requests
|
||||||
|
|
||||||
cypress-test:
|
cypress-test-release:
|
||||||
stage: test
|
stage: test
|
||||||
script:
|
script:
|
||||||
- REACT_APP_ENVIRONMENT=DEVELOPMENT REACT_APP_BASE_URL="https://release-api.appsmith.com" GIT_SHA=$CI_COMMIT_SHORT_SHA yarn build
|
- *set_env_variables
|
||||||
- yarn global add serve
|
- yarn global add serve
|
||||||
- serve -s build -p 3000 &
|
- serve -s build -p 3000 &
|
||||||
# This is required in order to ensure that all the test cases pass
|
# This is required in order to ensure that all the test cases pass
|
||||||
- echo "127.0.0.1 dev.appsmith.com" >> /etc/hosts
|
- echo "127.0.0.1 dev.appsmith.com" >> /etc/hosts
|
||||||
- yarn test
|
- yarn test
|
||||||
artifacts:
|
artifacts:
|
||||||
|
when: always
|
||||||
expire_in: 1 week
|
expire_in: 1 week
|
||||||
paths:
|
paths:
|
||||||
- build/
|
|
||||||
- cypress/screenshots
|
- cypress/screenshots
|
||||||
- cypress/videos
|
- cypress/videos
|
||||||
only:
|
only:
|
||||||
|
|
@ -64,19 +81,35 @@ docker-package-release:
|
||||||
- docker:dind
|
- docker:dind
|
||||||
stage: package
|
stage: package
|
||||||
script:
|
script:
|
||||||
- docker build --build-arg REACT_APP_ENVIRONMENT=STAGING --build-arg GIT_SHA=$CI_COMMIT_SHORT_SHA -t appsmith/appsmith-editor:release .
|
- *set_env_variables
|
||||||
|
- docker build -t appsmith/appsmith-editor:release .
|
||||||
- docker login -u $DOCKER_HUB_USERNAME -p $DOCKER_HUB_ACCESS_TOKEN
|
- docker login -u $DOCKER_HUB_USERNAME -p $DOCKER_HUB_ACCESS_TOKEN
|
||||||
- docker push appsmith/appsmith-editor:release
|
- docker push appsmith/appsmith-editor:release
|
||||||
only:
|
only:
|
||||||
- release
|
- release
|
||||||
|
|
||||||
|
react-build-prod:
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- *set_env_variables
|
||||||
|
- yarn install
|
||||||
|
- REACT_APP_ENVIRONMENT=$REACT_APP_ENVIRONMENT GIT_SHA=$CI_COMMIT_SHORT_SHA yarn build
|
||||||
|
artifacts:
|
||||||
|
when: on_success
|
||||||
|
expire_in: 1 week
|
||||||
|
paths:
|
||||||
|
- build/
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
|
||||||
docker-package-prod:
|
docker-package-prod:
|
||||||
image: docker:dind
|
image: docker:dind
|
||||||
services:
|
services:
|
||||||
- docker:dind
|
- docker:dind
|
||||||
stage: package
|
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 .
|
- *set_env_variables
|
||||||
|
- docker build -t appsmith/appsmith-editor:latest .
|
||||||
- docker login -u $DOCKER_HUB_USERNAME -p $DOCKER_HUB_ACCESS_TOKEN
|
- docker login -u $DOCKER_HUB_USERNAME -p $DOCKER_HUB_ACCESS_TOKEN
|
||||||
- docker push appsmith/appsmith-editor:latest
|
- docker push appsmith/appsmith-editor:latest
|
||||||
only:
|
only:
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,7 @@
|
||||||
FROM node:10.19-alpine as build-deps
|
FROM nginx:1.17.9-alpine
|
||||||
|
|
||||||
WORKDIR /usr/src/app
|
COPY ./build /var/www/appsmith
|
||||||
|
RUN ls -al /var/www/appsmith
|
||||||
ARG REACT_APP_ENVIRONMENT="DEVELOPMENT"
|
|
||||||
ARG GIT_SHA=""
|
|
||||||
|
|
||||||
ENV REACT_APP_ENVIRONMENT=${REACT_APP_ENVIRONMENT}
|
|
||||||
ENV REACT_APP_BASE_URL=${REACT_APP_BASE_URL}
|
|
||||||
ENV GIT_SHA=${GIT_SHA}
|
|
||||||
|
|
||||||
COPY package.json yarn.lock ./
|
|
||||||
COPY . ./
|
|
||||||
RUN yarn install && yarn build
|
|
||||||
|
|
||||||
# Use the output from the previous Docker build to create the nginx container
|
|
||||||
FROM nginx:1.17.9-alpine as final-image
|
|
||||||
COPY --from=build-deps /usr/src/app/docker/nginx.conf /etc/nginx/conf.d/default.conf
|
|
||||||
COPY --from=build-deps /usr/src/app/build /var/www/appsmith
|
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# GIT_SHA=$(eval git rev-parse HEAD)
|
|
||||||
# GIT_BRANCH=$(git branch --no-color | grep -E '^\*' | sed 's/\*[^a-z]*//g')
|
# GIT_BRANCH=$(git branch --no-color | grep -E '^\*' | sed 's/\*[^a-z]*//g')
|
||||||
|
|
||||||
# RELEASE="${GIT_BRANCH}_${GIT_SHA}"
|
# RELEASE="${GIT_BRANCH}_${GIT_SHA}"
|
||||||
|
|
||||||
|
|
||||||
# RELEASE=$(echo "$RELEASE" | sed -e 's/[\/\\\ .]/\-/g')
|
# RELEASE=$(echo "$RELEASE" | sed -e 's/[\/\\\ .]/\-/g')
|
||||||
# echo $RELEASE
|
# echo $RELEASE
|
||||||
|
|
||||||
|
GIT_SHA=$(eval git rev-parse HEAD)
|
||||||
|
echo $GIT_SHA
|
||||||
REACT_APP_SENTRY_RELEASE=$GIT_SHA craco --max-old-space-size=4096 build --config craco.build.config.js
|
REACT_APP_SENTRY_RELEASE=$GIT_SHA craco --max-old-space-size=4096 build --config craco.build.config.js
|
||||||
|
|
||||||
rm ./build/static/js/*.js.map
|
rm ./build/static/js/*.js.map
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
"@blueprintjs/timezone": "^3.6.0",
|
"@blueprintjs/timezone": "^3.6.0",
|
||||||
"@craco/craco": "^5.6.1",
|
"@craco/craco": "^5.6.1",
|
||||||
"@sentry/browser": "^5.6.3",
|
"@sentry/browser": "^5.6.3",
|
||||||
|
"@sentry/webpack-plugin": "^1.10.0",
|
||||||
"@syncfusion/ej2-react-grids": "^17.4.40",
|
"@syncfusion/ej2-react-grids": "^17.4.40",
|
||||||
"@types/chance": "^1.0.7",
|
"@types/chance": "^1.0.7",
|
||||||
"@types/fontfaceobserver": "^0.0.6",
|
"@types/fontfaceobserver": "^0.0.6",
|
||||||
|
|
@ -117,7 +118,6 @@
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.7.4",
|
"@babel/core": "^7.7.4",
|
||||||
"@sentry/webpack-plugin": "^1.10.0",
|
|
||||||
"@storybook/addon-contexts": "^5.2.6",
|
"@storybook/addon-contexts": "^5.2.6",
|
||||||
"@storybook/addon-docs": "^5.2.8",
|
"@storybook/addon-docs": "^5.2.8",
|
||||||
"@storybook/addon-knobs": "^5.2.6",
|
"@storybook/addon-knobs": "^5.2.6",
|
||||||
|
|
@ -158,8 +158,7 @@
|
||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
"hooks": {
|
"hooks": {
|
||||||
"pre-commit": "lint-staged",
|
"pre-commit": "lint-staged"
|
||||||
"pre-push": "yarn run test"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,14 +71,14 @@ class DatePickerComponent extends React.Component<DatePickerComponentProps> {
|
||||||
this.props.enableTimePicker
|
this.props.enableTimePicker
|
||||||
? {
|
? {
|
||||||
useAmPm: true,
|
useAmPm: true,
|
||||||
value: this.props.selectedDate || this.props.defaultDate,
|
value: this.props.selectedDate,
|
||||||
showArrowButtons: true,
|
showArrowButtons: true,
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
closeOnSelection={true}
|
closeOnSelection={true}
|
||||||
onChange={this.onDateSelected}
|
onChange={this.onDateSelected}
|
||||||
value={this.props.selectedDate || this.props.defaultDate}
|
value={this.props.selectedDate}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<DateRangeInput
|
<DateRangeInput
|
||||||
|
|
@ -121,7 +121,6 @@ class DatePickerComponent extends React.Component<DatePickerComponentProps> {
|
||||||
|
|
||||||
export interface DatePickerComponentProps extends ComponentProps {
|
export interface DatePickerComponentProps extends ComponentProps {
|
||||||
label: string;
|
label: string;
|
||||||
defaultDate?: Date;
|
|
||||||
dateFormat: string;
|
dateFormat: string;
|
||||||
enableTimePicker?: boolean;
|
enableTimePicker?: boolean;
|
||||||
selectedDate?: Date;
|
selectedDate?: Date;
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,8 @@ class DropDownComponent extends React.Component<DropDownComponentProps> {
|
||||||
rightIcon={IconNames.CHEVRON_DOWN}
|
rightIcon={IconNames.CHEVRON_DOWN}
|
||||||
text={
|
text={
|
||||||
!_.isEmpty(this.props.options) &&
|
!_.isEmpty(this.props.options) &&
|
||||||
this.props.selectedIndex !== undefined
|
this.props.selectedIndex !== undefined &&
|
||||||
|
this.props.selectedIndex > -1
|
||||||
? this.props.options[this.props.selectedIndex].label
|
? this.props.options[this.props.selectedIndex].label
|
||||||
: "-- Empty --"
|
: "-- Empty --"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -144,10 +144,19 @@ const DraggableComponent = (props: DraggableComponentProps) => {
|
||||||
props.widgetId === propertyPaneState.widgetId) ||
|
props.widgetId === propertyPaneState.widgetId) ||
|
||||||
props.widgetId !== propertyPaneState.widgetId
|
props.widgetId !== propertyPaneState.widgetId
|
||||||
) {
|
) {
|
||||||
|
AnalyticsUtil.logEvent("PROPERTY_PANE_OPEN_CLICK", {
|
||||||
|
widgetType: props.type,
|
||||||
|
widgetId: props.widgetId,
|
||||||
|
});
|
||||||
showPropertyPane && showPropertyPane(props.widgetId, undefined, true);
|
showPropertyPane && showPropertyPane(props.widgetId, undefined, true);
|
||||||
} else {
|
} else {
|
||||||
|
AnalyticsUtil.logEvent("PROPERTY_PANE_CLOSE_CLICK", {
|
||||||
|
widgetType: props.type,
|
||||||
|
widgetId: props.widgetId,
|
||||||
|
});
|
||||||
showPropertyPane && showPropertyPane();
|
showPropertyPane && showPropertyPane();
|
||||||
}
|
}
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -318,7 +318,7 @@ class DynamicActionCreator extends React.Component<Props & ReduxStateProps> {
|
||||||
) => void,
|
) => void,
|
||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
<div style={{ paddingLeft: 5 }}>
|
<div>
|
||||||
{selectedOption.arguments.map(arg => {
|
{selectedOption.arguments.map(arg => {
|
||||||
switch (arg.field) {
|
switch (arg.field) {
|
||||||
case "ACTION_SELECTOR_FIELD":
|
case "ACTION_SELECTOR_FIELD":
|
||||||
|
|
@ -357,14 +357,15 @@ class DynamicActionCreator extends React.Component<Props & ReduxStateProps> {
|
||||||
);
|
);
|
||||||
case "TEXT_FIELD":
|
case "TEXT_FIELD":
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={arg.label}>
|
<ControlWrapper key={arg.label}>
|
||||||
|
<label>{arg.label}</label>
|
||||||
<InputText
|
<InputText
|
||||||
label={arg.label}
|
label={arg.label}
|
||||||
value={arg.getSelectedValue(value, false)}
|
value={arg.getSelectedValue(value, false)}
|
||||||
onChange={e => handleUpdate(e, arg.valueChangeHandler)}
|
onChange={e => handleUpdate(e, arg.valueChangeHandler)}
|
||||||
isValid={true}
|
isValid={true}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</ControlWrapper>
|
||||||
);
|
);
|
||||||
case "ALERT_TYPE_SELECTOR_FIELD":
|
case "ALERT_TYPE_SELECTOR_FIELD":
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ export interface ControlData {
|
||||||
id: string;
|
id: string;
|
||||||
label: string;
|
label: string;
|
||||||
propertyName: string;
|
propertyName: string;
|
||||||
|
helpText?: string;
|
||||||
|
isJSConvertible?: boolean;
|
||||||
controlType: ControlType;
|
controlType: ControlType;
|
||||||
propertyValue?: any;
|
propertyValue?: any;
|
||||||
isValid: boolean;
|
isValid: boolean;
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,9 @@ export function InputText(props: {
|
||||||
onChange: (event: React.ChangeEvent<HTMLTextAreaElement> | string) => void;
|
onChange: (event: React.ChangeEvent<HTMLTextAreaElement> | string) => void;
|
||||||
isValid: boolean;
|
isValid: boolean;
|
||||||
validationMessage?: string;
|
validationMessage?: string;
|
||||||
|
placeholder?: string;
|
||||||
}) {
|
}) {
|
||||||
const { validationMessage, value, isValid, onChange } = props;
|
const { validationMessage, value, isValid, onChange, placeholder } = props;
|
||||||
return (
|
return (
|
||||||
<StyledDynamicInput>
|
<StyledDynamicInput>
|
||||||
<DynamicAutocompleteInput
|
<DynamicAutocompleteInput
|
||||||
|
|
@ -26,6 +27,7 @@ export function InputText(props: {
|
||||||
}}
|
}}
|
||||||
theme={"DARK"}
|
theme={"DARK"}
|
||||||
singleLine={false}
|
singleLine={false}
|
||||||
|
placeholder={placeholder}
|
||||||
/>
|
/>
|
||||||
</StyledDynamicInput>
|
</StyledDynamicInput>
|
||||||
);
|
);
|
||||||
|
|
@ -33,7 +35,13 @@ export function InputText(props: {
|
||||||
|
|
||||||
class InputTextControl extends BaseControl<InputControlProps> {
|
class InputTextControl extends BaseControl<InputControlProps> {
|
||||||
render() {
|
render() {
|
||||||
const { validationMessage, propertyValue, isValid, label } = this.props;
|
const {
|
||||||
|
validationMessage,
|
||||||
|
propertyValue,
|
||||||
|
isValid,
|
||||||
|
label,
|
||||||
|
placeholderText,
|
||||||
|
} = this.props;
|
||||||
return (
|
return (
|
||||||
<InputText
|
<InputText
|
||||||
label={label}
|
label={label}
|
||||||
|
|
@ -41,6 +49,7 @@ class InputTextControl extends BaseControl<InputControlProps> {
|
||||||
onChange={this.onTextChange}
|
onChange={this.onTextChange}
|
||||||
isValid={isValid}
|
isValid={isValid}
|
||||||
validationMessage={validationMessage}
|
validationMessage={validationMessage}
|
||||||
|
placeholder={placeholderText}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { ControlType } from "constants/PropertyControlConstants";
|
||||||
import styled from "constants/DefaultTheme";
|
import styled from "constants/DefaultTheme";
|
||||||
import { FormIcons } from "icons/FormIcons";
|
import { FormIcons } from "icons/FormIcons";
|
||||||
import { AnyStyledComponent } from "styled-components";
|
import { AnyStyledComponent } from "styled-components";
|
||||||
|
import { generateReactKey } from "utils/generators";
|
||||||
|
|
||||||
const StyledDeleteIcon = styled(FormIcons.DELETE_ICON as AnyStyledComponent)`
|
const StyledDeleteIcon = styled(FormIcons.DELETE_ICON as AnyStyledComponent)`
|
||||||
padding: 5px 5px;
|
padding: 5px 5px;
|
||||||
|
|
@ -28,16 +29,64 @@ const StyledOptionControlWrapper = styled(ControlWrapper)`
|
||||||
padding-right: 16px;
|
padding-right: 16px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
class OptionControl extends BaseControl<ControlProps> {
|
function updateOptionLabel<T>(
|
||||||
|
options: Array<T>,
|
||||||
|
index: number,
|
||||||
|
updatedLabel: string,
|
||||||
|
) {
|
||||||
|
return options.map((option: T, optionIndex) => {
|
||||||
|
if (index !== optionIndex) {
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...option,
|
||||||
|
label: updatedLabel,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateOptionValue<T>(
|
||||||
|
options: Array<T>,
|
||||||
|
index: number,
|
||||||
|
updatedValue: string,
|
||||||
|
) {
|
||||||
|
return options.map((option, optionIndex) => {
|
||||||
|
if (index !== optionIndex) {
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...option,
|
||||||
|
value: updatedValue,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
type DropDownOptionWithKey = DropdownOption & {
|
||||||
|
key: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OptionControl extends BaseControl<
|
||||||
|
ControlProps,
|
||||||
|
{
|
||||||
|
renderOptions: DropDownOptionWithKey[];
|
||||||
|
}
|
||||||
|
> {
|
||||||
|
constructor(props: ControlProps) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
renderOptions: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
render() {
|
render() {
|
||||||
const options: DropdownOption[] = this.props.propertyValue || [{}];
|
const { renderOptions } = this.state;
|
||||||
|
debugger;
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{options.map((option, index) => {
|
{renderOptions.map((option, index) => {
|
||||||
return (
|
return (
|
||||||
<StyledOptionControlWrapper
|
<StyledOptionControlWrapper
|
||||||
orientation={"HORIZONTAL"}
|
orientation={"HORIZONTAL"}
|
||||||
key={option.value}
|
key={option.key}
|
||||||
>
|
>
|
||||||
<StyledOptionControlInputGroup
|
<StyledOptionControlInputGroup
|
||||||
type={"text"}
|
type={"text"}
|
||||||
|
|
@ -76,49 +125,100 @@ class OptionControl extends BaseControl<ControlProps> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const { propertyValue } = this.props;
|
||||||
|
|
||||||
|
const options: DropdownOption[] = Array.isArray(propertyValue)
|
||||||
|
? propertyValue
|
||||||
|
: [{}];
|
||||||
|
|
||||||
|
options.map(option => {
|
||||||
|
return {
|
||||||
|
...option,
|
||||||
|
key: generateReactKey(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
this.setState({
|
||||||
|
renderOptions: options.map(option => {
|
||||||
|
return {
|
||||||
|
...option,
|
||||||
|
key: generateReactKey(),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
deleteOption = (index: number) => {
|
deleteOption = (index: number) => {
|
||||||
const options: DropdownOption[] = this.props.propertyValue.slice();
|
const { propertyValue } = this.props;
|
||||||
options.splice(index, 1);
|
const options: DropdownOption[] = Array.isArray(propertyValue)
|
||||||
this.updateProperty("options", options);
|
? propertyValue
|
||||||
|
: [{}];
|
||||||
|
const { renderOptions } = this.state;
|
||||||
|
|
||||||
|
const newOptions = options.filter((o, i) => i !== index);
|
||||||
|
const newRenderOptions = renderOptions.filter((o, i) => i !== index);
|
||||||
|
|
||||||
|
this.updateProperty("options", newOptions);
|
||||||
|
this.setState({
|
||||||
|
renderOptions: newRenderOptions,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
updateOptionLabel = (index: number, updatedLabel: string) => {
|
updateOptionLabel = (index: number, updatedLabel: string) => {
|
||||||
const options: DropdownOption[] = this.props.propertyValue;
|
const { propertyValue } = this.props;
|
||||||
|
const options: DropdownOption[] = Array.isArray(propertyValue)
|
||||||
|
? propertyValue
|
||||||
|
: [{}];
|
||||||
this.updateProperty(
|
this.updateProperty(
|
||||||
"options",
|
"options",
|
||||||
options.map((option, optionIndex) => {
|
updateOptionLabel(options, index, updatedLabel),
|
||||||
if (index !== optionIndex) {
|
|
||||||
return option;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
...option,
|
|
||||||
label: updatedLabel,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
renderOptions: updateOptionLabel(
|
||||||
|
this.state.renderOptions,
|
||||||
|
index,
|
||||||
|
updatedLabel,
|
||||||
|
),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
updateOptionValue = (index: number, updatedValue: string) => {
|
updateOptionValue = (index: number, updatedValue: string) => {
|
||||||
const options: DropdownOption[] = this.props.propertyValue;
|
const { propertyValue } = this.props;
|
||||||
|
const options: DropdownOption[] = Array.isArray(propertyValue)
|
||||||
|
? propertyValue
|
||||||
|
: [{}];
|
||||||
this.updateProperty(
|
this.updateProperty(
|
||||||
"options",
|
"options",
|
||||||
options.map((option, optionIndex) => {
|
updateOptionValue(options, index, updatedValue),
|
||||||
if (index !== optionIndex) {
|
|
||||||
return option;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
...option,
|
|
||||||
value: updatedValue,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
renderOptions: updateOptionValue(
|
||||||
|
this.state.renderOptions,
|
||||||
|
index,
|
||||||
|
updatedValue,
|
||||||
|
),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
addOption = () => {
|
addOption = () => {
|
||||||
const options: DropdownOption[] = this.props.propertyValue
|
const { propertyValue } = this.props;
|
||||||
? this.props.propertyValue.slice()
|
const options: DropdownOption[] = Array.isArray(propertyValue)
|
||||||
: [];
|
? propertyValue
|
||||||
|
: [{}];
|
||||||
|
const { renderOptions } = this.state;
|
||||||
|
|
||||||
options.push({ label: "", value: "" });
|
options.push({ label: "", value: "" });
|
||||||
|
renderOptions.push({
|
||||||
|
label: "",
|
||||||
|
value: "",
|
||||||
|
key: generateReactKey(),
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
renderOptions: renderOptions,
|
||||||
|
});
|
||||||
this.updateProperty("options", options);
|
this.updateProperty("options", options);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,3 @@ export type ControlType =
|
||||||
| "TIME_ZONE"
|
| "TIME_ZONE"
|
||||||
| "CODE_EDITOR"
|
| "CODE_EDITOR"
|
||||||
| "COLUMN_ACTION_SELECTOR";
|
| "COLUMN_ACTION_SELECTOR";
|
||||||
|
|
||||||
export const CONVERTIBLE_CONTROLS = [
|
|
||||||
"SWITCH",
|
|
||||||
"OPTION_INPUT",
|
|
||||||
"ACTION_SELECTOR",
|
|
||||||
"DATE_PICKER",
|
|
||||||
];
|
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,7 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
||||||
FILE_PICKER_WIDGET: {
|
FILE_PICKER_WIDGET: {
|
||||||
rows: 1,
|
rows: 1,
|
||||||
files: [],
|
files: [],
|
||||||
|
label: "Select Files",
|
||||||
columns: 4,
|
columns: 4,
|
||||||
widgetName: "FilePicker",
|
widgetName: "FilePicker",
|
||||||
isDefaultClickDisabled: true,
|
isDefaultClickDisabled: true,
|
||||||
|
|
@ -201,14 +202,14 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
||||||
isDefaultClickDisabled: true,
|
isDefaultClickDisabled: true,
|
||||||
},
|
},
|
||||||
FORM_WIDGET: {
|
FORM_WIDGET: {
|
||||||
rows: 10,
|
rows: 13,
|
||||||
columns: 10,
|
columns: 6,
|
||||||
widgetName: "Form",
|
widgetName: "Form",
|
||||||
blueprint: {
|
blueprint: {
|
||||||
view: [
|
view: [
|
||||||
{
|
{
|
||||||
type: "TEXT_WIDGET",
|
type: "TEXT_WIDGET",
|
||||||
size: { rows: 1, cols: 4 },
|
size: { rows: 1, cols: 12 },
|
||||||
position: { top: 0, left: 0 },
|
position: { top: 0, left: 0 },
|
||||||
props: {
|
props: {
|
||||||
text: "Title",
|
text: "Title",
|
||||||
|
|
@ -217,8 +218,8 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "FORM_BUTTON_WIDGET",
|
type: "FORM_BUTTON_WIDGET",
|
||||||
size: { rows: 1, cols: 3 },
|
size: { rows: 1, cols: 4 },
|
||||||
position: { top: 8, left: 13 },
|
position: { top: 11, left: 12 },
|
||||||
props: {
|
props: {
|
||||||
text: "Submit",
|
text: "Submit",
|
||||||
buttonStyle: "PRIMARY_BUTTON",
|
buttonStyle: "PRIMARY_BUTTON",
|
||||||
|
|
@ -228,8 +229,8 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "FORM_BUTTON_WIDGET",
|
type: "FORM_BUTTON_WIDGET",
|
||||||
size: { rows: 1, cols: 3 },
|
size: { rows: 1, cols: 4 },
|
||||||
position: { top: 8, left: 10 },
|
position: { top: 11, left: 8 },
|
||||||
props: {
|
props: {
|
||||||
text: "Reset",
|
text: "Reset",
|
||||||
buttonStyle: "SECONDARY_BUTTON",
|
buttonStyle: "SECONDARY_BUTTON",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { CONVERTIBLE_CONTROLS } from "constants/PropertyControlConstants";
|
|
||||||
import {
|
import {
|
||||||
ControlPropertyLabelContainer,
|
ControlPropertyLabelContainer,
|
||||||
ControlWrapper,
|
ControlWrapper,
|
||||||
|
|
@ -10,6 +9,7 @@ import { ControlIcons } from "icons/ControlIcons";
|
||||||
import PropertyControlFactory from "utils/PropertyControlFactory";
|
import PropertyControlFactory from "utils/PropertyControlFactory";
|
||||||
import { WidgetProps } from "widgets/BaseWidget";
|
import { WidgetProps } from "widgets/BaseWidget";
|
||||||
import { ControlConfig } from "reducers/entityReducers/propertyPaneConfigReducer";
|
import { ControlConfig } from "reducers/entityReducers/propertyPaneConfigReducer";
|
||||||
|
import { Tooltip } from "@blueprintjs/core";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
widgetProperties: WidgetProps;
|
widgetProperties: WidgetProps;
|
||||||
|
|
@ -18,6 +18,47 @@ type Props = {
|
||||||
onPropertyChange: (propertyName: string, propertyValue: any) => void;
|
onPropertyChange: (propertyName: string, propertyValue: any) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function UnderlinedLabel({
|
||||||
|
tooltip,
|
||||||
|
label,
|
||||||
|
}: {
|
||||||
|
tooltip?: string;
|
||||||
|
label: string;
|
||||||
|
}) {
|
||||||
|
const toolTipDefined = tooltip !== undefined;
|
||||||
|
return (
|
||||||
|
<Tooltip disabled={!toolTipDefined} content={tooltip} hoverOpenDelay={200}>
|
||||||
|
<div
|
||||||
|
style={
|
||||||
|
toolTipDefined
|
||||||
|
? {
|
||||||
|
height: "20px",
|
||||||
|
cursor: "help",
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
height: "20px",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
<span
|
||||||
|
style={
|
||||||
|
toolTipDefined
|
||||||
|
? {
|
||||||
|
borderBottom: "1px dashed",
|
||||||
|
width: "100%",
|
||||||
|
display: "inline-block",
|
||||||
|
position: "relative",
|
||||||
|
top: "-15px",
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
></span>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const PropertyControl = (props: Props) => {
|
const PropertyControl = (props: Props) => {
|
||||||
const {
|
const {
|
||||||
widgetProperties,
|
widgetProperties,
|
||||||
|
|
@ -54,7 +95,7 @@ const PropertyControl = (props: Props) => {
|
||||||
["dynamicProperties", propertyName],
|
["dynamicProperties", propertyName],
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
const isConvertible = CONVERTIBLE_CONTROLS.indexOf(config.controlType) > -1;
|
const isConvertible = !!propertyConfig.isJSConvertible;
|
||||||
const className = propertyConfig.label
|
const className = propertyConfig.label
|
||||||
.split(" ")
|
.split(" ")
|
||||||
.join("")
|
.join("")
|
||||||
|
|
@ -71,7 +112,11 @@ const PropertyControl = (props: Props) => {
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ControlPropertyLabelContainer>
|
<ControlPropertyLabelContainer>
|
||||||
<label>{label}</label>
|
<UnderlinedLabel
|
||||||
|
tooltip={propertyConfig.helpText}
|
||||||
|
label={label}
|
||||||
|
></UnderlinedLabel>
|
||||||
|
|
||||||
{isConvertible && (
|
{isConvertible && (
|
||||||
<JSToggleButton
|
<JSToggleButton
|
||||||
active={isDynamic}
|
active={isDynamic}
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,12 @@ class PropertyPane extends Component<
|
||||||
|
|
||||||
<CloseButton
|
<CloseButton
|
||||||
onClick={(e: any) => {
|
onClick={(e: any) => {
|
||||||
|
AnalyticsUtil.logEvent("PROPERTY_PANE_CLOSE_CLICK", {
|
||||||
|
widgetType: this.props.widgetProperties
|
||||||
|
? this.props.widgetProperties.type
|
||||||
|
: "",
|
||||||
|
widgetId: this.props.widgetId,
|
||||||
|
});
|
||||||
this.props.hidePropertyPane();
|
this.props.hidePropertyPane();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
@ -167,6 +173,40 @@ class PropertyPane extends Component<
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps: PropertyPaneProps & PropertyPaneFunctions) {
|
||||||
|
if (
|
||||||
|
this.props.widgetId !== prevProps.widgetId &&
|
||||||
|
this.props.widgetId !== undefined
|
||||||
|
) {
|
||||||
|
if (prevProps.widgetId && prevProps.widgetProperties) {
|
||||||
|
AnalyticsUtil.logEvent("PROPERTY_PANE_CLOSE", {
|
||||||
|
widgetType: prevProps.widgetProperties.type,
|
||||||
|
widgetId: prevProps.widgetId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.props.widgetProperties) {
|
||||||
|
AnalyticsUtil.logEvent("PROPERTY_PANE_OPEN", {
|
||||||
|
widgetType: this.props.widgetProperties.type,
|
||||||
|
widgetId: this.props.widgetId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.props.widgetId === prevProps.widgetId &&
|
||||||
|
this.props.isVisible &&
|
||||||
|
!prevProps.isVisible &&
|
||||||
|
this.props.widgetProperties !== undefined
|
||||||
|
) {
|
||||||
|
AnalyticsUtil.logEvent("PROPERTY_PANE_OPEN", {
|
||||||
|
widgetType: this.props.widgetProperties.type,
|
||||||
|
widgetId: this.props.widgetId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
onPropertyChange(propertyName: string, propertyValue: any) {
|
onPropertyChange(propertyName: string, propertyValue: any) {
|
||||||
this.props.updateWidgetProperty(
|
this.props.updateWidgetProperty(
|
||||||
this.props.widgetId,
|
this.props.widgetId,
|
||||||
|
|
|
||||||
|
|
@ -134,12 +134,10 @@ export function* evaluateDynamicBoundValueSaga(path: string): any {
|
||||||
|
|
||||||
export function* getActionParams(jsonPathKeys: string[] | undefined) {
|
export function* getActionParams(jsonPathKeys: string[] | undefined) {
|
||||||
if (_.isNil(jsonPathKeys)) return [];
|
if (_.isNil(jsonPathKeys)) return [];
|
||||||
const values: any = _.flatten(
|
const values: any = yield all(
|
||||||
yield all(
|
jsonPathKeys.map((jsonPath: string) => {
|
||||||
jsonPathKeys.map((jsonPath: string) => {
|
return call(evaluateDynamicBoundValueSaga, jsonPath);
|
||||||
return call(evaluateDynamicBoundValueSaga, jsonPath);
|
}),
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
const dynamicBindings: Record<string, string> = {};
|
const dynamicBindings: Record<string, string> = {};
|
||||||
jsonPathKeys.forEach((key, i) => {
|
jsonPathKeys.forEach((key, i) => {
|
||||||
|
|
@ -302,7 +300,13 @@ export function* executeActionTriggers(
|
||||||
AnalyticsUtil.logEvent("NAVIGATE", {
|
AnalyticsUtil.logEvent("NAVIGATE", {
|
||||||
navUrl: trigger.payload.url,
|
navUrl: trigger.payload.url,
|
||||||
});
|
});
|
||||||
window.location.href = trigger.payload.url;
|
// Add a default protocol if it doesn't exist.
|
||||||
|
let url = trigger.payload.url;
|
||||||
|
if (url.indexOf("://") === -1) {
|
||||||
|
url = "https://" + url;
|
||||||
|
}
|
||||||
|
window.location.assign(url);
|
||||||
|
|
||||||
if (event.callback) event.callback({ success: true });
|
if (event.callback) event.callback({ success: true });
|
||||||
} else {
|
} else {
|
||||||
if (event.callback) event.callback({ success: false });
|
if (event.callback) event.callback({ success: false });
|
||||||
|
|
@ -329,10 +333,12 @@ export function* executeAppAction(action: ReduxAction<ExecuteActionPayload>) {
|
||||||
const { dynamicString, event, responseData } = action.payload;
|
const { dynamicString, event, responseData } = action.payload;
|
||||||
const tree = yield select(evaluateDataTree);
|
const tree = yield select(evaluateDataTree);
|
||||||
const { triggers } = getDynamicValue(dynamicString, tree, responseData, true);
|
const { triggers } = getDynamicValue(dynamicString, tree, responseData, true);
|
||||||
if (triggers) {
|
if (triggers && triggers.length) {
|
||||||
yield all(
|
yield all(
|
||||||
triggers.map(trigger => call(executeActionTriggers, trigger, event)),
|
triggers.map(trigger => call(executeActionTriggers, trigger, event)),
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
if (event.callback) event.callback({ success: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -585,8 +591,7 @@ function* executePageLoadActionsSaga(action: ReduxAction<PageAction[][]>) {
|
||||||
const pageActions = action.payload;
|
const pageActions = action.payload;
|
||||||
for (const actionSet of pageActions) {
|
for (const actionSet of pageActions) {
|
||||||
const apiResponses = yield select(getActionResponses);
|
const apiResponses = yield select(getActionResponses);
|
||||||
const filteredSet = actionSet.filter(action => !apiResponses[action.id]);
|
yield* yield all(actionSet.map(a => call(executePageLoadAction, a)));
|
||||||
yield* yield all(filteredSet.map(a => call(executePageLoadAction, a)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -687,7 +692,7 @@ function* copyActionSaga(
|
||||||
export function* watchActionSagas() {
|
export function* watchActionSagas() {
|
||||||
yield all([
|
yield all([
|
||||||
takeEvery(ReduxActionTypes.FETCH_ACTIONS_INIT, fetchActionsSaga),
|
takeEvery(ReduxActionTypes.FETCH_ACTIONS_INIT, fetchActionsSaga),
|
||||||
takeLatest(ReduxActionTypes.EXECUTE_ACTION, executeAppAction),
|
takeEvery(ReduxActionTypes.EXECUTE_ACTION, executeAppAction),
|
||||||
takeLatest(ReduxActionTypes.RUN_API_REQUEST, runApiActionSaga),
|
takeLatest(ReduxActionTypes.RUN_API_REQUEST, runApiActionSaga),
|
||||||
takeLatest(ReduxActionTypes.CREATE_ACTION_INIT, createActionSaga),
|
takeLatest(ReduxActionTypes.CREATE_ACTION_INIT, createActionSaga),
|
||||||
takeLatest(ReduxActionTypes.UPDATE_ACTION_INIT, updateActionSaga),
|
takeLatest(ReduxActionTypes.UPDATE_ACTION_INIT, updateActionSaga),
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,8 @@ export function* errorSaga(
|
||||||
type,
|
type,
|
||||||
payload: { error, show = true },
|
payload: { error, show = true },
|
||||||
} = errorAction;
|
} = errorAction;
|
||||||
const message = error.message || ActionErrorDisplayMap[type](error);
|
const message =
|
||||||
|
error && error.message ? error.message : ActionErrorDisplayMap[type](error);
|
||||||
if (show) AppToaster.show({ message, type: ToastType.ERROR });
|
if (show) AppToaster.show({ message, type: ToastType.ERROR });
|
||||||
yield put({
|
yield put({
|
||||||
type: ReduxActionTypes.REPORT_ERROR,
|
type: ReduxActionTypes.REPORT_ERROR,
|
||||||
|
|
|
||||||
|
|
@ -123,12 +123,12 @@ export function* fetchPageSaga(
|
||||||
if (isValidResponse) {
|
if (isValidResponse) {
|
||||||
// Get Canvas payload
|
// Get Canvas payload
|
||||||
const canvasWidgetsPayload = getCanvasWidgetsPayload(fetchPageResponse);
|
const canvasWidgetsPayload = getCanvasWidgetsPayload(fetchPageResponse);
|
||||||
// Execute page load actions
|
|
||||||
yield put(executePageLoadActions(canvasWidgetsPayload.pageActions));
|
|
||||||
// Update the canvas
|
// Update the canvas
|
||||||
yield put(updateCanvas(canvasWidgetsPayload));
|
yield put(updateCanvas(canvasWidgetsPayload));
|
||||||
// dispatch fetch page success
|
// dispatch fetch page success
|
||||||
yield put(fetchPageSuccess());
|
yield put(fetchPageSuccess());
|
||||||
|
// Execute page load actions
|
||||||
|
yield put(executePageLoadActions(canvasWidgetsPayload.pageActions));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
yield put({
|
yield put({
|
||||||
|
|
@ -155,8 +155,6 @@ export function* fetchPublishedPageSaga(
|
||||||
const isValidResponse = yield validateResponse(response);
|
const isValidResponse = yield validateResponse(response);
|
||||||
if (isValidResponse) {
|
if (isValidResponse) {
|
||||||
const canvasWidgetsPayload = getCanvasWidgetsPayload(response);
|
const canvasWidgetsPayload = getCanvasWidgetsPayload(response);
|
||||||
// Execute page load actions
|
|
||||||
yield put(executePageLoadActions(canvasWidgetsPayload.pageActions));
|
|
||||||
yield put(updateCanvas(canvasWidgetsPayload));
|
yield put(updateCanvas(canvasWidgetsPayload));
|
||||||
yield put({
|
yield put({
|
||||||
type: ReduxActionTypes.FETCH_PUBLISHED_PAGE_SUCCESS,
|
type: ReduxActionTypes.FETCH_PUBLISHED_PAGE_SUCCESS,
|
||||||
|
|
@ -167,6 +165,8 @@ export function* fetchPublishedPageSaga(
|
||||||
pageWidgetId: canvasWidgetsPayload.pageWidgetId,
|
pageWidgetId: canvasWidgetsPayload.pageWidgetId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
// Execute page load actions
|
||||||
|
yield put(executePageLoadActions(canvasWidgetsPayload.pageActions));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
yield put({
|
yield put({
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import {
|
||||||
takeLatest,
|
takeLatest,
|
||||||
all,
|
all,
|
||||||
} from "redux-saga/effects";
|
} from "redux-saga/effects";
|
||||||
import { getNextEntityName } from "utils/AppsmithUtils";
|
import { convertToString, getNextEntityName } from "utils/AppsmithUtils";
|
||||||
import {
|
import {
|
||||||
SetWidgetDynamicPropertyPayload,
|
SetWidgetDynamicPropertyPayload,
|
||||||
updateWidgetProperty,
|
updateWidgetProperty,
|
||||||
|
|
@ -262,7 +262,8 @@ function* setWidgetDynamicPropertySaga(
|
||||||
};
|
};
|
||||||
if (isDynamic) {
|
if (isDynamic) {
|
||||||
dynamicProperties[propertyName] = true;
|
dynamicProperties[propertyName] = true;
|
||||||
yield put(updateWidgetProperty(widgetId, propertyName, "{{}}"));
|
const value = convertToString(widget[propertyName]);
|
||||||
|
yield put(updateWidgetProperty(widgetId, propertyName, value));
|
||||||
} else {
|
} else {
|
||||||
delete dynamicProperties[propertyName];
|
delete dynamicProperties[propertyName];
|
||||||
yield put(updateWidgetProperty(widgetId, propertyName, undefined));
|
yield put(updateWidgetProperty(widgetId, propertyName, undefined));
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import {
|
||||||
getResponseErrorMessage,
|
getResponseErrorMessage,
|
||||||
callAPI,
|
callAPI,
|
||||||
} from "./ErrorSagas";
|
} from "./ErrorSagas";
|
||||||
|
import * as Sentry from "@sentry/browser";
|
||||||
|
|
||||||
import { fetchOrgsSaga } from "./OrgSagas";
|
import { fetchOrgsSaga } from "./OrgSagas";
|
||||||
|
|
||||||
|
|
@ -295,6 +296,9 @@ export function* setCurrentUserSaga(action: ReduxAction<FetchUserRequest>) {
|
||||||
const me = yield call(fetchUserSaga, action);
|
const me = yield call(fetchUserSaga, action);
|
||||||
if (me) {
|
if (me) {
|
||||||
AnalyticsUtil.identifyUser(me.id, me);
|
AnalyticsUtil.identifyUser(me.id, me);
|
||||||
|
Sentry.configureScope(function(scope) {
|
||||||
|
scope.setUser({ email: me.email, id: me.id });
|
||||||
|
});
|
||||||
resetAuthExpiration();
|
resetAuthExpiration();
|
||||||
yield put({
|
yield put({
|
||||||
type: ReduxActionTypes.SET_CURRENT_USER_SUCCESS,
|
type: ReduxActionTypes.SET_CURRENT_USER_SUCCESS,
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,11 @@ export type EventName =
|
||||||
| "SAVE_DATA_SOURCE"
|
| "SAVE_DATA_SOURCE"
|
||||||
| "NAVIGATE"
|
| "NAVIGATE"
|
||||||
| "PAGE_LOAD"
|
| "PAGE_LOAD"
|
||||||
| "NAVIGATE_EDITOR";
|
| "NAVIGATE_EDITOR"
|
||||||
|
| "PROPERTY_PANE_OPEN"
|
||||||
|
| "PROPERTY_PANE_CLOSE"
|
||||||
|
| "PROPERTY_PANE_OPEN_CLICK"
|
||||||
|
| "PROPERTY_PANE_CLOSE_CLICK";
|
||||||
|
|
||||||
export type Gender = "MALE" | "FEMALE";
|
export type Gender = "MALE" | "FEMALE";
|
||||||
export interface User {
|
export interface User {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { ReduxAction } from "../constants/ReduxActionConstants";
|
import { ReduxAction } from "constants/ReduxActionConstants";
|
||||||
import { getAppsmithConfigs } from "configs";
|
import { getAppsmithConfigs } from "configs";
|
||||||
import * as Sentry from "@sentry/browser";
|
import * as Sentry from "@sentry/browser";
|
||||||
import AnalyticsUtil from "./AnalyticsUtil";
|
import AnalyticsUtil from "./AnalyticsUtil";
|
||||||
|
|
@ -77,3 +77,14 @@ export const getNextEntityName = (prefix: string, existingNames: string[]) => {
|
||||||
export const noop = () => {
|
export const noop = () => {
|
||||||
console.log("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 { WidgetType } from "constants/WidgetConstants";
|
||||||
import WidgetFactory from "./WidgetFactory";
|
import WidgetFactory from "./WidgetFactory";
|
||||||
import {
|
import {
|
||||||
|
VALIDATION_TYPES,
|
||||||
ValidationResponse,
|
ValidationResponse,
|
||||||
ValidationType,
|
ValidationType,
|
||||||
Validator,
|
Validator,
|
||||||
} from "constants/WidgetValidation";
|
} 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>;
|
export type WidgetPropertyValidationType = Record<string, ValidationType>;
|
||||||
|
|
||||||
class ValidationFactory {
|
class ValidationFactory {
|
||||||
|
|
|
||||||
|
|
@ -84,20 +84,16 @@ export const VALIDATORS: Record<ValidationType, Validator> = {
|
||||||
message: `${WIDGET_TYPE_VALIDATION_ERROR}: boolean`,
|
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) {
|
if (!isValid) {
|
||||||
try {
|
return {
|
||||||
parsed = !!value;
|
isValid: isValid,
|
||||||
isValid = true;
|
parsed: parsed,
|
||||||
} catch (e) {
|
message: `${WIDGET_TYPE_VALIDATION_ERROR}: boolean`,
|
||||||
console.error(`Error when parsing ${value} to boolean`);
|
};
|
||||||
console.error(e);
|
|
||||||
return {
|
|
||||||
isValid: false,
|
|
||||||
parsed: false,
|
|
||||||
message: `${WIDGET_TYPE_VALIDATION_ERROR}: boolean`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return { isValid, parsed };
|
return { isValid, parsed };
|
||||||
},
|
},
|
||||||
|
|
@ -217,6 +213,15 @@ export const VALIDATORS: Record<ValidationType, Validator> = {
|
||||||
return { isValid, parsed };
|
return { isValid, parsed };
|
||||||
},
|
},
|
||||||
[VALIDATION_TYPES.DATE]: (value: any): ValidationResponse => {
|
[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 isValid = moment(value).isValid();
|
||||||
const parsed = isValid ? moment(value).toDate() : new Date();
|
const parsed = isValid ? moment(value).toDate() : new Date();
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,10 @@ import {
|
||||||
WidgetProps,
|
WidgetProps,
|
||||||
WidgetDataProps,
|
WidgetDataProps,
|
||||||
} from "widgets/BaseWidget";
|
} from "widgets/BaseWidget";
|
||||||
import { WidgetPropertyValidationType } from "./ValidationFactory";
|
import {
|
||||||
|
WidgetPropertyValidationType,
|
||||||
|
BASE_WIDGET_VALIDATION,
|
||||||
|
} from "./ValidationFactory";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
type WidgetDerivedPropertyType = any;
|
type WidgetDerivedPropertyType = any;
|
||||||
|
|
@ -78,7 +81,7 @@ class WidgetFactory {
|
||||||
const map = this.widgetPropValidationMap.get(widgetType);
|
const map = this.widgetPropValidationMap.get(widgetType);
|
||||||
if (!map) {
|
if (!map) {
|
||||||
console.error("Widget type validation is not defined");
|
console.error("Widget type validation is not defined");
|
||||||
return {};
|
return BASE_WIDGET_VALIDATION;
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,10 @@ import { EditorContext } from "components/editorComponents/EditorContextProvider
|
||||||
import { PositionTypes } from "constants/WidgetConstants";
|
import { PositionTypes } from "constants/WidgetConstants";
|
||||||
|
|
||||||
import ErrorBoundary from "components/editorComponents/ErrorBoundry";
|
import ErrorBoundary from "components/editorComponents/ErrorBoundry";
|
||||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
import {
|
||||||
|
BASE_WIDGET_VALIDATION,
|
||||||
|
WidgetPropertyValidationType,
|
||||||
|
} from "utils/ValidationFactory";
|
||||||
import {
|
import {
|
||||||
DerivedPropertiesMap,
|
DerivedPropertiesMap,
|
||||||
TriggerPropertiesMap,
|
TriggerPropertiesMap,
|
||||||
|
|
@ -66,7 +69,7 @@ abstract class BaseWidget<
|
||||||
// Needed to send a default no validation option. In case a widget needs
|
// Needed to send a default no validation option. In case a widget needs
|
||||||
// validation implement this in the widget class again
|
// validation implement this in the widget class again
|
||||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||||
return {};
|
return BASE_WIDGET_VALIDATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getDerivedPropertiesMap(): DerivedPropertiesMap {
|
static getDerivedPropertiesMap(): DerivedPropertiesMap {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,10 @@ import ButtonComponent, {
|
||||||
ButtonType,
|
ButtonType,
|
||||||
} from "components/designSystems/blueprint/ButtonComponent";
|
} from "components/designSystems/blueprint/ButtonComponent";
|
||||||
import { EventType } from "constants/ActionConstants";
|
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 { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||||
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
||||||
|
|
||||||
|
|
@ -30,9 +33,8 @@ class ButtonWidget extends BaseWidget<
|
||||||
|
|
||||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||||
return {
|
return {
|
||||||
|
...BASE_WIDGET_VALIDATION,
|
||||||
text: VALIDATION_TYPES.TEXT,
|
text: VALIDATION_TYPES.TEXT,
|
||||||
isDisabled: VALIDATION_TYPES.BOOLEAN,
|
|
||||||
isVisible: VALIDATION_TYPES.BOOLEAN,
|
|
||||||
buttonStyle: VALIDATION_TYPES.TEXT,
|
buttonStyle: VALIDATION_TYPES.TEXT,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,16 @@ import { WidgetType } from "constants/WidgetConstants";
|
||||||
import CheckboxComponent from "components/designSystems/blueprint/CheckboxComponent";
|
import CheckboxComponent from "components/designSystems/blueprint/CheckboxComponent";
|
||||||
import { EventType } from "constants/ActionConstants";
|
import { EventType } from "constants/ActionConstants";
|
||||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
import {
|
||||||
|
WidgetPropertyValidationType,
|
||||||
|
BASE_WIDGET_VALIDATION,
|
||||||
|
} from "utils/ValidationFactory";
|
||||||
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
||||||
|
|
||||||
class CheckboxWidget extends BaseWidget<CheckboxWidgetProps, WidgetState> {
|
class CheckboxWidget extends BaseWidget<CheckboxWidgetProps, WidgetState> {
|
||||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||||
return {
|
return {
|
||||||
isDisabled: VALIDATION_TYPES.BOOLEAN,
|
...BASE_WIDGET_VALIDATION,
|
||||||
label: VALIDATION_TYPES.TEXT,
|
label: VALIDATION_TYPES.TEXT,
|
||||||
defaultCheckedState: VALIDATION_TYPES.BOOLEAN,
|
defaultCheckedState: VALIDATION_TYPES.BOOLEAN,
|
||||||
};
|
};
|
||||||
|
|
@ -34,18 +37,16 @@ class CheckboxWidget extends BaseWidget<CheckboxWidgetProps, WidgetState> {
|
||||||
|
|
||||||
componentDidUpdate(prevProps: CheckboxWidgetProps) {
|
componentDidUpdate(prevProps: CheckboxWidgetProps) {
|
||||||
super.componentDidUpdate(prevProps);
|
super.componentDidUpdate(prevProps);
|
||||||
if (this.props.defaultCheckedState.toString()) {
|
if (
|
||||||
if (
|
(this.props.isChecked !== prevProps.isChecked &&
|
||||||
(this.props.isChecked !== prevProps.isChecked &&
|
this.props.isChecked === undefined) ||
|
||||||
this.props.isChecked === undefined) ||
|
this.props.defaultCheckedState.toString() !==
|
||||||
this.props.defaultCheckedState.toString() !==
|
prevProps.defaultCheckedState.toString()
|
||||||
prevProps.defaultCheckedState.toString()
|
) {
|
||||||
) {
|
this.updateWidgetMetaProperty(
|
||||||
this.updateWidgetMetaProperty(
|
"isChecked",
|
||||||
"isChecked",
|
this.props.defaultCheckedState,
|
||||||
this.props.defaultCheckedState,
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,10 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
||||||
import { WidgetType } from "constants/WidgetConstants";
|
import { WidgetType } from "constants/WidgetConstants";
|
||||||
import { EventType } from "constants/ActionConstants";
|
import { EventType } from "constants/ActionConstants";
|
||||||
import DatePickerComponent from "components/designSystems/blueprint/DatePickerComponent";
|
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 { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||||
import {
|
import {
|
||||||
DerivedPropertiesMap,
|
DerivedPropertiesMap,
|
||||||
|
|
@ -13,8 +16,8 @@ import {
|
||||||
class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
||||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||||
return {
|
return {
|
||||||
|
...BASE_WIDGET_VALIDATION,
|
||||||
defaultDate: VALIDATION_TYPES.DATE,
|
defaultDate: VALIDATION_TYPES.DATE,
|
||||||
selectedDate: VALIDATION_TYPES.DATE,
|
|
||||||
timezone: VALIDATION_TYPES.TEXT,
|
timezone: VALIDATION_TYPES.TEXT,
|
||||||
enableTimePicker: VALIDATION_TYPES.BOOLEAN,
|
enableTimePicker: VALIDATION_TYPES.BOOLEAN,
|
||||||
dateFormat: VALIDATION_TYPES.TEXT,
|
dateFormat: VALIDATION_TYPES.TEXT,
|
||||||
|
|
@ -37,6 +40,21 @@ class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
||||||
onDateSelected: true,
|
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() {
|
getPageView() {
|
||||||
return (
|
return (
|
||||||
<DatePickerComponent
|
<DatePickerComponent
|
||||||
|
|
@ -45,7 +63,6 @@ class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
||||||
widgetId={this.props.widgetId}
|
widgetId={this.props.widgetId}
|
||||||
timezone={this.props.timezone}
|
timezone={this.props.timezone}
|
||||||
enableTimePicker={this.props.enableTimePicker}
|
enableTimePicker={this.props.enableTimePicker}
|
||||||
defaultDate={this.props.defaultDate}
|
|
||||||
datePickerType={"DATE_PICKER"}
|
datePickerType={"DATE_PICKER"}
|
||||||
onDateSelected={this.onDateSelected}
|
onDateSelected={this.onDateSelected}
|
||||||
selectedDate={this.props.selectedDate}
|
selectedDate={this.props.selectedDate}
|
||||||
|
|
@ -74,7 +91,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
||||||
export type DatePickerType = "DATE_PICKER" | "DATE_RANGE_PICKER";
|
export type DatePickerType = "DATE_PICKER" | "DATE_RANGE_PICKER";
|
||||||
|
|
||||||
export interface DatePickerWidgetProps extends WidgetProps {
|
export interface DatePickerWidgetProps extends WidgetProps {
|
||||||
defaultDate?: Date;
|
defaultDate: Date;
|
||||||
selectedDate: Date;
|
selectedDate: Date;
|
||||||
timezone?: string;
|
timezone?: string;
|
||||||
enableTimePicker: boolean;
|
enableTimePicker: boolean;
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,24 @@ import { WidgetType } from "constants/WidgetConstants";
|
||||||
import { EventType } from "constants/ActionConstants";
|
import { EventType } from "constants/ActionConstants";
|
||||||
import DropDownComponent from "components/designSystems/blueprint/DropdownComponent";
|
import DropDownComponent from "components/designSystems/blueprint/DropdownComponent";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
import {
|
||||||
|
WidgetPropertyValidationType,
|
||||||
|
BASE_WIDGET_VALIDATION,
|
||||||
|
} from "utils/ValidationFactory";
|
||||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||||
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
||||||
|
|
||||||
class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
|
class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
|
||||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||||
return {
|
return {
|
||||||
|
...BASE_WIDGET_VALIDATION,
|
||||||
placeholderText: VALIDATION_TYPES.TEXT,
|
placeholderText: VALIDATION_TYPES.TEXT,
|
||||||
label: VALIDATION_TYPES.TEXT,
|
label: VALIDATION_TYPES.TEXT,
|
||||||
options: VALIDATION_TYPES.OPTIONS_DATA,
|
options: VALIDATION_TYPES.OPTIONS_DATA,
|
||||||
selectionType: VALIDATION_TYPES.TEXT,
|
selectionType: VALIDATION_TYPES.TEXT,
|
||||||
selectedIndexArr: VALIDATION_TYPES.ARRAY,
|
selectedIndexArr: VALIDATION_TYPES.ARRAY,
|
||||||
isRequired: VALIDATION_TYPES.BOOLEAN,
|
isRequired: VALIDATION_TYPES.BOOLEAN,
|
||||||
|
defaultOptionValue: VALIDATION_TYPES.TEXT,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
static getDerivedPropertiesMap() {
|
static getDerivedPropertiesMap() {
|
||||||
|
|
@ -60,7 +65,8 @@ class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
|
||||||
) {
|
) {
|
||||||
this.updateWidgetMetaProperty("selectedIndex", undefined);
|
this.updateWidgetMetaProperty("selectedIndex", undefined);
|
||||||
this.updateWidgetMetaProperty("selectedIndexArr", []);
|
this.updateWidgetMetaProperty("selectedIndexArr", []);
|
||||||
} else if (this.props.defaultOptionValue) {
|
}
|
||||||
|
if (this.props.defaultOptionValue) {
|
||||||
if (
|
if (
|
||||||
(this.props.selectedIndex !== prevProps.selectedIndex &&
|
(this.props.selectedIndex !== prevProps.selectedIndex &&
|
||||||
this.props.selectedIndex === undefined) ||
|
this.props.selectedIndex === undefined) ||
|
||||||
|
|
@ -69,7 +75,11 @@ class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
|
||||||
const selectedIndex = _.findIndex(this.props.options, option => {
|
const selectedIndex = _.findIndex(this.props.options, option => {
|
||||||
return option.value === this.props.defaultOptionValue;
|
return option.value === this.props.defaultOptionValue;
|
||||||
});
|
});
|
||||||
this.updateWidgetMetaProperty("selectedIndex", selectedIndex);
|
if (selectedIndex > -1) {
|
||||||
|
this.updateWidgetMetaProperty("selectedIndex", selectedIndex);
|
||||||
|
} else {
|
||||||
|
this.updateWidgetMetaProperty("selectedIndex", undefined);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,10 @@ import Webcam from "@uppy/webcam";
|
||||||
import Url from "@uppy/url";
|
import Url from "@uppy/url";
|
||||||
import OneDrive from "@uppy/onedrive";
|
import OneDrive from "@uppy/onedrive";
|
||||||
import FilePickerComponent from "components/designSystems/appsmith/FilePickerComponent";
|
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 { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||||
import { EventType, ExecutionResult } from "constants/ActionConstants";
|
import { EventType, ExecutionResult } from "constants/ActionConstants";
|
||||||
import {
|
import {
|
||||||
|
|
@ -28,9 +31,11 @@ class FilePickerWidget extends BaseWidget<FilePickerWidgetProps, WidgetState> {
|
||||||
|
|
||||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||||
return {
|
return {
|
||||||
|
...BASE_WIDGET_VALIDATION,
|
||||||
label: VALIDATION_TYPES.TEXT,
|
label: VALIDATION_TYPES.TEXT,
|
||||||
maxNumFiles: VALIDATION_TYPES.NUMBER,
|
maxNumFiles: VALIDATION_TYPES.NUMBER,
|
||||||
allowedFileTypes: VALIDATION_TYPES.ARRAY,
|
allowedFileTypes: VALIDATION_TYPES.ARRAY,
|
||||||
|
files: VALIDATION_TYPES.ARRAY,
|
||||||
isRequired: VALIDATION_TYPES.BOOLEAN,
|
isRequired: VALIDATION_TYPES.BOOLEAN,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,10 @@ import ButtonComponent, {
|
||||||
ButtonType,
|
ButtonType,
|
||||||
} from "components/designSystems/blueprint/ButtonComponent";
|
} from "components/designSystems/blueprint/ButtonComponent";
|
||||||
import { EventType, ExecutionResult } from "constants/ActionConstants";
|
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 { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||||
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
||||||
|
|
||||||
|
|
@ -30,10 +33,11 @@ class FormButtonWidget extends BaseWidget<
|
||||||
|
|
||||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||||
return {
|
return {
|
||||||
|
...BASE_WIDGET_VALIDATION,
|
||||||
text: VALIDATION_TYPES.TEXT,
|
text: VALIDATION_TYPES.TEXT,
|
||||||
disabledWhenInvalid: VALIDATION_TYPES.BOOLEAN,
|
disabledWhenInvalid: VALIDATION_TYPES.BOOLEAN,
|
||||||
isVisible: VALIDATION_TYPES.BOOLEAN,
|
|
||||||
buttonStyle: VALIDATION_TYPES.TEXT,
|
buttonStyle: VALIDATION_TYPES.TEXT,
|
||||||
|
buttonType: VALIDATION_TYPES.TEXT,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,16 @@ import * as React from "react";
|
||||||
import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
||||||
import { WidgetType } from "constants/WidgetConstants";
|
import { WidgetType } from "constants/WidgetConstants";
|
||||||
import ImageComponent from "components/designSystems/appsmith/ImageComponent";
|
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";
|
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||||
|
|
||||||
class ImageWidget extends BaseWidget<ImageWidgetProps, WidgetState> {
|
class ImageWidget extends BaseWidget<ImageWidgetProps, WidgetState> {
|
||||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||||
return {
|
return {
|
||||||
|
...BASE_WIDGET_VALIDATION,
|
||||||
image: VALIDATION_TYPES.TEXT,
|
image: VALIDATION_TYPES.TEXT,
|
||||||
imageShape: VALIDATION_TYPES.TEXT,
|
imageShape: VALIDATION_TYPES.TEXT,
|
||||||
defaultImage: VALIDATION_TYPES.TEXT,
|
defaultImage: VALIDATION_TYPES.TEXT,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,10 @@ import InputComponent, {
|
||||||
InputComponentProps,
|
InputComponentProps,
|
||||||
} from "components/designSystems/blueprint/InputComponent";
|
} from "components/designSystems/blueprint/InputComponent";
|
||||||
import { EventType } from "constants/ActionConstants";
|
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 { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||||
import { FIELD_REQUIRED_ERROR } from "constants/messages";
|
import { FIELD_REQUIRED_ERROR } from "constants/messages";
|
||||||
import {
|
import {
|
||||||
|
|
@ -16,6 +19,7 @@ import {
|
||||||
class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
||||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||||
return {
|
return {
|
||||||
|
...BASE_WIDGET_VALIDATION,
|
||||||
inputType: VALIDATION_TYPES.TEXT,
|
inputType: VALIDATION_TYPES.TEXT,
|
||||||
defaultText: VALIDATION_TYPES.TEXT,
|
defaultText: VALIDATION_TYPES.TEXT,
|
||||||
isDisabled: VALIDATION_TYPES.BOOLEAN,
|
isDisabled: VALIDATION_TYPES.BOOLEAN,
|
||||||
|
|
@ -30,7 +34,9 @@ class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
||||||
inputValidators: VALIDATION_TYPES.ARRAY,
|
inputValidators: VALIDATION_TYPES.ARRAY,
|
||||||
focusIndex: VALIDATION_TYPES.NUMBER,
|
focusIndex: VALIDATION_TYPES.NUMBER,
|
||||||
isAutoFocusEnabled: VALIDATION_TYPES.BOOLEAN,
|
isAutoFocusEnabled: VALIDATION_TYPES.BOOLEAN,
|
||||||
|
onTextChanged: VALIDATION_TYPES.TEXT,
|
||||||
isRequired: VALIDATION_TYPES.BOOLEAN,
|
isRequired: VALIDATION_TYPES.BOOLEAN,
|
||||||
|
isValid: VALIDATION_TYPES.BOOLEAN,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
static getTriggerPropertyMap(): TriggerPropertiesMap {
|
static getTriggerPropertyMap(): TriggerPropertiesMap {
|
||||||
|
|
@ -59,20 +65,17 @@ class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
super.componentDidMount();
|
super.componentDidMount();
|
||||||
if (this.props.defaultText) {
|
const text = this.props.defaultText || "";
|
||||||
this.updateWidgetMetaProperty("text", this.props.defaultText);
|
this.updateWidgetMetaProperty("text", text);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps: InputWidgetProps) {
|
componentDidUpdate(prevProps: InputWidgetProps) {
|
||||||
super.componentDidUpdate(prevProps);
|
super.componentDidUpdate(prevProps);
|
||||||
if (this.props.defaultText) {
|
if (
|
||||||
if (
|
(this.props.text !== prevProps.text && this.props.text === undefined) ||
|
||||||
(this.props.text !== prevProps.text && this.props.text === undefined) ||
|
this.props.defaultText !== prevProps.defaultText
|
||||||
this.props.defaultText !== prevProps.defaultText
|
) {
|
||||||
) {
|
this.updateWidgetMetaProperty("text", this.props.defaultText);
|
||||||
this.updateWidgetMetaProperty("text", this.props.defaultText);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,22 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
||||||
import { WidgetType } from "constants/WidgetConstants";
|
import { WidgetType } from "constants/WidgetConstants";
|
||||||
import RadioGroupComponent from "components/designSystems/blueprint/RadioGroupComponent";
|
import RadioGroupComponent from "components/designSystems/blueprint/RadioGroupComponent";
|
||||||
import { EventType } from "constants/ActionConstants";
|
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 { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||||
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
||||||
|
|
||||||
class RadioGroupWidget extends BaseWidget<RadioGroupWidgetProps, WidgetState> {
|
class RadioGroupWidget extends BaseWidget<RadioGroupWidgetProps, WidgetState> {
|
||||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||||
return {
|
return {
|
||||||
|
...BASE_WIDGET_VALIDATION,
|
||||||
label: VALIDATION_TYPES.TEXT,
|
label: VALIDATION_TYPES.TEXT,
|
||||||
options: VALIDATION_TYPES.OPTIONS_DATA,
|
options: VALIDATION_TYPES.OPTIONS_DATA,
|
||||||
selectedOptionValue: VALIDATION_TYPES.TEXT,
|
selectedOptionValue: VALIDATION_TYPES.TEXT,
|
||||||
|
onSelectionChange: VALIDATION_TYPES.TEXT,
|
||||||
|
defaultOptionValue: VALIDATION_TYPES.TEXT,
|
||||||
isRequired: VALIDATION_TYPES.BOOLEAN,
|
isRequired: VALIDATION_TYPES.BOOLEAN,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -41,17 +47,15 @@ class RadioGroupWidget extends BaseWidget<RadioGroupWidgetProps, WidgetState> {
|
||||||
|
|
||||||
componentDidUpdate(prevProps: RadioGroupWidgetProps) {
|
componentDidUpdate(prevProps: RadioGroupWidgetProps) {
|
||||||
super.componentDidUpdate(prevProps);
|
super.componentDidUpdate(prevProps);
|
||||||
if (this.props.defaultOptionValue) {
|
if (
|
||||||
if (
|
(this.props.selectedOptionValue !== prevProps.selectedOptionValue &&
|
||||||
(this.props.selectedOptionValue !== prevProps.selectedOptionValue &&
|
this.props.selectedOptionValue === undefined) ||
|
||||||
this.props.selectedOptionValue === undefined) ||
|
this.props.defaultOptionValue !== prevProps.defaultOptionValue
|
||||||
this.props.defaultOptionValue !== prevProps.defaultOptionValue
|
) {
|
||||||
) {
|
this.updateWidgetMetaProperty(
|
||||||
this.updateWidgetMetaProperty(
|
"selectedOptionValue",
|
||||||
"selectedOptionValue",
|
this.props.defaultOptionValue,
|
||||||
this.props.defaultOptionValue,
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getPageView() {
|
getPageView() {
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,16 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
||||||
import { WidgetType } from "constants/WidgetConstants";
|
import { WidgetType } from "constants/WidgetConstants";
|
||||||
import { Intent } from "@blueprintjs/core";
|
import { Intent } from "@blueprintjs/core";
|
||||||
import SpinnerComponent from "components/designSystems/blueprint/SpinnerComponent";
|
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";
|
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||||
|
|
||||||
class SpinnerWidget extends BaseWidget<SpinnerWidgetProps, WidgetState> {
|
class SpinnerWidget extends BaseWidget<SpinnerWidgetProps, WidgetState> {
|
||||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||||
return {
|
return {
|
||||||
|
...BASE_WIDGET_VALIDATION,
|
||||||
size: VALIDATION_TYPES.NUMBER,
|
size: VALIDATION_TYPES.NUMBER,
|
||||||
value: VALIDATION_TYPES.NUMBER,
|
value: VALIDATION_TYPES.NUMBER,
|
||||||
ellipsize: VALIDATION_TYPES.BOOLEAN,
|
ellipsize: VALIDATION_TYPES.BOOLEAN,
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,10 @@ import { forIn } from "lodash";
|
||||||
import TableComponent from "components/designSystems/syncfusion/TableComponent";
|
import TableComponent from "components/designSystems/syncfusion/TableComponent";
|
||||||
|
|
||||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
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 { ColumnModel } from "@syncfusion/ej2-grids";
|
||||||
import { ColumnDirTypecast } from "@syncfusion/ej2-react-grids";
|
import { ColumnDirTypecast } from "@syncfusion/ej2-react-grids";
|
||||||
import { ColumnAction } from "components/propertyControls/ColumnActionSelectorControl";
|
import { ColumnAction } from "components/propertyControls/ColumnActionSelectorControl";
|
||||||
|
|
@ -30,6 +33,7 @@ function constructColumns(data: object[]): ColumnModel[] | ColumnDirTypecast[] {
|
||||||
class TableWidget extends BaseWidget<TableWidgetProps, WidgetState> {
|
class TableWidget extends BaseWidget<TableWidgetProps, WidgetState> {
|
||||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||||
return {
|
return {
|
||||||
|
...BASE_WIDGET_VALIDATION,
|
||||||
tableData: VALIDATION_TYPES.TABLE_DATA,
|
tableData: VALIDATION_TYPES.TABLE_DATA,
|
||||||
nextPageKey: VALIDATION_TYPES.TEXT,
|
nextPageKey: VALIDATION_TYPES.TEXT,
|
||||||
prevPageKey: 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 {
|
export interface TableWidgetProps extends WidgetProps {
|
||||||
nextPageKey?: string;
|
nextPageKey?: string;
|
||||||
prevPageKey?: string;
|
prevPageKey?: string;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,10 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
||||||
import { WidgetType } from "constants/WidgetConstants";
|
import { WidgetType } from "constants/WidgetConstants";
|
||||||
import TextComponent from "components/designSystems/blueprint/TextComponent";
|
import TextComponent from "components/designSystems/blueprint/TextComponent";
|
||||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
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 } = {
|
const LINE_HEIGHTS: { [key in TextStyle]: number } = {
|
||||||
// The following values are arrived at by multiplying line-height with font-size
|
// 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> {
|
class TextWidget extends BaseWidget<TextWidgetProps, WidgetState> {
|
||||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||||
return {
|
return {
|
||||||
|
...BASE_WIDGET_VALIDATION,
|
||||||
text: VALIDATION_TYPES.TEXT,
|
text: VALIDATION_TYPES.TEXT,
|
||||||
textStyle: VALIDATION_TYPES.TEXT,
|
textStyle: VALIDATION_TYPES.TEXT,
|
||||||
isVisible: VALIDATION_TYPES.BOOLEAN,
|
shouldScroll: VALIDATION_TYPES.BOOLEAN,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user