diff --git a/Gemfile b/Gemfile index f0456f85e..8566188a1 100755 --- a/Gemfile +++ b/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 diff --git a/Gemfile.lock b/Gemfile.lock index 9cae16168..4d1cd9e37 100644 --- a/Gemfile.lock +++ b/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) diff --git a/webpack/controls/webcam/flipper.ts b/webpack/controls/webcam/flipper.ts new file mode 100644 index 000000000..fbd6bad03 --- /dev/null +++ b/webpack/controls/webcam/flipper.ts @@ -0,0 +1,40 @@ +import { clamp } from "lodash"; + +/** Callback used in class Flipper. Called when you flip up or down. + * Useful for calling `setState` or `forceUpdate` when the flipper value + * changes. */ +type FlipFN = (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 { + 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); + +} diff --git a/webpack/controls/webcam/show.tsx b/webpack/controls/webcam/show.tsx index 06da9d9a4..983ae7695 100644 --- a/webpack/controls/webcam/show.tsx +++ b/webpack/controls/webcam/show.tsx @@ -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 { +const FALLBACK_FEED = { name: "", url: PLACEHOLDER_FARMBOT }; - state: State = { - current: 0 - }; +export class Show extends React.Component { + 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 ( - +