diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts
index 72f97892a048..7c9ba6239a30 100644
--- a/app/client/src/ce/constants/messages.ts
+++ b/app/client/src/ce/constants/messages.ts
@@ -2312,8 +2312,10 @@ export const EDITOR_PANE_TEXTS = {
query_create_tab_title: () => "Create new query from",
widgets_create_tab_title: () => "Drag & drop UI elements",
js_create_tab_title: () => "Create JS object from",
- queries_create_from_existing: () => "From existing datasource",
- queries_create_new: () => "New API",
+ js_create_modules: () => "JS modules (Beta)",
+ queries_create_from_existing: () => "Datasources",
+ queries_create_new: () => "Quick actions",
+ queries_create_modules: () => "Query modules (Beta)",
loading_building_blocks: () => "Loading building blocks",
empty_search_result: (type: string) => `No ${type} match your search`,
};
diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/hooks.tsx b/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/hooks.tsx
index f6693102099e..1973d893e064 100644
--- a/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/hooks.tsx
+++ b/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/hooks.tsx
@@ -1,4 +1,4 @@
-import React, { useCallback, useMemo } from "react";
+import { useCallback, useMemo } from "react";
import history from "utils/history";
import { useLocation } from "react-router";
import { FocusEntity, identifyEntityFromPath } from "navigation/FocusEntity";
@@ -33,7 +33,7 @@ import ListQuery from "pages/Editor/IDE/EditorPane/Query/List";
import type { AppState } from "@appsmith/reducers";
import keyBy from "lodash/keyBy";
import { getPluginEntityIcon } from "pages/Editor/Explorer/ExplorerIcons";
-import { Tag, type ListItemProps } from "design-system";
+import type { ListItemProps } from "design-system";
import { useCurrentEditorState } from "pages/Editor/IDE/hooks";
import { createAddClassName } from "pages/Editor/IDE/EditorPane/utils";
import { QueriesBlankState } from "pages/Editor/QueryEditor/QueriesBlankState";
@@ -182,12 +182,13 @@ export const useAddQueryListItems = () => {
[pageId, dispatch],
);
- const getListItems = (data: any[]) => {
+ const getListItems = (data: ActionOperation[]) => {
return data.map((fileOperation) => {
const title =
fileOperation.entityExplorerTitle ||
+ fileOperation.title ||
fileOperation.dsName ||
- fileOperation.title;
+ "";
const className = createAddClassName(title);
const icon =
fileOperation.icon ||
@@ -197,11 +198,10 @@ export const useAddQueryListItems = () => {
startIcon: icon,
wrapperClassName: className,
title,
- description: !!fileOperation.isBeta ? (
- Beta
- ) : (
- ""
- ),
+ description:
+ fileOperation.focusEntityType === FocusEntity.QUERY_MODULE_INSTANCE
+ ? fileOperation.dsName
+ : "",
descriptionType: "inline",
onClick: onCreateItemClick.bind(null, fileOperation),
} as ListItemProps;
diff --git a/app/client/src/pages/Editor/IDE/EditorPane/JS/Add.tsx b/app/client/src/pages/Editor/IDE/EditorPane/JS/Add.tsx
index 2e524f80deaf..e6daa9177b00 100644
--- a/app/client/src/pages/Editor/IDE/EditorPane/JS/Add.tsx
+++ b/app/client/src/pages/Editor/IDE/EditorPane/JS/Add.tsx
@@ -1,8 +1,8 @@
-import React, { useCallback } from "react";
+import React, { useCallback, useState } from "react";
import SegmentAddHeader from "../components/SegmentAddHeader";
import { EDITOR_PANE_TEXTS } from "@appsmith/constants/messages";
import type { ListItemProps } from "design-system";
-import { Flex, Tag } from "design-system";
+import { Flex, SearchInput } from "design-system";
import { useDispatch, useSelector } from "react-redux";
import { getCurrentPageId } from "selectors/editorSelectors";
import GroupedList from "../components/GroupedList";
@@ -12,11 +12,15 @@ import {
} from "@appsmith/pages/Editor/IDE/EditorPane/JS/hooks";
import type { ActionOperation } from "components/editorComponents/GlobalSearch/utils";
import type { AddProps } from "../types/AddProps";
-import { createAddClassName } from "../utils";
+import { createAddClassName, fuzzySearchInObjectItems } from "../utils";
+import { FocusEntity } from "navigation/FocusEntity";
+import type { GroupedListProps } from "../components/types";
+import { EmptySearchResult } from "../components/EmptySearchResult";
const AddJS = ({ containerProps, innerContainerProps }: AddProps) => {
const dispatch = useDispatch();
const pageId = useSelector(getCurrentPageId);
+ const [searchTerm, setSearchTerm] = useState("");
const groupedJsOperations = useGroupedAddJsOperations();
@@ -35,13 +39,27 @@ const AddJS = ({ containerProps, innerContainerProps }: AddProps) => {
return {
startIcon: data.icon,
title,
- description: !!data.isBeta ? Beta : "",
+ description:
+ data.focusEntityType === FocusEntity.JS_MODULE_INSTANCE
+ ? data.dsName
+ : "",
descriptionType: "inline",
onClick: onCreateItemClick.bind(null, data),
wrapperClassName: createAddClassName(title),
} as ListItemProps;
};
+ const groups = groupedJsOperations.map((op) => ({
+ groupTitle: op.title,
+ className: op.className,
+ items: op.operations.map(getListItems),
+ }));
+
+ const localGroups = fuzzySearchInObjectItems(
+ searchTerm,
+ groups,
+ );
+
return (
{
onCloseClick={closeAddJS}
titleMessage={EDITOR_PANE_TEXTS.js_create_tab_title}
/>
-
- ({
- groupTitle: op.title,
- className: op.className,
- items: op.operations.map(getListItems),
- }))}
- />
+
+ {localGroups.length > 0 ? : null}
+ {localGroups.length === 0 && searchTerm !== "" ? (
+
+ ) : null}
);
diff --git a/app/client/src/pages/Editor/IDE/EditorPane/JS/List.tsx b/app/client/src/pages/Editor/IDE/EditorPane/JS/List.tsx
index 465b05c7b5fd..78d355775d6c 100644
--- a/app/client/src/pages/Editor/IDE/EditorPane/JS/List.tsx
+++ b/app/client/src/pages/Editor/IDE/EditorPane/JS/List.tsx
@@ -3,6 +3,7 @@ import { useSelector } from "react-redux";
import { Flex, Text } from "design-system";
import styled from "styled-components";
+import type { EditorSegmentList } from "@appsmith/selectors/appIDESelectors";
import { selectJSSegmentEditorList } from "@appsmith/selectors/appIDESelectors";
import { useActiveAction } from "@appsmith/pages/Editor/Explorer/hooks";
import {
@@ -19,8 +20,8 @@ import { useJSAdd } from "@appsmith/pages/Editor/IDE/EditorPane/JS/hooks";
import { JSListItem } from "@appsmith/pages/Editor/IDE/EditorPane/JS/ListItem";
import { BlankState } from "./BlankState";
import { AddAndSearchbar } from "../components/AddAndSearchbar";
-import { fuzzySearchInFiles } from "../utils";
-import { EDITOR_PANE_TEXTS, createMessage } from "@appsmith/constants/messages";
+import { fuzzySearchInObjectItems } from "../utils";
+import { EmptySearchResult } from "../components/EmptySearchResult";
const JSContainer = styled(Flex)`
& .t--entity-item {
@@ -44,7 +45,10 @@ const ListJSObjects = () => {
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
- const localFiles = fuzzySearchInFiles(searchTerm, files);
+ const localFiles = fuzzySearchInObjectItems(
+ searchTerm,
+ files,
+ );
const canCreateActions = getHasCreateActionPermission(
isFeatureEnabled,
@@ -112,13 +116,7 @@ const ListJSObjects = () => {
);
})}
{localFiles.length === 0 && searchTerm !== "" ? (
-
- {createMessage(EDITOR_PANE_TEXTS.empty_search_result, "JS")}
-
+
) : null}
diff --git a/app/client/src/pages/Editor/IDE/EditorPane/Query/Add.tsx b/app/client/src/pages/Editor/IDE/EditorPane/Query/Add.tsx
index b46513abcc7e..686c98890194 100644
--- a/app/client/src/pages/Editor/IDE/EditorPane/Query/Add.tsx
+++ b/app/client/src/pages/Editor/IDE/EditorPane/Query/Add.tsx
@@ -1,5 +1,5 @@
-import React from "react";
-import { Flex } from "design-system";
+import React, { useState } from "react";
+import { Flex, SearchInput } from "design-system";
import { EDITOR_PANE_TEXTS } from "@appsmith/constants/messages";
import SegmentAddHeader from "../components/SegmentAddHeader";
@@ -10,12 +10,27 @@ import {
useQueryAdd,
} from "@appsmith/pages/Editor/IDE/EditorPane/Query/hooks";
import type { AddProps } from "../types/AddProps";
+import { fuzzySearchInObjectItems } from "../utils";
+import type { GroupedListProps } from "../components/types";
+import { EmptySearchResult } from "../components/EmptySearchResult";
const AddQuery = ({ containerProps, innerContainerProps }: AddProps) => {
+ const [searchTerm, setSearchTerm] = useState("");
const { getListItems } = useAddQueryListItems();
const groupedActionOperations = useGroupedAddQueryOperations();
const { closeAddQuery } = useQueryAdd();
+ const groups = groupedActionOperations.map((group) => ({
+ groupTitle: group.title,
+ className: group.className,
+ items: getListItems(group.operations),
+ }));
+
+ const localGroups = fuzzySearchInObjectItems(
+ searchTerm,
+ groups,
+ );
+
return (
{
onCloseClick={closeAddQuery}
titleMessage={EDITOR_PANE_TEXTS.query_create_tab_title}
/>
- ({
- groupTitle: group.title,
- className: group.className,
- items: getListItems(group.operations),
- }))}
- />
+
+ {localGroups.length > 0 ? : null}
+ {localGroups.length === 0 && searchTerm !== "" ? (
+
+ ) : null}
);
diff --git a/app/client/src/pages/Editor/IDE/EditorPane/Query/List.tsx b/app/client/src/pages/Editor/IDE/EditorPane/Query/List.tsx
index f23a0e2e02c4..ab40854ef2a4 100644
--- a/app/client/src/pages/Editor/IDE/EditorPane/Query/List.tsx
+++ b/app/client/src/pages/Editor/IDE/EditorPane/Query/List.tsx
@@ -11,6 +11,7 @@ import {
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import { getCurrentPageId } from "@appsmith/selectors/entitiesSelector";
+import type { EditorSegmentList } from "@appsmith/selectors/appIDESelectors";
import { selectQuerySegmentEditorList } from "@appsmith/selectors/appIDESelectors";
import { ActionParentEntityType } from "@appsmith/entities/Engine/actionHelpers";
import { FilesContextProvider } from "pages/Editor/Explorer/Files/FilesContextProvider";
@@ -19,8 +20,8 @@ import { QueryListItem } from "@appsmith/pages/Editor/IDE/EditorPane/Query/ListI
import { getShowWorkflowFeature } from "@appsmith/selectors/workflowSelectors";
import { BlankState } from "./BlankState";
import { AddAndSearchbar } from "../components/AddAndSearchbar";
-import { fuzzySearchInFiles } from "../utils";
-import { EDITOR_PANE_TEXTS, createMessage } from "@appsmith/constants/messages";
+import { fuzzySearchInObjectItems } from "../utils";
+import { EmptySearchResult } from "../components/EmptySearchResult";
const ListQuery = () => {
const [searchTerm, setSearchTerm] = useState("");
@@ -30,7 +31,10 @@ const ListQuery = () => {
const pagePermissions = useSelector(getPagePermissions);
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
- const localFiles = fuzzySearchInFiles(searchTerm, files);
+ const localFiles = fuzzySearchInObjectItems(
+ searchTerm,
+ files,
+ );
const canCreateActions = getHasCreateActionPermission(
isFeatureEnabled,
@@ -96,13 +100,7 @@ const ListQuery = () => {
);
})}
{localFiles.length === 0 && searchTerm !== "" ? (
-
- {createMessage(EDITOR_PANE_TEXTS.empty_search_result, "queries")}
-
+
) : null}
diff --git a/app/client/src/pages/Editor/IDE/EditorPane/components/EmptySearchResult.tsx b/app/client/src/pages/Editor/IDE/EditorPane/components/EmptySearchResult.tsx
new file mode 100644
index 000000000000..6407ea6e30b0
--- /dev/null
+++ b/app/client/src/pages/Editor/IDE/EditorPane/components/EmptySearchResult.tsx
@@ -0,0 +1,17 @@
+import React from "react";
+import { Text } from "design-system";
+import { EDITOR_PANE_TEXTS, createMessage } from "@appsmith/constants/messages";
+
+const EmptySearchResult = ({ type }: { type: string }) => {
+ return (
+
+ {createMessage(EDITOR_PANE_TEXTS.empty_search_result, type)}
+
+ );
+};
+
+export { EmptySearchResult };
diff --git a/app/client/src/pages/Editor/IDE/EditorPane/components/Group.tsx b/app/client/src/pages/Editor/IDE/EditorPane/components/Group.tsx
new file mode 100644
index 000000000000..134d190d7e51
--- /dev/null
+++ b/app/client/src/pages/Editor/IDE/EditorPane/components/Group.tsx
@@ -0,0 +1,76 @@
+import React, { useState } from "react";
+import type { GroupedListProps } from "./types";
+import { DEFAULT_GROUP_LIST_SIZE } from "./constants";
+import { Flex, List, Text } from "design-system";
+import styled from "styled-components";
+
+interface GroupProps {
+ group: GroupedListProps;
+}
+
+const StyledList = styled(List)`
+ padding: 0;
+ gap: 0;
+
+ & .ds-load-more .ads-v2-listitem__title {
+ --color: var(--ads-v2-color-fg-subtle);
+ }
+ & .ads-v2-listitem__wrapper .ads-v2-listitem__idesc {
+ opacity: 0;
+ }
+
+ & .ads-v2-listitem__wrapper:hover .ads-v2-listitem__idesc {
+ opacity: 1;
+ }
+`;
+
+const Group: React.FC = ({ group }) => {
+ const [visibleItems, setVisibleItems] = useState(
+ DEFAULT_GROUP_LIST_SIZE,
+ );
+ const { className, groupTitle } = group;
+ const items = group.items.slice(0, visibleItems);
+ const hasMoreItems = group.items.length > visibleItems;
+
+ const handleLoadMore = () => {
+ setVisibleItems(group.items.length);
+ };
+
+ if (hasMoreItems) {
+ items.push({
+ title: "Load more...",
+ description: "",
+ descriptionType: "inline",
+ onClick: handleLoadMore,
+ className: "ds-load-more",
+ });
+ }
+
+ // TODO: try to avoid this
+ if (hasMoreItems && groupTitle === "Datasources") {
+ items.push(group.items[group.items.length - 1]);
+ }
+
+ return (
+
+ {groupTitle ? (
+
+ {groupTitle}
+
+ ) : null}
+
+
+ );
+};
+
+export { Group };
diff --git a/app/client/src/pages/Editor/IDE/EditorPane/components/GroupedList.tsx b/app/client/src/pages/Editor/IDE/EditorPane/components/GroupedList.tsx
index 268bf614b8be..960b2459613c 100644
--- a/app/client/src/pages/Editor/IDE/EditorPane/components/GroupedList.tsx
+++ b/app/client/src/pages/Editor/IDE/EditorPane/components/GroupedList.tsx
@@ -1,27 +1,24 @@
import React from "react";
+import type { FlexProps } from "design-system";
+import { Flex } from "design-system";
import styled from "styled-components";
-import type { FlexProps, ListItemProps } from "design-system";
-import { Flex, List, Text } from "design-system";
-
-const StyledList = styled(List)`
- padding: 0;
- gap: 0;
-`;
-
-export type GroupedListProps = Array<{
- groupTitle?: string;
- className: string;
- items: ListItemProps[];
-}>;
+import type { GroupedListProps } from "./types";
+import { Group } from "./Group";
interface Props {
- groups: GroupedListProps;
+ groups: GroupedListProps[];
flexProps?: FlexProps;
}
+const StyledFlex = styled(Flex)`
+ & .groups-list-group:last-child {
+ border-bottom: none;
+ }
+`;
+
const GroupedList = (props: Props) => {
return (
- {
{...props.flexProps}
>
{props.groups.map((group) => (
-
- {group.groupTitle ? (
-
- {group.groupTitle}
-
- ) : null}
-
-
+
))}
-
+
);
};
diff --git a/app/client/src/pages/Editor/IDE/EditorPane/components/SegmentAddHeader.tsx b/app/client/src/pages/Editor/IDE/EditorPane/components/SegmentAddHeader.tsx
index b07ba8870e3f..c33dfe8bdaef 100644
--- a/app/client/src/pages/Editor/IDE/EditorPane/components/SegmentAddHeader.tsx
+++ b/app/client/src/pages/Editor/IDE/EditorPane/components/SegmentAddHeader.tsx
@@ -20,9 +20,6 @@ const SegmentAddHeader = (props: Props) => {
: "var(--ads-v2-color-gray-50)"
}
justifyContent="space-between"
- pl="spaces-4"
- pr="spaces-2"
- py="spaces-2"
>
{createMessage(props.titleMessage)}
diff --git a/app/client/src/pages/Editor/IDE/EditorPane/components/constants.ts b/app/client/src/pages/Editor/IDE/EditorPane/components/constants.ts
new file mode 100644
index 000000000000..3f7096e37f7b
--- /dev/null
+++ b/app/client/src/pages/Editor/IDE/EditorPane/components/constants.ts
@@ -0,0 +1 @@
+export const DEFAULT_GROUP_LIST_SIZE = 5;
diff --git a/app/client/src/pages/Editor/IDE/EditorPane/components/types.ts b/app/client/src/pages/Editor/IDE/EditorPane/components/types.ts
new file mode 100644
index 000000000000..2ad6e33c0993
--- /dev/null
+++ b/app/client/src/pages/Editor/IDE/EditorPane/components/types.ts
@@ -0,0 +1,7 @@
+import type { ListItemProps } from "design-system";
+
+export interface GroupedListProps {
+ groupTitle?: string;
+ className: string;
+ items: ListItemProps[];
+}
diff --git a/app/client/src/pages/Editor/IDE/EditorPane/fuzzySearchInFiles.test.ts b/app/client/src/pages/Editor/IDE/EditorPane/fuzzySearchInFiles.test.ts
index b9a4c068a381..458e9e188ace 100644
--- a/app/client/src/pages/Editor/IDE/EditorPane/fuzzySearchInFiles.test.ts
+++ b/app/client/src/pages/Editor/IDE/EditorPane/fuzzySearchInFiles.test.ts
@@ -1,5 +1,5 @@
import type { EditorSegmentList } from "@appsmith/selectors/appIDESelectors";
-import { fuzzySearchInFiles } from "./utils";
+import { fuzzySearchInObjectItems } from "./utils";
import { PluginType } from "entities/Action";
const sampleFiles: EditorSegmentList = [
@@ -19,14 +19,14 @@ const sampleFiles: EditorSegmentList = [
},
];
-describe("fuzzySearchInFiles", () => {
+describe("fuzzySearchInObjectItems", () => {
it("should return all files when the search string is empty", () => {
- const result = fuzzySearchInFiles("", sampleFiles);
+ const result = fuzzySearchInObjectItems("", sampleFiles);
expect(result).toEqual(sampleFiles);
});
it("should return the correct file when the search string exactly matches a file title", () => {
- const result = fuzzySearchInFiles("file1", sampleFiles);
+ const result = fuzzySearchInObjectItems("file1", sampleFiles);
expect(result).toEqual([
{
group: "Group 1",
@@ -36,12 +36,12 @@ describe("fuzzySearchInFiles", () => {
});
it("should return an empty array when no files match the search string", () => {
- const result = fuzzySearchInFiles("nonexistentfile", sampleFiles);
+ const result = fuzzySearchInObjectItems("nonexistentfile", sampleFiles);
expect(result).toEqual([]);
});
it("should return all files containing the common substring in their titles", () => {
- const result = fuzzySearchInFiles("file", sampleFiles);
+ const result = fuzzySearchInObjectItems("file", sampleFiles);
expect(result).toEqual(sampleFiles);
});
});
diff --git a/app/client/src/pages/Editor/IDE/EditorPane/utils.ts b/app/client/src/pages/Editor/IDE/EditorPane/utils.ts
index 390f5d201f1e..30bae96772ea 100644
--- a/app/client/src/pages/Editor/IDE/EditorPane/utils.ts
+++ b/app/client/src/pages/Editor/IDE/EditorPane/utils.ts
@@ -1,5 +1,5 @@
import Fuse from "fuse.js";
-import type { EditorSegmentList } from "@appsmith/selectors/appIDESelectors";
+import get from "lodash/get";
export const createAddClassName = (name: string) => {
return "t--datasoucre-create-option-" + name.toLowerCase().replace(/ /g, "_");
@@ -8,22 +8,24 @@ export const createAddClassName = (name: string) => {
const FUSE_OPTIONS = {
shouldSort: true,
threshold: 0.1,
- keys: ["title"],
};
-export const fuzzySearchInFiles = (
+export const fuzzySearchInObjectItems = (
searchStr: string,
- files: EditorSegmentList,
-) => {
+ files: T,
+ keysToSearch = ["title"],
+ itemsKey = "items",
+): T => {
if (searchStr && searchStr !== "") {
const newFiles = files
- .map((group) => {
- const fuse = new Fuse(group.items, FUSE_OPTIONS);
+ .map((group: any) => {
+ const items = get(group, itemsKey);
+ const fuse = new Fuse(items, { ...FUSE_OPTIONS, keys: keysToSearch });
const resultItems = fuse.search(searchStr);
return { ...group, items: resultItems };
})
.filter((group) => group.items.length > 0);
- return newFiles;
+ return newFiles as T;
}
return files;
diff --git a/app/client/src/pages/Editor/JSEditor/JSAddState.tsx b/app/client/src/pages/Editor/JSEditor/JSAddState.tsx
index 8d58080709a8..bd0e2dd410a7 100644
--- a/app/client/src/pages/Editor/JSEditor/JSAddState.tsx
+++ b/app/client/src/pages/Editor/JSEditor/JSAddState.tsx
@@ -4,7 +4,7 @@ import AddJS from "pages/Editor/IDE/EditorPane/JS/Add";
const JSAddState = () => {
return (
-
+
{
return (
-
+