Integrate WebcamFeed resource with app, remove `webcam_url` from Device interface

pull/415/head
Rick Carlino 2017-08-21 09:31:47 -05:00
parent 66e2b2b643
commit 8254c007ee
9 changed files with 51 additions and 26 deletions

View File

@ -27,6 +27,10 @@ FarmBot::Application.routes.draw do
patch "/device/:id" => "devices#update", as: :patch_device_redirect
put "/users/:id" => "users#update", as: :put_users_redirect
patch "/users/:id" => "users#update", as: :patch_users_redirect
put "/webcam_feed/:id" => "webcam_feeds#update",
as: :put_webcam_feed_redirect
patch "/webcam_feed/:id" => "webcam_feeds#update",
as: :patch_webcam_feed_redirect
end

View File

@ -8,8 +8,7 @@ export let FAKE_RESOURCES: TaggedResource[] = [
"specialStatus": undefined,
"body": {
"id": 415,
"name": "wispy-firefly-846",
"webcam_url": undefined
"name": "wispy-firefly-846"
},
"uuid": "device.415.0"
},

View File

@ -141,7 +141,8 @@ export function urlFor(tag: ResourceName) {
users: API.current.usersPath,
device: API.current.devicePath,
images: API.current.imagesPath,
logs: API.current.logsPath
logs: API.current.logsPath,
webcam_feed: API.current.webcamFeedPath
};
let url = OPTIONS[tag];
if (url) {

View File

@ -34,7 +34,7 @@ export class Controls extends React.Component<Props, {}> {
</Col>
<Col xs={12} sm={6}>
<WebcamPanel bot={this.props.bot}
account={this.props.account}
feed={this.props.feed}
dispatch={this.props.dispatch} />
</Col>
</Row>

View File

@ -1,13 +1,16 @@
import { BotState, Xyz, BotPosition } from "../devices/interfaces";
import { Vector3 } from "farmbot/dist";
import { TaggedPeripheral, TaggedDevice } from "../resources/tagged_resources";
import { RestResources } from "../resources/interfaces";
import { TaggedUser } from "../resources/tagged_resources";
import {
TaggedUser,
TaggedWebcamFeed,
TaggedPeripheral
} from "../resources/tagged_resources";
export interface Props {
dispatch: Function;
bot: BotState;
account: TaggedDevice;
feed: TaggedWebcamFeed;
user: TaggedUser | undefined;
peripherals: TaggedPeripheral[];
resources: RestResources;
@ -23,7 +26,7 @@ export interface MoveProps {
export interface WebcamPanelProps {
dispatch: Function;
bot: BotState;
account: TaggedDevice;
feed: TaggedWebcamFeed;
}
export interface WebcamPanelState {

View File

@ -1,7 +1,7 @@
import { Everything } from "../interfaces";
import {
selectAllPeripherals,
getDeviceAccountSettings
getFeed
} from "../resources/selectors";
import { Props } from "./interfaces";
import { maybeFetchUser } from "../resources/selectors";
@ -12,7 +12,7 @@ export function mapStateToProps(props: Everything): Props {
let resources = props.resources;
return {
account: getDeviceAccountSettings(resources.index),
feed: getFeed(resources.index),
dispatch: props.dispatch,
bot: props.bot,
user: maybeFetchUser(props.resources.index),

View File

@ -1,13 +1,12 @@
import * as React from "react";
import { t } from "i18next";
import { Widget, WidgetHeader } from "../ui";
import { WebcamPanelState, WebcamPanelProps } from "./interfaces";
import { WebcamPanelState, WebcamPanelProps, WebcamFeed } from "./interfaces";
import { PLACEHOLDER_FARMBOT } from "../farmware/images/image_flipper";
import { showUrl } from "./show_url";
import { ToolTips } from "../constants";
import { overwrite, edit, save } from "../api/crud";
import { API } from "../api/api";
import { DeviceAccountSettings } from "../devices/interfaces";
import { createOK } from "../resources/actions";
import axios from "axios";
import { HttpData } from "../util";
@ -20,33 +19,33 @@ export class WebcamPanel extends
toggle = () => { this.setState({ isEditing: !this.state.isEditing }); };
save = () => {
this.props.dispatch(save(this.props.account.uuid));
this.props.dispatch(save(this.props.feed.uuid));
this.toggle();
};
edit = (update: Partial<DeviceAccountSettings>) => {
this.props.dispatch(edit(this.props.account, update));
edit = (update: Partial<WebcamFeed>) => {
this.props.dispatch(edit(this.props.feed, update));
};
resetURL = () => {
axios
.get(API.current.devicePath)
.then((resp: HttpData<DeviceAccountSettings>) => {
.then((resp: HttpData<WebcamFeed>) => {
// TODO: We're starting to hit use cases where we need edit/undo.
// Revisit this one when undo/redo is implemented.
this.props.dispatch(overwrite(this.props.account, resp.data));
this.props.dispatch(createOK(this.props.account));
this.props.dispatch(overwrite(this.props.feed, resp.data));
this.props.dispatch(createOK(this.props.feed));
});
}
clearURL = () => {
// TODO: This should set webcam_url to "", but the input box to "https://"
this.props.dispatch(edit(this.props.account, { webcam_url: "https://" }));
// TODO: This should set url to "", but the input box to "https://"
this.props.dispatch(edit(this.props.feed, { url: "https://" }));
(document.querySelector(".webcam-url-input") as HTMLInputElement).focus();
}
render() {
let url = this.props.account.body.webcam_url || PLACEHOLDER_FARMBOT;
let url = this.props.feed.body.url || PLACEHOLDER_FARMBOT;
let dirty = !!this.props.bot.dirty;
let { isEditing } = this.state;
@ -58,7 +57,7 @@ export class WebcamPanel extends
className="fb-button green"
onClick={this.save}
>
{t("Save")}{this.props.account.specialStatus ? "" : "*"}
{t("Save")}{this.props.feed.specialStatus ? "" : "*"}
</button>
}
{isEditing &&
@ -83,9 +82,9 @@ export class WebcamPanel extends
<label>{t("Set Webcam URL:")}</label>
<input
type="text"
onChange={e => this.edit({ webcam_url: e.currentTarget.value })}
onChange={e => this.edit({ url: e.currentTarget.value })}
placeholder="https://"
value={this.props.account.body.webcam_url}
value={this.props.feed.body.url}
className="webcam-url-input" />
</div>
}

View File

@ -32,7 +32,6 @@ export interface Props {
export interface DeviceAccountSettings {
id: number;
name: string;
webcam_url?: string;
timezone?: string | undefined;
last_seen?: string | undefined;
}

View File

@ -25,7 +25,8 @@ import {
TaggedSequence,
TaggedTool,
TaggedToolSlotPointer,
TaggedUser
TaggedUser,
TaggedWebcamFeed
} from "./tagged_resources";
import { CowardlyDictionary, betterCompact, sortResourcesById } from "../util";
type StringMap = CowardlyDictionary<string>;
@ -439,6 +440,25 @@ export function getDeviceAccountSettings(index: ResourceIndex) {
}
}
export function getFeed(index: ResourceIndex): TaggedWebcamFeed {
let list = index.byKind.webcam_feed;
let uuid = list[0];
let device = index.references[uuid || -1];
switch (list.length) {
case 0:
throw new Error("Missing webcam feed");
case 1:
if (device && device.kind === "webcam_feed") {
sanityCheck(device);
return device;
} else {
throw new Error("Malformed webcam feed");
}
default:
throw new Error("Too many webcam feeds. Expected exactly 1.");
}
}
export function maybeFetchUser(index: ResourceIndex):
TaggedUser | undefined {
let list = index.byKind.users;