Skip to content

Commit 41f573b

Browse files
authored
Merge pull request #789 from snowe2010/add-data-query-filter
Add a filter to the New Data Source modal
2 parents f830bd5 + 3e1a31f commit 41f573b

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

client/packages/lowcoder/src/pages/datasource/pluginPanel.tsx

+49
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import {
1111
apiPluginsForQueryLibrary,
1212
databasePlugins,
1313
} from "@lowcoder-ee/constants/datasourceConstants";
14+
import { Search } from "components/Search";
15+
import { CreateDropdown } from "@lowcoder-ee/pages/ApplicationV2/CreateDropdown";
16+
import React, { useState } from "react";
1417

1518
export const DataSourceButton = styled(AntdButton)`
1619
&&& {
@@ -66,17 +69,62 @@ const SectionBody = styled.div`
6669
gap: 8px;
6770
`;
6871

72+
const OperationRightWrapper = styled.div`
73+
display: flex;
74+
align-items: center;
75+
flex-shrink: 0;
76+
margin-left: auto;
77+
@media screen and (max-width: 500px) {
78+
> Button {
79+
display: none;
80+
}
81+
}
82+
`;
83+
84+
/**
85+
* Function source: https://stackoverflow.com/a/69623589/1394698, thanks to Jan Turoň
86+
*
87+
* Stripping diacritics and natively comparing the strings is much faster than using localeCompare.
88+
* localeCompare also fails to search partials, it only searches the full string match, so is quite
89+
* useless for a filter box.
90+
*
91+
* This method sacrifices some of the benefits of localeCompare, such as κόσμε == kosme and instead
92+
* focuses solely on diacritics, which should be fine for the general use case.
93+
*
94+
* @param str the full string to search against (for this panel, it's always the Data Source #name)
95+
* @param sub the filter string to search with
96+
*/
97+
export const localeContains = (str: string, sub: string): boolean => {
98+
if (sub === "") return true;
99+
if (!sub || !str.length) return false;
100+
sub = "" + sub;
101+
if (sub.length > str.length) return false;
102+
let ascii = (s: string) => s.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
103+
return ascii(str).includes(ascii(sub));
104+
}
105+
69106
export const PluginPanel = (props: { onSelect: (t: DataSourceTypeInfo) => void }) => {
70107
const datasourceTypes = useSelector(getDataSourceTypes);
71108
const currentPage = useCurrentPage();
109+
const [searchValue, setSearchValue] = useState("");
72110
const apiList = currentPage === "queryLibrary" ? apiPluginsForQueryLibrary : apiPlugins;
111+
73112
return (
74113
<PanelWrapper>
114+
<OperationRightWrapper>
115+
<Search
116+
placeholder={trans("search")}
117+
value={searchValue}
118+
onChange={(e) => setSearchValue(e.target.value)}
119+
style={{ width: "192px", height: "32px", margin: "0" }}
120+
/>
121+
</OperationRightWrapper>
75122
<SectionWrapper>
76123
<SectionLabel>{trans("query.database")}</SectionLabel>
77124
<SectionBody>
78125
{datasourceTypes
79126
.filter((t) => databasePlugins.includes(t.id) || t.definition?.category === "database")
127+
.filter((t) => localeContains(t.name, searchValue))
80128
.map((t) => {
81129
return (
82130
<DataSourceButton key={t.id} onClick={() => props.onSelect(t)}>
@@ -92,6 +140,7 @@ export const PluginPanel = (props: { onSelect: (t: DataSourceTypeInfo) => void }
92140
<SectionBody>
93141
{datasourceTypes
94142
.filter((t) => apiList.includes(t.id) || t.definition?.category === "api")
143+
.filter((t) => localeContains(t.name, searchValue))
95144
.map((t) => (
96145
<DataSourceButton key={t.id} onClick={() => props.onSelect(t)}>
97146
{t.id && getBottomResIcon(t.id, "large", t.definition?.icon)}

0 commit comments

Comments
 (0)