Ready for testing
parent
b3aab2eafc
commit
6318dc4615
4
Gemfile
4
Gemfile
|
@ -31,9 +31,9 @@ group :development, :test do
|
|||
gem "database_cleaner"
|
||||
gem "pry"
|
||||
gem "factory_girl_rails"
|
||||
gem "faker", "~> 1.8.4"
|
||||
gem "faker"
|
||||
gem "smarf_doc", git: "https://github.com/RickCarlino/smarf_doc.git"
|
||||
gem "rails-erd", "1.5.2"
|
||||
gem "rails-erd"
|
||||
# TODO: Upgrade versions when they fix this stuff:
|
||||
# https://stackoverflow.com/questions/43983466
|
||||
# /controller-test-emits-debug-failure-messages-after-rails-5-1-upgrade
|
||||
|
|
10
Gemfile.lock
10
Gemfile.lock
|
@ -134,14 +134,14 @@ GEM
|
|||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2016.0521)
|
||||
mimemagic (0.3.2)
|
||||
mini_portile2 (2.2.0)
|
||||
mini_portile2 (2.3.0)
|
||||
minitest (5.10.3)
|
||||
multi_json (1.12.2)
|
||||
mutations (0.8.1)
|
||||
activesupport
|
||||
nio4r (2.1.0)
|
||||
nokogiri (1.8.0)
|
||||
mini_portile2 (~> 2.2.0)
|
||||
nokogiri (1.8.1)
|
||||
mini_portile2 (~> 2.3.0)
|
||||
orm_adapter (0.5.0)
|
||||
paperclip (5.1.0)
|
||||
activemodel (>= 4.2.0)
|
||||
|
@ -267,7 +267,7 @@ DEPENDENCIES
|
|||
delayed_job_active_record
|
||||
devise
|
||||
factory_girl_rails
|
||||
faker (~> 1.8.4)
|
||||
faker
|
||||
figaro
|
||||
fog-google!
|
||||
foreman
|
||||
|
@ -281,7 +281,7 @@ DEPENDENCIES
|
|||
rack-attack
|
||||
rack-cors
|
||||
rails
|
||||
rails-erd (= 1.5.2)
|
||||
rails-erd
|
||||
rails_12factor
|
||||
rollbar
|
||||
rspec (~> 3.5.0)
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
import { clamp } from "lodash";
|
||||
|
||||
/** Callback used in class Flipper<T>. Called when you flip up or down.
|
||||
* Useful for calling `setState` or `forceUpdate` when the flipper value
|
||||
* changes. */
|
||||
type FlipFN = <T>(next: T | undefined, index: number) => void;
|
||||
|
||||
/** Improved array that is useful for up/down situations such as the webcam
|
||||
* feed flipper UI. TODO: This can be re-used for farmware image viewer. */
|
||||
export class Flipper<T> {
|
||||
private go = (n: number) =>
|
||||
(cb: FlipFN) => {
|
||||
this.inc(n);
|
||||
cb(this.current, this.index);
|
||||
}
|
||||
|
||||
private inc = (num: number) => {
|
||||
const i = this.index;
|
||||
this.index = clamp(i + num, 0, this.list.length - 1);
|
||||
return this.index;
|
||||
}
|
||||
|
||||
/** Retrieve the currently viewed item. Returns a fallback when unable to find
|
||||
* an element. */
|
||||
get current(): T { return this.list[this.index] || this.fallback; }
|
||||
|
||||
constructor(public list: T[],
|
||||
public fallback: T,
|
||||
private index: number,
|
||||
) { }
|
||||
|
||||
/** Move to next item in the list (if possible) and execute
|
||||
* provided callback. */
|
||||
up = this.go(1);
|
||||
|
||||
/** Move to previous item in the list (if possible) and execute
|
||||
* provided callback. */
|
||||
down = this.go(-1);
|
||||
|
||||
}
|
|
@ -3,35 +3,38 @@ import { Widget, WidgetHeader } from "../../ui/index";
|
|||
import { t } from "i18next";
|
||||
import { ToolTips } from "../../constants";
|
||||
import { WebcamPanelProps } from "./interfaces";
|
||||
import { clamp } from "lodash";
|
||||
import { PLACEHOLDER_FARMBOT } from "../../farmware/images/image_flipper";
|
||||
import { Flipper } from "./flipper";
|
||||
|
||||
type State = {
|
||||
/** We might need to move this in to Redux and use a UUID instead of an index,
|
||||
/** Current index in the webcam feed list.
|
||||
*
|
||||
* We might need to move this in to Redux and use a UUID instead of an index,
|
||||
* depending on user needs.
|
||||
*/
|
||||
current: number;
|
||||
};
|
||||
|
||||
export class Show extends React.Component<WebcamPanelProps, State> {
|
||||
const FALLBACK_FEED = { name: "", url: PLACEHOLDER_FARMBOT };
|
||||
|
||||
state: State = {
|
||||
current: 0
|
||||
};
|
||||
export class Show extends React.Component<WebcamPanelProps, State> {
|
||||
NO_FEED = t(`No webcams yet. Click the edit button to add a feed URL.`);
|
||||
|
||||
state: State = { current: 0 };
|
||||
|
||||
render() {
|
||||
const { props } = this;
|
||||
const unsaved = !!props.feeds.filter(x => x.specialStatus !== undefined).length;
|
||||
const f = this.props.feeds.map(x => x.body);
|
||||
const flipper = new Flipper(f, {
|
||||
name: "Missing",
|
||||
url: PLACEHOLDER_FARMBOT
|
||||
}, this.state.current);
|
||||
const msg = this.props.feeds.length ?
|
||||
"" : t(`No webcams yet. Click the edit button to add a feed URL.`);
|
||||
const unsaved = !!props
|
||||
.feeds
|
||||
.filter(x => x.specialStatus !== undefined)
|
||||
.length;
|
||||
const feeds = this.props.feeds.map(x => x.body);
|
||||
const flipper = new Flipper(feeds, FALLBACK_FEED, this.state.current);
|
||||
const msg = this.props.feeds.length ? "" : this.NO_FEED;
|
||||
const title = flipper.current.name || "Webcam Feeds";
|
||||
return (
|
||||
<Widget>
|
||||
<WidgetHeader title="Webcams" helpText={ToolTips.WEBCAM}>
|
||||
<WidgetHeader title={title} helpText={ToolTips.WEBCAM}>
|
||||
<button
|
||||
className="fb-button gray"
|
||||
onClick={props.onToggle}>
|
||||
|
@ -65,29 +68,3 @@ export class Show extends React.Component<WebcamPanelProps, State> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Flipper<T> {
|
||||
private go = (n: number) =>
|
||||
(cb: (next: T | undefined, index: number) => void) => {
|
||||
this.inc(n);
|
||||
console.log("HEY" + this.index);
|
||||
cb(this.current, this.index);
|
||||
}
|
||||
|
||||
private inc = (num: number) => {
|
||||
const i = this.index;
|
||||
this.index = clamp(i + num, 0, this.list.length - 1);
|
||||
return this.index;
|
||||
}
|
||||
|
||||
get current(): T { return this.list[this.index] || this.fallback; }
|
||||
|
||||
constructor(public list: T[],
|
||||
public fallback: T,
|
||||
private index: number,
|
||||
) { }
|
||||
|
||||
up = this.go(1);
|
||||
down = this.go(-1);
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue