feat: add logger highlighting, support regular and case matching

This commit is contained in:
huzibaca 2024-11-19 04:10:10 +08:00
parent 2a7b22c96f
commit 95123aceb5
No known key found for this signature in database
GPG Key ID: D4364EE4851DC302
3 changed files with 41 additions and 23 deletions

View File

@ -7,20 +7,19 @@ import matchCaseIcon from "@/assets/image/component/match_case.svg?react";
import matchWholeWordIcon from "@/assets/image/component/match_whole_word.svg?react";
import useRegularExpressionIcon from "@/assets/image/component/use_regular_expression.svg?react";
export type SearchState = {
text: string;
matchCase: boolean;
matchWholeWord: boolean;
useRegularExpression: boolean;
};
type SearchProps = {
placeholder?: string;
matchCase?: boolean;
matchWholeWord?: boolean;
useRegularExpression?: boolean;
onSearch: (
match: (content: string) => boolean,
state: {
text: string;
matchCase: boolean;
matchWholeWord: boolean;
useRegularExpression: boolean;
}
) => void;
onSearch: (match: (content: string) => boolean, state: SearchState) => void;
};
export const BaseSearchBox = styled((props: SearchProps) => {
@ -28,10 +27,10 @@ export const BaseSearchBox = styled((props: SearchProps) => {
const inputRef = useRef<HTMLInputElement>(null);
const [matchCase, setMatchCase] = useState(props.matchCase ?? false);
const [matchWholeWord, setMatchWholeWord] = useState(
props.matchWholeWord ?? false
props.matchWholeWord ?? false,
);
const [useRegularExpression, setUseRegularExpression] = useState(
props.useRegularExpression ?? false
props.useRegularExpression ?? false,
);
const [errorMessage, setErrorMessage] = useState("");
@ -60,7 +59,7 @@ export const BaseSearchBox = styled((props: SearchProps) => {
matchCase,
matchWholeWord,
useRegularExpression,
}
},
);
};

View File

@ -1,4 +1,5 @@
import { styled, Box } from "@mui/material";
import { SearchState } from "@/components/base/base-search-box";
const Item = styled(Box)(({ theme: { palette, typography } }) => ({
padding: "8px 0",
@ -41,24 +42,41 @@ const Item = styled(Box)(({ theme: { palette, typography } }) => ({
interface Props {
value: ILogItem;
searchText?: string;
searchState?: SearchState;
}
const LogItem = ({ value, searchText }: Props) => {
const LogItem = ({ value, searchState }: Props) => {
const renderHighlightText = (text: string) => {
if (!searchText?.trim()) return text;
if (!searchState?.text.trim()) return text;
try {
const parts = text.split(new RegExp(`(${searchText})`, "gi"));
return parts.map((part, index) =>
part.toLowerCase() === searchText.toLowerCase() ? (
const searchText = searchState.text;
let pattern: string;
if (searchState.useRegularExpression) {
try {
new RegExp(searchText);
pattern = searchText;
} catch {
pattern = searchText.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
} else {
const escaped = searchText.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
pattern = searchState.matchWholeWord ? `\\b${escaped}\\b` : escaped;
}
const flags = searchState.matchCase ? "g" : "gi";
const parts = text.split(new RegExp(`(${pattern})`, flags));
return parts.map((part, index) => {
return index % 2 === 1 ? (
<span key={index} className="highlight">
{part}
</span>
) : (
part
),
);
);
});
} catch {
return text;
}

View File

@ -15,6 +15,7 @@ import LogItem from "@/components/log/log-item";
import { useTheme } from "@mui/material/styles";
import { BaseSearchBox } from "@/components/base/base-search-box";
import { BaseStyledSelect } from "@/components/base/base-styled-select";
import { SearchState } from "@/components/base/base-search-box";
const LogPage = () => {
const { t } = useTranslation();
@ -27,7 +28,7 @@ const LogPage = () => {
);
const [match, setMatch] = useState(() => (_: string) => true);
const logData = useLogData(logLevel);
const [searchText, setSearchText] = useState("");
const [searchState, setSearchState] = useState<SearchState>();
const filterLogs = useMemo(() => {
return logData
@ -96,7 +97,7 @@ const LogPage = () => {
<BaseSearchBox
onSearch={(matcher, state) => {
setMatch(() => matcher);
setSearchText(state.text);
setSearchState(state);
}}
/>
</Box>
@ -114,7 +115,7 @@ const LogPage = () => {
initialTopMostItemIndex={999}
data={filterLogs}
itemContent={(index, item) => (
<LogItem value={item} searchText={searchText} />
<LogItem value={item} searchState={searchState} />
)}
followOutput={"smooth"}
/>