Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: reuse table filter component in recurring actions feature #7328

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions web/html/src/components/table/TableFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useState } from "react";

import { Select } from "components/input";
import { Form } from "components/input/Form";
import { SelectSearchField } from "components/table/SelectSearchField";

const renderSearchField = (props) => {
const { field } = props;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works, but feels a bit weird. I think it would make sense to either destruct everything (const { field, criteria, placeholder, onSearch, name } = props), or destruct nothing and use props.field in the line below this one. I think the latter makes more sense, but either way is fine with me as long as it's consistent.

const selectedOption = props.filterOptions.find((it) => it.value === field);
if (selectedOption?.filterOptions) {
return <SelectSearchField label={selectedOption.label} options={selectedOption.filterOptions} {...props} />;
}
return (
<div className="form-group">
<input
className="form-control"
value={props.criteria || ""}
placeholder={props.placeholder}
type="text"
onChange={(e) => props.onSearch?.(e.target.value)}
name={props.name}
/>
</div>
);
};

export const TableFilter = (props) => {
// Dummy model and onChange to reuse the Select component as it requires a Form
let model = {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this doesn't change it can be const.

const onChange = () => {};

const [selectedFilter, setSelectedFilter] = useState(props.field || "");
const handleChangeFilter = (value) => {
setSelectedFilter(value);
props.onSearchField?.(value);
};

return (
<Form model={model} onChange={onChange} title={t("Filter")} className="row">
<div className="col-sm-4">
<Select
name="filter"
placeholder={t("Select a filter")}
defaultValue={selectedFilter}
options={props.filterOptions}
onChange={(_name: string | undefined, value: string) => handleChangeFilter(value)}
/>
</div>
<div className="col-sm-6">{props.field && renderSearchField(props)}</div>
</Form>
);
};

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
// Field options for filtering in recurring actions list.
const SCHEDULE_NAME_OPTION = { value: "schedule_name", label: t("Schedule Name") };
const TARGET_NAME_OPTION = { value: "target_name", label: t("Target Name") };
export const TARGET_TYPE_OPTION = { value: "target_type", label: t("Target Type") };
export const ACTION_TYPE_OPTION = { value: "action_type", label: t("Action Type") };

export const SEARCH_FIELD_OPTIONS = [SCHEDULE_NAME_OPTION, TARGET_TYPE_OPTION, TARGET_NAME_OPTION, ACTION_TYPE_OPTION];

// Value options for filtering by Target Type in recurring actions list
export const ALL_OPTION = { value: "ALL", label: t("All") };
const ORG_OPTION = { value: "ORG", label: t("Organization") };
const GROUP_OPTION = { value: "GROUP", label: t("Group") };
const MINION_OPTION = { value: "MINION", label: t("Minion") };
export const TARGET_TYPE_OPTIONS = [ALL_OPTION, ORG_OPTION, GROUP_OPTION, MINION_OPTION];
export const TARGET_TYPE_OPTIONS = [ORG_OPTION, GROUP_OPTION, MINION_OPTION];

// Value options for filtering by Action Type in recurring actions list
const HIGHSTATE_OPTION = { value: "HIGHSTATE", label: t("Highstate") };
const CUSTOM_STATE_OPTION = { value: "CUSTOM_STATE", label: t("Custom State") };
export const ACTION_TYPE_OPTIONS = [ALL_OPTION, CUSTOM_STATE_OPTION, HIGHSTATE_OPTION];
export const ACTION_TYPE_OPTIONS = [CUSTOM_STATE_OPTION, HIGHSTATE_OPTION];

// Field options for filtering in recurring actions list.
const SCHEDULE_NAME_OPTION = { value: "schedule_name", label: t("Schedule Name") };
const TARGET_NAME_OPTION = { value: "target_name", label: t("Target Name") };
export const TARGET_TYPE_OPTION = { value: "target_type", label: t("Target Type"), filterOptions: TARGET_TYPE_OPTIONS };
export const ACTION_TYPE_OPTION = { value: "action_type", label: t("Action Type"), filterOptions: ACTION_TYPE_OPTIONS };

export const SEARCH_FIELD_OPTIONS = [SCHEDULE_NAME_OPTION, TARGET_TYPE_OPTION, TARGET_NAME_OPTION, ACTION_TYPE_OPTION];
Original file line number Diff line number Diff line change
@@ -1,57 +1,7 @@
import { useState } from "react";
import { TableFilter } from "components/table/TableFilter";

import { Select } from "components/input";
import { Form } from "components/input/Form";

import { ActionTypeFilter } from "./recurring-actions-search-action-type-filter";
import { TargetTypeFilter } from "./recurring-actions-search-target-type-filter";
import { ACTION_TYPE_OPTION, SEARCH_FIELD_OPTIONS, TARGET_TYPE_OPTION } from "./recurring-actions-search-utils";

const renderSearchField = (props) => {
const { field } = props;
if (field === TARGET_TYPE_OPTION.value) {
return <TargetTypeFilter {...props} />;
} else if (field === ACTION_TYPE_OPTION.value) {
return <ActionTypeFilter {...props} />;
}
return (
<div className="form-group">
<input
className="form-control"
value={props.criteria || ""}
placeholder={props.placeholder}
type="text"
onChange={(e) => props.onSearch?.(e.target.value)}
name={props.name}
/>
</div>
);
};
import { SEARCH_FIELD_OPTIONS } from "./recurring-actions-search-utils";

export const RecurringActionsSearch = (props) => {
// Dummy model and onChange to reuse the Select component as it requires a Form
let model = {};
const onChange = () => {};

const [filterValue, setFilterValue] = useState("");
const handleChangeSearchField = (value) => {
setFilterValue(value);
props.onSearchField?.(value);
};

return (
<Form model={model} onChange={onChange} title={t("Filter")} className="row">
<div className="col-sm-4">
<Select
name="filter"
placeholder={t("Select a filter")}
defaultValue={filterValue}
options={SEARCH_FIELD_OPTIONS}
inputClass="col-sm-12"
onChange={(name: string | undefined, value: string) => handleChangeSearchField(value)}
/>
</div>
<div className="col-sm-6">{props.field && renderSearchField(props)}</div>
</Form>
);
return <TableFilter filterOptions={SEARCH_FIELD_OPTIONS} {...props} />;
};
51 changes: 2 additions & 49 deletions web/html/src/manager/systems/list-filter.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import { useState } from "react";

import { Select } from "components/input";
import { Form } from "components/input/Form";
import { SelectSearchField } from "components/table/SelectSearchField";
import { TableFilter } from "components/table/TableFilter";

const SYSTEM_KIND_OPTIONS = [
{ value: "mgr_server", label: t("Manager Server") },
Expand Down Expand Up @@ -56,49 +52,6 @@ const allListOptions = [
{ value: "group_count", label: t("Groups") },
];

const renderSearchField = (props) => {
const { field } = props;
const selectedOption = allListOptions.find((it) => it.value === field);
if (selectedOption?.filterOptions) {
return <SelectSearchField label={selectedOption.label} options={selectedOption.filterOptions} {...props} />;
}
return (
<div className="form-group">
<input
className="form-control"
value={props.criteria || ""}
placeholder={props.placeholder}
type="text"
onChange={(e) => props.onSearch?.(e.target.value)}
name={props.name}
/>
</div>
);
};

export const SystemsListFilter = (props) => {
// Dummy model and onChange to reuse the Select component as it requires a Form
let model = {};
const onChange = () => {};

const [filterValue, setFilterValue] = useState(props.field || "");
const handleChangeSearchField = (value) => {
setFilterValue(value);
props.onSearchField?.(value);
};

return (
<Form model={model} onChange={onChange} title={t("Filter")} className="row">
<div className="col-sm-4">
<Select
name="filter"
placeholder={t("Select a filter")}
defaultValue={filterValue}
options={allListOptions}
onChange={(_name: string | undefined, value: string) => handleChangeSearchField(value)}
/>
</div>
<div className="col-sm-6">{props.field && renderSearchField(props)}</div>
</Form>
);
return <TableFilter filterOptions={allListOptions} {...props} />;
};
Loading