import React from "react"; import type { ControlProps } from "./BaseControl"; import BaseControl from "./BaseControl"; import { Button, Icon } from "design-system"; import { CUSTOM_WIDGET_BUILDER_EVENTS } from "pages/Editor/CustomWidgetBuilder/constants"; import { CUSTOM_WIDGET_FEATURE, createMessage, } from "@appsmith/constants/messages"; import CustomWidgetBuilderService from "utils/CustomWidgetBuilderService"; import styled from "styled-components"; import AnalyticsUtil from "@appsmith/utils/AnalyticsUtil"; import { xor } from "lodash"; interface ButtonControlState { isSourceEditorOpen: boolean; } const StyledButton = styled(Button)` width: 100%; `; class ButtonControl extends BaseControl { state: ButtonControlState = { isSourceEditorOpen: false, }; private onMessageCancelFunctions: Array<() => void> = []; getPayload = () => { return { name: this.props.widgetProperties.widgetName, widgetId: this.props.widgetProperties.widgetId, srcDoc: this.props.widgetProperties.srcDoc, uncompiledSrcDoc: this.props.widgetProperties.uncompiledSrcDoc, model: this.props.widgetProperties.__evaluation__?.evaluatedValues ?.defaultModel, events: this.props.widgetProperties.events.reduce( (prev: Record, curr: string) => { prev[curr] = this.props.widgetProperties[curr]; return prev; }, {}, ), theme: this.props.widgetProperties.__evaluation__?.evaluatedValues?.theme, }; }; registerEvents() { const builder = CustomWidgetBuilderService.getBuilder( this.props.widgetProperties.widgetId, ); if (builder) { this.onMessageCancelFunctions.push( builder.onMessage(CUSTOM_WIDGET_BUILDER_EVENTS.READY, () => { builder.postMessage({ type: CUSTOM_WIDGET_BUILDER_EVENTS.READY_ACK, ...this.getPayload(), }); }), ); this.onMessageCancelFunctions.push( builder.onMessage( CUSTOM_WIDGET_BUILDER_EVENTS.UPDATE_SRCDOC, (data: any) => { this.props.onBatchUpdateProperties?.({ srcDoc: data.srcDoc, uncompiledSrcDoc: data.uncompiledSrcDoc, }); }, ), ); this.onMessageCancelFunctions.push( builder.onMessage(CUSTOM_WIDGET_BUILDER_EVENTS.DISCONNECTED, () => { CustomWidgetBuilderService.closeBuilder( this.props.widgetProperties.widgetId, false, ); this.setState({ isSourceEditorOpen: false, }); this.dispostEvents(); }), ); } } dispostEvents() { this.onMessageCancelFunctions.forEach((fn) => fn()); this.onMessageCancelFunctions = []; } onCTAClick = () => { AnalyticsUtil.logEvent("CUSTOM_WIDGET_EDIT_SOURCE_CLICKED", { widgetId: this.props.widgetProperties.widgetId, }); if ( CustomWidgetBuilderService.isConnected( this.props.widgetProperties.widgetId, ) ) { CustomWidgetBuilderService.focus(this.props.widgetProperties.widgetId); } else { CustomWidgetBuilderService.createBuilder( this.props.widgetProperties.widgetId, ); this.registerEvents(); this.setState({ isSourceEditorOpen: true, }); } }; beforeWindowUnload = () => { CustomWidgetBuilderService.closeBuilder( this.props.widgetProperties.widgetId, true, ); }; componentDidMount(): void { window.addEventListener("beforeunload", this.beforeWindowUnload); if ( CustomWidgetBuilderService.isConnected( this.props.widgetProperties.widgetId, ) ) { CustomWidgetBuilderService.getBuilder( this.props.widgetProperties.widgetId, )?.postMessage({ type: CUSTOM_WIDGET_BUILDER_EVENTS.RESUME, ...this.getPayload(), }); this.registerEvents(); } } componentWillUnmount(): void { CustomWidgetBuilderService.getBuilder( this.props.widgetProperties.widgetId, )?.postMessage({ type: CUSTOM_WIDGET_BUILDER_EVENTS.PAUSE, }); this.dispostEvents(); window.removeEventListener("beforeunload", this.beforeWindowUnload); } componentDidUpdate(prevProps: Readonly): void { if ( CustomWidgetBuilderService.isConnected( this.props.widgetProperties.widgetId, ) ) { /* * Value is true if an event is added, removed or renamed */ const hasEventLengthChanged = xor( this.props.widgetProperties.events, prevProps.widgetProperties.events, )?.length !== 0; /* * Value is true if an event binding is changed */ const hasEventExpressionChanged = this.props.widgetProperties.events.some( (event: string) => { return ( prevProps.widgetProperties[event] !== this.props.widgetProperties[event] ); }, ); const hasEventChanged = hasEventLengthChanged || hasEventExpressionChanged; const hasWidgetNameChanged = prevProps.widgetProperties.widgetName !== this.props.widgetProperties.widgetName; const hasDefaultModelChanged = prevProps.widgetProperties.__evaluation__?.evaluatedValues ?.defaultModel !== this.props.widgetProperties.__evaluation__?.evaluatedValues ?.defaultModel; const hasThemeChanged = this.props.widgetProperties.__evaluation__?.evaluatedValues?.theme !== this.props.widgetProperties.__evaluation__?.evaluatedValues?.theme; if ( hasWidgetNameChanged || hasEventChanged || hasDefaultModelChanged || hasThemeChanged ) { const builder = CustomWidgetBuilderService.getBuilder( this.props.widgetProperties.widgetId, ); builder?.postMessage({ type: CUSTOM_WIDGET_BUILDER_EVENTS.UPDATE_REFERENCES, name: this.props.widgetProperties.widgetName, model: this.props.widgetProperties.__evaluation__?.evaluatedValues ?.defaultModel, events: this.props.widgetProperties.events.reduce( (prev: Record, curr: string) => { prev[curr] = this.props.widgetProperties[curr]; return prev; }, {}, ), theme: this.props.widgetProperties.__evaluation__?.evaluatedValues?.theme, }); } } } render() { return ( {this.state.isSourceEditorOpen || CustomWidgetBuilderService.isConnected( this.props.widgetProperties.widgetId, ) ? createMessage(CUSTOM_WIDGET_FEATURE.editSource.goToSourceCTA) : createMessage(CUSTOM_WIDGET_FEATURE.editSource.editSourceCTA)}   ); } static getControlType() { return "CUSTOM_WIDGET_EDIT_BUTTON_CONTROL"; } } export default ButtonControl;