From eebe03725e8c6e558f0fa29b4fec406ac4819512 Mon Sep 17 00:00:00 2001 From: Ilia Znamenskii Date: Fri, 14 Mar 2025 11:05:51 +0100 Subject: [PATCH 1/7] add generate schema button --- .../components/PluginActionToolbar.tsx | 22 +++- .../src/PluginActionEditor/hooks/index.ts | 1 + .../store/pluginActionEditorSelectors.ts | 10 ++ .../store/pluginEditorReducer.ts | 22 ++++ .../src/actions/generateSchemaActions.ts | 18 +++ app/client/src/api/SchemaAPI.ts | 17 +++ .../hooks/useHandleGenerateSchemaClick.ts | 17 +++ .../src/ce/constants/ReduxActionConstants.tsx | 12 ++ app/client/src/ce/constants/messages.ts | 1 + app/client/src/ce/sagas/index.tsx | 2 + .../hooks/useHandleGenerateSchemaClick.ts | 1 + app/client/src/pages/Editor/JSEditor/Form.tsx | 28 ++++- .../JSEditorToolbar/JSEditorToolbar.tsx | 16 ++- .../components/JSFunctionGenerateSchema.tsx | 25 ++++ .../JSEditor/JSEditorToolbar/constants.ts | 1 + .../src/reducers/uiReducers/jsPaneReducer.ts | 48 +++++++- app/client/src/sagas/GenerateSchemaSaga.ts | 109 ++++++++++++++++++ app/client/src/selectors/jsPaneSelectors.ts | 8 ++ 18 files changed, 351 insertions(+), 7 deletions(-) create mode 100644 app/client/src/actions/generateSchemaActions.ts create mode 100644 app/client/src/api/SchemaAPI.ts create mode 100644 app/client/src/ce/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts create mode 100644 app/client/src/ee/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts create mode 100644 app/client/src/pages/Editor/JSEditor/JSEditorToolbar/components/JSFunctionGenerateSchema.tsx create mode 100644 app/client/src/sagas/GenerateSchemaSaga.ts diff --git a/app/client/src/PluginActionEditor/components/PluginActionToolbar.tsx b/app/client/src/PluginActionEditor/components/PluginActionToolbar.tsx index d0ff690cf114..5e1d4521577b 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionToolbar.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionToolbar.tsx @@ -7,9 +7,14 @@ import { useBlockExecution, useHandleRunClick, useAnalyticsOnRunClick, + useHandleGenerateSchemaClick, } from "../hooks"; import { useSelector } from "react-redux"; -import { isActionRunning } from "../store"; +import { + isActionRunning, + isActionSaving, + isActionSchemaGenerating, +} from "../store"; import PluginActionSettings from "./PluginActionSettings"; import { PluginActionContextMenu } from "./PluginActionContextMenu"; @@ -22,9 +27,12 @@ interface PluginActionToolbarProps { const PluginActionToolbar = (props: PluginActionToolbarProps) => { const { action } = usePluginActionContext(); const { handleRunClick } = useHandleRunClick(); + const { handleGenerateSchemaClick } = useHandleGenerateSchemaClick(); const { callRunActionAnalytics } = useAnalyticsOnRunClick(); const blockExecution = useBlockExecution(); const isRunning = useSelector(isActionRunning(action.id)); + const isSaving = useSelector(isActionSaving(action.id)); + const isSchemaGenerating = useSelector(isActionSchemaGenerating(action.id)); const onRunClick = useCallback(() => { callRunActionAnalytics(); @@ -43,7 +51,7 @@ const PluginActionToolbar = (props: PluginActionToolbarProps) => { > + {props.menuContent ? ( const getActionRunningState = (state: AppState) => state.ui.pluginActionEditor.isRunning; +const getActionSchemaGeneratingState = (state: AppState) => + state.ui.pluginActionEditor.isSchemaGenerating; + +export const isActionSchemaGenerating = (id: string) => + createSelector( + [getActionSchemaGeneratingState], + (isSchemaGeneratingMap) => + id in isSchemaGeneratingMap && isSchemaGeneratingMap[id], + ); + export const isActionRunning = (id: string) => createSelector( [getActionRunningState], diff --git a/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts b/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts index 3bcafcdc6359..5cc203e7e326 100644 --- a/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts +++ b/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts @@ -22,6 +22,7 @@ export interface PluginActionEditorState { isCreating: boolean; isRunning: Record; isSaving: Record; + isSchemaGenerating: Record; isDeleting: Record; isDirty: Record; runErrorMessage: Record; @@ -34,6 +35,7 @@ const initialState: PluginActionEditorState = { isCreating: false, isRunning: {}, isSaving: {}, + isSchemaGenerating: {}, isDeleting: {}, isDirty: {}, runErrorMessage: {}, @@ -141,6 +143,26 @@ export const handlers = { set(state, ["isRunning", id], false); set(state, ["runErrorMessage", id], error.message); }, + [ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_REQUEST]: ( + state: PluginActionEditorState, + action: ReduxAction<{ + id: string; + }>, + ) => { + set(state, ["isSchemaGenerating", action.payload.id], true); + }, + [ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_SUCCESS]: ( + state: PluginActionEditorState, + action: ReduxAction<{ id: string }>, + ) => { + set(state, ["isSchemaGenerating", action.payload.id], false); + }, + [ReduxActionErrorTypes.GENERATE_PLUGIN_ACTION_SCHEMA_ERROR]: ( + state: PluginActionEditorState, + action: ReduxAction<{ id: string }>, + ) => { + set(state, ["isSchemaGenerating", action.payload.id], false); + }, [ReduxActionTypes.SET_PLUGIN_ACTION_EDITOR_FORM_SELECTED_TAB]: ( state: PluginActionEditorState, action: ReduxAction<{ selectedTab: string }>, diff --git a/app/client/src/actions/generateSchemaActions.ts b/app/client/src/actions/generateSchemaActions.ts new file mode 100644 index 000000000000..ce479e9744eb --- /dev/null +++ b/app/client/src/actions/generateSchemaActions.ts @@ -0,0 +1,18 @@ +import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; +import type { JSAction } from "entities/JSCollection"; + +export const generateJSFunctionSchema = (action: JSAction) => { + return { + type: ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_REQUEST, + payload: { + action, + }, + }; +}; + +export const generatePluginActionSchema = (id: string) => { + return { + type: ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_REQUEST, + payload: { id }, + }; +}; diff --git a/app/client/src/api/SchemaAPI.ts b/app/client/src/api/SchemaAPI.ts new file mode 100644 index 000000000000..44044c7b356c --- /dev/null +++ b/app/client/src/api/SchemaAPI.ts @@ -0,0 +1,17 @@ +import API from "api/Api"; +import type { AxiosPromise } from "axios"; + +export interface GenerateSchemaResponse { + description: string; + schema: unknown; +} + +export class SchemaAPI extends API { + static url = "v1/actions"; + + static async generateSchema( + actionId: string, + ): Promise> { + return API.patch(`${SchemaAPI.url}/${actionId}/schema`); + } +} diff --git a/app/client/src/ce/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts b/app/client/src/ce/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts new file mode 100644 index 000000000000..2aea4c588884 --- /dev/null +++ b/app/client/src/ce/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts @@ -0,0 +1,17 @@ +import { generatePluginActionSchema } from "actions/generateSchemaActions"; +import { usePluginActionContext } from "PluginActionEditor/PluginActionContext"; +import { useCallback } from "react"; +import { useDispatch } from "react-redux"; + +function useHandleGenerateSchemaClick() { + const { action } = usePluginActionContext(); + const dispatch = useDispatch(); + + const handleGenerateSchemaClick = useCallback(() => { + dispatch(generatePluginActionSchema(action?.id ?? "")); + }, [action?.id, dispatch]); + + return { handleGenerateSchemaClick }; +} + +export { useHandleGenerateSchemaClick }; diff --git a/app/client/src/ce/constants/ReduxActionConstants.tsx b/app/client/src/ce/constants/ReduxActionConstants.tsx index 6ff622ee5ca1..2df11a46963b 100644 --- a/app/client/src/ce/constants/ReduxActionConstants.tsx +++ b/app/client/src/ce/constants/ReduxActionConstants.tsx @@ -710,6 +710,16 @@ const ActionExecutionTypes = { RUN_ACTION_REQUEST: "RUN_ACTION_REQUEST", RUN_ACTION_CANCELLED: "RUN_ACTION_CANCELLED", RUN_ACTION_SUCCESS: "RUN_ACTION_SUCCESS", + GENERATE_JS_FUNCTION_SCHEMA_REQUEST: "GENERATE_JS_FUNCTION_SCHEMA_REQUEST", + GENERATE_JS_FUNCTION_SCHEMA_CANCELLED: + "GENERATE_JS_FUNCTION_SCHEMA_CANCELLED", + GENERATE_JS_FUNCTION_SCHEMA_SUCCESS: "GENERATE_JS_FUNCTION_SCHEMA_SUCCESS", + GENERATE_PLUGIN_ACTION_SCHEMA_REQUEST: + "GENERATE_PLUGIN_ACTION_SCHEMA_REQUEST", + GENERATE_PLUGIN_ACTION_SCHEMA_CANCELLED: + "GENERATE_PLUGIN_ACTION_SCHEMA_CANCELLED", + GENERATE_PLUGIN_ACTION_SCHEMA_SUCCESS: + "GENERATE_PLUGIN_ACTION_SCHEMA_SUCCESS", CLEAR_ACTION_RESPONSE: "CLEAR_ACTION_RESPONSE", SHOW_ACTION_MODAL: "SHOW_ACTION_MODAL", CANCEL_ACTION_MODAL: "CANCEL_ACTION_MODAL", @@ -722,6 +732,8 @@ const ActionExecutionTypes = { const ActionExecutionErrorTypes = { RUN_ACTION_ERROR: "RUN_ACTION_ERROR", + GENERATE_JS_FUNCTION_SCHEMA_ERROR: "GENERATE_JS_FUNCTION_SCHEMA_ERROR", + GENERATE_PLUGIN_ACTION_SCHEMA_ERROR: "GENERATE_PLUGIN_ACTION_SCHEMA_ERROR", EXECUTE_PLUGIN_ACTION_ERROR: "EXECUTE_PLUGIN_ACTION_ERROR", }; diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts index b066fb375104..af8fdb259e56 100644 --- a/app/client/src/ce/constants/messages.ts +++ b/app/client/src/ce/constants/messages.ts @@ -649,6 +649,7 @@ export const EXPORT_DEFAULT_BEGINNING = () => `Start object with export default`; export const ACTION_EXECUTION_FAILED = (actionName: string) => `The action "${actionName}" has failed.`; +export const CANNOT_GENERATE_SCHEMA = () => "Can't generate schema"; export const JS_EXECUTION_TRIGGERED = () => "Function triggered"; export const JS_EXECUTION_SUCCESS = () => "Function executed"; export const JS_EXECUTION_FAILURE = () => "Function execution failed"; diff --git a/app/client/src/ce/sagas/index.tsx b/app/client/src/ce/sagas/index.tsx index 577711a4f01c..1805ec448477 100644 --- a/app/client/src/ce/sagas/index.tsx +++ b/app/client/src/ce/sagas/index.tsx @@ -51,6 +51,7 @@ import communityTemplateSagas from "sagas/CommunityTemplatesSagas"; import anvilSagas from "layoutSystems/anvil/integrations/sagas"; import ideSagas from "sagas/IDESaga"; import sendSideBySideWidgetHoverAnalyticsEventSaga from "sagas/AnalyticsSaga"; +import { watchGeneratePluginActionSchemaSaga } from "sagas/GenerateSchemaSaga"; import gitSagas from "git/sagas"; /* Sagas that are registered by a module that is designed to be independent of the core platform */ @@ -64,6 +65,7 @@ export const sagas = [ watchJSActionSagas, watchActionExecutionSagas, watchPluginActionExecutionSagas, + watchGeneratePluginActionSchemaSaga, widgetOperationSagas, errorSagas, watchDatasourcesSagas, diff --git a/app/client/src/ee/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts b/app/client/src/ee/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts new file mode 100644 index 000000000000..18eec4a97ae4 --- /dev/null +++ b/app/client/src/ee/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts @@ -0,0 +1 @@ +export * from "ce/PluginActionEditor/hooks/useHandleGenerateSchemaClick"; diff --git a/app/client/src/pages/Editor/JSEditor/Form.tsx b/app/client/src/pages/Editor/JSEditor/Form.tsx index 1cc944e0226c..a587ae67cbe5 100644 --- a/app/client/src/pages/Editor/JSEditor/Form.tsx +++ b/app/client/src/pages/Editor/JSEditor/Form.tsx @@ -30,7 +30,11 @@ import { } from "./utils"; import JSObjectHotKeys from "./JSObjectHotKeys"; import { Form, FormWrapper } from "./styledComponents"; -import { getJSPaneConfigSelectedTab } from "selectors/jsPaneSelectors"; +import { + getIsGeneratingSchema, + getIsJSCollectionSaving, + getJSPaneConfigSelectedTab, +} from "selectors/jsPaneSelectors"; import type { EventLocation } from "ee/utils/analyticsUtilTypes"; import { setCodeEditorCursorAction, @@ -57,6 +61,7 @@ import { getJSActionOption, type OnUpdateSettingsProps, } from "./JSEditorToolbar"; +import { generateJSFunctionSchema } from "../../../actions/generateSchemaActions"; interface JSFormProps { jsCollectionData: JSCollectionData; @@ -153,6 +158,12 @@ function JSEditorForm({ selectedJSActionOption.data?.id || "", ), ); + const isGeneratingSchema = useSelector((state: AppState) => + getIsGeneratingSchema(state, currentJSCollection.id), + ); + const isJSCollectionSaving = useSelector((state: AppState) => + getIsJSCollectionSaving(state, currentJSCollection.id), + ); useEffect(() => { if (hash) { @@ -287,6 +298,12 @@ function JSEditorForm({ } }; + const handleGenerateSchemaButtonClick = async () => { + if (selectedJSActionOption.data?.id) { + dispatch(generateJSFunctionSchema(selectedJSActionOption.data)); + } + }; + useEffect(() => { if (parseErrors.length || isEmpty(jsActions)) { setDisableRunFunctionality(true); @@ -339,10 +356,16 @@ function JSEditorForm({ { handleRunAction(event, "JS_OBJECT_MAIN_RUN_BUTTON"); }} + onGenerateSchemaButtonClick={handleGenerateSchemaButtonClick} onSelect={handleJSActionOptionSelection} onUpdateSettings={onUpdateSettings} saveJSObjectName={saveJSObjectName} diff --git a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx b/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx index e48a11848870..fb25097109f5 100644 --- a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx +++ b/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx @@ -10,6 +10,8 @@ import { createMessage, JS_EDITOR_SETTINGS } from "ee/constants/messages"; import { JSFunctionSettings } from "./components/JSFunctionSettings"; import { convertJSActionsToDropdownOptions } from "./utils"; import { JSObjectNameEditor } from "./JSObjectNameEditor"; +import { JSFunctionGenerateSchema } from "./components/JSFunctionGenerateSchema"; +import { Flex } from "@appsmith/ads"; interface Props { changePermitted: boolean; @@ -20,12 +22,17 @@ interface Props { hideContextMenuOnEditor?: boolean; contextMenu: React.ReactNode; disableRunFunctionality: boolean; + disableGenerateSchemaFunctionality: boolean; executePermitted: boolean; loading: boolean; + isGeneratingSchema: boolean; jsCollection: JSCollection; onButtonClick: ( event: React.MouseEvent | KeyboardEvent, ) => void; + onGenerateSchemaButtonClick: ( + event: React.MouseEvent | KeyboardEvent, + ) => void; onSelect: DropdownOnSelect; jsActions: JSAction[]; selected: JSActionDropdownOption; @@ -55,7 +62,7 @@ export const JSEditorToolbar = (props: Props) => { )} -
+ { selected={props.selected} showTooltip={!props.selected.data} /> -
+ + {props.showSettings ? ( ) => void; +} + +export const JSFunctionGenerateSchema = (props: Props) => { + return ( + + ); +}; diff --git a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/constants.ts b/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/constants.ts index 27f3945f41ac..eb1e9be1eccd 100644 --- a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/constants.ts +++ b/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/constants.ts @@ -8,6 +8,7 @@ export const RUN_BUTTON_DEFAULTS = { export const testLocators = { runJSAction: "run-js-action", runJSActionTestID: "t--run-js-action", + generateSchemaJSActionTestID: "t--generate-schema-js-action", }; export const NO_FUNCTION_DROPDOWN_OPTION = { label: "No function available", diff --git a/app/client/src/reducers/uiReducers/jsPaneReducer.ts b/app/client/src/reducers/uiReducers/jsPaneReducer.ts index 79fbcb633bc7..d9bd4ea5f3da 100644 --- a/app/client/src/reducers/uiReducers/jsPaneReducer.ts +++ b/app/client/src/reducers/uiReducers/jsPaneReducer.ts @@ -4,7 +4,7 @@ import { ReduxActionTypes, ReduxActionErrorTypes, } from "ee/constants/ReduxActionConstants"; -import type { JSCollection } from "entities/JSCollection"; +import type { JSAction, JSCollection } from "entities/JSCollection"; import { ActionExecutionResizerHeight } from "PluginActionEditor/components/PluginActionResponse/constants"; export enum JSEditorTab { @@ -23,6 +23,7 @@ export interface JsPaneReduxState { isSaving: Record; isDeleting: Record; isDirty: Record; + isSchemaGenerating: Record; selectedConfigTab: JSEditorTab; debugger: JSPaneDebuggerState; } @@ -32,6 +33,7 @@ const initialState: JsPaneReduxState = { isSaving: {}, isDeleting: {}, isDirty: {}, + isSchemaGenerating: {}, selectedConfigTab: JSEditorTab.CODE, debugger: { open: false, @@ -175,6 +177,50 @@ const jsPaneReducer = createReducer(initialState, { isSaving: false, }; }, + [ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_REQUEST]: ( + state: JsPaneReduxState, + action: ReduxAction<{ + action: JSAction; + }>, + ) => { + if (!action.payload.action.collectionId) return state; + + return { + ...state, + isSchemaGenerating: { + ...state.isSchemaGenerating, + [action.payload.action.collectionId]: true, + }, + }; + }, + [ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_SUCCESS]: ( + state: JsPaneReduxState, + action: ReduxAction<{ action: JSAction }>, + ) => { + if (!action.payload.action.collectionId) return state; + + return { + ...state, + isSchemaGenerating: { + ...state.isSchemaGenerating, + [action.payload.action.collectionId]: false, + }, + }; + }, + [ReduxActionErrorTypes.GENERATE_JS_FUNCTION_SCHEMA_ERROR]: ( + state: JsPaneReduxState, + action: ReduxAction<{ action: JSAction }>, + ) => { + if (!action.payload.action.collectionId) return state; + + return { + ...state, + isSchemaGenerating: { + ...state.isSchemaGenerating, + [action.payload.action.collectionId]: false, + }, + }; + }, }); export default jsPaneReducer; diff --git a/app/client/src/sagas/GenerateSchemaSaga.ts b/app/client/src/sagas/GenerateSchemaSaga.ts new file mode 100644 index 000000000000..9b16757cdb27 --- /dev/null +++ b/app/client/src/sagas/GenerateSchemaSaga.ts @@ -0,0 +1,109 @@ +import { toast } from "@appsmith/ads"; +import { createMessage } from "@appsmith/ads-old"; +import { CANNOT_GENERATE_SCHEMA } from "ee/constants/messages"; +import { + ReduxActionErrorTypes, + ReduxActionTypes, +} from "ee/constants/ReduxActionConstants"; +import { all, call, put, takeLatest } from "redux-saga/effects"; +import { updateFunctionProperty } from "../actions/jsPaneActions"; +import { updateActionProperty } from "../actions/pluginActionActions"; +import type { ReduxAction } from "../actions/ReduxActionTypes"; +import type { ApiResponse } from "../api/ApiResponses"; +import { SchemaAPI, type GenerateSchemaResponse } from "../api/SchemaAPI"; +import type { JSAction } from "../entities/JSCollection"; + +function* generatePluginActionSchemaSaga(action: ReduxAction<{ id: string }>) { + const { id } = action.payload; + + try { + const response: ApiResponse = yield call( + SchemaAPI.generateSchema, + id, + ); + + yield put( + updateActionProperty({ + id, + field: "schema", + value: response.data.schema, + }), + ); + yield put( + updateActionProperty({ + id, + field: "description", + value: response.data.description, + }), + ); + + yield put({ + type: ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_SUCCESS, + payload: { id }, + }); + } catch (error) { + yield put({ + type: ReduxActionErrorTypes.GENERATE_PLUGIN_ACTION_SCHEMA_ERROR, + payload: { id }, + }); + + toast.show(createMessage(CANNOT_GENERATE_SCHEMA), { + kind: "error", + }); + } +} + +function* generateJSFunctionSchemaSuccessSaga( + reduxAction: ReduxAction<{ action: JSAction }>, +) { + const { action } = reduxAction.payload; + + try { + const response: ApiResponse = yield call( + SchemaAPI.generateSchema, + action.id, + ); + + yield put( + updateFunctionProperty({ + action, + propertyName: "schema", + value: response.data.schema, + }), + ); + yield put( + updateFunctionProperty({ + action, + propertyName: "description", + value: response.data.description, + }), + ); + + yield put({ + type: ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_SUCCESS, + payload: { action }, + }); + } catch (error) { + yield put({ + type: ReduxActionErrorTypes.GENERATE_JS_FUNCTION_SCHEMA_ERROR, + payload: { action }, + }); + + toast.show(createMessage(CANNOT_GENERATE_SCHEMA), { + kind: "error", + }); + } +} + +export function* watchGeneratePluginActionSchemaSaga() { + yield all([ + takeLatest( + ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_REQUEST, + generatePluginActionSchemaSaga, + ), + takeLatest( + ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_REQUEST, + generateJSFunctionSchemaSuccessSaga, + ), + ]); +} diff --git a/app/client/src/selectors/jsPaneSelectors.ts b/app/client/src/selectors/jsPaneSelectors.ts index a41c0d31c0d3..abb35e542ce8 100644 --- a/app/client/src/selectors/jsPaneSelectors.ts +++ b/app/client/src/selectors/jsPaneSelectors.ts @@ -22,3 +22,11 @@ export const getLastJSTab = (state: AppState): FocusEntityInfo | undefined => { return identifyEntityFromPath(urlWithoutQueryParams); } }; + +export const getIsGeneratingSchema = (state: AppState, collectionId: string) => + state.ui.jsPane.isSchemaGenerating[collectionId]; + +export const getIsJSCollectionSaving = ( + state: AppState, + collectionId: string, +) => state.ui.jsPane.isSaving[collectionId]; From 75c2a496e7cc546b8d2b3473fb8c0a986eb6285c Mon Sep 17 00:00:00 2001 From: Ilia Znamenskii Date: Mon, 17 Mar 2025 14:38:04 +0100 Subject: [PATCH 2/7] add generate schema button --- .../components/PluginActionToolbar.tsx | 26 ++++- .../hooks/useHandleGenerateSchemaClick.ts | 17 +++ .../store/pluginActionEditorSelectors.ts | 10 ++ .../store/pluginEditorReducer.ts | 22 ++++ .../src/actions/generateSchemaActions.ts | 18 +++ app/client/src/api/SchemaAPI.ts | 17 +++ .../src/ce/constants/ReduxActionConstants.tsx | 12 ++ app/client/src/ce/constants/messages.ts | 1 + app/client/src/ce/sagas/index.tsx | 2 + app/client/src/pages/Editor/JSEditor/Form.tsx | 28 ++++- .../JSEditorToolbar/JSEditorToolbar.tsx | 23 +++- .../components/JSFunctionGenerateSchema.tsx | 25 ++++ .../JSEditor/JSEditorToolbar/constants.ts | 1 + .../src/reducers/uiReducers/jsPaneReducer.ts | 48 +++++++- app/client/src/sagas/GenerateSchemaSaga.ts | 109 ++++++++++++++++++ app/client/src/selectors/jsPaneSelectors.ts | 8 ++ 16 files changed, 360 insertions(+), 7 deletions(-) create mode 100644 app/client/src/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts create mode 100644 app/client/src/actions/generateSchemaActions.ts create mode 100644 app/client/src/api/SchemaAPI.ts create mode 100644 app/client/src/pages/Editor/JSEditor/JSEditorToolbar/components/JSFunctionGenerateSchema.tsx create mode 100644 app/client/src/sagas/GenerateSchemaSaga.ts diff --git a/app/client/src/PluginActionEditor/components/PluginActionToolbar.tsx b/app/client/src/PluginActionEditor/components/PluginActionToolbar.tsx index d0ff690cf114..c2fa12b59da3 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionToolbar.tsx +++ b/app/client/src/PluginActionEditor/components/PluginActionToolbar.tsx @@ -9,9 +9,15 @@ import { useAnalyticsOnRunClick, } from "../hooks"; import { useSelector } from "react-redux"; -import { isActionRunning } from "../store"; +import { + isActionRunning, + isActionSaving, + isActionSchemaGenerating, +} from "../store"; import PluginActionSettings from "./PluginActionSettings"; import { PluginActionContextMenu } from "./PluginActionContextMenu"; +import { useHandleGenerateSchemaClick } from "../hooks/useHandleGenerateSchemaClick"; +import { getIsAnvilLayoutEnabled } from "../../layoutSystems/anvil/integrations/selectors"; interface PluginActionToolbarProps { runOptions?: React.ReactNode; @@ -22,9 +28,13 @@ interface PluginActionToolbarProps { const PluginActionToolbar = (props: PluginActionToolbarProps) => { const { action } = usePluginActionContext(); const { handleRunClick } = useHandleRunClick(); + const { handleGenerateSchemaClick } = useHandleGenerateSchemaClick(); const { callRunActionAnalytics } = useAnalyticsOnRunClick(); const blockExecution = useBlockExecution(); const isRunning = useSelector(isActionRunning(action.id)); + const isSaving = useSelector(isActionSaving(action.id)); + const isSchemaGenerating = useSelector(isActionSchemaGenerating(action.id)); + const isAnvilEnabled = useSelector(getIsAnvilLayoutEnabled); const onRunClick = useCallback(() => { callRunActionAnalytics(); @@ -43,7 +53,7 @@ const PluginActionToolbar = (props: PluginActionToolbarProps) => { > + {isAnvilEnabled && ( + + )} {props.menuContent ? ( { + dispatch(generatePluginActionSchema(action?.id ?? "")); + }, [action?.id, dispatch]); + + return { handleGenerateSchemaClick }; +} + +export { useHandleGenerateSchemaClick }; diff --git a/app/client/src/PluginActionEditor/store/pluginActionEditorSelectors.ts b/app/client/src/PluginActionEditor/store/pluginActionEditorSelectors.ts index d931e8210639..f0af8494b56d 100644 --- a/app/client/src/PluginActionEditor/store/pluginActionEditorSelectors.ts +++ b/app/client/src/PluginActionEditor/store/pluginActionEditorSelectors.ts @@ -20,6 +20,16 @@ export const isActionDirty = (id: string) => const getActionRunningState = (state: AppState) => state.ui.pluginActionEditor.isRunning; +const getActionSchemaGeneratingState = (state: AppState) => + state.ui.pluginActionEditor.isSchemaGenerating; + +export const isActionSchemaGenerating = (id: string) => + createSelector( + [getActionSchemaGeneratingState], + (isSchemaGeneratingMap) => + id in isSchemaGeneratingMap && isSchemaGeneratingMap[id], + ); + export const isActionRunning = (id: string) => createSelector( [getActionRunningState], diff --git a/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts b/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts index 3bcafcdc6359..5cc203e7e326 100644 --- a/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts +++ b/app/client/src/PluginActionEditor/store/pluginEditorReducer.ts @@ -22,6 +22,7 @@ export interface PluginActionEditorState { isCreating: boolean; isRunning: Record; isSaving: Record; + isSchemaGenerating: Record; isDeleting: Record; isDirty: Record; runErrorMessage: Record; @@ -34,6 +35,7 @@ const initialState: PluginActionEditorState = { isCreating: false, isRunning: {}, isSaving: {}, + isSchemaGenerating: {}, isDeleting: {}, isDirty: {}, runErrorMessage: {}, @@ -141,6 +143,26 @@ export const handlers = { set(state, ["isRunning", id], false); set(state, ["runErrorMessage", id], error.message); }, + [ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_REQUEST]: ( + state: PluginActionEditorState, + action: ReduxAction<{ + id: string; + }>, + ) => { + set(state, ["isSchemaGenerating", action.payload.id], true); + }, + [ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_SUCCESS]: ( + state: PluginActionEditorState, + action: ReduxAction<{ id: string }>, + ) => { + set(state, ["isSchemaGenerating", action.payload.id], false); + }, + [ReduxActionErrorTypes.GENERATE_PLUGIN_ACTION_SCHEMA_ERROR]: ( + state: PluginActionEditorState, + action: ReduxAction<{ id: string }>, + ) => { + set(state, ["isSchemaGenerating", action.payload.id], false); + }, [ReduxActionTypes.SET_PLUGIN_ACTION_EDITOR_FORM_SELECTED_TAB]: ( state: PluginActionEditorState, action: ReduxAction<{ selectedTab: string }>, diff --git a/app/client/src/actions/generateSchemaActions.ts b/app/client/src/actions/generateSchemaActions.ts new file mode 100644 index 000000000000..ce479e9744eb --- /dev/null +++ b/app/client/src/actions/generateSchemaActions.ts @@ -0,0 +1,18 @@ +import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; +import type { JSAction } from "entities/JSCollection"; + +export const generateJSFunctionSchema = (action: JSAction) => { + return { + type: ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_REQUEST, + payload: { + action, + }, + }; +}; + +export const generatePluginActionSchema = (id: string) => { + return { + type: ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_REQUEST, + payload: { id }, + }; +}; diff --git a/app/client/src/api/SchemaAPI.ts b/app/client/src/api/SchemaAPI.ts new file mode 100644 index 000000000000..44044c7b356c --- /dev/null +++ b/app/client/src/api/SchemaAPI.ts @@ -0,0 +1,17 @@ +import API from "api/Api"; +import type { AxiosPromise } from "axios"; + +export interface GenerateSchemaResponse { + description: string; + schema: unknown; +} + +export class SchemaAPI extends API { + static url = "v1/actions"; + + static async generateSchema( + actionId: string, + ): Promise> { + return API.patch(`${SchemaAPI.url}/${actionId}/schema`); + } +} diff --git a/app/client/src/ce/constants/ReduxActionConstants.tsx b/app/client/src/ce/constants/ReduxActionConstants.tsx index 6ff622ee5ca1..2df11a46963b 100644 --- a/app/client/src/ce/constants/ReduxActionConstants.tsx +++ b/app/client/src/ce/constants/ReduxActionConstants.tsx @@ -710,6 +710,16 @@ const ActionExecutionTypes = { RUN_ACTION_REQUEST: "RUN_ACTION_REQUEST", RUN_ACTION_CANCELLED: "RUN_ACTION_CANCELLED", RUN_ACTION_SUCCESS: "RUN_ACTION_SUCCESS", + GENERATE_JS_FUNCTION_SCHEMA_REQUEST: "GENERATE_JS_FUNCTION_SCHEMA_REQUEST", + GENERATE_JS_FUNCTION_SCHEMA_CANCELLED: + "GENERATE_JS_FUNCTION_SCHEMA_CANCELLED", + GENERATE_JS_FUNCTION_SCHEMA_SUCCESS: "GENERATE_JS_FUNCTION_SCHEMA_SUCCESS", + GENERATE_PLUGIN_ACTION_SCHEMA_REQUEST: + "GENERATE_PLUGIN_ACTION_SCHEMA_REQUEST", + GENERATE_PLUGIN_ACTION_SCHEMA_CANCELLED: + "GENERATE_PLUGIN_ACTION_SCHEMA_CANCELLED", + GENERATE_PLUGIN_ACTION_SCHEMA_SUCCESS: + "GENERATE_PLUGIN_ACTION_SCHEMA_SUCCESS", CLEAR_ACTION_RESPONSE: "CLEAR_ACTION_RESPONSE", SHOW_ACTION_MODAL: "SHOW_ACTION_MODAL", CANCEL_ACTION_MODAL: "CANCEL_ACTION_MODAL", @@ -722,6 +732,8 @@ const ActionExecutionTypes = { const ActionExecutionErrorTypes = { RUN_ACTION_ERROR: "RUN_ACTION_ERROR", + GENERATE_JS_FUNCTION_SCHEMA_ERROR: "GENERATE_JS_FUNCTION_SCHEMA_ERROR", + GENERATE_PLUGIN_ACTION_SCHEMA_ERROR: "GENERATE_PLUGIN_ACTION_SCHEMA_ERROR", EXECUTE_PLUGIN_ACTION_ERROR: "EXECUTE_PLUGIN_ACTION_ERROR", }; diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts index b066fb375104..af8fdb259e56 100644 --- a/app/client/src/ce/constants/messages.ts +++ b/app/client/src/ce/constants/messages.ts @@ -649,6 +649,7 @@ export const EXPORT_DEFAULT_BEGINNING = () => `Start object with export default`; export const ACTION_EXECUTION_FAILED = (actionName: string) => `The action "${actionName}" has failed.`; +export const CANNOT_GENERATE_SCHEMA = () => "Can't generate schema"; export const JS_EXECUTION_TRIGGERED = () => "Function triggered"; export const JS_EXECUTION_SUCCESS = () => "Function executed"; export const JS_EXECUTION_FAILURE = () => "Function execution failed"; diff --git a/app/client/src/ce/sagas/index.tsx b/app/client/src/ce/sagas/index.tsx index 577711a4f01c..1805ec448477 100644 --- a/app/client/src/ce/sagas/index.tsx +++ b/app/client/src/ce/sagas/index.tsx @@ -51,6 +51,7 @@ import communityTemplateSagas from "sagas/CommunityTemplatesSagas"; import anvilSagas from "layoutSystems/anvil/integrations/sagas"; import ideSagas from "sagas/IDESaga"; import sendSideBySideWidgetHoverAnalyticsEventSaga from "sagas/AnalyticsSaga"; +import { watchGeneratePluginActionSchemaSaga } from "sagas/GenerateSchemaSaga"; import gitSagas from "git/sagas"; /* Sagas that are registered by a module that is designed to be independent of the core platform */ @@ -64,6 +65,7 @@ export const sagas = [ watchJSActionSagas, watchActionExecutionSagas, watchPluginActionExecutionSagas, + watchGeneratePluginActionSchemaSaga, widgetOperationSagas, errorSagas, watchDatasourcesSagas, diff --git a/app/client/src/pages/Editor/JSEditor/Form.tsx b/app/client/src/pages/Editor/JSEditor/Form.tsx index 1cc944e0226c..a587ae67cbe5 100644 --- a/app/client/src/pages/Editor/JSEditor/Form.tsx +++ b/app/client/src/pages/Editor/JSEditor/Form.tsx @@ -30,7 +30,11 @@ import { } from "./utils"; import JSObjectHotKeys from "./JSObjectHotKeys"; import { Form, FormWrapper } from "./styledComponents"; -import { getJSPaneConfigSelectedTab } from "selectors/jsPaneSelectors"; +import { + getIsGeneratingSchema, + getIsJSCollectionSaving, + getJSPaneConfigSelectedTab, +} from "selectors/jsPaneSelectors"; import type { EventLocation } from "ee/utils/analyticsUtilTypes"; import { setCodeEditorCursorAction, @@ -57,6 +61,7 @@ import { getJSActionOption, type OnUpdateSettingsProps, } from "./JSEditorToolbar"; +import { generateJSFunctionSchema } from "../../../actions/generateSchemaActions"; interface JSFormProps { jsCollectionData: JSCollectionData; @@ -153,6 +158,12 @@ function JSEditorForm({ selectedJSActionOption.data?.id || "", ), ); + const isGeneratingSchema = useSelector((state: AppState) => + getIsGeneratingSchema(state, currentJSCollection.id), + ); + const isJSCollectionSaving = useSelector((state: AppState) => + getIsJSCollectionSaving(state, currentJSCollection.id), + ); useEffect(() => { if (hash) { @@ -287,6 +298,12 @@ function JSEditorForm({ } }; + const handleGenerateSchemaButtonClick = async () => { + if (selectedJSActionOption.data?.id) { + dispatch(generateJSFunctionSchema(selectedJSActionOption.data)); + } + }; + useEffect(() => { if (parseErrors.length || isEmpty(jsActions)) { setDisableRunFunctionality(true); @@ -339,10 +356,16 @@ function JSEditorForm({ { handleRunAction(event, "JS_OBJECT_MAIN_RUN_BUTTON"); }} + onGenerateSchemaButtonClick={handleGenerateSchemaButtonClick} onSelect={handleJSActionOptionSelection} onUpdateSettings={onUpdateSettings} saveJSObjectName={saveJSObjectName} diff --git a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx b/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx index e48a11848870..5dfedbd0e625 100644 --- a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx +++ b/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx @@ -1,4 +1,5 @@ import React, { useState } from "react"; +import { useSelector } from "react-redux"; import { IDEToolbar, ToolbarSettingsPopover } from "IDE"; import { JSFunctionRun } from "./components/JSFunctionRun"; import type { JSActionDropdownOption, OnUpdateSettingsProps } from "./types"; @@ -10,6 +11,9 @@ import { createMessage, JS_EDITOR_SETTINGS } from "ee/constants/messages"; import { JSFunctionSettings } from "./components/JSFunctionSettings"; import { convertJSActionsToDropdownOptions } from "./utils"; import { JSObjectNameEditor } from "./JSObjectNameEditor"; +import { JSFunctionGenerateSchema } from "./components/JSFunctionGenerateSchema"; +import { Flex } from "@appsmith/ads"; +import { getIsAnvilLayoutEnabled } from "../../../../layoutSystems/anvil/integrations/selectors"; interface Props { changePermitted: boolean; @@ -20,12 +24,17 @@ interface Props { hideContextMenuOnEditor?: boolean; contextMenu: React.ReactNode; disableRunFunctionality: boolean; + disableGenerateSchemaFunctionality: boolean; executePermitted: boolean; loading: boolean; + isGeneratingSchema: boolean; jsCollection: JSCollection; onButtonClick: ( event: React.MouseEvent | KeyboardEvent, ) => void; + onGenerateSchemaButtonClick: ( + event: React.MouseEvent | KeyboardEvent, + ) => void; onSelect: DropdownOnSelect; jsActions: JSAction[]; selected: JSActionDropdownOption; @@ -42,6 +51,7 @@ interface Props { */ export const JSEditorToolbar = (props: Props) => { const [isOpen, setIsOpen] = useState(false); + const isAnvilEnabled = useSelector(getIsAnvilLayoutEnabled); // Render the IDEToolbar with JSFunctionRun and JSFunctionSettings components return ( @@ -55,7 +65,7 @@ export const JSEditorToolbar = (props: Props) => { )} -
+ { selected={props.selected} showTooltip={!props.selected.data} /> -
+ {isAnvilEnabled && ( + + )} + {props.showSettings ? ( ) => void; +} + +export const JSFunctionGenerateSchema = (props: Props) => { + return ( + + ); +}; diff --git a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/constants.ts b/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/constants.ts index 27f3945f41ac..eb1e9be1eccd 100644 --- a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/constants.ts +++ b/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/constants.ts @@ -8,6 +8,7 @@ export const RUN_BUTTON_DEFAULTS = { export const testLocators = { runJSAction: "run-js-action", runJSActionTestID: "t--run-js-action", + generateSchemaJSActionTestID: "t--generate-schema-js-action", }; export const NO_FUNCTION_DROPDOWN_OPTION = { label: "No function available", diff --git a/app/client/src/reducers/uiReducers/jsPaneReducer.ts b/app/client/src/reducers/uiReducers/jsPaneReducer.ts index 79fbcb633bc7..d9bd4ea5f3da 100644 --- a/app/client/src/reducers/uiReducers/jsPaneReducer.ts +++ b/app/client/src/reducers/uiReducers/jsPaneReducer.ts @@ -4,7 +4,7 @@ import { ReduxActionTypes, ReduxActionErrorTypes, } from "ee/constants/ReduxActionConstants"; -import type { JSCollection } from "entities/JSCollection"; +import type { JSAction, JSCollection } from "entities/JSCollection"; import { ActionExecutionResizerHeight } from "PluginActionEditor/components/PluginActionResponse/constants"; export enum JSEditorTab { @@ -23,6 +23,7 @@ export interface JsPaneReduxState { isSaving: Record; isDeleting: Record; isDirty: Record; + isSchemaGenerating: Record; selectedConfigTab: JSEditorTab; debugger: JSPaneDebuggerState; } @@ -32,6 +33,7 @@ const initialState: JsPaneReduxState = { isSaving: {}, isDeleting: {}, isDirty: {}, + isSchemaGenerating: {}, selectedConfigTab: JSEditorTab.CODE, debugger: { open: false, @@ -175,6 +177,50 @@ const jsPaneReducer = createReducer(initialState, { isSaving: false, }; }, + [ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_REQUEST]: ( + state: JsPaneReduxState, + action: ReduxAction<{ + action: JSAction; + }>, + ) => { + if (!action.payload.action.collectionId) return state; + + return { + ...state, + isSchemaGenerating: { + ...state.isSchemaGenerating, + [action.payload.action.collectionId]: true, + }, + }; + }, + [ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_SUCCESS]: ( + state: JsPaneReduxState, + action: ReduxAction<{ action: JSAction }>, + ) => { + if (!action.payload.action.collectionId) return state; + + return { + ...state, + isSchemaGenerating: { + ...state.isSchemaGenerating, + [action.payload.action.collectionId]: false, + }, + }; + }, + [ReduxActionErrorTypes.GENERATE_JS_FUNCTION_SCHEMA_ERROR]: ( + state: JsPaneReduxState, + action: ReduxAction<{ action: JSAction }>, + ) => { + if (!action.payload.action.collectionId) return state; + + return { + ...state, + isSchemaGenerating: { + ...state.isSchemaGenerating, + [action.payload.action.collectionId]: false, + }, + }; + }, }); export default jsPaneReducer; diff --git a/app/client/src/sagas/GenerateSchemaSaga.ts b/app/client/src/sagas/GenerateSchemaSaga.ts new file mode 100644 index 000000000000..9b16757cdb27 --- /dev/null +++ b/app/client/src/sagas/GenerateSchemaSaga.ts @@ -0,0 +1,109 @@ +import { toast } from "@appsmith/ads"; +import { createMessage } from "@appsmith/ads-old"; +import { CANNOT_GENERATE_SCHEMA } from "ee/constants/messages"; +import { + ReduxActionErrorTypes, + ReduxActionTypes, +} from "ee/constants/ReduxActionConstants"; +import { all, call, put, takeLatest } from "redux-saga/effects"; +import { updateFunctionProperty } from "../actions/jsPaneActions"; +import { updateActionProperty } from "../actions/pluginActionActions"; +import type { ReduxAction } from "../actions/ReduxActionTypes"; +import type { ApiResponse } from "../api/ApiResponses"; +import { SchemaAPI, type GenerateSchemaResponse } from "../api/SchemaAPI"; +import type { JSAction } from "../entities/JSCollection"; + +function* generatePluginActionSchemaSaga(action: ReduxAction<{ id: string }>) { + const { id } = action.payload; + + try { + const response: ApiResponse = yield call( + SchemaAPI.generateSchema, + id, + ); + + yield put( + updateActionProperty({ + id, + field: "schema", + value: response.data.schema, + }), + ); + yield put( + updateActionProperty({ + id, + field: "description", + value: response.data.description, + }), + ); + + yield put({ + type: ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_SUCCESS, + payload: { id }, + }); + } catch (error) { + yield put({ + type: ReduxActionErrorTypes.GENERATE_PLUGIN_ACTION_SCHEMA_ERROR, + payload: { id }, + }); + + toast.show(createMessage(CANNOT_GENERATE_SCHEMA), { + kind: "error", + }); + } +} + +function* generateJSFunctionSchemaSuccessSaga( + reduxAction: ReduxAction<{ action: JSAction }>, +) { + const { action } = reduxAction.payload; + + try { + const response: ApiResponse = yield call( + SchemaAPI.generateSchema, + action.id, + ); + + yield put( + updateFunctionProperty({ + action, + propertyName: "schema", + value: response.data.schema, + }), + ); + yield put( + updateFunctionProperty({ + action, + propertyName: "description", + value: response.data.description, + }), + ); + + yield put({ + type: ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_SUCCESS, + payload: { action }, + }); + } catch (error) { + yield put({ + type: ReduxActionErrorTypes.GENERATE_JS_FUNCTION_SCHEMA_ERROR, + payload: { action }, + }); + + toast.show(createMessage(CANNOT_GENERATE_SCHEMA), { + kind: "error", + }); + } +} + +export function* watchGeneratePluginActionSchemaSaga() { + yield all([ + takeLatest( + ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_REQUEST, + generatePluginActionSchemaSaga, + ), + takeLatest( + ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_REQUEST, + generateJSFunctionSchemaSuccessSaga, + ), + ]); +} diff --git a/app/client/src/selectors/jsPaneSelectors.ts b/app/client/src/selectors/jsPaneSelectors.ts index a41c0d31c0d3..abb35e542ce8 100644 --- a/app/client/src/selectors/jsPaneSelectors.ts +++ b/app/client/src/selectors/jsPaneSelectors.ts @@ -22,3 +22,11 @@ export const getLastJSTab = (state: AppState): FocusEntityInfo | undefined => { return identifyEntityFromPath(urlWithoutQueryParams); } }; + +export const getIsGeneratingSchema = (state: AppState, collectionId: string) => + state.ui.jsPane.isSchemaGenerating[collectionId]; + +export const getIsJSCollectionSaving = ( + state: AppState, + collectionId: string, +) => state.ui.jsPane.isSaving[collectionId]; From 664e0130fdd472540b3e9a2b55a8b6930083f969 Mon Sep 17 00:00:00 2001 From: Ilia Znamenskii Date: Mon, 17 Mar 2025 15:28:34 +0100 Subject: [PATCH 3/7] fix tests --- .../Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.test.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.test.tsx b/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.test.tsx index dd8a655d2ed5..04ffe7eb0fe9 100644 --- a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.test.tsx +++ b/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.test.tsx @@ -23,6 +23,9 @@ const defaultProps = { jsCollection: JSObject, onButtonClick: jest.fn(), onSelect: jest.fn(), + disableGenerateSchemaFunctionality: false, + isGeneratingSchema: false, + onGenerateSchemaButtonClick: jest.fn(), jsActions: JSObject.actions, selected: { label: "JSObject1.myFun1", From 389201712962e160e9c7db02cda31094f9f557a5 Mon Sep 17 00:00:00 2001 From: Ilia Znamenskii Date: Mon, 17 Mar 2025 15:34:22 +0100 Subject: [PATCH 4/7] rename watchGenerateSchemaSaga --- app/client/src/ce/sagas/index.tsx | 4 ++-- app/client/src/sagas/GenerateSchemaSaga.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/client/src/ce/sagas/index.tsx b/app/client/src/ce/sagas/index.tsx index 1805ec448477..1c4dad9a333e 100644 --- a/app/client/src/ce/sagas/index.tsx +++ b/app/client/src/ce/sagas/index.tsx @@ -51,7 +51,7 @@ import communityTemplateSagas from "sagas/CommunityTemplatesSagas"; import anvilSagas from "layoutSystems/anvil/integrations/sagas"; import ideSagas from "sagas/IDESaga"; import sendSideBySideWidgetHoverAnalyticsEventSaga from "sagas/AnalyticsSaga"; -import { watchGeneratePluginActionSchemaSaga } from "sagas/GenerateSchemaSaga"; +import { watchGenerateSchemaSaga } from "sagas/GenerateSchemaSaga"; import gitSagas from "git/sagas"; /* Sagas that are registered by a module that is designed to be independent of the core platform */ @@ -65,7 +65,7 @@ export const sagas = [ watchJSActionSagas, watchActionExecutionSagas, watchPluginActionExecutionSagas, - watchGeneratePluginActionSchemaSaga, + watchGenerateSchemaSaga, widgetOperationSagas, errorSagas, watchDatasourcesSagas, diff --git a/app/client/src/sagas/GenerateSchemaSaga.ts b/app/client/src/sagas/GenerateSchemaSaga.ts index 9b16757cdb27..fa1e8aa5987e 100644 --- a/app/client/src/sagas/GenerateSchemaSaga.ts +++ b/app/client/src/sagas/GenerateSchemaSaga.ts @@ -95,7 +95,7 @@ function* generateJSFunctionSchemaSuccessSaga( } } -export function* watchGeneratePluginActionSchemaSaga() { +export function* watchGenerateSchemaSaga() { yield all([ takeLatest( ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_REQUEST, From 62aef31eae0e8a64905a8013ce19b6454475f9a7 Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Tue, 18 Mar 2025 11:22:13 +0530 Subject: [PATCH 5/7] chore: Split Plugin Action Toolbar --- app/client/src/PluginActionEditor/index.ts | 2 +- .../src/actions/generateSchemaActions.ts | 18 --- app/client/src/api/SchemaAPI.ts | 17 --- .../components/PluginActionToolbar.tsx | 34 ++---- .../hooks/useHandleGenerateSchemaClick.ts | 17 --- app/client/src/ce/sagas/index.tsx | 2 - .../components/PluginActionToolbar.tsx | 1 + app/client/src/sagas/GenerateSchemaSaga.ts | 109 ------------------ 8 files changed, 9 insertions(+), 191 deletions(-) delete mode 100644 app/client/src/actions/generateSchemaActions.ts delete mode 100644 app/client/src/api/SchemaAPI.ts rename app/client/src/{ => ce}/PluginActionEditor/components/PluginActionToolbar.tsx (62%) delete mode 100644 app/client/src/ce/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts create mode 100644 app/client/src/ee/PluginActionEditor/components/PluginActionToolbar.tsx delete mode 100644 app/client/src/sagas/GenerateSchemaSaga.ts diff --git a/app/client/src/PluginActionEditor/index.ts b/app/client/src/PluginActionEditor/index.ts index 8a2cb80ae68f..8b72d13c7ae6 100644 --- a/app/client/src/PluginActionEditor/index.ts +++ b/app/client/src/PluginActionEditor/index.ts @@ -3,7 +3,7 @@ export { PluginActionContextProvider, usePluginActionContext, } from "./PluginActionContext"; -export { default as PluginActionToolbar } from "./components/PluginActionToolbar"; +export { PluginActionToolbar } from "ee/PluginActionEditor/components/PluginActionToolbar"; export { default as PluginActionForm } from "./components/PluginActionForm"; export { default as PluginActionResponse } from "./components/PluginActionResponse"; export type { diff --git a/app/client/src/actions/generateSchemaActions.ts b/app/client/src/actions/generateSchemaActions.ts deleted file mode 100644 index ce479e9744eb..000000000000 --- a/app/client/src/actions/generateSchemaActions.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; -import type { JSAction } from "entities/JSCollection"; - -export const generateJSFunctionSchema = (action: JSAction) => { - return { - type: ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_REQUEST, - payload: { - action, - }, - }; -}; - -export const generatePluginActionSchema = (id: string) => { - return { - type: ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_REQUEST, - payload: { id }, - }; -}; diff --git a/app/client/src/api/SchemaAPI.ts b/app/client/src/api/SchemaAPI.ts deleted file mode 100644 index 44044c7b356c..000000000000 --- a/app/client/src/api/SchemaAPI.ts +++ /dev/null @@ -1,17 +0,0 @@ -import API from "api/Api"; -import type { AxiosPromise } from "axios"; - -export interface GenerateSchemaResponse { - description: string; - schema: unknown; -} - -export class SchemaAPI extends API { - static url = "v1/actions"; - - static async generateSchema( - actionId: string, - ): Promise> { - return API.patch(`${SchemaAPI.url}/${actionId}/schema`); - } -} diff --git a/app/client/src/PluginActionEditor/components/PluginActionToolbar.tsx b/app/client/src/ce/PluginActionEditor/components/PluginActionToolbar.tsx similarity index 62% rename from app/client/src/PluginActionEditor/components/PluginActionToolbar.tsx rename to app/client/src/ce/PluginActionEditor/components/PluginActionToolbar.tsx index 5e1d4521577b..492de60eeedc 100644 --- a/app/client/src/PluginActionEditor/components/PluginActionToolbar.tsx +++ b/app/client/src/ce/PluginActionEditor/components/PluginActionToolbar.tsx @@ -2,21 +2,16 @@ import React, { useCallback } from "react"; import { IDEToolbar } from "IDE"; import { Button, Tooltip } from "@appsmith/ads"; import { modText } from "utils/helpers"; -import { usePluginActionContext } from "../PluginActionContext"; +import { usePluginActionContext } from "PluginActionEditor/PluginActionContext"; import { useBlockExecution, useHandleRunClick, useAnalyticsOnRunClick, - useHandleGenerateSchemaClick, -} from "../hooks"; +} from "PluginActionEditor/hooks"; import { useSelector } from "react-redux"; -import { - isActionRunning, - isActionSaving, - isActionSchemaGenerating, -} from "../store"; -import PluginActionSettings from "./PluginActionSettings"; -import { PluginActionContextMenu } from "./PluginActionContextMenu"; +import { isActionRunning } from "PluginActionEditor/store"; +import PluginActionSettings from "PluginActionEditor/components/PluginActionSettings"; +import { PluginActionContextMenu } from "PluginActionEditor/components/PluginActionContextMenu"; interface PluginActionToolbarProps { runOptions?: React.ReactNode; @@ -24,15 +19,12 @@ interface PluginActionToolbarProps { menuContent?: React.ReactNode[] | React.ReactNode; } -const PluginActionToolbar = (props: PluginActionToolbarProps) => { +export const PluginActionToolbar = (props: PluginActionToolbarProps) => { const { action } = usePluginActionContext(); const { handleRunClick } = useHandleRunClick(); - const { handleGenerateSchemaClick } = useHandleGenerateSchemaClick(); const { callRunActionAnalytics } = useAnalyticsOnRunClick(); const blockExecution = useBlockExecution(); const isRunning = useSelector(isActionRunning(action.id)); - const isSaving = useSelector(isActionSaving(action.id)); - const isSchemaGenerating = useSelector(isActionSchemaGenerating(action.id)); const onRunClick = useCallback(() => { callRunActionAnalytics(); @@ -51,7 +43,7 @@ const PluginActionToolbar = (props: PluginActionToolbarProps) => { > - {props.menuContent ? ( { ); }; - -export default PluginActionToolbar; diff --git a/app/client/src/ce/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts b/app/client/src/ce/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts deleted file mode 100644 index 2aea4c588884..000000000000 --- a/app/client/src/ce/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { generatePluginActionSchema } from "actions/generateSchemaActions"; -import { usePluginActionContext } from "PluginActionEditor/PluginActionContext"; -import { useCallback } from "react"; -import { useDispatch } from "react-redux"; - -function useHandleGenerateSchemaClick() { - const { action } = usePluginActionContext(); - const dispatch = useDispatch(); - - const handleGenerateSchemaClick = useCallback(() => { - dispatch(generatePluginActionSchema(action?.id ?? "")); - }, [action?.id, dispatch]); - - return { handleGenerateSchemaClick }; -} - -export { useHandleGenerateSchemaClick }; diff --git a/app/client/src/ce/sagas/index.tsx b/app/client/src/ce/sagas/index.tsx index 1805ec448477..577711a4f01c 100644 --- a/app/client/src/ce/sagas/index.tsx +++ b/app/client/src/ce/sagas/index.tsx @@ -51,7 +51,6 @@ import communityTemplateSagas from "sagas/CommunityTemplatesSagas"; import anvilSagas from "layoutSystems/anvil/integrations/sagas"; import ideSagas from "sagas/IDESaga"; import sendSideBySideWidgetHoverAnalyticsEventSaga from "sagas/AnalyticsSaga"; -import { watchGeneratePluginActionSchemaSaga } from "sagas/GenerateSchemaSaga"; import gitSagas from "git/sagas"; /* Sagas that are registered by a module that is designed to be independent of the core platform */ @@ -65,7 +64,6 @@ export const sagas = [ watchJSActionSagas, watchActionExecutionSagas, watchPluginActionExecutionSagas, - watchGeneratePluginActionSchemaSaga, widgetOperationSagas, errorSagas, watchDatasourcesSagas, diff --git a/app/client/src/ee/PluginActionEditor/components/PluginActionToolbar.tsx b/app/client/src/ee/PluginActionEditor/components/PluginActionToolbar.tsx new file mode 100644 index 000000000000..940a4bc54661 --- /dev/null +++ b/app/client/src/ee/PluginActionEditor/components/PluginActionToolbar.tsx @@ -0,0 +1 @@ +export * from "ce/PluginActionEditor/components/PluginActionToolbar"; diff --git a/app/client/src/sagas/GenerateSchemaSaga.ts b/app/client/src/sagas/GenerateSchemaSaga.ts deleted file mode 100644 index 9b16757cdb27..000000000000 --- a/app/client/src/sagas/GenerateSchemaSaga.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { toast } from "@appsmith/ads"; -import { createMessage } from "@appsmith/ads-old"; -import { CANNOT_GENERATE_SCHEMA } from "ee/constants/messages"; -import { - ReduxActionErrorTypes, - ReduxActionTypes, -} from "ee/constants/ReduxActionConstants"; -import { all, call, put, takeLatest } from "redux-saga/effects"; -import { updateFunctionProperty } from "../actions/jsPaneActions"; -import { updateActionProperty } from "../actions/pluginActionActions"; -import type { ReduxAction } from "../actions/ReduxActionTypes"; -import type { ApiResponse } from "../api/ApiResponses"; -import { SchemaAPI, type GenerateSchemaResponse } from "../api/SchemaAPI"; -import type { JSAction } from "../entities/JSCollection"; - -function* generatePluginActionSchemaSaga(action: ReduxAction<{ id: string }>) { - const { id } = action.payload; - - try { - const response: ApiResponse = yield call( - SchemaAPI.generateSchema, - id, - ); - - yield put( - updateActionProperty({ - id, - field: "schema", - value: response.data.schema, - }), - ); - yield put( - updateActionProperty({ - id, - field: "description", - value: response.data.description, - }), - ); - - yield put({ - type: ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_SUCCESS, - payload: { id }, - }); - } catch (error) { - yield put({ - type: ReduxActionErrorTypes.GENERATE_PLUGIN_ACTION_SCHEMA_ERROR, - payload: { id }, - }); - - toast.show(createMessage(CANNOT_GENERATE_SCHEMA), { - kind: "error", - }); - } -} - -function* generateJSFunctionSchemaSuccessSaga( - reduxAction: ReduxAction<{ action: JSAction }>, -) { - const { action } = reduxAction.payload; - - try { - const response: ApiResponse = yield call( - SchemaAPI.generateSchema, - action.id, - ); - - yield put( - updateFunctionProperty({ - action, - propertyName: "schema", - value: response.data.schema, - }), - ); - yield put( - updateFunctionProperty({ - action, - propertyName: "description", - value: response.data.description, - }), - ); - - yield put({ - type: ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_SUCCESS, - payload: { action }, - }); - } catch (error) { - yield put({ - type: ReduxActionErrorTypes.GENERATE_JS_FUNCTION_SCHEMA_ERROR, - payload: { action }, - }); - - toast.show(createMessage(CANNOT_GENERATE_SCHEMA), { - kind: "error", - }); - } -} - -export function* watchGeneratePluginActionSchemaSaga() { - yield all([ - takeLatest( - ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_REQUEST, - generatePluginActionSchemaSaga, - ), - takeLatest( - ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_REQUEST, - generateJSFunctionSchemaSuccessSaga, - ), - ]); -} From e013cb703758f9e3a368139fcbc93f8e36d8c543 Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Tue, 18 Mar 2025 11:32:09 +0530 Subject: [PATCH 6/7] remove transfered files --- .../src/PluginActionEditor/hooks/index.ts | 1 - .../hooks/useHandleGenerateSchemaClick.ts | 17 --- .../src/actions/generateSchemaActions.ts | 18 --- app/client/src/api/SchemaAPI.ts | 17 --- app/client/src/ce/sagas/index.tsx | 2 - .../hooks/useHandleGenerateSchemaClick.ts | 1 - app/client/src/sagas/GenerateSchemaSaga.ts | 109 ------------------ 7 files changed, 165 deletions(-) delete mode 100644 app/client/src/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts delete mode 100644 app/client/src/actions/generateSchemaActions.ts delete mode 100644 app/client/src/api/SchemaAPI.ts delete mode 100644 app/client/src/ee/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts delete mode 100644 app/client/src/sagas/GenerateSchemaSaga.ts diff --git a/app/client/src/PluginActionEditor/hooks/index.ts b/app/client/src/PluginActionEditor/hooks/index.ts index a8914e8ef10d..c6a483d54fc1 100644 --- a/app/client/src/PluginActionEditor/hooks/index.ts +++ b/app/client/src/PluginActionEditor/hooks/index.ts @@ -4,4 +4,3 @@ export { useHandleDuplicateClick } from "./useHandleDuplicateClick"; export { useHandleRunClick } from "ee/PluginActionEditor/hooks/useHandleRunClick"; export { useBlockExecution } from "ee/PluginActionEditor/hooks/useBlockExecution"; export { useAnalyticsOnRunClick } from "ee/PluginActionEditor/hooks/useAnalyticsOnRunClick"; -export { useHandleGenerateSchemaClick } from "ee/PluginActionEditor/hooks/useHandleGenerateSchemaClick"; diff --git a/app/client/src/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts b/app/client/src/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts deleted file mode 100644 index 2aea4c588884..000000000000 --- a/app/client/src/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { generatePluginActionSchema } from "actions/generateSchemaActions"; -import { usePluginActionContext } from "PluginActionEditor/PluginActionContext"; -import { useCallback } from "react"; -import { useDispatch } from "react-redux"; - -function useHandleGenerateSchemaClick() { - const { action } = usePluginActionContext(); - const dispatch = useDispatch(); - - const handleGenerateSchemaClick = useCallback(() => { - dispatch(generatePluginActionSchema(action?.id ?? "")); - }, [action?.id, dispatch]); - - return { handleGenerateSchemaClick }; -} - -export { useHandleGenerateSchemaClick }; diff --git a/app/client/src/actions/generateSchemaActions.ts b/app/client/src/actions/generateSchemaActions.ts deleted file mode 100644 index ce479e9744eb..000000000000 --- a/app/client/src/actions/generateSchemaActions.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; -import type { JSAction } from "entities/JSCollection"; - -export const generateJSFunctionSchema = (action: JSAction) => { - return { - type: ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_REQUEST, - payload: { - action, - }, - }; -}; - -export const generatePluginActionSchema = (id: string) => { - return { - type: ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_REQUEST, - payload: { id }, - }; -}; diff --git a/app/client/src/api/SchemaAPI.ts b/app/client/src/api/SchemaAPI.ts deleted file mode 100644 index 44044c7b356c..000000000000 --- a/app/client/src/api/SchemaAPI.ts +++ /dev/null @@ -1,17 +0,0 @@ -import API from "api/Api"; -import type { AxiosPromise } from "axios"; - -export interface GenerateSchemaResponse { - description: string; - schema: unknown; -} - -export class SchemaAPI extends API { - static url = "v1/actions"; - - static async generateSchema( - actionId: string, - ): Promise> { - return API.patch(`${SchemaAPI.url}/${actionId}/schema`); - } -} diff --git a/app/client/src/ce/sagas/index.tsx b/app/client/src/ce/sagas/index.tsx index 1c4dad9a333e..577711a4f01c 100644 --- a/app/client/src/ce/sagas/index.tsx +++ b/app/client/src/ce/sagas/index.tsx @@ -51,7 +51,6 @@ import communityTemplateSagas from "sagas/CommunityTemplatesSagas"; import anvilSagas from "layoutSystems/anvil/integrations/sagas"; import ideSagas from "sagas/IDESaga"; import sendSideBySideWidgetHoverAnalyticsEventSaga from "sagas/AnalyticsSaga"; -import { watchGenerateSchemaSaga } from "sagas/GenerateSchemaSaga"; import gitSagas from "git/sagas"; /* Sagas that are registered by a module that is designed to be independent of the core platform */ @@ -65,7 +64,6 @@ export const sagas = [ watchJSActionSagas, watchActionExecutionSagas, watchPluginActionExecutionSagas, - watchGenerateSchemaSaga, widgetOperationSagas, errorSagas, watchDatasourcesSagas, diff --git a/app/client/src/ee/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts b/app/client/src/ee/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts deleted file mode 100644 index 18eec4a97ae4..000000000000 --- a/app/client/src/ee/PluginActionEditor/hooks/useHandleGenerateSchemaClick.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "ce/PluginActionEditor/hooks/useHandleGenerateSchemaClick"; diff --git a/app/client/src/sagas/GenerateSchemaSaga.ts b/app/client/src/sagas/GenerateSchemaSaga.ts deleted file mode 100644 index fa1e8aa5987e..000000000000 --- a/app/client/src/sagas/GenerateSchemaSaga.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { toast } from "@appsmith/ads"; -import { createMessage } from "@appsmith/ads-old"; -import { CANNOT_GENERATE_SCHEMA } from "ee/constants/messages"; -import { - ReduxActionErrorTypes, - ReduxActionTypes, -} from "ee/constants/ReduxActionConstants"; -import { all, call, put, takeLatest } from "redux-saga/effects"; -import { updateFunctionProperty } from "../actions/jsPaneActions"; -import { updateActionProperty } from "../actions/pluginActionActions"; -import type { ReduxAction } from "../actions/ReduxActionTypes"; -import type { ApiResponse } from "../api/ApiResponses"; -import { SchemaAPI, type GenerateSchemaResponse } from "../api/SchemaAPI"; -import type { JSAction } from "../entities/JSCollection"; - -function* generatePluginActionSchemaSaga(action: ReduxAction<{ id: string }>) { - const { id } = action.payload; - - try { - const response: ApiResponse = yield call( - SchemaAPI.generateSchema, - id, - ); - - yield put( - updateActionProperty({ - id, - field: "schema", - value: response.data.schema, - }), - ); - yield put( - updateActionProperty({ - id, - field: "description", - value: response.data.description, - }), - ); - - yield put({ - type: ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_SUCCESS, - payload: { id }, - }); - } catch (error) { - yield put({ - type: ReduxActionErrorTypes.GENERATE_PLUGIN_ACTION_SCHEMA_ERROR, - payload: { id }, - }); - - toast.show(createMessage(CANNOT_GENERATE_SCHEMA), { - kind: "error", - }); - } -} - -function* generateJSFunctionSchemaSuccessSaga( - reduxAction: ReduxAction<{ action: JSAction }>, -) { - const { action } = reduxAction.payload; - - try { - const response: ApiResponse = yield call( - SchemaAPI.generateSchema, - action.id, - ); - - yield put( - updateFunctionProperty({ - action, - propertyName: "schema", - value: response.data.schema, - }), - ); - yield put( - updateFunctionProperty({ - action, - propertyName: "description", - value: response.data.description, - }), - ); - - yield put({ - type: ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_SUCCESS, - payload: { action }, - }); - } catch (error) { - yield put({ - type: ReduxActionErrorTypes.GENERATE_JS_FUNCTION_SCHEMA_ERROR, - payload: { action }, - }); - - toast.show(createMessage(CANNOT_GENERATE_SCHEMA), { - kind: "error", - }); - } -} - -export function* watchGenerateSchemaSaga() { - yield all([ - takeLatest( - ReduxActionTypes.GENERATE_PLUGIN_ACTION_SCHEMA_REQUEST, - generatePluginActionSchemaSaga, - ), - takeLatest( - ReduxActionTypes.GENERATE_JS_FUNCTION_SCHEMA_REQUEST, - generateJSFunctionSchemaSuccessSaga, - ), - ]); -} From c0b76039714bf64155c0d41c6f72cda881bcd968 Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Tue, 18 Mar 2025 15:08:38 +0530 Subject: [PATCH 7/7] chore: Split JS Editor Toolbar --- .../JSEditorToolbar/JSEditorToolbar.test.tsx | 3 -- .../JSEditorToolbar/JSEditorToolbar.tsx | 36 ++++++------------- .../JSEditorToolbar/JSEditorToolbar.tsx | 1 + app/client/src/pages/Editor/JSEditor/Form.tsx | 28 ++------------- .../components/JSFunctionGenerateSchema.tsx | 25 ------------- .../Editor/JSEditor/JSEditorToolbar/index.ts | 2 +- 6 files changed, 14 insertions(+), 81 deletions(-) rename app/client/src/{ => ce}/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.test.tsx (96%) rename app/client/src/{ => ce}/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx (68%) create mode 100644 app/client/src/ee/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx delete mode 100644 app/client/src/pages/Editor/JSEditor/JSEditorToolbar/components/JSFunctionGenerateSchema.tsx diff --git a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.test.tsx b/app/client/src/ce/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.test.tsx similarity index 96% rename from app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.test.tsx rename to app/client/src/ce/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.test.tsx index 04ffe7eb0fe9..dd8a655d2ed5 100644 --- a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.test.tsx +++ b/app/client/src/ce/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.test.tsx @@ -23,9 +23,6 @@ const defaultProps = { jsCollection: JSObject, onButtonClick: jest.fn(), onSelect: jest.fn(), - disableGenerateSchemaFunctionality: false, - isGeneratingSchema: false, - onGenerateSchemaButtonClick: jest.fn(), jsActions: JSObject.actions, selected: { label: "JSObject1.myFun1", diff --git a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx b/app/client/src/ce/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx similarity index 68% rename from app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx rename to app/client/src/ce/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx index 5dfedbd0e625..8357b14813b1 100644 --- a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx +++ b/app/client/src/ce/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar.tsx @@ -1,19 +1,18 @@ import React, { useState } from "react"; -import { useSelector } from "react-redux"; import { IDEToolbar, ToolbarSettingsPopover } from "IDE"; -import { JSFunctionRun } from "./components/JSFunctionRun"; -import type { JSActionDropdownOption, OnUpdateSettingsProps } from "./types"; +import { JSFunctionRun } from "pages/Editor/JSEditor/JSEditorToolbar/components/JSFunctionRun"; +import type { + JSActionDropdownOption, + OnUpdateSettingsProps, +} from "pages/Editor/JSEditor/JSEditorToolbar/types"; import type { SaveActionNameParams } from "PluginActionEditor"; import type { ReduxAction } from "actions/ReduxActionTypes"; import type { JSAction, JSCollection } from "entities/JSCollection"; import type { DropdownOnSelect } from "@appsmith/ads-old"; import { createMessage, JS_EDITOR_SETTINGS } from "ee/constants/messages"; -import { JSFunctionSettings } from "./components/JSFunctionSettings"; -import { convertJSActionsToDropdownOptions } from "./utils"; -import { JSObjectNameEditor } from "./JSObjectNameEditor"; -import { JSFunctionGenerateSchema } from "./components/JSFunctionGenerateSchema"; -import { Flex } from "@appsmith/ads"; -import { getIsAnvilLayoutEnabled } from "../../../../layoutSystems/anvil/integrations/selectors"; +import { JSFunctionSettings } from "pages/Editor/JSEditor/JSEditorToolbar/components/JSFunctionSettings"; +import { convertJSActionsToDropdownOptions } from "pages/Editor/JSEditor/JSEditorToolbar/utils"; +import { JSObjectNameEditor } from "pages/Editor/JSEditor/JSEditorToolbar/JSObjectNameEditor"; interface Props { changePermitted: boolean; @@ -24,17 +23,12 @@ interface Props { hideContextMenuOnEditor?: boolean; contextMenu: React.ReactNode; disableRunFunctionality: boolean; - disableGenerateSchemaFunctionality: boolean; executePermitted: boolean; loading: boolean; - isGeneratingSchema: boolean; jsCollection: JSCollection; onButtonClick: ( event: React.MouseEvent | KeyboardEvent, ) => void; - onGenerateSchemaButtonClick: ( - event: React.MouseEvent | KeyboardEvent, - ) => void; onSelect: DropdownOnSelect; jsActions: JSAction[]; selected: JSActionDropdownOption; @@ -51,7 +45,6 @@ interface Props { */ export const JSEditorToolbar = (props: Props) => { const [isOpen, setIsOpen] = useState(false); - const isAnvilEnabled = useSelector(getIsAnvilLayoutEnabled); // Render the IDEToolbar with JSFunctionRun and JSFunctionSettings components return ( @@ -65,7 +58,7 @@ export const JSEditorToolbar = (props: Props) => { )} - +
{ selected={props.selected} showTooltip={!props.selected.data} /> - {isAnvilEnabled && ( - - )} - +
{props.showSettings ? ( - getIsGeneratingSchema(state, currentJSCollection.id), - ); - const isJSCollectionSaving = useSelector((state: AppState) => - getIsJSCollectionSaving(state, currentJSCollection.id), - ); useEffect(() => { if (hash) { @@ -298,12 +287,6 @@ function JSEditorForm({ } }; - const handleGenerateSchemaButtonClick = async () => { - if (selectedJSActionOption.data?.id) { - dispatch(generateJSFunctionSchema(selectedJSActionOption.data)); - } - }; - useEffect(() => { if (parseErrors.length || isEmpty(jsActions)) { setDisableRunFunctionality(true); @@ -356,16 +339,10 @@ function JSEditorForm({ { handleRunAction(event, "JS_OBJECT_MAIN_RUN_BUTTON"); }} - onGenerateSchemaButtonClick={handleGenerateSchemaButtonClick} onSelect={handleJSActionOptionSelection} onUpdateSettings={onUpdateSettings} saveJSObjectName={saveJSObjectName} diff --git a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/components/JSFunctionGenerateSchema.tsx b/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/components/JSFunctionGenerateSchema.tsx deleted file mode 100644 index 9507f8de56e4..000000000000 --- a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/components/JSFunctionGenerateSchema.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from "react"; - -import { Button } from "@appsmith/ads"; -import { testLocators } from "../constants"; - -interface Props { - disabled: boolean; - isLoading: boolean; - onButtonClick: (event: React.MouseEvent) => void; -} - -export const JSFunctionGenerateSchema = (props: Props) => { - return ( - - ); -}; diff --git a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/index.ts b/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/index.ts index 88dc44b167cc..6ec1f8ded007 100644 --- a/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/index.ts +++ b/app/client/src/pages/Editor/JSEditor/JSEditorToolbar/index.ts @@ -1,4 +1,4 @@ -export { JSEditorToolbar } from "./JSEditorToolbar"; +export { JSEditorToolbar } from "ee/pages/Editor/JSEditor/JSEditorToolbar/JSEditorToolbar"; export { type OnUpdateSettingsProps,