Merge pull request #29770 from appsmithorg/release

chore: 21/12 daily promotion
This commit is contained in:
Trisha Anand 2023-12-21 11:10:13 +05:30 committed by GitHub
commit 9060ba21d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 276 additions and 145 deletions

View File

@ -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: |

View File

@ -28,7 +28,7 @@
"userDensityRatio": 1.5
},
"innerSpacing": {
"minV": 2.25,
"minV": 1.5,
"maxV": 3,
"minR": 2,
"maxR": 3,

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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<T> 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 {

View File

@ -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 });
};

View File

@ -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 {

View File

@ -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];

View File

@ -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",

View File

@ -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 = "",

View File

@ -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,
});

View File

@ -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,

View File

@ -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 <Placeholder>{createMessage(NO_CONNECTIONS)}</Placeholder>;
}
if (!additionalSections && !showSchema && !showSuggestedWidgets) {
return null;
}
return (
<SideBar>
{actionRightPaneBackLink}
<CollapsibleGroupContainer>
{additionalSections && (
<>
<CollapsibleGroup maxHeight={"50%"}>
{additionalSections}
</CollapsibleGroup>
<StyledDivider />
</>
<CollapsibleGroup maxHeight={"50%"}>
{additionalSections}
</CollapsibleGroup>
)}
<CollapsibleGroup height={additionalSections ? "50%" : "100%"}>
{showSchema && (
<CollapsibleSection
data-testId="datasource-schema-container"
height={
datasourceStructure?.tables?.length && !isLoadingSchema
? "50%"
: "auto"
}
id={SCHEMA_SECTION_ID}
ref={schemaRef}
>
<Collapsible
CustomLabelComponent={DatasourceStructureHeader}
containerRef={schemaRef}
datasource={{ id: datasourceId }}
expand={!showSuggestedWidgets}
label="Schema"
<>
{additionalSections && <StyledDivider />}
<CollapsibleSection
data-testId="datasource-schema-container"
height={
datasourceStructure?.tables?.length && !isLoadingSchema
? showSuggestedWidgets
? "50%"
: "100%"
: "auto"
}
id={SCHEMA_SECTION_ID}
ref={schemaRef}
>
<DataStructureListWrapper>
<DataStructureList
context={context}
currentActionId={params?.queryId || ""}
datasourceId={datasourceId || ""}
datasourceStructure={datasourceStructure}
pluginName={pluginName}
step={0}
/>
</DataStructureListWrapper>
</Collapsible>
</CollapsibleSection>
<Collapsible
CustomLabelComponent={DatasourceStructureHeader}
containerRef={schemaRef}
datasource={{ id: datasourceId }}
expand={!suggestedWidgetsEnabled}
label="Schema"
>
<DataStructureListWrapper>
<DataStructureList
context={context}
currentActionId={params?.queryId || ""}
datasourceId={datasourceId || ""}
datasourceStructure={datasourceStructure}
pluginName={pluginName}
step={0}
/>
</DataStructureListWrapper>
</Collapsible>
</CollapsibleSection>
</>
)}
{showSchema && <StyledDivider />}
{showSuggestedWidgets ? (
{showSuggestedWidgets && showSchema && <StyledDivider />}
{showSuggestedWidgets && suggestedWidgetsEnabled && (
<CollapsibleSection height={"40%"} marginTop={12}>
<SuggestedWidgets
actionName={actionName}
@ -354,7 +357,8 @@ function ActionSidebar({
suggestedWidgets={suggestedWidgets as SuggestedWidget[]}
/>
</CollapsibleSection>
) : (
)}
{showSuggestedWidgets && !suggestedWidgetsEnabled && (
<DisabledCollapsible
label={createMessage(BINDING_SECTION_LABEL)}
tooltipLabel={createMessage(BINDINGS_DISABLED_TOOLTIP)}

View File

@ -0,0 +1,24 @@
import {
getPluginDatasourceComponentFromId,
getPluginNameFromId,
} from "@appsmith/selectors/entitiesSelector";
import { DatasourceComponentTypes } from "api/PluginApi";
import { SCHEMALESS_PLUGINS } from "pages/Editor/DatasourceInfo/DatasourceStructureContainer";
import { useSelector } from "react-redux";
function useShowSchema(pluginId: string) {
const pluginDatasourceForm = useSelector((state) =>
getPluginDatasourceComponentFromId(state, pluginId),
);
const pluginName = useSelector((state) =>
getPluginNameFromId(state, pluginId),
);
return (
pluginDatasourceForm !== DatasourceComponentTypes.RestAPIDatasourceForm &&
!SCHEMALESS_PLUGINS.includes(pluginName)
);
}
export default useShowSchema;

View File

@ -1,2 +1,2 @@
export * from "./baseRoutes";
export * from "./appRoutes";
export * from "@appsmith/constants/routes/appRoutes";

View File

@ -0,0 +1 @@
export * from "ce/constants/routes/appRoutes";

View File

@ -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,
};

View File

@ -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

View File

@ -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 {

View File

@ -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 (
<DatasourceContainer>
<TabbedViewContainer className="tab-container-right-sidebar">
@ -334,7 +339,7 @@ function ApiRightPane(props: ApiRightPaneProps) {
)}
</TabPanel>
<TabPanel value={API_RIGHT_PANE_TABS.CONNECTIONS}>
<SomeWrapper>
<ActionRightPaneWrapper>
<ActionRightPane
actionName={props.actionName}
actionRightPaneBackLink={props.actionRightPaneBackLink}
@ -343,9 +348,10 @@ function ApiRightPane(props: ApiRightPaneProps) {
hasConnections={hasDependencies}
hasResponse={props.hasResponse}
pluginId={props.pluginId}
showSchema={showSchema}
suggestedWidgets={props.suggestedWidgets}
/>
</SomeWrapper>
</ActionRightPaneWrapper>
</TabPanel>
</Tabs>
)}

View File

@ -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)
}
/>
);
});

View File

@ -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());

