group fixes and additions

pull/1494/head
gabrielburnworth 2019-10-08 12:22:40 -07:00
parent 0e85a10dc5
commit 8d3c537332
7 changed files with 113 additions and 37 deletions

View File

@ -562,6 +562,12 @@ export namespace Content {
export const CONFIRM_PLANT_DELETION =
trim(`Show a confirmation dialog when deleting a plant.`);
export const SORT_DESCRIPTION =
trim(`When executing a sequence over a Group of locations, FarmBot will
travel to each group member in the order of the chosen sort method.
If the random option is chosen, FarmBot will travel in a random order
every time, so the ordering shown below will only be representative.`);
// Device
export const NOT_HTTPS =
trim(`WARNING: Sending passwords via HTTP:// is not secure.`);

View File

@ -27,6 +27,7 @@ import {
dropPlant, dragPlant, beginPlantDrag, maybeSavePlantLocation
} from "./layers/plants/plant_actions";
import { chooseLocation } from "../move_to";
import { GroupOrder } from "../point_groups/group_order_visual";
export class GardenMap extends
React.Component<GardenMapProps, Partial<GardenMapState>> {
@ -343,6 +344,9 @@ export class GardenMap extends
data={this.props.designer.currentPoint}
key={"currentPoint"}
mapTransformProps={this.mapTransformProps} />
GroupOrder = () => <GroupOrder
plants={this.props.plants}
mapTransformProps={this.mapTransformProps} />
Bugs = () => showBugs() ? <Bugs mapTransformProps={this.mapTransformProps}
botSize={this.props.botSize} /> : <g />
@ -365,6 +369,7 @@ export class GardenMap extends
<this.SelectionBox />
<this.TargetCoordinate />
<this.DrawnPoint />
<this.GroupOrder />
<this.Bugs />
</svg>
</svg>

View File

@ -0,0 +1,36 @@
import { fakePointGroup } from "../../../__test_support__/fake_state/resources";
const mockGroup = fakePointGroup();
mockGroup.body.point_ids = [1, 2, 3];
jest.mock("../group_detail", () => ({ fetchGroupFromUrl: () => mockGroup }));
import * as React from "react";
import { mount } from "enzyme";
import { GroupOrder, GroupOrderProps } from "../group_order_visual";
import {
fakeMapTransformProps
} from "../../../__test_support__/map_transform_props";
import { fakePlant } from "../../../__test_support__/fake_state/resources";
describe("<GroupOrder />", () => {
const fakeProps = (): GroupOrderProps => {
const plant1 = fakePlant();
plant1.body.id = 1;
const plant2 = fakePlant();
plant2.body.id = 2;
const plant3 = fakePlant();
plant3.body.id = 3;
const plant4 = fakePlant();
plant4.body.id = undefined;
const plant5 = fakePlant();
plant5.body.id = 5;
return {
mapTransformProps: fakeMapTransformProps(),
plants: [plant1, plant2, plant3],
};
};
it("renders group order", () => {
const wrapper = mount(<GroupOrder {...fakeProps()} />);
expect(wrapper.find("line").length).toEqual(3);
});
});

View File

@ -4,8 +4,9 @@ import { init, save } from "../../api/crud";
import { history } from "../../history";
import { GetState } from "../../redux/interfaces";
import { findPointGroup } from "../../resources/selectors";
import { t } from "../../i18next_wrapper";
const UNTITLED = "Untitled Group";
const UNTITLED = () => t("Untitled Group");
interface CreateGroupProps {
/** TaggedPoint UUIDs */
@ -21,7 +22,7 @@ export const createGroup = ({ points, name }: CreateGroupProps) => {
.map(x => x ? x.body.id : undefined);
const point_ids = betterCompact(possiblyNil);
const group: PointGroup =
({ name: name || UNTITLED, point_ids, sort_type: "xy_ascending" });
({ name: name || UNTITLED(), point_ids, sort_type: "xy_ascending" });
const action = init("PointGroup", group);
dispatch(action);
return dispatch(save(action.payload.uuid)).then(() => {

View File

@ -0,0 +1,36 @@
import * as React from "react";
import { store } from "../../redux/store";
import { MapTransformProps, TaggedPlant } from "../map/interfaces";
import { fetchGroupFromUrl } from "./group_detail";
import { isUndefined } from "lodash";
import { sortGroupBy } from "./point_group_sort_selector";
import { Color } from "../../ui";
import { transformXY } from "../map/util";
export interface GroupOrderProps {
plants: TaggedPlant[];
mapTransformProps: MapTransformProps;
}
const sortedPointCoordinates =
(plants: TaggedPlant[]): { x: number, y: number }[] => {
const group = fetchGroupFromUrl(store.getState().resources.index);
if (isUndefined(group)) { return []; }
const groupPlants = plants
.filter(p => group.body.point_ids.includes(p.body.id || 0));
return sortGroupBy(group.body.sort_type, groupPlants)
.map(p => ({ x: p.body.x, y: p.body.y }));
};
export const GroupOrder = (props: GroupOrderProps) => {
const points = sortedPointCoordinates(props.plants);
return <g id="group-order"
stroke={Color.mediumGray} strokeWidth={3} strokeDasharray={12}>
{points.map((p, i) => {
const prev = i > 0 ? points[i - 1] : p;
const one = transformXY(prev.x, prev.y, props.mapTransformProps);
const two = transformXY(p.x, p.y, props.mapTransformProps);
return <line key={i} x1={one.qx} y1={one.qy} x2={two.qx} y2={two.qy} />;
})}
</g>;
};

View File

@ -1,41 +1,38 @@
import * as React from "react";
import { PointGroupSortType } from "farmbot/dist/resources/api_resources";
import {
FBSelect,
DropDownItem
} from "../../ui";
import { FBSelect, DropDownItem } from "../../ui";
import { t } from "../../i18next_wrapper";
import { trim } from "../../util/util";
import { TaggedPlant } from "../map/interfaces";
import { shuffle, sortBy } from "lodash";
import { Content } from "../../constants";
interface Props {
onChange(value: PointGroupSortType): void;
value: PointGroupSortType;
}
const optionsTable: Record<PointGroupSortType, string> = {
"random": "Random Order",
"xy_ascending": "X/Y, Ascending",
"xy_descending": "X/Y, Descending",
"yx_ascending": "Y/X, Ascending",
"yx_descending": "Y/X Descending",
}; // Typechecker will remind us when this needs an update. Don't simplify - RC
const optionsTable = (): Record<PointGroupSortType, string> => ({
"random": t("Random Order"),
"xy_ascending": t("X/Y, Ascending"),
"xy_descending": t("X/Y, Descending"),
"yx_ascending": t("Y/X, Ascending"),
"yx_descending": t("Y/X, Descending"),
}); // Typechecker will remind us when this needs an update. Don't simplify - RC
const optionPlusDescriptions =
const optionPlusDescriptions = () =>
(Object
.entries(optionsTable) as [PointGroupSortType, string][])
.entries(optionsTable()) as [PointGroupSortType, string][])
.map(x => ({ label: x[1], value: x[0] }));
const optionList =
optionPlusDescriptions.map(x => x.value);
optionPlusDescriptions().map(x => x.value);
export const isSortType = (x: unknown): x is PointGroupSortType => {
return optionList.includes(x as PointGroupSortType);
};
const selected = (value: PointGroupSortType) => ({
label: t(optionsTable[value] || value),
label: t(optionsTable()[value] || value),
value: value
});
@ -44,13 +41,6 @@ export const sortTypeChange = (cb: Function) => (ddi: DropDownItem) => {
isSortType(value) && cb(value);
};
const SORT_DESC = trim(`When executing a sequence
over a Group of locations, FarmBot will travel to
each group member in the order of the chosen sort
method. If the random option is chosen, FarmBot will
travel in a random order every time, so the
ordering shown below will only be representative.`);
export function PointGroupSortSelector(p: Props) {
return <div>
@ -60,11 +50,11 @@ export function PointGroupSortSelector(p: Props) {
</label>
</div>
<FBSelect
list={optionPlusDescriptions}
list={optionPlusDescriptions()}
selectedItem={selected(p.value as PointGroupSortType)}
onChange={sortTypeChange(p.onChange)} />
<p>
{(p.value == "random") ? t(SORT_DESC) : ""}
{(p.value == "random") ? t(Content.SORT_DESCRIPTION) : ""}
</p>
</div>;
}

View File

@ -18,19 +18,21 @@ npm run translation-check
See the [README](https://github.com/FarmBot/Farmbot-Web-App#translating-the-web-app-into-your-language) for contribution instructions.
Total number of phrases identified by the language helper for translation: __1086__
Total number of phrases identified by the language helper for translation: __1101__
|Language|Percent translated|Translated|Untranslated|Other Translations|
|:---:|---:|---:|---:|---:|
|da|10%|110|976|27|
|de|39%|421|665|125|
|es|94%|1019|67|156|
|fr|70%|765|321|182|
|it|8%|89|997|175|
|nl|7%|79|1007|145|
|pt|7%|71|1015|164|
|ru|56%|606|480|205|
|zh|8%|86|1000|145|
|af|100%|1101|0|1|
|da|10%|110|991|31|
|de|38%|420|681|128|
|es|92%|1015|86|160|
|fr|69%|762|339|186|
|it|8%|89|1012|178|
|nl|7%|79|1022|148|
|pt|6%|71|1030|167|
|ru|55%|604|497|208|
|th|0%|0|1101|0|
|zh|8%|86|1015|148|
**Percent translated** refers to the percent of phrases identified by the
language helper that have been translated. Additional phrases not identified