Ready for testing

pull/460/head
Rick Carlino 2017-09-20 07:19:35 -05:00
parent b3aab2eafc
commit 6318dc4615
4 changed files with 65 additions and 48 deletions

View File

@ -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

View File

@ -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)

View File

@ -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);
}

View File

@ -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);
}