From 73ee6e9ba7a09766dcac041a34bfebdeb8fe9928 Mon Sep 17 00:00:00 2001 From: Ilia Date: Wed, 12 Mar 2025 13:59:36 +0100 Subject: [PATCH] feat: add action resp viz (#39690) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Fixes #39554 _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="@tag.Sanity" ### :mag: Cypress test results > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: > Commit: 1a5b458e43a338ad74eb48908a16ce695a6f53e2 > Cypress dashboard. > Tags: `@tag.Sanity` > Spec: >
Wed, 12 Mar 2025 12:57:34 UTC ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No ## Summary by CodeRabbit ## Summary by CodeRabbit - **New Features** - Added a new forward arrow icon for enhanced design consistency. - Expanded sidebar functionality to support an optional extra title button for additional actions. - Introduced a comprehensive visualization experience, including interactive components for generating, saving, and displaying visualizations, along with prompt inputs, suggestions, and a results view. - Enhanced action capabilities to support visualization data and debugging with a new visualization tab. - Enabled new release functionalities via an updated feature flag system. - **Style** - Refined sidebar title spacing and layout for improved presentation. --- .../ads/src/Icon/Icon.provider.tsx | 4 + .../src/components/Sidebar/src/Sidebar.tsx | 3 +- .../components/Sidebar/src/SidebarContent.tsx | 40 ++--- .../components/Sidebar/src/styles.module.css | 5 +- .../src/components/Sidebar/src/types.ts | 1 + .../Visualization/Visualization.tsx | 111 ++++++++++++++ .../components/EmptyVisualization.tsx | 18 +++ .../components/LoadingOverlay.tsx | 22 +++ .../Visualization/components/PromptInput.tsx | 47 ++++++ .../Visualization/components/Result.tsx | 138 ++++++++++++++++++ .../components/SuggestionButtons.tsx | 43 ++++++ .../components/Visualization/index.ts | 1 + .../Visualization/useGenerateVisualization.ts | 77 ++++++++++ .../Visualization/useSaveVisualization.ts | 41 ++++++ app/client/src/api/ActionAPI.tsx | 43 ++++++ .../src/assets/images/no-visualization.svg | 1 + app/client/src/ce/entities/FeatureFlag.ts | 2 + .../editorComponents/Debugger/constants.ts | 1 + app/client/src/entities/Action/index.ts | 9 ++ .../anvil/integrations/selectors.ts | 4 + .../src/utils/hooks/useFeatureFlagOverride.ts | 1 + 21 files changed, 589 insertions(+), 23 deletions(-) create mode 100644 app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/Visualization.tsx create mode 100644 app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/components/EmptyVisualization.tsx create mode 100644 app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/components/LoadingOverlay.tsx create mode 100644 app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/components/PromptInput.tsx create mode 100644 app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/components/Result.tsx create mode 100644 app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/components/SuggestionButtons.tsx create mode 100644 app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/index.ts create mode 100644 app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/useGenerateVisualization.ts create mode 100644 app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/useSaveVisualization.ts create mode 100644 app/client/src/assets/images/no-visualization.svg diff --git a/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx b/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx index 1bdf87646d..16f6de3db0 100644 --- a/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx +++ b/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx @@ -8,6 +8,9 @@ const AddMoreIcon = importRemixIcon( const AddMoreFillIcon = importRemixIcon( async () => import("remixicon-react/AddCircleFillIcon"), ); +const ArrowGoForwardLineIcon = importRemixIcon( + async () => import("remixicon-react/ArrowGoForwardLineIcon"), +); const ArrowGoBackLineIcon = importRemixIcon( async () => import("remixicon-react/ArrowGoBackLineIcon"), ); @@ -1178,6 +1181,7 @@ const ICON_LOOKUP = { "add-line": AddLineIcon, "add-more": AddMoreIcon, "add-more-fill": AddMoreFillIcon, + "arrow-go-forward": ArrowGoForwardLineIcon, "alert-fill": AlertFillIcon, "alert-line": AlertLineIcon, "align-center": AlignCenter, diff --git a/app/client/packages/design-system/widgets/src/components/Sidebar/src/Sidebar.tsx b/app/client/packages/design-system/widgets/src/components/Sidebar/src/Sidebar.tsx index f758522a82..353d1c1654 100644 --- a/app/client/packages/design-system/widgets/src/components/Sidebar/src/Sidebar.tsx +++ b/app/client/packages/design-system/widgets/src/components/Sidebar/src/Sidebar.tsx @@ -14,6 +14,7 @@ const _Sidebar = (props: SidebarProps, ref: Ref) => { children, className, collapsible = "offcanvas", + extraTitleButton, onEnter: onEnterProp, onEntered: onEnteredProp, onExit: onExitProp, @@ -47,7 +48,7 @@ const _Sidebar = (props: SidebarProps, ref: Ref) => { }; const content = ( - + {typeof children === "function" ? children({ isAnimating, state }) : children} diff --git a/app/client/packages/design-system/widgets/src/components/Sidebar/src/SidebarContent.tsx b/app/client/packages/design-system/widgets/src/components/Sidebar/src/SidebarContent.tsx index 9c88ff3cf8..e3e46dbe8d 100644 --- a/app/client/packages/design-system/widgets/src/components/Sidebar/src/SidebarContent.tsx +++ b/app/client/packages/design-system/widgets/src/components/Sidebar/src/SidebarContent.tsx @@ -1,5 +1,5 @@ import clsx from "clsx"; -import React, { type Ref } from "react"; +import React, { type ReactNode, type Ref } from "react"; import { Flex } from "../../Flex"; import { Text } from "../../Text"; @@ -9,6 +9,7 @@ import { useSidebar } from "./use-sidebar"; interface SidebarContentProps { title?: string; + extraTitleButton?: ReactNode; className?: string; children: React.ReactNode; } @@ -17,7 +18,7 @@ const _SidebarContent = ( props: SidebarContentProps, ref: Ref, ) => { - const { children, className, title, ...rest } = props; + const { children, className, extraTitleButton, title, ...rest } = props; const { isMobile, setState, state } = useSidebar(); return ( @@ -39,26 +40,29 @@ const _SidebarContent = ( className={styles.sidebarTitle} fontWeight={500} lineClamp={1} - textAlign="center" > {title} )} - {!isMobile && ( - + + + + + {generateVisualization.elements ? ( + + + + ) : ( + + )} + {generateVisualization.isLoading && } + + + ); +}; diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/components/EmptyVisualization.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/components/EmptyVisualization.tsx new file mode 100644 index 0000000000..a56b24a96b --- /dev/null +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/components/EmptyVisualization.tsx @@ -0,0 +1,18 @@ +import { Flex, Text } from "@appsmith/ads"; +import NoVisualizationSVG from "assets/images/no-visualization.svg"; +import React from "react"; + +export const EmptyVisualization = () => { + return ( + + No visualization + The response visualization will be shown here + + ); +}; diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/components/LoadingOverlay.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/components/LoadingOverlay.tsx new file mode 100644 index 0000000000..f61aeeef22 --- /dev/null +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/components/LoadingOverlay.tsx @@ -0,0 +1,22 @@ +import { Flex, Text } from "@appsmith/ads"; +import React from "react"; + +export const LoadingOverlay = () => { + return ( + + + Generating visualization... + + + ); +}; diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/components/PromptInput.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/components/PromptInput.tsx new file mode 100644 index 0000000000..d69dd29d75 --- /dev/null +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Visualization/components/PromptInput.tsx @@ -0,0 +1,47 @@ +import { Button, Input } from "@appsmith/ads"; +import React from "react"; +import styled from "styled-components"; + +interface PromptInputProps { + value: string; + onChange: (value: string) => void; + onSubmit: () => void; + isLoading: boolean; + isDisabled: boolean; +} + +const PromptForm = styled.form` + display: flex; + flex: 1; + gap: var(--ads-v2-spaces-3); +`; + +export const PromptInput = (props: PromptInputProps) => { + const { isDisabled, isLoading, onChange, onSubmit, value } = props; + + return ( + { + e.preventDefault(); + onSubmit(); + }} + > + +