mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-14 01:15:44 +01:00
refactor FilterInput component / enable delayed instant search
This commit is contained in:
@@ -21,66 +21,53 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
import React, { ChangeEvent, FormEvent } from "react";
|
import React, { FC, FormEvent, useEffect, useState } from "react";
|
||||||
import { WithTranslation, withTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { createAttributesForTesting } from "../devBuild";
|
import { createAttributesForTesting } from "../devBuild";
|
||||||
|
|
||||||
type Props = WithTranslation & {
|
type Props = {
|
||||||
filter: (p: string) => void;
|
filter: (p: string) => void;
|
||||||
value?: string;
|
value?: string;
|
||||||
testId?: string;
|
testId?: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = {
|
|
||||||
value: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const FixedHeightInput = styled.input`
|
const FixedHeightInput = styled.input`
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
class FilterInput extends React.Component<Props, State> {
|
const FilterInput: FC<Props> = ({ filter, value, testId, placeholder }) => {
|
||||||
constructor(props: Props) {
|
const [stateValue, setStateValue] = useState(value || "");
|
||||||
super(props);
|
const [timeoutId, setTimeoutId] = useState(0);
|
||||||
this.state = {
|
const [t] = useTranslation("commons");
|
||||||
value: this.props.value ? this.props.value : ""
|
|
||||||
};
|
useEffect(() => {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
if (!stateValue) {
|
||||||
|
// no delay if filter input was deleted
|
||||||
|
filter(stateValue);
|
||||||
|
} else {
|
||||||
|
// with delay while typing
|
||||||
|
const id = setTimeout(() => filter(stateValue), 1000);
|
||||||
|
setTimeoutId(id);
|
||||||
}
|
}
|
||||||
|
}, [stateValue]);
|
||||||
|
|
||||||
handleChange = (event: ChangeEvent<HTMLInputElement>) => {
|
const handleSubmit = (event: FormEvent) => {
|
||||||
this.setState({
|
filter(stateValue);
|
||||||
value: event.target.value
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleSubmit = (event: FormEvent) => {
|
|
||||||
this.props.filter(this.state.value);
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidUpdate = ({ value: oldValue }: Props) => {
|
|
||||||
const { value: newValue } = this.props;
|
|
||||||
const { value: stateValue } = this.state;
|
|
||||||
if (oldValue !== newValue && newValue !== stateValue) {
|
|
||||||
this.setState({
|
|
||||||
value: newValue || ""
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { t, testId, placeholder } = this.props;
|
|
||||||
return (
|
return (
|
||||||
<form className="input-field" onSubmit={this.handleSubmit} {...createAttributesForTesting(testId)}>
|
<form className="input-field" onSubmit={handleSubmit} {...createAttributesForTesting(testId)}>
|
||||||
<div className="control has-icons-left">
|
<div className="control has-icons-left">
|
||||||
<FixedHeightInput
|
<FixedHeightInput
|
||||||
className="input"
|
className="input"
|
||||||
type="search"
|
type="search"
|
||||||
placeholder={placeholder || t("filterEntries")}
|
placeholder={placeholder || t("filterEntries")}
|
||||||
value={this.state.value}
|
value={stateValue}
|
||||||
onChange={this.handleChange}
|
onChange={event => setStateValue(event.target.value)}
|
||||||
/>
|
/>
|
||||||
<span className="icon is-small is-left">
|
<span className="icon is-small is-left">
|
||||||
<i className="fas fa-search" />
|
<i className="fas fa-search" />
|
||||||
@@ -88,7 +75,6 @@ class FilterInput extends React.Component<Props, State> {
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default withTranslation("commons")(FilterInput);
|
export default FilterInput;
|
||||||
|
|||||||
@@ -12435,10 +12435,10 @@ mini-create-react-context@^0.4.0:
|
|||||||
"@babel/runtime" "^7.5.5"
|
"@babel/runtime" "^7.5.5"
|
||||||
tiny-warning "^1.0.3"
|
tiny-warning "^1.0.3"
|
||||||
|
|
||||||
mini-css-extract-plugin@^0.11.0:
|
mini-css-extract-plugin@^0.12.0:
|
||||||
version "0.11.3"
|
version "0.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.3.tgz#15b0910a7f32e62ffde4a7430cfefbd700724ea6"
|
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.12.0.tgz#ddeb74fd6304ca9f99c1db74acc7d5b507705454"
|
||||||
integrity sha512-n9BA8LonkOkW1/zn+IbLPQmovsL0wMb9yx75fMJQZf2X1Zoec9yTZtyMePcyu19wPkmFbzZZA6fLTotpFhQsOA==
|
integrity sha512-z6PQCe9rd1XUwZ8gMaEVwwRyZlrYy8Ba1gRjFP5HcV51HkXX+XlwZ+a1iAYTjSYwgNBXoNR7mhx79mDpOn5fdw==
|
||||||
dependencies:
|
dependencies:
|
||||||
loader-utils "^1.1.0"
|
loader-utils "^1.1.0"
|
||||||
normalize-url "1.9.1"
|
normalize-url "1.9.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user