Skip to content

Commit 2bc7d03

Browse files
committed
added local storage based searchableText
Signed-off-by: nassery318 <nassery318@gmail.com>
1 parent c1ba79d commit 2bc7d03

File tree

6 files changed

+33
-16
lines changed

6 files changed

+33
-16
lines changed

apps/frontend/src/components/cluster-topology/Cluster.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useState } from "react"
22
import { useSelector } from "react-redux"
33
import { Server, CheckCircle2 } from "lucide-react"
44
import { useParams } from "react-router"
5-
import { CONNECTED } from "@common/src/constants.ts"
5+
import { CONNECTED, MAX_CONNECTIONS } from "@common/src/constants.ts"
66
import { AppHeader } from "../ui/app-header"
77
import RouteContainer from "../ui/route-container"
88
import { StatCard } from "../ui/stat-card"
@@ -62,6 +62,8 @@ export function Cluster() {
6262
})
6363
})
6464

65+
const highlight = searchQuery && filteredEntries.length < MAX_CONNECTIONS ? searchQuery : ""
66+
6567
return (
6668
<RouteContainer className="overflow-y-hidden" title="Cluster Topology">
6769
<AppHeader icon={<Server size={20} />} title="Cluster Topology" />
@@ -110,6 +112,7 @@ export function Cluster() {
110112
return (
111113
<ClusterNode
112114
clusterId={clusterId!}
115+
highlight={highlight}
113116
key={primaryKey}
114117
primary={primary}
115118
primaryData={primaryData}

apps/frontend/src/components/cluster-topology/cluster-node.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Badge } from "../ui/badge"
77
import { CustomTooltip } from "../ui/tooltip"
88
import { Button } from "../ui/button"
99
import { Typography } from "../ui/typography"
10+
import { HighlightSearchMatch } from "../ui/highlight-search-match"
1011
import type { RootState } from "@/store.ts"
1112
import type { PrimaryNode, ParsedNodeInfo } from "@/state/valkey-features/cluster/clusterSlice"
1213
import { connectPending, type ConnectionDetails } from "@/state/valkey-features/connection/connectionSlice.ts"
@@ -20,13 +21,15 @@ interface ClusterNodeProps {
2021
primary: PrimaryNode
2122
primaryData: ParsedNodeInfo
2223
clusterId: string
24+
highlight?: string
2325
}
2426

2527
export function ClusterNode({
2628
primaryKey,
2729
primary,
2830
primaryData,
2931
clusterId,
32+
highlight = "",
3033
}: ClusterNodeProps) {
3134
const navigate = useNavigate()
3235
const dispatch = useAppDispatch()
@@ -83,12 +86,14 @@ export function ClusterNode({
8386
<Server className="text-primary shrink-0" size={18} />
8487
<div className="flex flex-col gap-1 min-w-0">
8588
<div className="flex items-center gap-2 flex-wrap">
86-
<Typography variant={"label"}>{primaryData?.server_name || primaryKey}</Typography>
89+
<Typography variant={"label"}>
90+
<HighlightSearchMatch query={highlight} text={primaryData?.server_name || primaryKey} />
91+
</Typography>
8792
<Badge className="text-xs px-2 py-0" variant={isConnected ? "success" : "secondary"}>
8893
PRIMARY
8994
</Badge>
9095
</div>
91-
<Typography variant="bodyXs">{`${primary.host}:${primary.port}`}</Typography>
96+
<Typography variant="bodyXs"><HighlightSearchMatch query={highlight} text={`${primary.host}:${primary.port}`} /></Typography>
9297
<NodeDetails nodeData={primaryData} />
9398
</div>
9499
</div>
@@ -109,7 +114,9 @@ export function ClusterNode({
109114
return (
110115
<div className="flex items-center mb-2 gap-1" key={replicaKey}>
111116
<Server className="text-primary shrink-0" size={16} />
112-
<Typography className="underline" variant="bodyXs">{replicaKey}</Typography>
117+
<Typography className="underline" variant="bodyXs">
118+
<HighlightSearchMatch query={highlight} text={replicaKey} />
119+
</Typography>
113120
</div>
114121
)
115122
})}

apps/frontend/src/components/connection/Connection.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@ import { selectConnections } from "@/state/valkey-features/connection/connection
1414
import { ConnectionEntry } from "@/components/connection/ConnectionEntry.tsx"
1515
import { ClusterConnectionGroup } from "@/components/connection/ClusterConnectionGroup.tsx"
1616

17-
const matchesSearch = (q: string, connectionId: string, connection: ConnectionState) => {
18-
const { host, port, username, alias } = connection.connectionDetails
19-
return [connectionId, host, port, username, alias]
20-
.filter(Boolean)
21-
.some((v) => v!.toLowerCase().includes(q))
22-
}
17+
const matchesSearch = (q: string, connection: ConnectionState) =>
18+
connection.searchableText.includes(q)
2319

2420
export function Connection() {
2521
const [showConnectionForm, setShowConnectionForm] = useState(false)
@@ -68,12 +64,12 @@ export function Connection() {
6864
const filteredClusterGroups: typeof clusterGroups = {}
6965
if (q) {
7066
for (const [clusterId, conns] of Object.entries(clusterGroups)) {
71-
const matched = conns.filter(({ connectionId, connection }) => matchesSearch(q, connectionId, connection))
67+
const matched = conns.filter(({ connection }) => matchesSearch(q, connection))
7268
if (matched.length > 0) filteredClusterGroups[clusterId] = matched
7369
}
7470
}
7571
const filteredStandaloneConnections = q
76-
? standaloneConnections.filter(({ connectionId, connection }) => matchesSearch(q, connectionId, connection))
72+
? standaloneConnections.filter(({ connection }) => matchesSearch(q, connection))
7773
: standaloneConnections
7874

7975
const hasFilteredClusters = q ? Object.keys(filteredClusterGroups).length > 0 : Object.keys(clusterGroups).length > 0

apps/frontend/src/components/ui/accordion.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export default function Accordion({ accordionName, accordionItems, valueType = "
9696
{formatKey(key)}
9797
</Typography>
9898
{singleMetricDescriptions[key] && (
99-
<TooltipIcon description={`${singleMetricDescriptions[key].description} ${singleMetricDescriptions[key].unit}` } size={13} />
99+
<TooltipIcon description={singleMetricDescriptions[key].description} size={13} />
100100
)}
101101
</div>
102102
<Typography variant="bodySm">{formatMetricValue(key, value, valueType)}</Typography>

apps/frontend/src/state/epics/valkeyEpics.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export const connectionEpic = (store: Store) =>
8383
connectionDetails: baseConnectionDetails,
8484
status: NOT_CONNECTED,
8585
connectionHistory: connection?.connectionHistory ?? [],
86+
searchableText: connection?.searchableText ?? "",
8687
}
8788

8889
currentConnections[payload.connectionId] = connectionToSave
@@ -291,6 +292,7 @@ export const updateConnectionDetailsEpic = (store: Store) =>
291292
if (connection && currentConnections[connectionId]) {
292293
currentConnections[connectionId].connectionDetails = connection.connectionDetails
293294
currentConnections[connectionId].connectionHistory = connection.connectionHistory || []
295+
currentConnections[connectionId].searchableText = connection.searchableText ?? ""
294296
localStorage.setItem(LOCAL_STORAGE.VALKEY_CONNECTIONS, JSON.stringify(currentConnections))
295297
}
296298
} catch (e) {

apps/frontend/src/state/valkey-features/connection/connectionSlice.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export interface ConnectionState {
5050
status: ConnectionStatus;
5151
errorMessage: string | null;
5252
connectionDetails: ConnectionDetails;
53+
searchableText: string;
5354
reconnect?: ReconnectState;
5455
connectionHistory?: ConnectionHistoryEntry[];
5556
wasEdit?: boolean;
@@ -59,9 +60,15 @@ export interface ValkeyConnectionsState {
5960
[connectionId: string]: ConnectionState
6061
}
6162

63+
const buildSearchableText = (connectionId: string, details: ConnectionDetails) =>
64+
[connectionId, details.host, details.port, details.username, details.alias]
65+
.filter(Boolean)
66+
.join(" ")
67+
.toLowerCase()
68+
6269
const currentConnections = R.pipe(
6370
(v: string) => localStorage.getItem(v),
64-
(s) => (s === null ? {} : JSON.parse(s)),
71+
(s) => (s === null ? {} : JSON.parse(s) as ValkeyConnectionsState),
6572
)(LOCAL_STORAGE.VALKEY_CONNECTIONS)
6673

6774
const connectionSlice = createSlice({
@@ -97,7 +104,7 @@ const connectionSlice = createSlice({
97104
clusterSlotStatsEnabled: false,
98105
jsonModuleAvailable: false,
99106
},
100-
107+
searchableText: buildSearchableText(connectionId, connectionDetails),
101108
wasEdit: isEdit,
102109
...(isRetry && existingConnection?.reconnect && {
103110
reconnect: existingConnection.reconnect,
@@ -225,10 +232,12 @@ const connectionSlice = createSlice({
225232
},
226233
updateConnectionDetails: (state, action) => {
227234
const { connectionId, ...details } = action.payload
228-
state.connections[connectionId].connectionDetails = {
235+
const merged = {
229236
...state.connections[connectionId].connectionDetails,
230237
...details,
231238
}
239+
state.connections[connectionId].connectionDetails = merged
240+
state.connections[connectionId].searchableText = buildSearchableText(connectionId, merged)
232241
},
233242
deleteConnection: (state, { payload: { connectionId } }) => {
234243
return R.dissocPath(["connections", connectionId], state)

0 commit comments

Comments
 (0)