diff --git a/.github/workflows/server-build.yml b/.github/workflows/server-build.yml index 35c1de30ec..273a67de21 100644 --- a/.github/workflows/server-build.yml +++ b/.github/workflows/server-build.yml @@ -158,7 +158,6 @@ jobs: APPSMITH_REDIS_URL: "redis://127.0.0.1:6379" APPSMITH_ENCRYPTION_PASSWORD: "password" APPSMITH_ENCRYPTION_SALT: "salt" - APPSMITH_IS_SELF_HOSTED: false APPSMITH_ENVFILE_PATH: /tmp/dummy.env APPSMITH_VERBOSE_LOGGING_ENABLED: false run: | @@ -179,7 +178,6 @@ jobs: APPSMITH_REDIS_URL: "redis://127.0.0.1:6379" APPSMITH_ENCRYPTION_PASSWORD: "password" APPSMITH_ENCRYPTION_SALT: "salt" - APPSMITH_IS_SELF_HOSTED: false APPSMITH_ENVFILE_PATH: /tmp/dummy.env APPSMITH_VERBOSE_LOGGING_ENABLED: false run: | diff --git a/app/client/packages/design-system/theming/src/token/src/defaultTokens.json b/app/client/packages/design-system/theming/src/token/src/defaultTokens.json index 331666bf89..5d7ad426f8 100644 --- a/app/client/packages/design-system/theming/src/token/src/defaultTokens.json +++ b/app/client/packages/design-system/theming/src/token/src/defaultTokens.json @@ -28,7 +28,7 @@ "userDensityRatio": 1.5 }, "innerSpacing": { - "minV": 2.25, + "minV": 1.5, "maxV": 3, "minR": 2, "maxR": 3, diff --git a/app/client/packages/design-system/widgets/src/components/TagGroup/src/styles.module.css b/app/client/packages/design-system/widgets/src/components/TagGroup/src/styles.module.css index 028cf1f4ac..511298f727 100644 --- a/app/client/packages/design-system/widgets/src/components/TagGroup/src/styles.module.css +++ b/app/client/packages/design-system/widgets/src/components/TagGroup/src/styles.module.css @@ -20,11 +20,11 @@ } .tag { - height: var(--sizing-6); + height: var(--sizing-5); color: var(--color-fg); background-color: var(--color-bg-neutral-subtle); border-radius: var(--border-radius-1); - padding: 0 var(--inner-spacing-2); + padding: 0 var(--inner-spacing-1); outline: none; cursor: default; display: flex; @@ -75,7 +75,7 @@ background: none; border: none; padding: 0; - margin-inline-start: var(--inner-spacing-1); + margin-inline-start: var(--inner-spacing-0); color: var(--color-fg); transition: color 200ms; outline: none; diff --git a/app/client/packages/design-system/widgets/src/styles/src/text-input.module.css b/app/client/packages/design-system/widgets/src/styles/src/text-input.module.css index c8afae1782..3c6e588840 100644 --- a/app/client/packages/design-system/widgets/src/styles/src/text-input.module.css +++ b/app/client/packages/design-system/widgets/src/styles/src/text-input.module.css @@ -111,11 +111,11 @@ * START ICON AND END ICON *----------------------------------------------------------------------------- */ - & [data-field-input-start-icon] { + & [data-field-input-start-icon] div { width: max-content; } - & [data-field-input-end-icon] { + & [data-field-input-end-icon] div { width: max-content; } } diff --git a/app/client/src/api/ActionAPI.tsx b/app/client/src/api/ActionAPI.tsx index da36735c7d..ac4ca07dc8 100644 --- a/app/client/src/api/ActionAPI.tsx +++ b/app/client/src/api/ActionAPI.tsx @@ -10,6 +10,7 @@ import type { WidgetType } from "constants/WidgetConstants"; import { omit } from "lodash"; import type { OtlpSpan } from "UITelemetry/generateTraces"; import { wrapFnWithParentTraceContext } from "UITelemetry/generateTraces"; +import type { ActionContextTypeInterface } from "@appsmith/entities/Engine/actionHelpers"; export interface CreateActionRequest extends APIRequest { datasourceId: string; @@ -141,11 +142,13 @@ export interface CopyActionRequest { } export interface UpdateActionNameRequest { - pageId: string; + pageId?: string; actionId: string; - layoutId: string; + layoutId?: string; newName: string; oldName: string; + moduleId?: string; + contextType?: ActionContextTypeInterface; } export interface FetchActionsPayload { diff --git a/app/client/src/ce/actions/helpers.ts b/app/client/src/ce/actions/helpers.ts index 3a2f800cdc..ed6504125b 100644 --- a/app/client/src/ce/actions/helpers.ts +++ b/app/client/src/ce/actions/helpers.ts @@ -5,6 +5,8 @@ import { } from "actions/apiPaneActions"; import { createNewJSCollection } from "actions/jsPaneActions"; import { ACTION_PARENT_ENTITY_TYPE } from "@appsmith/entities/Engine/actionHelpers"; +import { saveActionName } from "actions/pluginActionActions"; +import { saveJSObjectName } from "actions/jsActionActions"; export const createNewQueryBasedOnParentEntity = ( entityId: string, @@ -37,3 +39,23 @@ export const createNewJSCollectionBasedOnParentEntity = ( ) => { return createNewJSCollection(entityId, from); }; + +export const saveActionNameBasedOnParentEntity = ( + id: string, + name: string, + // Used in EE + // eslint-disable-next-line @typescript-eslint/no-unused-vars + parentEntityType = ACTION_PARENT_ENTITY_TYPE.PAGE, +) => { + return saveActionName({ id, name }); +}; + +export const saveJSObjectNameBasedOnParentEntity = ( + id: string, + name: string, + // Used in EE + // eslint-disable-next-line @typescript-eslint/no-unused-vars + parentEntityType = ACTION_PARENT_ENTITY_TYPE.PAGE, +) => { + return saveJSObjectName({ id, name }); +}; diff --git a/app/client/src/ce/api/JSActionAPI.tsx b/app/client/src/ce/api/JSActionAPI.tsx index 85a46b7740..d4951c24ed 100644 --- a/app/client/src/ce/api/JSActionAPI.tsx +++ b/app/client/src/ce/api/JSActionAPI.tsx @@ -5,7 +5,7 @@ import type { ApiResponse } from "api/ApiResponses"; import type { Variable, JSAction } from "entities/JSCollection"; import type { PluginType } from "entities/Action"; import type { FetchActionsPayload } from "api/ActionAPI"; -import type { ActionContextType } from "@appsmith/entities/DataTree/types"; +import type { ActionContextTypeInterface } from "@appsmith/entities/Engine/actionHelpers"; export type JSCollectionCreateUpdateResponse = ApiResponse & { id: string; @@ -17,11 +17,13 @@ export interface MoveJSCollectionRequest { name: string; } export interface UpdateJSObjectNameRequest { - pageId: string; + pageId?: string; actionCollectionId: string; - layoutId: string; + layoutId?: string; newName: string; oldName: string; + moduleId?: string; + contextType?: ActionContextTypeInterface; } export interface CreateJSCollectionRequest { @@ -35,7 +37,8 @@ export interface CreateJSCollectionRequest { applicationId: string; pluginType: PluginType; workflowId?: string; - contextType?: ActionContextType; + contextType?: ActionContextTypeInterface; + moduleId?: string; } export interface SetFunctionPropertyPayload { diff --git a/app/client/src/constants/routes/appRoutes.ts b/app/client/src/ce/constants/routes/appRoutes.ts similarity index 98% rename from app/client/src/constants/routes/appRoutes.ts rename to app/client/src/ce/constants/routes/appRoutes.ts index 36d74c39e8..855fe741a5 100644 --- a/app/client/src/constants/routes/appRoutes.ts +++ b/app/client/src/ce/constants/routes/appRoutes.ts @@ -152,3 +152,5 @@ export const PLACEHOLDER_PAGE_SLUG = "page"; export const SHOW_FILE_PICKER_KEY = "showPicker"; export const RESPONSE_STATUS = "response_status"; + +export const basePathForActiveAction = [BUILDER_PATH, BUILDER_PATH_DEPRECATED]; diff --git a/app/client/src/ce/entities/DataTree/types.ts b/app/client/src/ce/entities/DataTree/types.ts index f145075ee6..7dcd60f015 100644 --- a/app/client/src/ce/entities/DataTree/types.ts +++ b/app/client/src/ce/entities/DataTree/types.ts @@ -22,14 +22,6 @@ import type { ModuleInstance } from "@appsmith/constants/ModuleInstanceConstants export type ActionDispatcher = (...args: any[]) => ActionDescription; -export enum CreateNewActionKey { - PAGE = "pageId", -} - -export enum ActionContextType { - PAGE = "PAGE", -} - export const ENTITY_TYPE = { ACTION: "ACTION", WIDGET: "WIDGET", diff --git a/app/client/src/ce/entities/Engine/actionHelpers.ts b/app/client/src/ce/entities/Engine/actionHelpers.ts index d236a81411..53b7cb2487 100644 --- a/app/client/src/ce/entities/Engine/actionHelpers.ts +++ b/app/client/src/ce/entities/Engine/actionHelpers.ts @@ -8,9 +8,17 @@ import { fetchDatasources } from "actions/datasourceActions"; import { fetchPageDSLs } from "actions/pageActions"; import { fetchPlugins } from "actions/pluginActions"; -export enum ACTION_PARENT_ENTITY_TYPE { - PAGE = "PAGE", -} +export const CreateNewActionKey = { + PAGE: "pageId", +} as const; + +export const ActionContextType = { + PAGE: "PAGE", +} as const; + +export const ACTION_PARENT_ENTITY_TYPE = { + PAGE: "PAGE", +} as const; export const getPageDependencyActions = ( currentWorkspaceId: string = "", diff --git a/app/client/src/ce/pages/Editor/Explorer/hooks.ts b/app/client/src/ce/pages/Editor/Explorer/hooks.ts index 689a70f8e1..05a2374b38 100644 --- a/app/client/src/ce/pages/Editor/Explorer/hooks.ts +++ b/app/client/src/ce/pages/Editor/Explorer/hooks.ts @@ -16,13 +16,12 @@ import type { ActionData } from "@appsmith/reducers/entityReducers/actionsReduce import { matchPath, useLocation } from "react-router"; import { API_EDITOR_ID_PATH, - BUILDER_PATH, - BUILDER_PATH_DEPRECATED, JS_COLLECTION_ID_PATH, QUERIES_EDITOR_ID_PATH, } from "constants/routes"; import { SAAS_EDITOR_API_ID_PATH } from "pages/Editor/SaaSEditor/constants"; import { TEMP_DATASOURCE_ID } from "constants/Datasource"; +import { basePathForActiveAction } from "@appsmith/constants/routes/appRoutes"; const findWidgets = (widgets: CanvasStructure, keyword: string) => { if (!widgets || !widgets.widgetName) return widgets; @@ -266,9 +265,10 @@ export const useEntityEditState = (entityId: string) => { export function useActiveAction() { const location = useLocation(); + const path = basePathForActiveAction; const baseMatch = matchPath<{ apiId: string }>(location.pathname, { - path: [BUILDER_PATH, BUILDER_PATH_DEPRECATED], + path, strict: false, exact: false, }); diff --git a/app/client/src/ce/reducers/entityReducers/jsActionsReducer.tsx b/app/client/src/ce/reducers/entityReducers/jsActionsReducer.tsx index acf38d450c..27df84526a 100644 --- a/app/client/src/ce/reducers/entityReducers/jsActionsReducer.tsx +++ b/app/client/src/ce/reducers/entityReducers/jsActionsReducer.tsx @@ -91,7 +91,14 @@ export const handlers = { return { ...jsCollection, isLoading: false, - config: action.payload.data, + config: action.payload.data.isPublic + ? { + ...action.payload.data, + isMainJSCollection: true, + displayName: "Main", + hideContextMenu: true, + } + : action.payload.data, activeJSActionId: findIndex(jsCollection.config.actions, { id: jsCollection.activeJSActionId, diff --git a/app/client/src/components/editorComponents/ActionRightPane/index.tsx b/app/client/src/components/editorComponents/ActionRightPane/index.tsx index fe641b9c84..3758d2ee70 100644 --- a/app/client/src/components/editorComponents/ActionRightPane/index.tsx +++ b/app/client/src/components/editorComponents/ActionRightPane/index.tsx @@ -22,10 +22,7 @@ import type { } from "api/ActionAPI"; import { getPagePermissions } from "selectors/editorSelectors"; import DatasourceStructureHeader from "pages/Editor/DatasourceInfo/DatasourceStructureHeader"; -import { - DatasourceStructureContainer as DataStructureList, - SCHEMALESS_PLUGINS, -} from "pages/Editor/DatasourceInfo/DatasourceStructureContainer"; +import { DatasourceStructureContainer as DataStructureList } from "pages/Editor/DatasourceInfo/DatasourceStructureContainer"; import { getDatasourceStructureById, getIsFetchingDatasourceStructure, @@ -171,6 +168,8 @@ function ActionSidebar({ hasConnections, hasResponse, pluginId, + showSchema, + showSuggestedWidgets = true, suggestedWidgets, }: { actionName: string; @@ -182,6 +181,8 @@ function ActionSidebar({ context: DatasourceStructureContext; additionalSections?: React.ReactNode; actionRightPaneBackLink: React.ReactNode; + showSuggestedWidgets?: boolean; + showSchema: boolean; }) { const dispatch = useDispatch(); const widgets = useSelector(getWidgets); @@ -267,10 +268,6 @@ function ActionSidebar({ }); }; - const showSchema = - pluginDatasourceForm !== DatasourceComponentTypes.RestAPIDatasourceForm && - !SCHEMALESS_PLUGINS.includes(pluginName); - useEffect(() => { if (showSchema) { checkAndShowWalkthrough(); @@ -286,13 +283,13 @@ function ActionSidebar({ pagePermissions, ); - const showSuggestedWidgets = + const suggestedWidgetsEnabled = canEditPage && hasResponse && suggestedWidgets && !!suggestedWidgets.length; const showSnipingMode = hasResponse && hasWidgets; if ( !hasConnections && - !showSuggestedWidgets && + !suggestedWidgetsEnabled && !showSnipingMode && // putting this here to make the placeholder only appear for rest APIs. pluginDatasourceForm === DatasourceComponentTypes.RestAPIDatasourceForm @@ -300,53 +297,59 @@ function ActionSidebar({ return {createMessage(NO_CONNECTIONS)}; } + if (!additionalSections && !showSchema && !showSuggestedWidgets) { + return null; + } + return ( {actionRightPaneBackLink} {additionalSections && ( - <> - - {additionalSections} - - - + + {additionalSections} + )} {showSchema && ( - - + {additionalSections && } + - - - - - + + + + + + + )} - {showSchema && } - {showSuggestedWidgets ? ( + {showSuggestedWidgets && showSchema && } + {showSuggestedWidgets && suggestedWidgetsEnabled && ( - ) : ( + )} + {showSuggestedWidgets && !suggestedWidgetsEnabled && ( + getPluginDatasourceComponentFromId(state, pluginId), + ); + + const pluginName = useSelector((state) => + getPluginNameFromId(state, pluginId), + ); + + return ( + pluginDatasourceForm !== DatasourceComponentTypes.RestAPIDatasourceForm && + !SCHEMALESS_PLUGINS.includes(pluginName) + ); +} + +export default useShowSchema; diff --git a/app/client/src/constants/routes/index.ts b/app/client/src/constants/routes/index.ts index 0728b7b067..bd7bef5030 100644 --- a/app/client/src/constants/routes/index.ts +++ b/app/client/src/constants/routes/index.ts @@ -1,2 +1,2 @@ export * from "./baseRoutes"; -export * from "./appRoutes"; +export * from "@appsmith/constants/routes/appRoutes"; diff --git a/app/client/src/ee/constants/routes/appRoutes.ts b/app/client/src/ee/constants/routes/appRoutes.ts new file mode 100644 index 0000000000..6fc5b6ffb8 --- /dev/null +++ b/app/client/src/ee/constants/routes/appRoutes.ts @@ -0,0 +1 @@ +export * from "ce/constants/routes/appRoutes"; diff --git a/app/client/src/ee/entities/Engine/actionHelpers.ts b/app/client/src/ee/entities/Engine/actionHelpers.ts index 580a3b24fa..d4a115f6b3 100644 --- a/app/client/src/ee/entities/Engine/actionHelpers.ts +++ b/app/client/src/ee/entities/Engine/actionHelpers.ts @@ -1,6 +1,16 @@ export * from "ce/entities/Engine/actionHelpers"; +import type { + ActionContextType, + CreateNewActionKey, +} from "ce/entities/Engine/actionHelpers"; import { ACTION_PARENT_ENTITY_TYPE as CE_ACTION_PARENT_ENTITY_TYPE } from "ce/entities/Engine/actionHelpers"; +export type CreateNewActionKeyInterface = + (typeof CreateNewActionKey)[keyof typeof CreateNewActionKey]; + +export type ActionContextTypeInterface = + (typeof ActionContextType)[keyof typeof ActionContextType]; + export const ACTION_PARENT_ENTITY_TYPE = { ...CE_ACTION_PARENT_ENTITY_TYPE, }; diff --git a/app/client/src/entities/Action/index.ts b/app/client/src/entities/Action/index.ts index a0dd33983c..de1fbf7094 100644 --- a/app/client/src/entities/Action/index.ts +++ b/app/client/src/entities/Action/index.ts @@ -5,7 +5,7 @@ import type { LayoutOnLoadActionErrors } from "constants/AppsmithActionConstants import type { Plugin } from "api/PluginApi"; import type { AutoGeneratedHeader } from "pages/Editor/APIEditor/helpers"; import type { EventLocation } from "@appsmith/utils/analyticsUtilTypes"; -import type { ActionContextType } from "@appsmith/entities/DataTree/types"; +import type { ActionContextTypeInterface } from "@appsmith/entities/Engine/actionHelpers"; export enum PluginType { API = "API", @@ -163,7 +163,7 @@ export interface BaseAction { moduleId?: string; moduleInstanceId?: string; workflowId?: string; - contextType?: ActionContextType; + contextType?: ActionContextTypeInterface; // This is used to identify the main js collection of a workflow // added here to avoid ts error in entitiesSelector file, in practice // will always be undefined for non js actions diff --git a/app/client/src/entities/JSCollection/index.ts b/app/client/src/entities/JSCollection/index.ts index 11e2089096..93cafe915a 100644 --- a/app/client/src/entities/JSCollection/index.ts +++ b/app/client/src/entities/JSCollection/index.ts @@ -1,7 +1,7 @@ import type { BaseAction } from "../Action"; import type { PluginType } from "entities/Action"; import type { LayoutOnLoadActionErrors } from "constants/AppsmithActionConstants/ActionConstants"; -import type { ActionContextType } from "@appsmith/entities/DataTree/types"; +import type { ActionContextTypeInterface } from "@appsmith/entities/Engine/actionHelpers"; export interface Variable { name: string; @@ -24,11 +24,15 @@ export interface JSCollection { moduleId?: string; moduleInstanceId?: string; workflowId?: string; - contextType?: ActionContextType; + contextType?: ActionContextTypeInterface; // This is used to identify the main js collection of a workflow // main js collection is the entrypoint for a workflow // cannot be deleted or renamed isMainJSCollection?: boolean; + displayName?: string; + hideEditIconOnEditor?: boolean; + hideContextMenu?: boolean; + hideContextMenuOnEditor?: boolean; } export interface JSActionConfig { diff --git a/app/client/src/pages/Editor/APIEditor/ApiRightPane.tsx b/app/client/src/pages/Editor/APIEditor/ApiRightPane.tsx index c698676482..2bad629176 100644 --- a/app/client/src/pages/Editor/APIEditor/ApiRightPane.tsx +++ b/app/client/src/pages/Editor/APIEditor/ApiRightPane.tsx @@ -20,6 +20,7 @@ import { DatasourceStructureContext } from "entities/Datasource"; import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; import type { SuggestedWidget } from "api/ActionAPI"; +import useShowSchema from "components/editorComponents/ActionRightPane/useShowSchema"; interface ApiRightPaneProps { additionalSections?: React.ReactNode; @@ -142,7 +143,7 @@ const DataSourceNameContainer = styled.div` } `; -const SomeWrapper = styled.div` +const ActionRightPaneWrapper = styled.div` height: 100%; padding: 0 var(--ads-v2-spaces-4); `; @@ -209,6 +210,8 @@ function ApiRightPane(props: ApiRightPaneProps) { const selectedTab = useSelector(getApiRightPaneSelectedTab); const currentEnvironmentId = useSelector(getCurrentEnvironmentId); + const showSchema = useShowSchema(props.pluginId); + const setSelectedTab = useCallback((selectedIndex: string) => { dispatch(setApiRightPaneSelectedTab(selectedIndex)); }, []); @@ -230,6 +233,8 @@ function ApiRightPane(props: ApiRightPaneProps) { [props.datasources, props.currentActionDatasourceId], ); + if (!props.additionalSections && !props.showTabbedSection) return null; + return ( @@ -334,7 +339,7 @@ function ApiRightPane(props: ApiRightPaneProps) { )} - + - + )} diff --git a/app/client/src/pages/Editor/Explorer/Actions/ActionEntity.tsx b/app/client/src/pages/Editor/Explorer/Actions/ActionEntity.tsx index 12b67f85f0..f869d2074c 100644 --- a/app/client/src/pages/Editor/Explorer/Actions/ActionEntity.tsx +++ b/app/client/src/pages/Editor/Explorer/Actions/ActionEntity.tsx @@ -3,7 +3,6 @@ import { useSelector } from "react-redux"; import Entity, { EntityClassNames } from "../Entity"; import ActionEntityContextMenu from "./ActionEntityContextMenu"; import history, { NavigationMethod } from "utils/history"; -import { saveActionName } from "actions/pluginActionActions"; import PerformanceTracker, { PerformanceTransactionName, } from "utils/PerformanceTracker"; @@ -25,9 +24,15 @@ import { } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers"; import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag"; +import { saveActionNameBasedOnParentEntity } from "@appsmith/actions/helpers"; +import type { ActionParentEntityTypeInterface } from "@appsmith/entities/Engine/actionHelpers"; -const getUpdateActionNameReduxAction = (id: string, name: string) => { - return saveActionName({ id, name }); +const getUpdateActionNameReduxAction = ( + id: string, + name: string, + parentEntityType: ActionParentEntityTypeInterface, +) => { + return saveActionNameBasedOnParentEntity(id, name, parentEntityType); }; interface ExplorerActionEntityProps { @@ -37,6 +42,7 @@ interface ExplorerActionEntityProps { type: PluginType; isActive: boolean; parentEntityId: string; + parentEntityType: ActionParentEntityTypeInterface; } export const ExplorerActionEntity = memo((props: ExplorerActionEntityProps) => { @@ -113,7 +119,9 @@ export const ExplorerActionEntity = memo((props: ExplorerActionEntityProps) => { name={action.name} searchKeyword={props.searchKeyword} step={props.step} - updateEntityName={getUpdateActionNameReduxAction} + updateEntityName={(id, name) => + getUpdateActionNameReduxAction(id, name, props.parentEntityType) + } /> ); }); diff --git a/app/client/src/pages/Editor/Explorer/Datasources/DatasourceStarterLayoutPrompt.tsx b/app/client/src/pages/Editor/Explorer/Datasources/DatasourceStarterLayoutPrompt.tsx index 8fbcc9a1ea..9d5adb7ad5 100644 --- a/app/client/src/pages/Editor/Explorer/Datasources/DatasourceStarterLayoutPrompt.tsx +++ b/app/client/src/pages/Editor/Explorer/Datasources/DatasourceStarterLayoutPrompt.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from "react"; +import React, { useCallback, useMemo } from "react"; import { Popover, PopoverContent, @@ -32,6 +32,7 @@ import { INTEGRATION_TABS } from "constants/routes"; import { Colors } from "constants/Colors"; import AnalyticsUtil from "utils/AnalyticsUtil"; import { STARTER_BUILDING_BLOCK_TEMPLATE_NAME } from "constants/TemplatesConstants"; +import { useAppWideAndOtherDatasource } from "@appsmith/pages/Editor/Explorer/hooks"; function DatasourceStarterLayoutPrompt() { const dispatch = useDispatch(); @@ -45,12 +46,21 @@ function DatasourceStarterLayoutPrompt() { const buildingBlockSourcePageId = useSelector( buildingBlocksSourcePageIdSelector, ); + const { appWideDS } = useAppWideAndOtherDatasource(); const disablePrompt = () => dispatch(hideStarterBuildingBlockDatasourcePrompt()); - const showActivePageDatasourcePrompt = - buildingBlockSourcePageId === pageId && showDatasourcePrompt; + const showActivePageDatasourcePrompt = useMemo( + () => + buildingBlockSourcePageId === pageId && + showDatasourcePrompt && + // Here we are checking, if user already has some datasources added to the application + // in few cases user go through "start with data" and then "forks a starter building block from canvas" + // this condition prevents showing the popup if datasource is already connected. + appWideDS.length === 1, + [buildingBlockSourcePageId, pageId, showDatasourcePrompt, appWideDS], + ); const onClickConnect = useCallback(() => { dispatch(hideStarterBuildingBlockDatasourcePrompt()); diff --git a/app/client/src/pages/Editor/Explorer/Files/FilesContextProvider.tsx b/app/client/src/pages/Editor/Explorer/Files/FilesContextProvider.tsx index 89ed194eb8..60c23fc3ae 100644 --- a/app/client/src/pages/Editor/Explorer/Files/FilesContextProvider.tsx +++ b/app/client/src/pages/Editor/Explorer/Files/FilesContextProvider.tsx @@ -1,6 +1,5 @@ import React, { createContext, useMemo } from "react"; import type { ActionParentEntityTypeInterface } from "@appsmith/entities/Engine/actionHelpers"; -import { ACTION_PARENT_ENTITY_TYPE } from "@appsmith/entities/Engine/actionHelpers"; export enum ActionEntityContextMenuItemsEnum { EDIT_NAME = "Edit Name", @@ -10,9 +9,18 @@ export enum ActionEntityContextMenuItemsEnum { DELETE = "Delete", } +export const defaultMenuItems = [ + ActionEntityContextMenuItemsEnum.EDIT_NAME, + ActionEntityContextMenuItemsEnum.DELETE, + ActionEntityContextMenuItemsEnum.SHOW_BINDING, + ActionEntityContextMenuItemsEnum.COPY, + ActionEntityContextMenuItemsEnum.MOVE, +]; + interface FilesContextContextProps { canCreateActions: boolean; editorId: string; // applicationId, workflowId or packageId + menuItems?: ActionEntityContextMenuItemsEnum[]; parentEntityId: string; // page, workflow or module parentEntityType: ActionParentEntityTypeInterface; showModules?: boolean; @@ -36,33 +44,19 @@ export const FilesContextProvider = ({ canCreateActions, children, editorId, + menuItems, parentEntityId, parentEntityType, selectFilesForExplorer, showModules, }: FilesContextProviderProps) => { - const menuItems = useMemo(() => { - const items = [ - ActionEntityContextMenuItemsEnum.EDIT_NAME, - ActionEntityContextMenuItemsEnum.DELETE, - ]; - if (parentEntityType === ACTION_PARENT_ENTITY_TYPE.PAGE) { - items.push( - ActionEntityContextMenuItemsEnum.SHOW_BINDING, - ActionEntityContextMenuItemsEnum.COPY, - ActionEntityContextMenuItemsEnum.MOVE, - ); - } - return items; - }, [parentEntityType]); - const value = useMemo(() => { return { canCreateActions, editorId, parentEntityId, parentEntityType, - menuItems, + menuItems: menuItems || defaultMenuItems, selectFilesForExplorer, showModules, }; @@ -70,6 +64,7 @@ export const FilesContextProvider = ({ canCreateActions, parentEntityId, parentEntityType, + menuItems, showModules, selectFilesForExplorer, editorId, diff --git a/app/client/src/pages/Editor/Explorer/Files/index.tsx b/app/client/src/pages/Editor/Explorer/Files/index.tsx index bcaea6af0e..fc2f8334b0 100644 --- a/app/client/src/pages/Editor/Explorer/Files/index.tsx +++ b/app/client/src/pages/Editor/Explorer/Files/index.tsx @@ -117,6 +117,7 @@ function Files() { isActive={entity.id === activeActionId} key={entity.id} parentEntityId={parentEntityId} + parentEntityType={parentEntityType} searchKeyword={""} step={2} type={type} @@ -129,6 +130,7 @@ function Files() { isActive={entity.id === activeActionId} key={entity.id} parentEntityId={parentEntityId} + parentEntityType={parentEntityType} searchKeyword={""} step={2} type={type} diff --git a/app/client/src/pages/Editor/Explorer/JSActions/JSActionContextMenu.tsx b/app/client/src/pages/Editor/Explorer/JSActions/JSActionContextMenu.tsx index 2d0b258a17..d531997f04 100644 --- a/app/client/src/pages/Editor/Explorer/JSActions/JSActionContextMenu.tsx +++ b/app/client/src/pages/Editor/Explorer/JSActions/JSActionContextMenu.tsx @@ -35,7 +35,7 @@ interface EntityContextMenuProps { className?: string; canManage: boolean; canDelete: boolean; - showMenuItems: boolean; + hideMenuItems: boolean; } export function JSCollectionEntityContextMenu(props: EntityContextMenuProps) { // Import the context @@ -164,7 +164,7 @@ export function JSCollectionEntityContextMenu(props: EntityContextMenuProps) { }, ].filter(Boolean); - return !props.showMenuItems && optionsTree.length > 0 ? ( + return !props.hideMenuItems && optionsTree.length > 0 ? ( { - return saveJSObjectName({ id, name }); +const getUpdateJSObjectName = ( + id: string, + name: string, + parentEntityType: ActionParentEntityTypeInterface, +) => { + return saveJSObjectNameBasedOnParentEntity(id, name, parentEntityType); }; export const ExplorerJSCollectionEntity = memo( @@ -39,7 +44,7 @@ export const ExplorerJSCollectionEntity = memo( getJSCollection(state, props.id), ) as JSCollection; const location = useLocation(); - const { parentEntityId } = props; + const { parentEntityId, parentEntityType } = props; const navigateToUrl = jsCollectionIdURL({ parentEntityId, collectionId: jsAction.id, @@ -78,27 +83,27 @@ export const ExplorerJSCollectionEntity = memo( canDelete={canDeleteJSAction} canManage={canManageJSAction} className={EntityClassNames.CONTEXT_MENU} + hideMenuItems={jsAction?.hideContextMenu || false} id={jsAction.id} name={jsAction.name} - showMenuItems={jsAction?.isMainJSCollection || false} /> ); return ( } + name={jsAction?.displayName || jsAction.name} searchKeyword={props.searchKeyword} step={props.step} - updateEntityName={getUpdateJSObjectName} + updateEntityName={(id, name) => + getUpdateJSObjectName(id, name, parentEntityType) + } /> ); }, diff --git a/app/client/src/pages/Editor/IDE/PagesPane/JS_Section.tsx b/app/client/src/pages/Editor/IDE/PagesPane/JS_Section.tsx index ea9cc8486e..96fa5d4f12 100644 --- a/app/client/src/pages/Editor/IDE/PagesPane/JS_Section.tsx +++ b/app/client/src/pages/Editor/IDE/PagesPane/JS_Section.tsx @@ -86,6 +86,7 @@ const JSSection = () => { isActive={JSobject.id === activeActionId} key={JSobject.id} parentEntityId={pageId} + parentEntityType={ACTION_PARENT_ENTITY_TYPE.PAGE} searchKeyword={""} step={2} type={JSobject.type as PluginType} diff --git a/app/client/src/pages/Editor/IDE/PagesPane/ListQuery.tsx b/app/client/src/pages/Editor/IDE/PagesPane/ListQuery.tsx index 8ccc010455..e36f2556ce 100644 --- a/app/client/src/pages/Editor/IDE/PagesPane/ListQuery.tsx +++ b/app/client/src/pages/Editor/IDE/PagesPane/ListQuery.tsx @@ -80,6 +80,7 @@ const ListQuery = () => { isActive={file.id === activeActionId} key={file.id} parentEntityId={pageId} + parentEntityType={ACTION_PARENT_ENTITY_TYPE.PAGE} searchKeyword={""} step={1} type={file.type} diff --git a/app/client/src/pages/Editor/JSEditor/Form.tsx b/app/client/src/pages/Editor/JSEditor/Form.tsx index 631166c0ee..8135f62b78 100644 --- a/app/client/src/pages/Editor/JSEditor/Form.tsx +++ b/app/client/src/pages/Editor/JSEditor/Form.tsx @@ -321,13 +321,14 @@ function JSEditorForm({ - {!currentJSCollection.isMainJSCollection && contextMenu} + {!currentJSCollection.hideContextMenuOnEditor && contextMenu} (); @@ -365,6 +367,13 @@ export function EditorJSONtoForm(props: Props) { userWorkspacePermissions, ); + const showSchema = useShowSchema(currentActionConfig?.pluginId || ""); + + const showRightPane = + showSchema || + showSuggestedWidgets || + Boolean(actionRightPaneAdditionSections); + // get the current action's plugin name const currentActionPluginName = useSelector((state: AppState) => getPluginNameFromId(state, currentActionConfig?.pluginId || ""), @@ -783,19 +792,23 @@ export function EditorJSONtoForm(props: Props) { )} - - - + {showRightPane && ( + + + + )} diff --git a/app/client/src/pages/Editor/QueryEditor/QueryEditorContext.tsx b/app/client/src/pages/Editor/QueryEditor/QueryEditorContext.tsx index f4ddbef98b..f5e4a990d2 100644 --- a/app/client/src/pages/Editor/QueryEditor/QueryEditorContext.tsx +++ b/app/client/src/pages/Editor/QueryEditor/QueryEditorContext.tsx @@ -17,6 +17,7 @@ interface QueryEditorContextContextProps { ) => ReduxAction; closeEditorLink?: React.ReactNode; actionRightPaneAdditionSections?: React.ReactNode; + showSuggestedWidgets?: boolean; } type QueryEditorContextProviderProps = @@ -36,6 +37,7 @@ export function QueryEditorContextProvider({ onCreateDatasourceClick, onEntityNotFoundBackClick, saveActionName, + showSuggestedWidgets, }: QueryEditorContextProviderProps) { const value = useMemo( () => ({ @@ -47,6 +49,7 @@ export function QueryEditorContextProvider({ onCreateDatasourceClick, onEntityNotFoundBackClick, saveActionName, + showSuggestedWidgets, }), [ actionRightPaneBackLink, @@ -57,6 +60,7 @@ export function QueryEditorContextProvider({ onCreateDatasourceClick, onEntityNotFoundBackClick, saveActionName, + showSuggestedWidgets, ], ); diff --git a/app/client/src/utils/AppsmithUtils.tsx b/app/client/src/utils/AppsmithUtils.tsx index 889271864e..9e3d2cd2c8 100644 --- a/app/client/src/utils/AppsmithUtils.tsx +++ b/app/client/src/utils/AppsmithUtils.tsx @@ -11,7 +11,8 @@ import { osName } from "react-device-detect"; import type { ActionDataState } from "@appsmith/reducers/entityReducers/actionsReducer"; import type { JSCollectionData } from "@appsmith/reducers/entityReducers/jsActionsReducer"; import AnalyticsUtil from "./AnalyticsUtil"; -import { CreateNewActionKey } from "@appsmith/entities/DataTree/types"; +import type { CreateNewActionKeyInterface } from "@appsmith/entities/Engine/actionHelpers"; +import { CreateNewActionKey } from "@appsmith/entities/Engine/actionHelpers"; export const initializeAnalyticsAndTrackers = async () => { const appsmithConfigs = getAppsmithConfigs(); @@ -198,10 +199,10 @@ export const getDuplicateName = (prefix: string, existingNames: string[]) => { export const createNewApiName = ( actions: ActionDataState, entityId: string, - key: CreateNewActionKey = CreateNewActionKey.PAGE, + key: CreateNewActionKeyInterface = CreateNewActionKey.PAGE, ) => { const pageApiNames = actions - .filter((a) => a.config[key] === entityId) + .filter((a: any) => a.config[key] === entityId) .map((a) => a.config.name); return getNextEntityName("Api", pageApiNames); }; @@ -209,10 +210,10 @@ export const createNewApiName = ( export const createNewJSFunctionName = ( jsActions: JSCollectionData[], entityId: string, - key: CreateNewActionKey = CreateNewActionKey.PAGE, + key: CreateNewActionKeyInterface = CreateNewActionKey.PAGE, ) => { const pageJsFunctionNames = jsActions - .filter((a) => a.config[key] === entityId) + .filter((a: any) => a.config[key] === entityId) .map((a) => a.config.name); return getNextEntityName("JSObject", pageJsFunctionNames); }; @@ -229,10 +230,10 @@ export const createNewQueryName = ( queries: ActionDataState, entityId: string, prefix = "Query", - key: CreateNewActionKey = CreateNewActionKey.PAGE, + key: CreateNewActionKeyInterface = CreateNewActionKey.PAGE, ) => { const pageApiNames = queries - .filter((a) => a.config[key] === entityId) + .filter((a: any) => a.config[key] === entityId) .map((a) => a.config.name); return getNextEntityName(prefix, pageApiNames); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java index 4d88a4a237..62b11f594e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog2.java @@ -2412,8 +2412,9 @@ public class DatabaseChangelog2 { return; } - @ChangeSet(order = "031", id = "create-system-themes-v3", author = "", runAlways = true) - public void createSystemThemes3(MongoTemplate mongoTemplate) throws IOException { + @ChangeSet(order = "031", id = "create-themes-indices", author = "") + public void createThemesIndices(MongoTemplate mongoTemplate) { + Index systemThemeIndex = new Index() .on(fieldName(QTheme.theme.isSystemTheme), Sort.Direction.ASC) .named("system_theme_index") @@ -2428,6 +2429,11 @@ public class DatabaseChangelog2 { dropIndexIfExists(mongoTemplate, Theme.class, "system_theme_index"); dropIndexIfExists(mongoTemplate, Theme.class, "application_id_index"); ensureIndexes(mongoTemplate, Theme.class, systemThemeIndex, applicationIdIndex); + } + + // The order 031-a is ensured to run after 031, as theme indices might be a requirement. + @ChangeSet(order = "031-a", id = "create-system-themes-v3", author = "", runAlways = true) + public void createSystemThemes3(MongoTemplate mongoTemplate) throws IOException { final String themesJson = StreamUtils.copyToString( new DefaultResourceLoader().getResource("system-themes.json").getInputStream(),