PromucFlow_constructor/app/client/src/widgets/InputWidget.tsx

217 lines
6.6 KiB
TypeScript
Raw Normal View History

2019-09-12 08:11:25 +00:00
import React from "react";
import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
import { WidgetType } from "constants/WidgetConstants";
2020-03-06 09:45:21 +00:00
import InputComponent, {
InputComponentProps,
} from "components/designSystems/blueprint/InputComponent";
2020-02-18 10:41:52 +00:00
import { EventType } from "constants/ActionConstants";
2020-03-16 07:59:07 +00:00
import {
WidgetPropertyValidationType,
BASE_WIDGET_VALIDATION,
} from "utils/WidgetValidation";
2019-11-22 13:12:39 +00:00
import { VALIDATION_TYPES } from "constants/WidgetValidation";
2020-03-06 09:45:21 +00:00
import { FIELD_REQUIRED_ERROR } from "constants/messages";
import {
DerivedPropertiesMap,
TriggerPropertiesMap,
} from "utils/WidgetFactory";
import * as Sentry from "@sentry/react";
2020-10-06 09:01:51 +00:00
import withMeta, { WithMeta } from "./MetaHOC";
2019-09-12 08:11:25 +00:00
2020-10-06 09:01:51 +00:00
class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
2019-11-22 13:12:39 +00:00
static getPropertyValidationMap(): WidgetPropertyValidationType {
return {
2020-03-16 07:59:07 +00:00
...BASE_WIDGET_VALIDATION,
2019-11-22 13:12:39 +00:00
inputType: VALIDATION_TYPES.TEXT,
defaultText: VALIDATION_TYPES.TEXT,
isDisabled: VALIDATION_TYPES.BOOLEAN,
text: VALIDATION_TYPES.TEXT,
2020-04-03 02:42:45 +00:00
regex: VALIDATION_TYPES.REGEX,
2019-11-22 13:12:39 +00:00
errorMessage: VALIDATION_TYPES.TEXT,
placeholderText: VALIDATION_TYPES.TEXT,
maxChars: VALIDATION_TYPES.NUMBER,
minNum: VALIDATION_TYPES.NUMBER,
maxNum: VALIDATION_TYPES.NUMBER,
label: VALIDATION_TYPES.TEXT,
inputValidators: VALIDATION_TYPES.ARRAY,
focusIndex: VALIDATION_TYPES.NUMBER,
isAutoFocusEnabled: VALIDATION_TYPES.BOOLEAN,
// onTextChanged: VALIDATION_TYPES.ACTION_SELECTOR,
2020-03-06 09:45:21 +00:00
isRequired: VALIDATION_TYPES.BOOLEAN,
2020-03-16 07:59:07 +00:00
isValid: VALIDATION_TYPES.BOOLEAN,
2019-11-22 13:12:39 +00:00
};
}
2020-02-18 10:41:52 +00:00
static getTriggerPropertyMap(): TriggerPropertiesMap {
return {
onTextChanged: true,
};
}
2019-10-31 05:28:11 +00:00
2020-03-06 09:45:21 +00:00
static getDerivedPropertiesMap(): DerivedPropertiesMap {
return {
isValid: `{{
function(){
let parsedRegex = null;
if (this.regex) {
2020-10-11 13:32:02 +00:00
/*
* break up the regexp pattern into 4 parts: given regex, regex prefix , regex pattern, regex flags
* Example /appsmith/i will be split into ["/appsmith/gi", "/", "appsmith", "gi"]
*/
const regexParts = this.regex.match(/(\\/?)(.+)\\1([a-z]*)/i);
if (!regexParts) {
parsedRegex = new RegExp(this.regex);
} else {
/*
* if we don't have a regex flags (gmisuy), convert provided string into regexp directly
/*
if (regexParts[3] && !/^(?!.*?(.).*?\\1)[gmisuy]+$/.test(regexParts[3])) {
parsedRegex = RegExp(this.regex);
}
/*
* if we have a regex flags, use it to form regexp
*/
parsedRegex = new RegExp(regexParts[2], regexParts[3]);
}
}
if (this.inputType === "EMAIL") {
const emailRegex = new RegExp(/^\\w+([\\.-]?\\w+)*@\\w+([\\.-]?\\w+)*(\\.\\w{2,3})+$/);
return emailRegex.test(this.text);
}
else if (this.inputType === "NUMBER") {
return !isNaN(this.text)
}
else if (this.isRequired) {
if(this.text && this.text.length) {
if (parsedRegex) {
return parsedRegex.test(this.text)
} else {
return true;
}
} else {
return false;
}
} if (parsedRegex) {
return parsedRegex.test(this.text)
} else {
return true;
}
}()
}}`,
value: `{{this.text}}`,
2020-03-06 09:45:21 +00:00
};
2019-10-31 05:28:11 +00:00
}
2020-04-17 16:15:09 +00:00
static getDefaultPropertiesMap(): Record<string, string> {
return {
text: "defaultText",
};
}
static getMetaPropertiesMap(): Record<string, any> {
return {
text: undefined,
isFocused: false,
isDirty: false,
};
2019-10-31 05:28:11 +00:00
}
onValueChange = (value: string) => {
2020-10-06 16:47:16 +00:00
this.props.updateWidgetMetaProperty("text", value, {
dynamicString: this.props.onTextChanged,
event: {
type: EventType.ON_TEXT_CHANGE,
},
});
2020-03-06 09:45:21 +00:00
if (!this.props.isDirty) {
2020-10-06 09:01:51 +00:00
this.props.updateWidgetMetaProperty("isDirty", true);
2020-03-06 09:45:21 +00:00
}
2020-10-06 09:01:51 +00:00
};
2019-10-31 05:28:11 +00:00
2020-03-06 09:45:21 +00:00
handleFocusChange = (focusState: boolean) => {
2020-10-06 09:01:51 +00:00
this.props.updateWidgetMetaProperty("isFocused", focusState);
2020-03-06 09:45:21 +00:00
};
2019-09-12 08:11:25 +00:00
getPageView() {
2020-10-06 09:01:51 +00:00
const value = this.props.text || "";
2020-03-06 14:29:10 +00:00
const isInvalid =
"isValid" in this.props && !this.props.isValid && !!this.props.isDirty;
2020-03-06 09:45:21 +00:00
const conditionalProps: Partial<InputComponentProps> = {};
conditionalProps.errorMessage = this.props.errorMessage;
if (this.props.isRequired && value.length === 0) {
conditionalProps.errorMessage = FIELD_REQUIRED_ERROR;
}
if (this.props.maxChars) conditionalProps.maxChars = this.props.maxChars;
if (this.props.maxNum) conditionalProps.maxNum = this.props.maxNum;
if (this.props.minNum) conditionalProps.minNum = this.props.minNum;
2019-10-30 10:23:20 +00:00
return (
<InputComponent
2020-03-06 09:45:21 +00:00
value={value}
isInvalid={isInvalid}
2019-10-31 05:28:11 +00:00
onValueChange={this.onValueChange}
2019-10-30 10:23:20 +00:00
widgetId={this.props.widgetId}
inputType={this.props.inputType}
disabled={this.props.isDisabled}
2019-10-31 05:28:11 +00:00
label={this.props.label}
2019-10-30 10:23:20 +00:00
defaultValue={this.props.defaultText}
placeholder={this.props.placeholderText}
2019-12-03 04:41:10 +00:00
isLoading={this.props.isLoading}
2020-02-13 09:32:24 +00:00
multiline={
2020-02-06 07:01:25 +00:00
this.props.bottomRow - this.props.topRow > 1 &&
this.props.inputType === "TEXT"
}
2019-10-30 10:23:20 +00:00
stepSize={1}
2020-03-06 09:45:21 +00:00
onFocusChange={this.handleFocusChange}
showError={!!this.props.isFocused}
{...conditionalProps}
2019-10-30 10:23:20 +00:00
/>
);
2019-09-12 08:11:25 +00:00
}
getWidgetType(): WidgetType {
return "INPUT_WIDGET";
}
}
export const InputTypes: { [key: string]: string } = {
TEXT: "TEXT",
NUMBER: "NUMBER",
INTEGER: "INTEGER",
PHONE_NUMBER: "PHONE_NUMBER",
EMAIL: "EMAIL",
PASSWORD: "PASSWORD",
CURRENCY: "CURRENCY",
SEARCH: "SEARCH",
};
export type InputType = typeof InputTypes[keyof typeof InputTypes];
2019-09-12 08:11:25 +00:00
export interface InputValidator {
validationRegex: string;
errorMessage: string;
}
2020-10-06 09:01:51 +00:00
export interface InputWidgetProps extends WidgetProps, WithMeta {
2019-09-12 08:11:25 +00:00
inputType: InputType;
defaultText?: string;
2019-10-30 10:23:20 +00:00
isDisabled?: boolean;
2020-04-17 16:15:09 +00:00
text: string;
2019-10-31 05:28:11 +00:00
regex?: string;
errorMessage?: string;
placeholderText?: string;
maxChars?: number;
2019-10-30 10:23:20 +00:00
minNum?: number;
maxNum?: number;
2020-02-18 10:41:52 +00:00
onTextChanged?: string;
2019-09-12 08:11:25 +00:00
label: string;
inputValidators: InputValidator[];
2020-03-06 09:45:21 +00:00
isValid: boolean;
focusIndex?: number;
isAutoFocusEnabled?: boolean;
2020-03-06 09:45:21 +00:00
isRequired?: boolean;
isFocused?: boolean;
isDirty?: boolean;
2019-09-12 08:11:25 +00:00
}
export default InputWidget;
2020-10-06 09:01:51 +00:00
export const ProfiledInputWidget = Sentry.withProfiler(withMeta(InputWidget));