group fixes and additions
parent
0e85a10dc5
commit
8d3c537332
|
@ -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.`);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
|
@ -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(() => {
|
||||
|
|
|
@ -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>;
|
||||
};
|
|
@ -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>;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue