diff --git a/client/packages/lowcoder/src/pages/datasource/pluginPanel.tsx b/client/packages/lowcoder/src/pages/datasource/pluginPanel.tsx index 11f11fd8e..e5d714a84 100644 --- a/client/packages/lowcoder/src/pages/datasource/pluginPanel.tsx +++ b/client/packages/lowcoder/src/pages/datasource/pluginPanel.tsx @@ -11,6 +11,9 @@ import { apiPluginsForQueryLibrary, databasePlugins, } from "@lowcoder-ee/constants/datasourceConstants"; +import { Search } from "components/Search"; +import { CreateDropdown } from "@lowcoder-ee/pages/ApplicationV2/CreateDropdown"; +import React, { useState } from "react"; export const DataSourceButton = styled(AntdButton)` &&& { @@ -66,17 +69,62 @@ const SectionBody = styled.div` gap: 8px; `; +const OperationRightWrapper = styled.div` + display: flex; + align-items: center; + flex-shrink: 0; + margin-left: auto; + @media screen and (max-width: 500px) { + > Button { + display: none; + } + } +`; + +/** + * Function source: https://stackoverflow.com/a/69623589/1394698, thanks to Jan Turoň + * + * Stripping diacritics and natively comparing the strings is much faster than using localeCompare. + * localeCompare also fails to search partials, it only searches the full string match, so is quite + * useless for a filter box. + * + * This method sacrifices some of the benefits of localeCompare, such as κόσμε == kosme and instead + * focuses solely on diacritics, which should be fine for the general use case. + * + * @param str the full string to search against (for this panel, it's always the Data Source #name) + * @param sub the filter string to search with + */ +export const localeContains = (str: string, sub: string): boolean => { + if (sub === "") return true; + if (!sub || !str.length) return false; + sub = "" + sub; + if (sub.length > str.length) return false; + let ascii = (s: string) => s.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase(); + return ascii(str).includes(ascii(sub)); +} + export const PluginPanel = (props: { onSelect: (t: DataSourceTypeInfo) => void }) => { const datasourceTypes = useSelector(getDataSourceTypes); const currentPage = useCurrentPage(); + const [searchValue, setSearchValue] = useState(""); const apiList = currentPage === "queryLibrary" ? apiPluginsForQueryLibrary : apiPlugins; + return ( + + setSearchValue(e.target.value)} + style={{ width: "192px", height: "32px", margin: "0" }} + /> + {trans("query.database")} {datasourceTypes .filter((t) => databasePlugins.includes(t.id) || t.definition?.category === "database") + .filter((t) => localeContains(t.name, searchValue)) .map((t) => { return ( props.onSelect(t)}> @@ -92,6 +140,7 @@ export const PluginPanel = (props: { onSelect: (t: DataSourceTypeInfo) => void } {datasourceTypes .filter((t) => apiList.includes(t.id) || t.definition?.category === "api") + .filter((t) => localeContains(t.name, searchValue)) .map((t) => ( props.onSelect(t)}> {t.id && getBottomResIcon(t.id, "large", t.definition?.icon)}