feat(logs): support search/filter logs

This commit is contained in:
Haishan 2019-01-14 00:24:23 +08:00
parent eb76f7c194
commit fd07fae633
7 changed files with 63 additions and 48 deletions

View file

@ -0,0 +1,7 @@
import Search from './Search';
import { getSearchText, updateSearchText } from 'd/logs';
const mapStateToProps = s => ({ searchText: getSearchText(s) });
const actions = { updateSearchText };
export default Search({ mapStateToProps, actions });

View file

@ -10,6 +10,7 @@ import ContentHeader from 'c/ContentHeader';
import useRemainingViewPortHeight from '../hooks/useRemainingViewPortHeight';
// TODO move this into a redux action
import { fetchLogs } from '../api/logs';
import LogSearch from './LogSearch';
import { getLogsForDisplay, appendLog } from 'd/logs';
import yacd from 's/yacd.svg';
@ -72,6 +73,7 @@ export default function Logs() {
return (
<div>
<ContentHeader title="Logs" />
<LogSearch />
<div ref={refLogsContainer} style={{ paddingBottom }}>
{logs.length === 0 ? (
<div

View file

@ -1,49 +1,7 @@
import React, { useState, useMemo } from 'react';
import Icon from 'c/Icon';
import search from 's/search.svg';
import { useActions, useStoreState } from 'm/store';
import debounce from 'lodash-es/debounce';
import s0 from './RuleSearch.module.scss';
import Search from './Search';
import { getSearchText, updateSearchText } from 'd/rules';
const mapStateToProps = s => ({
searchText: getSearchText(s)
});
const mapStateToProps = s => ({ searchText: getSearchText(s) });
const actions = { updateSearchText };
export default React.memo(function RuleSearch() {
const { updateSearchText } = useActions(actions);
const updateSearchTextDebounced = useMemo(
() => debounce(updateSearchText, 300),
[updateSearchText]
);
const { searchText } = useStoreState(mapStateToProps);
const [text, setText] = useState(searchText);
const onChange = e => {
setText(e.target.value);
updateSearchTextDebounced(e.target.value);
};
return (
<div className={s0.RuleSearch}>
<div className={s0.RuleSearchContainer}>
<div className={s0.inputWrapper}>
<input
type="text"
value={text}
onChange={onChange}
className={s0.input}
/>
</div>
<div className={s0.iconWrapper}>
<Icon id={search.id} />
</div>
</div>
</div>
);
});
export default Search({ mapStateToProps, actions });

45
src/components/Search.js Normal file
View file

@ -0,0 +1,45 @@
import React, { memo, useState, useMemo } from 'react';
import Icon from 'c/Icon';
import search from 's/search.svg';
import { useActions, useStoreState } from 'm/store';
import debounce from 'lodash-es/debounce';
import s0 from './Search.module.scss';
function getSerachComponent({ mapStateToProps, actions }) {
return memo(function RuleSearch() {
const { updateSearchText } = useActions(actions);
const updateSearchTextDebounced = useMemo(
() => debounce(updateSearchText, 300),
[updateSearchText]
);
const { searchText } = useStoreState(mapStateToProps);
const [text, setText] = useState(searchText);
const onChange = e => {
setText(e.target.value);
updateSearchTextDebounced(e.target.value);
};
return (
<div className={s0.RuleSearch}>
<div className={s0.RuleSearchContainer}>
<div className={s0.inputWrapper}>
<input
type="text"
value={text}
onChange={onChange}
className={s0.input}
/>
</div>
<div className={s0.iconWrapper}>
<Icon id={search.id} />
</div>
</div>
</div>
);
});
}
export default getSerachComponent;

View file

@ -7,10 +7,12 @@ const LogSize = 300;
const getLogs = s => s.logs.logs;
const getTail = s => s.logs.tail;
export const getSearchText = s => s.logs.searchText;
export const getLogsForDisplay = createSelector(
getLogs,
getTail,
(logs, tail) => {
getSearchText,
(logs, tail, searchText) => {
const x = [];
for (let i = tail; i >= 0; i--) {
x.push(logs[i]);
@ -20,7 +22,9 @@ export const getLogsForDisplay = createSelector(
x.push(logs[i]);
}
}
return x;
if (searchText === '') return x;
return x.filter(r => r.payload.toLowerCase().indexOf(searchText) >= 0);
}
);

View file

@ -1,7 +1,6 @@
import * as rulesAPI from 'a/rules';
import { getClashAPIConfig } from 'd/app';
import invariant from 'invariant';
// import { debounce } from 'lodash-es';
import { createSelector } from 'reselect';
export const getAllRules = s => s.rules.allRules;