Skip to content

Commit

Permalink
move groups UI into header
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielburnworth committed Jul 13, 2022
1 parent e1c75f7 commit 3e05352
Show file tree
Hide file tree
Showing 17 changed files with 162 additions and 146 deletions.
9 changes: 4 additions & 5 deletions frontend/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ export namespace ToolTips {
every time, so the ordering shown below will only be representative.`);

export const CRITERIA_SELECTION_COUNT =
trim(`Filter additions can only be removed by changing filters.
Click and drag in the map to modify selection filters.
Filters will be applied at the time of sequence execution. The final
selection at that time may differ from the selection currently
displayed.`);
trim(`Manually add group members by clicking in the map. Group members
selected by filters can only be removed by changing the filters.
Filters will be applied at the time of sequence execution.
Group members at that time may differ from those currently displayed.`);

export const DOT_NOTATION_TIP =
trim(`Tip: Use dot notation (i.e., 'meta.color') to access meta fields.`);
Expand Down
20 changes: 19 additions & 1 deletion frontend/css/farm_designer/farm_designer_panels.scss
Original file line number Diff line number Diff line change
Expand Up @@ -1670,6 +1670,20 @@ li {
}

.group-detail-panel {
.panel-header-icon-group {
display: flex;
float: right;
padding: 1.5rem;
.fa-sort {
margin-top: 0.25rem;
color: $white;
}
.fa-trash {
margin-top: 0.25rem;
margin-left: 1rem;
color: $dark_red;
}
}
.panel-content {
max-height: calc(100vh - 14rem);
overflow-y: auto;
Expand Down Expand Up @@ -1915,6 +1929,7 @@ li {
.lt-gt-criteria,
.location-criteria {
display: inline-block;
position: relative;
.row {
margin-left: 0;
margin-right: -2.5rem;
Expand All @@ -1937,7 +1952,9 @@ li {
margin-top: 2rem !important;
}
.edit-in-map {
float: right;
position: absolute;
top: 0;
right: 0;
button {
margin: 1rem !important;
width: 5rem !important;
Expand Down Expand Up @@ -2440,6 +2457,7 @@ li {
}
}

.group-detail-panel,
.designer-regimen-editor-panel,
.designer-sequence-editor-panel {
.panel-header {
Expand Down
4 changes: 2 additions & 2 deletions frontend/point_groups/__tests__/actions_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe("createGroup()", () => {
expect(init).toHaveBeenCalledWith("PointGroup", expect.objectContaining({
name: "Name123",
point_ids: [1, 2],
sort_type: "xy_ascending",
sort_type: "nn",
criteria: DEFAULT_CRITERIA,
}));
expect(save).toHaveBeenCalledWith("???");
Expand All @@ -62,7 +62,7 @@ describe("createGroup()", () => {
expect(init).toHaveBeenCalledWith("PointGroup", expect.objectContaining({
name: "Untitled Group",
point_ids: [4],
sort_type: "xy_ascending",
sort_type: "nn",
criteria: DEFAULT_CRITERIA,
}));
expect(save).toHaveBeenCalledWith("???");
Expand Down
77 changes: 20 additions & 57 deletions frontend/point_groups/__tests__/group_detail_active_test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
jest.mock("../../api/crud", () => ({
save: jest.fn(),
overwrite: jest.fn(),
edit: jest.fn(),
}));

jest.mock("../../farm_designer/map/actions", () => ({
setHoveredPlant: jest.fn(),
}));
Expand All @@ -15,26 +9,25 @@ jest.mock("../../plants/select_plants", () => ({
}));

jest.mock("../../ui/help", () => ({
Help: jest.fn(props => <p>{props.text}</p>),
Help: jest.fn(props => <p>{props.text}{props.customIcon}</p>),
}));

import React from "react";
import {
GroupDetailActive, GroupDetailActiveProps,
GroupDetailActive, GroupDetailActiveProps, GroupSortSelection,
GroupSortSelectionProps,
} from "../group_detail_active";
import { mount, shallow } from "enzyme";
import { mount } from "enzyme";
import {
fakePointGroup, fakePlant, fakePoint,
} from "../../__test_support__/fake_state/resources";
import { edit } from "../../api/crud";
import { SpecialStatus } from "farmbot";
import { DEFAULT_CRITERIA } from "../criteria/interfaces";
import { setSelectionPointType } from "../../plants/select_plants";
import { fakeToolTransformProps } from "../../__test_support__/fake_tool_info";
import { ToolTips } from "../../constants";
import { cloneDeep } from "lodash";

describe("<GroupDetailActive/>", () => {
describe("<GroupDetailActive />", () => {
const fakeProps = (): GroupDetailActiveProps => {
const plant = fakePlant();
plant.body.id = 1;
Expand Down Expand Up @@ -73,7 +66,6 @@ describe("<GroupDetailActive/>", () => {
const p = fakeProps();
p.group.specialStatus = SpecialStatus.SAVED;
const wrapper = mount(<GroupDetailActive {...p} />);
expect(wrapper.find("input").first().prop("defaultValue")).toContain("XYZ");
expect(wrapper.find(".group-member-display").length).toEqual(1);
});

Expand All @@ -85,58 +77,29 @@ describe("<GroupDetailActive/>", () => {
expect(setSelectionPointType).toHaveBeenCalledWith(undefined);
});

it("changes group name", () => {
const p = fakeProps();
const parentWrapper = shallow(<GroupDetailActive {...p} />);
const wrapper = shallow(parentWrapper.find("GroupNameInput").getElement());
wrapper.find("input").first().simulate("blur", {
currentTarget: { value: "new group name" }
});
expect(edit).toHaveBeenCalledWith(p.group, { name: "new group name" });
});

it("doesn't change group name", () => {
const p = fakeProps();
const parentWrapper = shallow(<GroupDetailActive {...p} />);
const wrapper = shallow(parentWrapper.find("GroupNameInput").getElement());
wrapper.find("input").first().simulate("blur", {
currentTarget: { value: "" }
});
expect(edit).not.toHaveBeenCalled();
});

it("shows paths", () => {
const p = fakeProps();
const wrapper = mount(<GroupDetailActive {...p} />);
expect(wrapper.text().toLowerCase()).toContain("0m");
});

it("shows random warning text", () => {
const p = fakeProps();
p.group.body.sort_type = "random";
const wrapper = mount(<GroupDetailActive {...p} />);
expect(wrapper.text()).toContain(ToolTips.SORT_DESCRIPTION);
});

it("doesn't show icons", () => {
const wrapper = mount(<GroupDetailActive {...fakeProps()} />);
wrapper.setState({ iconDisplay: false });
expect(wrapper.find(".groups-list-wrapper").length).toEqual(0);
});
});

describe("<GroupSortSelection />", () => {
const fakeProps = (): GroupSortSelectionProps => ({
group: fakePointGroup(),
dispatch: jest.fn(),
pointsSelectedByGroup: [fakePoint()],
});

it("doesn't show filters tooltip addition", () => {
const wrapper = mount(<GroupDetailActive {...fakeProps()} />);
expect(wrapper.text()).not.toContain(ToolTips.CRITERIA_SELECTION_COUNT);
it("renders", () => {
const wrapper = mount(<GroupSortSelection {...fakeProps()} />);
expect(wrapper.text().toLowerCase()).toContain("ascending");
});

it("shows filters tooltip addition", () => {
it("renders random notice", () => {
const p = fakeProps();
const point = fakePoint();
point.body.x = 0;
p.allPoints = [point];
p.group.body.point_ids = [];
p.group.body.criteria.number_eq = { x: [0] };
const wrapper = mount(<GroupDetailActive {...p} />);
expect(wrapper.text()).toContain(ToolTips.CRITERIA_SELECTION_COUNT);
p.group.body.sort_type = "random";
const wrapper = mount(<GroupSortSelection {...p} />);
expect(wrapper.html()).toContain("exclamation-triangle");
});
});
23 changes: 18 additions & 5 deletions frontend/point_groups/__tests__/group_detail_test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ jest.mock("../../history", () => ({

jest.mock("../group_detail_active", () => ({
GroupDetailActive: () => <div />,
GroupSortSelection: () => <div />,
}));

jest.mock("../../api/crud", () => ({
destroy: jest.fn(),
}));

import React from "react";
Expand All @@ -27,6 +32,7 @@ import {
fakePointGroup, fakeWebAppConfig,
} from "../../__test_support__/fake_state/resources";
import { PointType } from "farmbot";
import { destroy } from "../../api/crud";

describe("<GroupDetail />", () => {
const fakeProps = (): GroupDetailProps => {
Expand Down Expand Up @@ -76,16 +82,23 @@ describe("<GroupDetail />", () => {
});

it.each<[string, PointType]>([
["plant", "Plant"],
["weed", "Weed"],
["point", "GenericPointer"],
["slot", "ToolSlot"],
["plants", "Plant"],
["weeds", "Weed"],
["points", "GenericPointer"],
["tools", "ToolSlot"],
])("renders %s group", (title, pointerType) => {
mockPath = Path.mock(Path.groups(1));
const p = fakeProps();
p.group && (p.group.body.criteria.string_eq = { pointer_type: [pointerType] });
const wrapper = mount(<GroupDetail {...p} />);
expect(wrapper.text().toLowerCase()).toContain(`edit ${title} group`);
expect(wrapper.html()).toContain("go back to " + title);
});

it("deletes group", () => {
mockPath = Path.mock(Path.groups(1));
const wrapper = mount(<GroupDetail {...fakeProps()} />);
wrapper.find(".fa-trash").first().simulate("click");
expect(destroy).toHaveBeenCalled();
});
});

Expand Down
2 changes: 1 addition & 1 deletion frontend/point_groups/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const createGroup = (props: CreateGroupProps) =>
const group: PointGroup = {
name: groupName || t("Untitled Group"),
point_ids,
sort_type: "xy_ascending",
sort_type: "nn",
criteria: criteria || DEFAULT_CRITERIA,
};
const action = init("PointGroup", group);
Expand Down
28 changes: 14 additions & 14 deletions frontend/point_groups/criteria/show.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,20 @@ export const NumberLtGtInput = (props: NumberLtGtInputProps) => {
export const LocationSelection = (props: LocationSelectionProps) =>
<div className="location-criteria">
<p className={"category"}>{t("Location")}</p>
<div className={"edit-in-map"}>
<ToggleButton
title={props.editGroupAreaInMap
? t("map boxes will change location filter")
: t("map boxes will manually add plants")}
customText={{ textFalse: t("off"), textTrue: t("on") }}
toggleValue={props.editGroupAreaInMap}
toggleAction={() =>
props.dispatch({
type: Actions.EDIT_GROUP_AREA_IN_MAP,
payload: !props.editGroupAreaInMap
})} />
<label>{t("edit in map")}</label>
</div>
<ClearCategory
group={props.group}
criteriaCategories={["number_lt", "number_gt"]}
Expand All @@ -208,18 +222,4 @@ export const LocationSelection = (props: LocationSelectionProps) =>
criteriaKey={axis}
group={props.group}
dispatch={props.dispatch} />)}
<div className={"edit-in-map"}>
<ToggleButton
title={props.editGroupAreaInMap
? t("map boxes will change location filter")
: t("map boxes will manually add plants")}
customText={{ textFalse: t("off"), textTrue: t("on") }}
toggleValue={props.editGroupAreaInMap}
toggleAction={() =>
props.dispatch({
type: Actions.EDIT_GROUP_AREA_IN_MAP,
payload: !props.editGroupAreaInMap
})} />
<label>{t("edit in map")}</label>
</div>
</div>;
30 changes: 27 additions & 3 deletions frontend/point_groups/group_detail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
selectAllTools,
} from "../resources/selectors";
import { getPathArray } from "../history";
import { GroupDetailActive } from "./group_detail_active";
import { GroupDetailActive, GroupSortSelection } from "./group_detail_active";
import { uniq } from "lodash";
import { UUID } from "../resources/interfaces";
import {
Expand All @@ -23,6 +23,10 @@ import { BooleanSetting, NumericSetting } from "../session_keys";
import { isBotOriginQuadrant } from "../farm_designer/interfaces";
import { validPointTypes } from "../plants/select_plants";
import { Path } from "../internal_urls";
import { destroy } from "../api/crud";
import { ResourceTitle } from "../sequences/panel/editor";
import { Popover } from "../ui";
import { pointsSelectedByGroup } from "./criteria/apply";

export interface GroupDetailProps {
dispatch: Function;
Expand Down Expand Up @@ -95,8 +99,28 @@ export class RawGroupDetail extends React.Component<GroupDetailProps, {}> {
<DesignerPanelHeader
panelName={Panel.Groups}
panel={Panel.Groups}
backTo={panelInfo(group).backTo}
title={panelInfo(group).title} />
titleElement={<ResourceTitle
key={group?.body.name}
resource={group}
save={true}
fallback={t("No Group selected")}
dispatch={this.props.dispatch} />}
backTo={panelInfo(group).backTo}>
<div className={"panel-header-icon-group"}>
{group &&
<Popover
target={<i className={"fa fa-sort"}
title={t("Sort by")} />}
content={
<GroupSortSelection group={group} dispatch={this.props.dispatch}
pointsSelectedByGroup={pointsSelectedByGroup(
group, this.props.allPoints)} />} />}
{group &&
<i className={"fa fa-trash"}
title={t("Delete group")}
onClick={() => this.props.dispatch(destroy(group.uuid))} />}
</div>
</DesignerPanelHeader>
<DesignerPanelContent panelName={"groups"}>
{group
? <GroupDetailActive {...this.props} group={group} />
Expand Down
Loading

0 comments on commit 3e05352

Please sign in to comment.