Skip to content

Commit

Permalink
Retain filter string for contains and match types (#223)
Browse files Browse the repository at this point in the history
* Show filter value in SearchBox for CONTAINS and MATCH filters
  • Loading branch information
adrianmroz authored Nov 5, 2018
1 parent 2796379 commit a2cf9c9
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 64 deletions.
24 changes: 15 additions & 9 deletions src/client/components/clearable-input/clearable-input.mocha.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,31 @@
*/

import { expect } from "chai";
import { shallow } from "enzyme";
import * as React from "react";
import * as ReactDOM from "react-dom";
import * as TestUtils from "react-dom/test-utils";

import { renderIntoDocument } from "../../utils/test-utils";

import { ClearableInput } from "./clearable-input";

describe("ClearableInput", () => {
it("adds the correct class", () => {
var renderedComponent = renderIntoDocument(
it("should add empty class name", () => {
const renderedComponent = shallow(
<ClearableInput
onChange={null}
value={null}
/>
);

expect(TestUtils.isCompositeComponent(renderedComponent), "should be composite").to.equal(true);
expect(ReactDOM.findDOMNode(renderedComponent).className, "should contain class").to.contain("clearable-input");
expect(renderedComponent.hasClass("empty")).to.be.true;
});

it("should add custom class name", () => {
const renderedComponent = shallow(
<ClearableInput
onChange={null}
value={null}
className="foobar"
/>
);

expect(renderedComponent.hasClass("foobar")).to.be.true;
});
});
74 changes: 30 additions & 44 deletions src/client/components/clearable-input/clearable-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ import * as React from "react";
import { SvgIcon } from "../svg-icon/svg-icon";
import "./clearable-input.scss";

function focusOnInput(component: HTMLInputElement): any {
if (!component) return;
(component as any).focus();
function focusOnInput(input: HTMLInputElement): any {
if (!input) return;
input.focus();
const length = input.value.length;
input.setSelectionRange(length, length);
}

export interface ClearableInputProps {
Expand All @@ -34,44 +36,28 @@ export interface ClearableInputProps {
onBlur?: React.FocusEventHandler<HTMLElement>;
}

export interface ClearableInputState {
}

export class ClearableInput extends React.Component<ClearableInputProps, ClearableInputState> {
static defaultProps = {
type: "text",
value: ""
};

onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
this.props.onChange(e.target.value);
}

onClear = () => {
this.props.onChange("");
}

render() {
const { className, type, placeholder, focusOnMount, value, onBlur } = this.props;

const ref = focusOnMount ? focusOnInput : null;

const classNames = ["clearable-input"];
if (className) classNames.push(className);
if (!value) classNames.push("empty");

return <div className={classNames.join(" ")}>
<input
type={type}
placeholder={placeholder}
value={value}
onChange={this.onChange}
onBlur={onBlur}
ref={ref}
/>
<div className="clear" onClick={this.onClear}>
<SvgIcon svg={require("../../icons/x.svg")} />
</div>
</div>;
}
}
export const ClearableInput: React.SFC<ClearableInputProps> = ({ className, placeholder, focusOnMount, onBlur, onChange, value = "", type = "text" }) => {
const change = (e: React.ChangeEvent<HTMLInputElement>) => onChange(e.target.value);

const clear = () => onChange("");

const ref = focusOnMount ? focusOnInput : null;

const classNames = ["clearable-input"];
if (className) classNames.push(className);
if (!value) classNames.push("empty");

return <div className={classNames.join(" ")}>
<input
type={type}
placeholder={placeholder}
value={value}
onChange={change}
onBlur={onBlur}
ref={ref}
/>
<div className="clear" onClick={clear}>
<SvgIcon svg={require("../../icons/x.svg")} />
</div>
</div>;
};
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export class GlobalEventListener extends React.Component<GlobalEventListenerProp
if (this.props.mouseUp) this.props.mouseUp(e);
}

onKeydown(e: KeyboardEvent) {
onKeydown = (e: KeyboardEvent) => {
if (this.props.escape && escapeKey(e)) this.props.escape(e);
if (this.props.enter && enterKey(e)) this.props.enter(e);
if (this.props.right && rightKey(e)) this.props.right(e);
Expand Down
28 changes: 18 additions & 10 deletions src/client/components/string-filter-menu/string-filter-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { Clicker } from "../../../common/models/clicker/clicker";
import { Dimension } from "../../../common/models/dimension/dimension";
import { DragPosition } from "../../../common/models/drag-position/drag-position";
import { Essence } from "../../../common/models/essence/essence";
import { FilterClause } from "../../../common/models/filter-clause/filter-clause";
import { FilterClause, StringFilterAction, StringFilterClause } from "../../../common/models/filter-clause/filter-clause";
import { Filter, FilterMode } from "../../../common/models/filter/filter";
import { Stage } from "../../../common/models/stage/stage";
import { Timekeeper } from "../../../common/models/timekeeper/timekeeper";
Expand Down Expand Up @@ -57,22 +57,30 @@ export class StringFilterMenu extends React.Component<StringFilterMenuProps, Str
super(props);
this.state = {
filterMode: null,
searchText: null
searchText: ""
};
}

componentWillMount() {
var { essence, dimension } = this.props;
var { colors } = essence;
const { essence: { colors, filter }, dimension } = this.props;

var filterMode = essence.filter.getModeForDimension(dimension);
const filterMode = filter.getModeForDimension(dimension);
if (filterMode && !this.state.filterMode) {
this.setState({ filterMode });
const searchText = this.getInitialSearchText();
this.setState({ filterMode, searchText });
} else if (colors) {
this.setState({ filterMode: FilterMode.INCLUDE });
}
}

getInitialSearchText(): string {
const { essence, dimension } = this.props;
const filterClause = essence.filter.getClauseForDimension(dimension);
if (!(filterClause instanceof StringFilterClause)) throw new Error(`Expected StringFilterClause. Got ${filterClause}`);
if (filterClause.action === StringFilterAction.IN) return "";
return filterClause.values.first();
}

onSelectFilterOption = (filterMode: FilterMode) => {
this.setState({ filterMode });
}
Expand All @@ -83,7 +91,7 @@ export class StringFilterMenu extends React.Component<StringFilterMenuProps, Str

updateFilter: (clause: FilterClause) => Filter = clause => {
const { essence, dimension, changePosition } = this.props;
var { filter } = essence;
const { filter } = essence;

if (!clause) return filter.removeClause(dimension.name);
if (changePosition) {
Expand All @@ -101,7 +109,7 @@ export class StringFilterMenu extends React.Component<StringFilterMenuProps, Str
const { dimension } = this.props;
const dimensionKind = dimension.kind;

var filterOptions: FilterOption[] = FilterOptionsDropdown.getFilterOptions(FilterMode.INCLUDE, FilterMode.EXCLUDE);
let filterOptions: FilterOption[] = FilterOptionsDropdown.getFilterOptions(FilterMode.INCLUDE, FilterMode.EXCLUDE);
if (dimensionKind !== "boolean") filterOptions = filterOptions.concat(FilterOptionsDropdown.getFilterOptions(FilterMode.REGEX, FilterMode.CONTAINS));

return filterOptions;
Expand Down Expand Up @@ -134,8 +142,8 @@ export class StringFilterMenu extends React.Component<StringFilterMenuProps, Str
const { filterMode, searchText } = this.state;
if (!dimension) return null;

var menuSize: Stage = null;
var menuCont: JSX.Element = null;
let menuSize: Stage = null;
let menuCont: JSX.Element = null;

if (filterMode === FilterMode.REGEX || filterMode === FilterMode.CONTAINS) {
menuSize = Stage.fromSize(350, 410);
Expand Down

0 comments on commit a2cf9c9

Please sign in to comment.