Farmbot-Web-App/frontend/farm_designer/point_groups/group_detail_active.tsx

149 lines
4.2 KiB
TypeScript

import * as React from "react";
import { Panel } from "../panel_header";
import { t } from "../../i18next_wrapper";
import {
DesignerPanel,
DesignerPanelContent,
DesignerPanelHeader
} from "../plants/designer_panel";
import { TaggedPointGroup, SpecialStatus } from "farmbot";
import { DeleteButton } from "../../controls/pin_form_fields";
import { svgToUrl, DEFAULT_ICON } from "../../open_farm/icons";
import { overwrite, save, edit } from "../../api/crud";
import { Dictionary } from "lodash";
import { cachedCrop } from "../../open_farm/cached_crop";
import { toggleHoveredPlant } from "../actions";
import { TaggedPlant } from "../map/interfaces";
interface GroupDetailActiveProps {
dispatch: Function;
group: TaggedPointGroup;
plants: TaggedPlant[];
}
interface State {
icons: Dictionary<string | undefined>
}
const removePoint = (group: TaggedPointGroup, pointId: number) => {
type Body = (typeof group)["body"];
const nextGroup: Body = { ...group.body };
nextGroup.point_ids = nextGroup.point_ids.filter(x => x !== pointId);
return overwrite(group, nextGroup);
};
interface LittleIconProps {
/** URL (or even a data-url) to the icon image. */
icon: string;
group: TaggedPointGroup;
plant: TaggedPlant;
dispatch: Function;
}
export const LittleIcon =
({ group, plant: point, icon, dispatch }: LittleIconProps) => {
const { body } = point;
const p = point;
const plantUUID = point.uuid;
return <span
key={plantUUID}
onMouseEnter={() => dispatch(toggleHoveredPlant(plantUUID, icon))}
onMouseLeave={() => dispatch(toggleHoveredPlant(undefined, icon))}
onClick={() => dispatch(removePoint(group, body.id || 0))}>
<img src={icon} alt={p.body.name} width={32} height={32} />
</span>;
};
export class GroupDetailActive
extends React.Component<GroupDetailActiveProps, State> {
state: State = { icons: {} };
update = ({ currentTarget }: React.SyntheticEvent<HTMLInputElement>) => {
this
.props
.dispatch(edit(this.props.group, { name: currentTarget.value }));
};
performLookup = (plant: TaggedPlant) => {
cachedCrop(plant.body.openfarm_slug)
.then(x => {
this.setState({
icons: {
...this.state.icons,
[plant.uuid]: x.svg_icon
}
});
});
return DEFAULT_ICON;
}
findIcon = (plant: TaggedPlant) => {
const svg = this.state.icons[plant.uuid];
return svg ? svgToUrl(svg) : this.performLookup(plant);
}
get name() {
const { group } = this.props;
return group ? group.body.name : "Group Not found";
}
get icons() {
return this
.props
.plants
.map(point => {
return <LittleIcon
key={point.uuid}
icon={this.findIcon(point)}
group={this.props.group}
plant={point}
dispatch={this.props.dispatch} />;
});
}
saveGroup = () => {
this.props.dispatch(save(this.props.group.uuid));
}
render() {
const { group } = this.props;
return <DesignerPanel panelName={"groups"} panelColor={"blue"}>
<DesignerPanelHeader
onBack={this.saveGroup}
panelName={Panel.Groups}
panelColor={"blue"}
title={t("Edit Group")}
backTo={"/app/designer/groups"}>
<a
className="right-button"
title={t("Save Changes to Group")}
onClick={this.saveGroup}>
{t("Save")}{group.specialStatus === SpecialStatus.SAVED ? "" : "*"}
</a>
</DesignerPanelHeader>
<DesignerPanelContent
panelName={"groups"}>
<label>{t("GROUP NAME")}</label>
<input
defaultValue={this.name}
onChange={this.update} />
<label>
{t("GROUP MEMBERS ({{count}})", { count: this.icons.length })}
</label>
<p>
{t("Click plants in map to add or remove.")}
</p>
<div className="groups-list-wrapper">
{this.icons}
</div>
<DeleteButton
className="groups-delete-btn"
dispatch={this.props.dispatch}
uuid={group.uuid}
onDestroy={history.back}>
{t("DELETE GROUP")}
</DeleteButton>
</DesignerPanelContent>
</DesignerPanel>;
}
}