View File

@ -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,

View File

@ -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}

View File

@ -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 ? (
<ContextMenu
className={props.className}
optionTree={optionsTree as TreeDropdownOption[]}

View File

@ -2,7 +2,6 @@ import React, { memo, useCallback } from "react";
import Entity, { EntityClassNames } from "../Entity";
import history, { NavigationMethod } from "utils/history";
import JSCollectionEntityContextMenu from "./JSActionContextMenu";
import { saveJSObjectName } from "actions/jsActionActions";
import { useSelector } from "react-redux";
import { getJSCollection } from "@appsmith/selectors/entitiesSelector";
import type { AppState } from "@appsmith/reducers";
@ -18,7 +17,8 @@ import {
} from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { Icon } from "design-system";
import { saveJSObjectNameBasedOnParentEntity } from "@appsmith/actions/helpers";
import type { ActionParentEntityTypeInterface } from "@appsmith/entities/Engine/actionHelpers";
interface ExplorerJSCollectionEntityProps {
step: number;
@ -27,10 +27,15 @@ interface ExplorerJSCollectionEntityProps {
isActive: boolean;
type: PluginType;
parentEntityId: string;
parentEntityType: ActionParentEntityTypeInterface;
}
const getUpdateJSObjectName = (id: string, name: string) => {
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 (
<Entity
action={navigateToJSCollection}
active={props.isActive}
alwaysShowRightIcon={!!jsAction.isMainJSCollection}
canEditEntityName={canManageJSAction}
className="t--jsaction"
contextMenu={contextMenu}
entityId={jsAction.id}
icon={JsFileIconV2(16, 16)}
key={jsAction.id}
name={jsAction.name}
rightIcon={!!jsAction.isMainJSCollection && <Icon name="pin-3" />}
name={jsAction?.displayName || jsAction.name}
searchKeyword={props.searchKeyword}
step={props.step}
updateEntityName={getUpdateJSObjectName}
updateEntityName={(id, name) =>
getUpdateJSObjectName(id, name, parentEntityType)
}
/>
);
},

View File

@ -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}

View File

@ -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}

View File

@ -321,13 +321,14 @@ function JSEditorForm({
<NameWrapper className="t--nameOfJSObject">
<JSObjectNameEditor
disabled={
!isChangePermitted || !!currentJSCollection.isMainJSCollection
!isChangePermitted ||
!!currentJSCollection.hideEditIconOnEditor
}
saveJSObjectName={saveJSObjectName}
/>
</NameWrapper>
<ActionButtons className="t--formActionButtons">
{!currentJSCollection.isMainJSCollection && contextMenu}
{!currentJSCollection.hideContextMenuOnEditor && contextMenu}
<JSFunctionRun
disabled={disableRunFunctionality || !isExecutePermitted}
isLoading={isExecutingCurrentJSAction}

View File

@ -26,7 +26,7 @@ import NameEditorComponent, {
import { getSavingStatusForJSObjectName } from "selectors/actionSelectors";
import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants";
interface SaveActionNameParams {
export interface SaveActionNameParams {
id: string;
name: string;
}

View File

@ -91,6 +91,7 @@ import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { QueryEditorContext } from "./QueryEditorContext";
import QueryResponseTabView from "./QueryResponseView";
import { setDebuggerSelectedTab, showDebugger } from "actions/debuggerActions";
import useShowSchema from "components/editorComponents/ActionRightPane/useShowSchema";
const QueryFormContainer = styled.form`
flex: 1;
@ -332,6 +333,7 @@ export function EditorJSONtoForm(props: Props) {
closeEditorLink,
moreActionsMenu,
saveActionName,
showSuggestedWidgets = true,
} = useContext(QueryEditorContext);
const params = useParams<{ apiId?: string; queryId?: string }>();
@ -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) {
)}
</SecondaryWrapper>
</div>
<SidebarWrapper show={shouldOpenActionPaneByDefault}>
<ActionRightPane
actionName={actionName}
actionRightPaneBackLink={actionRightPaneBackLink}
additionalSections={actionRightPaneAdditionSections}
context={DatasourceStructureContext.QUERY_EDITOR}
datasourceId={props.datasourceId}
hasConnections={hasDependencies}
hasResponse={!!actionResponse}
pluginId={props.pluginId}
suggestedWidgets={actionResponse?.suggestedWidgets}
/>
</SidebarWrapper>
{showRightPane && (
<SidebarWrapper show={shouldOpenActionPaneByDefault}>
<ActionRightPane
actionName={actionName}
actionRightPaneBackLink={actionRightPaneBackLink}
additionalSections={actionRightPaneAdditionSections}
context={DatasourceStructureContext.QUERY_EDITOR}
datasourceId={props.datasourceId}
hasConnections={hasDependencies}
hasResponse={!!actionResponse}
pluginId={props.pluginId}
showSchema={showSchema}
showSuggestedWidgets={showSuggestedWidgets}
suggestedWidgets={actionResponse?.suggestedWidgets}
/>
</SidebarWrapper>
)}
</Wrapper>
</QueryFormContainer>
</>

View File

@ -17,6 +17,7 @@ interface QueryEditorContextContextProps {
) => ReduxAction<SaveActionNameParams>;
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,
],
);

View File

@ -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);

View File

@ -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(),