Skip to content

Commit

Permalink
feat: support two search mode
Browse files Browse the repository at this point in the history
  • Loading branch information
wtlin1228 committed Oct 5, 2024
1 parent 748c06f commit f0e82b7
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 19 deletions.
41 changes: 32 additions & 9 deletions crates/api_server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use dt_core::{
portable::Portable,
tracker::{DependencyTracker, TraceTarget},
};
use serde::Serialize;
use serde::{Deserialize, Serialize};
use std::{
collections::{HashMap, HashSet},
fs::File,
Expand All @@ -32,19 +32,40 @@ struct SearchResponse {
trace_result: HashMap<String, HashMap<String, HashMap<String, Vec<Vec<Step>>>>>,
}

#[get("/search/{search}")]
#[derive(Deserialize)]
struct Info {
q: String,
exact_match: bool,
}

#[get("/search")]
async fn search(
data: web::Data<AppState>,
path: web::Path<String>,
info: web::Query<Info>,
) -> Result<web::Json<SearchResponse>> {
let search = path.into_inner();
let search = &info.q;
let exact_match = info.exact_match;

// TODO: deal with search mode
let mut matched_i18n_keys: Vec<String> = Vec::new();
for (i18n_key, translation) in data.translation_json.iter() {
if translation == &search {
matched_i18n_keys.push(i18n_key.to_owned());
match exact_match {
true => {
for (i18n_key, translation) in data.translation_json.iter() {
if translation == search {
matched_i18n_keys.push(i18n_key.to_owned());
}
}
}
false => {
for (i18n_key, translation) in data.translation_json.iter() {
if translation.contains(search) {
matched_i18n_keys.push(i18n_key.to_owned());
}
}
}
}

if matched_i18n_keys.len() == 0 {
return Err(error::ErrorNotFound(format!("No result for {}", search)));
}

let mut dependency_tracker = DependencyTracker::new(&data.used_by_graph, true);
Expand Down Expand Up @@ -122,7 +143,9 @@ async fn search(
#[actix_web::main]
async fn main() -> std::io::Result<()> {
// TODO: get portable path from args
let mut file = File::open("<the portable path>")?;
// let mut file = File::open("<the portable path>")?;
let mut file =
File::open("/Users/linweitang/rust/js-symbol-dependency-tracker/outputs/naopleon-06.json")?;
let mut exported = String::new();
file.read_to_string(&mut exported)?;
let portable = Portable::import(&exported).unwrap();
Expand Down
13 changes: 8 additions & 5 deletions web/src/search/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ export type SearchResult = {
trace_result: TraceResult;
};

export async function getSearchResult(search: string): Promise<SearchResult> {
const url = `http://127.0.0.1:8080/search/${encodeURIComponent(search)}`;
export async function getSearchResult(
search: string,
exactMatch: boolean
): Promise<SearchResult> {
const url = `http://127.0.0.1:8080/search?q=${encodeURIComponent(
search
)}&exact_match=${exactMatch}`;

if (search === "demo") {
return mockedSearchResult;
Expand All @@ -25,8 +30,6 @@ export async function getSearchResult(search: string): Promise<SearchResult> {
return data;
} catch (error) {
// Handle and re-throw the error so React Query can capture it
throw new Error(
`Failed to fetch search results: ${(error as Error).message}`
);
throw new Error((error as Error).message);
}
}
20 changes: 18 additions & 2 deletions web/src/search/components/SearchInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,19 @@ import Paper from "@mui/material/Paper";
import InputBase from "@mui/material/InputBase";
import IconButton from "@mui/material/IconButton";
import SearchIcon from "@mui/icons-material/Search";
import BlurOffIcon from "@mui/icons-material/BlurOff";
import BlurOnIcon from "@mui/icons-material/BlurOn";

export function CustomizedInputBase({
handleSearch,
isSearching,
exactMatch,
setExactMatch,
}: {
handleSearch: (search: string) => void;
isSearching: boolean;
exactMatch: boolean;
setExactMatch: (b: boolean) => void;
}) {
const inputRef = React.useRef<HTMLInputElement>();

Expand All @@ -34,8 +40,8 @@ export function CustomizedInputBase({
<InputBase
fullWidth
sx={{ ml: 1, flex: 1 }}
placeholder="Search Translation Key"
inputProps={{ "aria-label": "search translation key" }}
placeholder="Search Translation"
inputProps={{ "aria-label": "search translation" }}
inputRef={inputRef}
disabled={isSearching}
/>
Expand All @@ -55,6 +61,16 @@ export function CustomizedInputBase({
>
<SearchIcon />
</IconButton>
<IconButton
type="button"
sx={{ p: "10px" }}
aria-label="toggle match whole word"
onClick={() => {
setExactMatch(!exactMatch);
}}
>
{exactMatch ? <BlurOffIcon /> : <BlurOnIcon />}
</IconButton>
</Paper>
);
}
7 changes: 6 additions & 1 deletion web/src/search/components/TreeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,12 @@ export const TreeView = React.memo(function TreeView({
data: SearchResult;
}) {
return (
<Box>
<Box
sx={{
"overflow-x": "scroll",
pb: 2,
}}
>
<StyledTreeView>
{Object.entries(data.trace_result).map(
([i18nKey, urlToTraceTargets]) => (
Expand Down
7 changes: 5 additions & 2 deletions web/src/search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import { getSearchResult } from "./api";

export const Search = () => {
const [search, setSearch] = React.useState<undefined | string>();
const [exactMatch, setExactMatch] = React.useState<boolean>(true);
const { isPending, isLoading, isError, data, error } = useQuery({
queryKey: ["search", search],
queryFn: () => getSearchResult(search!),
queryKey: ["search", search, exactMatch],
queryFn: () => getSearchResult(search!, exactMatch),
enabled: search !== undefined,
staleTime: 5 * 1000,
retry: false,
Expand All @@ -34,6 +35,8 @@ export const Search = () => {
setSearch(search);
}}
isSearching={isLoading}
exactMatch={exactMatch}
setExactMatch={setExactMatch}
/>
<Paper elevation={1} sx={{ padding: 2 }}>
{isPending ? (
Expand Down

0 comments on commit f0e82b7

Please sign in to comment.