ownership change form draft
parent
7bafa4bc04
commit
e48e32bc7c
|
@ -230,6 +230,23 @@ a {
|
|||
}
|
||||
}
|
||||
|
||||
.change-ownership-form {
|
||||
p {
|
||||
padding: 1rem;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
.row {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
label {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
button {
|
||||
margin-top: 1rem;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.pin-bindings-widget {
|
||||
.fa-th-large {
|
||||
color: $dark_gray;
|
||||
|
|
|
@ -24,17 +24,18 @@ describe("<Devices/>", () => {
|
|||
images: [],
|
||||
dispatch: jest.fn(),
|
||||
resources: buildResourceIndex(FAKE_RESOURCES).index,
|
||||
sourceFbosConfig: jest.fn()
|
||||
sourceFbosConfig: jest.fn(),
|
||||
shouldDisplay: jest.fn()
|
||||
});
|
||||
|
||||
it("renders relevant panels", () => {
|
||||
const el = shallow(<Devices {...p() } />);
|
||||
const el = shallow(<Devices {...p()} />);
|
||||
expect(el.find(FarmbotOsSettings).length).toBe(1);
|
||||
});
|
||||
|
||||
it("Crashes when logged out", () => {
|
||||
const props = p();
|
||||
props.auth = undefined;
|
||||
expect(() => render(<Devices {...props } />)).toThrow();
|
||||
expect(() => render(<Devices {...props} />)).toThrow();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -27,12 +27,13 @@ describe("<FarmbotOsSettings/>", () => {
|
|||
botToMqttStatus: "up",
|
||||
sourceFbosConfig: (x) => {
|
||||
return { value: bot.hardware.configuration[x], consistent: true };
|
||||
}
|
||||
},
|
||||
shouldDisplay: jest.fn()
|
||||
};
|
||||
};
|
||||
|
||||
it("renders settings", () => {
|
||||
const osSettings = mount(<FarmbotOsSettings {...fakeProps() } />);
|
||||
const osSettings = mount(<FarmbotOsSettings {...fakeProps()} />);
|
||||
expect(osSettings.find("input").length).toBe(1);
|
||||
expect(osSettings.find("button").length).toBe(6);
|
||||
["NAME", "TIME ZONE", "LAST SEEN", "FARMBOT OS", "CAMERA", "FIRMWARE"]
|
||||
|
@ -41,7 +42,7 @@ describe("<FarmbotOsSettings/>", () => {
|
|||
|
||||
it("fetches OS release notes", async () => {
|
||||
mockReleaseNoteData = { data: "intro\n\n# v6\n\n* note" };
|
||||
const osSettings = await mount(<FarmbotOsSettings {...fakeProps() } />);
|
||||
const osSettings = await mount(<FarmbotOsSettings {...fakeProps()} />);
|
||||
await expect(axios.get).toHaveBeenCalledWith(
|
||||
expect.stringContaining("RELEASE_NOTES.md"));
|
||||
expect(osSettings.state().osReleaseNotes)
|
||||
|
@ -50,7 +51,7 @@ describe("<FarmbotOsSettings/>", () => {
|
|||
|
||||
it("doesn't fetch OS release notes", async () => {
|
||||
mockReleaseNoteData = { data: "empty notes" };
|
||||
const osSettings = await mount(<FarmbotOsSettings {...fakeProps() } />);
|
||||
const osSettings = await mount(<FarmbotOsSettings {...fakeProps()} />);
|
||||
await expect(axios.get).toHaveBeenCalledWith(
|
||||
expect.stringContaining("RELEASE_NOTES.md"));
|
||||
expect(osSettings.state().osReleaseNotes)
|
||||
|
@ -86,7 +87,7 @@ describe("<FbosDetails />", () => {
|
|||
};
|
||||
|
||||
it("renders", () => {
|
||||
const wrapper = mount(<FbosDetails {...fakeProps() } />);
|
||||
const wrapper = mount(<FbosDetails {...fakeProps()} />);
|
||||
["Environment: ---",
|
||||
"Commit: ---",
|
||||
"Target: ---",
|
||||
|
|
|
@ -157,7 +157,8 @@ export class FarmbotOsSettings
|
|||
<PowerAndReset
|
||||
controlPanelState={this.props.bot.controlPanelState}
|
||||
dispatch={this.props.dispatch}
|
||||
sourceFbosConfig={sourceFbosConfig} />
|
||||
sourceFbosConfig={sourceFbosConfig}
|
||||
shouldDisplay={this.props.shouldDisplay} />
|
||||
</MustBeOnline>
|
||||
</WidgetBody>
|
||||
</form>
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
const mockDevice = {
|
||||
send: jest.fn(() => { return Promise.resolve(); }),
|
||||
};
|
||||
jest.mock("../../../../device", () => ({
|
||||
getDevice: () => (mockDevice)
|
||||
}));
|
||||
|
||||
import * as React from "react";
|
||||
import { ChangeOwnershipForm } from "../change_ownership_form";
|
||||
import { mount } from "enzyme";
|
||||
|
||||
describe("<ChangeOwnershipForm/>", () => {
|
||||
it("renders", () => {
|
||||
const wrapper = mount(<ChangeOwnershipForm />);
|
||||
["email", "password", "server"]
|
||||
.map(string => expect(wrapper.text().toLowerCase()).toContain(string));
|
||||
});
|
||||
|
||||
it("submits", () => {
|
||||
const wrapper = mount(<ChangeOwnershipForm />);
|
||||
wrapper.find("button").simulate("click");
|
||||
expect(mockDevice.send).toHaveBeenCalledWith({
|
||||
"kind": "rpc_request",
|
||||
"args": { "label": expect.any(String) },
|
||||
"body": [
|
||||
{
|
||||
"kind": "pair",
|
||||
"args": { "label": "email", "value": "" }
|
||||
},
|
||||
{
|
||||
"kind": "pair",
|
||||
"args": { "label": "secret", "value": 0 }
|
||||
},
|
||||
{
|
||||
"kind": "pair",
|
||||
"args": { "label": "server", "value": "https://my.farm.bot" }
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
});
|
|
@ -20,7 +20,8 @@ describe("<PowerAndReset/>", () => {
|
|||
dispatch: jest.fn(x => x(jest.fn(), fakeState)),
|
||||
sourceFbosConfig: (x) => {
|
||||
return { value: bot.hardware.configuration[x], consistent: true };
|
||||
}
|
||||
},
|
||||
shouldDisplay: jest.fn()
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
import * as React from "react";
|
||||
import { Row, Col, BlurableInput } from "../../../ui/index";
|
||||
import { t } from "i18next";
|
||||
import { info, success } from "farmbot-toastr";
|
||||
import { getDevice } from "../../../device";
|
||||
import { rpcRequest } from "farmbot";
|
||||
|
||||
interface ChangeOwnershipFormState {
|
||||
email: string;
|
||||
password: string;
|
||||
server: string;
|
||||
}
|
||||
|
||||
export class ChangeOwnershipForm
|
||||
extends React.Component<{}, ChangeOwnershipFormState> {
|
||||
state = {
|
||||
email: "",
|
||||
password: "",
|
||||
server: "https://my.farm.bot"
|
||||
};
|
||||
|
||||
submitOwnershipChange = () => {
|
||||
info(t("Sending change of ownership..."), t("Sending"));
|
||||
getDevice()
|
||||
.send(rpcRequest([
|
||||
{ kind: "pair", args: { label: "email", value: this.state.email } },
|
||||
{ kind: "pair", args: { label: "secret", value: 0 } },
|
||||
{ kind: "pair", args: { label: "server", value: this.state.server } }
|
||||
// tslint:disable-next-line:no-any
|
||||
] as any))
|
||||
.then(() => {
|
||||
success(t("Received change of ownership."));
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className={"change-ownership-form"}>
|
||||
<Row>
|
||||
<p>
|
||||
{t("Change the account FarmBot is connected to.")}
|
||||
</p>
|
||||
<Col xs={4}>
|
||||
<label>
|
||||
{t("Email")}
|
||||
</label>
|
||||
</Col>
|
||||
<Col xs={8}>
|
||||
<BlurableInput
|
||||
allowEmpty={true}
|
||||
onCommit={e => this.setState({ email: e.currentTarget.value })}
|
||||
name="email"
|
||||
value={this.state.email}
|
||||
type="email" />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col xs={4}>
|
||||
<label>
|
||||
{t("Password")}
|
||||
</label>
|
||||
</Col>
|
||||
<Col xs={8}>
|
||||
<BlurableInput
|
||||
allowEmpty={true}
|
||||
onCommit={e => this.setState({ password: e.currentTarget.value })}
|
||||
name="password"
|
||||
value={this.state.password}
|
||||
type="password" />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col xs={4}>
|
||||
<label>
|
||||
{t("Server")}
|
||||
</label>
|
||||
</Col>
|
||||
<Col xs={8}>
|
||||
<BlurableInput
|
||||
allowEmpty={true}
|
||||
onCommit={e => this.setState({ server: e.currentTarget.value })}
|
||||
name="server"
|
||||
value={this.state.server}
|
||||
type="text" />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<button
|
||||
className={"fb-button gray"}
|
||||
onClick={this.submitOwnershipChange}>
|
||||
{t("submit")}
|
||||
</button>
|
||||
</Row>
|
||||
</div>;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import { SourceFbosConfig, BotState, ControlPanelState } from "../../interfaces";
|
||||
import { ShouldDisplay } from "../../../sequences/interfaces";
|
||||
|
||||
export interface AutoSyncRowProps {
|
||||
dispatch: Function;
|
||||
|
@ -20,6 +21,7 @@ export interface PowerAndResetProps {
|
|||
controlPanelState: ControlPanelState;
|
||||
dispatch: Function;
|
||||
sourceFbosConfig: SourceFbosConfig;
|
||||
shouldDisplay: ShouldDisplay;
|
||||
}
|
||||
|
||||
export interface FactoryResetRowProps {
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
import * as React from "react";
|
||||
import { Header } from "../hardware_settings/header";
|
||||
import { Collapse } from "@blueprintjs/core";
|
||||
import { Collapse, Popover, Position } from "@blueprintjs/core";
|
||||
import { RestartRow } from "./restart_row";
|
||||
import { ShutdownRow } from "./shutdown_row";
|
||||
import { FactoryResetRow } from "./factory_reset_row";
|
||||
import { PowerAndResetProps } from "./interfaces";
|
||||
import { ChangeOwnershipForm } from "./change_ownership_form";
|
||||
import { t } from "i18next";
|
||||
|
||||
export function PowerAndReset(props: PowerAndResetProps) {
|
||||
const { dispatch, sourceFbosConfig } = props;
|
||||
const { dispatch, sourceFbosConfig, shouldDisplay } = props;
|
||||
const { power_and_reset } = props.controlPanelState;
|
||||
return <section>
|
||||
<div style={{ fontSize: "1px" }}>
|
||||
|
@ -24,6 +25,14 @@ export function PowerAndReset(props: PowerAndResetProps) {
|
|||
<FactoryResetRow
|
||||
dispatch={dispatch}
|
||||
sourceFbosConfig={sourceFbosConfig} />
|
||||
{shouldDisplay("change_ownership") &&
|
||||
<Popover position={Position.BOTTOM_LEFT}>
|
||||
<p className={"release-notes-button"}>
|
||||
{t("Change Ownership")}
|
||||
<i className="fa fa-caret-down" />
|
||||
</p>
|
||||
<ChangeOwnershipForm />
|
||||
</Popover>}
|
||||
</Collapse>
|
||||
</section>;
|
||||
}
|
||||
|
|
|
@ -65,7 +65,8 @@ export class Devices extends React.Component<Props, {}> {
|
|||
bot={this.props.bot}
|
||||
botToMqttLastSeen={botToMqttLastSeen}
|
||||
botToMqttStatus={botToMqttStatus}
|
||||
sourceFbosConfig={this.props.sourceFbosConfig} />
|
||||
sourceFbosConfig={this.props.sourceFbosConfig}
|
||||
shouldDisplay={this.props.shouldDisplay} />
|
||||
<ConnectivityPanel
|
||||
status={this.props.deviceAccount.specialStatus}
|
||||
onRefresh={this.refresh}
|
||||
|
|
|
@ -18,6 +18,7 @@ import { WD_ENV } from "../farmware/weed_detector/remote_env/interfaces";
|
|||
import { ConnectionStatus, ConnectionState, NetworkState } from "../connectivity/interfaces";
|
||||
import { IntegerSize } from "../util";
|
||||
import { WebAppConfig } from "../config_storage/web_app_configs";
|
||||
import { ShouldDisplay } from "../sequences/interfaces";
|
||||
|
||||
export interface Props {
|
||||
userToApi: ConnectionStatus | undefined;
|
||||
|
@ -30,6 +31,7 @@ export interface Props {
|
|||
dispatch: Function;
|
||||
resources: ResourceIndex;
|
||||
sourceFbosConfig: SourceFbosConfig;
|
||||
shouldDisplay: ShouldDisplay;
|
||||
}
|
||||
|
||||
export type SourceFbosConfig = (config: ConfigurationName) =>
|
||||
|
@ -121,6 +123,7 @@ export interface FarmbotOsProps {
|
|||
botToMqttLastSeen: string;
|
||||
dispatch: Function;
|
||||
sourceFbosConfig: SourceFbosConfig;
|
||||
shouldDisplay: ShouldDisplay;
|
||||
}
|
||||
|
||||
export interface FarmbotOsState {
|
||||
|
|
|
@ -2,16 +2,20 @@ import { Everything } from "../interfaces";
|
|||
import { Props } from "./interfaces";
|
||||
import {
|
||||
selectAllImages,
|
||||
getDeviceAccountSettings
|
||||
getDeviceAccountSettings,
|
||||
maybeGetDevice
|
||||
} from "../resources/selectors";
|
||||
import { sourceFbosConfigValue } from "./components/source_fbos_config_value";
|
||||
import { getFbosConfig } from "../resources/selectors_by_kind";
|
||||
import { determineInstalledOsVersion, shouldDisplay } from "../util";
|
||||
|
||||
export function mapStateToProps(props: Everything): Props {
|
||||
const conf = getFbosConfig(props.resources.index);
|
||||
const { hardware } = props.bot;
|
||||
const fbosConfig = (conf && conf.body && conf.body.api_migrated)
|
||||
? conf.body : undefined;
|
||||
const installedOsVersion = determineInstalledOsVersion(
|
||||
props.bot, maybeGetDevice(props.resources.index));
|
||||
return {
|
||||
userToApi: props.bot.connectivity["user.api"],
|
||||
userToMqtt: props.bot.connectivity["user.mqtt"],
|
||||
|
@ -23,5 +27,6 @@ export function mapStateToProps(props: Everything): Props {
|
|||
images: selectAllImages(props.resources.index),
|
||||
resources: props.resources.index,
|
||||
sourceFbosConfig: sourceFbosConfigValue(fbosConfig, hardware.configuration),
|
||||
shouldDisplay: shouldDisplay(installedOsVersion, props.bot.minOsFeatureData),
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue