import React from "react"; import BaseWidget, { WidgetProps, WidgetState } from "widgets/BaseWidget"; import { WidgetType } from "constants/WidgetConstants"; import { RateSize } from "../constants"; import RateComponent from "../component"; import { ValidationTypes } from "constants/WidgetValidation"; import { DerivedPropertiesMap } from "utils/WidgetFactory"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; import { AutocompleteDataType } from "utils/autocomplete/TernServer"; function validateDefaultRate(value: unknown, props: any, _: any) { try { let parsed = value; let isValid = false; if (_.isString(value as string)) { if (/^\d+\.?\d*$/.test(value as string)) { parsed = Number(value); isValid = true; } else { if (value === "") { return { isValid: true, parsed: 0, }; } return { isValid: false, parsed: 0, messages: [`Value must be a number`], }; } } if (Number.isFinite(parsed)) { isValid = true; } // default rate must be less than max count if (!_.isNaN(props.maxCount) && Number(value) > Number(props.maxCount)) { return { isValid: false, parsed, messages: [`This value must be less than or equal to max count`], }; } // default rate can be a decimal only if Allow half property is true if (!props.isAllowHalf && !Number.isInteger(parsed)) { return { isValid: false, parsed, messages: [`This value can be a decimal only if 'Allow half' is true`], }; } return { isValid, parsed }; } catch (e) { return { isValid: false, parsed: value, messages: [`Could not validate `], }; } } class RateWidget extends BaseWidget { static getPropertyPaneConfig() { return [ { sectionName: "General", children: [ { propertyName: "maxCount", helpText: "Sets the maximum allowed rating", label: "Max Rating", controlType: "INPUT_TEXT", placeholderText: "5", isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.NUMBER, params: { natural: true }, }, }, { propertyName: "defaultRate", helpText: "Sets the default rating", label: "Default Rating", controlType: "INPUT_TEXT", placeholderText: "2.5", isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.FUNCTION, params: { fn: validateDefaultRate, expected: { type: "number", example: 5, autocompleteDataType: AutocompleteDataType.NUMBER, }, }, }, dependencies: ["maxCount", "isAllowHalf"], }, { propertyName: "activeColor", label: "Active color", controlType: "COLOR_PICKER", isBindProperty: false, isTriggerProperty: false, }, { propertyName: "inactiveColor", label: "Inactive color", controlType: "COLOR_PICKER", isBindProperty: false, isTriggerProperty: false, }, { propertyName: "tooltips", helpText: "Sets the tooltip contents of stars", label: "Tooltips", controlType: "INPUT_TEXT", placeholderText: '["Bad", "Neutral", "Good"]', isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.ARRAY, params: { children: { type: ValidationTypes.TEXT } }, }, }, { propertyName: "size", label: "Size", controlType: "DROP_DOWN", options: [ { label: "Small", value: "SMALL", }, { label: "Medium", value: "MEDIUM", }, { label: "Large", value: "LARGE", }, ], isBindProperty: false, isTriggerProperty: false, }, { propertyName: "isAllowHalf", helpText: "Controls if user can submit half stars", label: "Allow half stars", controlType: "SWITCH", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN }, }, { propertyName: "isVisible", helpText: "Controls the visibility of the widget", label: "Visible", controlType: "SWITCH", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN }, }, { propertyName: "isDisabled", helpText: "Disables input to the widget", label: "Disabled", controlType: "SWITCH", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN }, }, { propertyName: "animateLoading", label: "Animate Loading", controlType: "SWITCH", helpText: "Controls the loading of the widget", defaultValue: true, isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN }, }, ], }, { sectionName: "Events", children: [ { helpText: "Triggers an action when the rate is changed", propertyName: "onRateChanged", label: "onChange", controlType: "ACTION_SELECTOR", isJSConvertible: true, isBindProperty: true, isTriggerProperty: true, }, ], }, ]; } static getDefaultPropertiesMap(): Record { return { rate: "defaultRate", }; } static getDerivedPropertiesMap(): DerivedPropertiesMap { return { value: `{{ this.rate }}`, }; } static getMetaPropertiesMap(): Record { return { rate: undefined, }; } valueChangedHandler = (value: number) => { this.props.updateWidgetMetaProperty("rate", value, { triggerPropertyName: "onRateChanged", dynamicString: this.props.onRateChanged, event: { type: EventType.ON_RATE_CHANGED, }, }); }; getPageView() { return ( (this.props.rate || this.props.rate === 0) && ( ) ); } static getWidgetType(): WidgetType { return "RATE_WIDGET"; } } export interface RateWidgetProps extends WidgetProps { maxCount: number; size: RateSize; defaultRate?: number; rate?: number; activeColor?: string; inactiveColor?: string; isAllowHalf?: boolean; onRateChanged?: string; tooltips?: Array; } export default RateWidget;