From 3e1a31ff94e0ab12cd00556171000ed2b4295dde Mon Sep 17 00:00:00 2001 From: "Tyler B. Thrailkill" Date: Mon, 1 Apr 2024 19:16:24 -0600 Subject: [PATCH] Add a filter to the New Data Source modal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add a filter to make it easier to find the data source you're looking for in the New Data Source modal found in both the lower pane when creating an app, and the Data Source page when in Home. The filtering ignores case and diacritics, but is not a fuzzy filter as I thought that would be too confusing for a simple search like this. The localeContains function comes from StackOverflow user Jan Turoň, https://stackoverflow.com/a/69623589/1394698 The function sacrifices complete compatibility with the localeCompare function for a simplified diacritics check which should suffice for the majority of lowcoder use cases. I initially tried to get the npm library locale-includes working, but Vite really doesn't like it, and it failed to compile no matter what I tried. --- .../src/pages/datasource/pluginPanel.tsx | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) 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)}