From 37047aef5402ce88afb7debb6441d586923ffb5b Mon Sep 17 00:00:00 2001 From: gabrielburnworth Date: Wed, 6 Feb 2019 17:36:11 -0800 Subject: [PATCH] parcel migration cleanup --- .circleci/config.yml | 1 + app/controllers/dashboard_controller.rb | 5 +- .../dashboard/confirmation_page.html.erb | 51 +++++++++++++++---- app/views/dashboard/front_page.html.erb | 2 +- app/views/dashboard/main_app.html.erb | 2 +- app/views/dashboard/password_reset.html.erb | 2 +- app/views/dashboard/tos_update.html.erb | 2 +- .../resource_index_builder.ts | 4 +- frontend/controls/controls.tsx | 2 +- .../controls/move/motor_position_plot.tsx | 2 +- frontend/controls/move/step_size_selector.tsx | 3 +- frontend/css/_index.scss | 2 +- frontend/css/global.scss | 5 +- frontend/css/image_flipper.scss | 1 + frontend/css/status_ticker.scss | 1 + frontend/devices/connectivity/diagram.tsx | 2 +- frontend/devices/devices.tsx | 2 +- .../farm_events/calendar/index.ts | 4 +- .../farm_events/calendar/scheduler.ts | 3 +- .../farm_designer/farm_events/farm_events.tsx | 6 +-- frontend/farm_designer/index.tsx | 5 +- .../map/layers/spread/spread_layer.tsx | 3 +- frontend/farm_designer/search_selectors.ts | 4 +- frontend/farmware/index.tsx | 2 +- .../front_page/__tests__/front_page_test.tsx | 19 ++++--- frontend/logs/index.tsx | 2 +- frontend/regimens/index.tsx | 5 +- frontend/regimens/state_to_props.ts | 9 ++-- .../locals_list/location_form_list.ts | 11 ++-- frontend/sequences/sequences.tsx | 2 +- .../step_tiles/tile_move_absolute.tsx | 3 +- frontend/tools/index.tsx | 2 +- package.json | 7 +-- 33 files changed, 100 insertions(+), 76 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 07852d988..f3777e832 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,6 +31,7 @@ jobs: name: Run linters command: | sudo docker-compose run parcel npm run tslint + sudo docker-compose run parcel npm run sass-check sudo docker-compose run parcel npm run sass-lint sudo docker-compose run parcel npm run typecheck - run: diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 917de9358..ee54b81d1 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -47,8 +47,8 @@ class DashboardController < ApplicationController .join(" ") PARCEL_HMR_OPTS = [ - "--hmr-hostname #{ENV.fetch("API_HOST")}", - "--hmr-port 3808" + "--no-hmr", + "--no-cache" ].join(" ") PARCEL_CLI_OUTRO = [ @@ -75,6 +75,7 @@ class DashboardController < ApplicationController end def confirmation_page + load_css_assets user = User.find_by!(confirmation_token: params.fetch(:token)) # Two use cases: re-confirmation Email change klass = user.unconfirmed_email? ? Users::Reverify : Users::Verify diff --git a/app/views/dashboard/confirmation_page.html.erb b/app/views/dashboard/confirmation_page.html.erb index 39c2e19b1..bb23d4740 100644 --- a/app/views/dashboard/confirmation_page.html.erb +++ b/app/views/dashboard/confirmation_page.html.erb @@ -1,10 +1,41 @@ -<% if @already_registered %> - You have already verified your account. - Please <%= link_to "log in", "/" %>. -<% else %> -

You are now being <%= link_to "redirected", app_landing_page_path %>.

- -<% end %> +
+
+
+

+ Account verification +

+
+
+
+
+
+
+ <% if @already_registered %> + Already verified + <% else %> + Verification success + <% end %> +
+
+
+
+
+ <% if @already_registered %> + You have already verified your account. + Please <%= link_to "log in", "/" %>. + <% else %> + You are now being <%= link_to "redirected", app_landing_page_path %>. + + <% end %> +
+
+
+
+
+
+
+
+
diff --git a/app/views/dashboard/front_page.html.erb b/app/views/dashboard/front_page.html.erb index 9046ef559..4d5af9468 100644 --- a/app/views/dashboard/front_page.html.erb +++ b/app/views/dashboard/front_page.html.erb @@ -1 +1 @@ -<%# Not needed yet. %> +<%# Intentionally blank template required by router for content generated by frontend. %> diff --git a/app/views/dashboard/main_app.html.erb b/app/views/dashboard/main_app.html.erb index 9046ef559..4d5af9468 100644 --- a/app/views/dashboard/main_app.html.erb +++ b/app/views/dashboard/main_app.html.erb @@ -1 +1 @@ -<%# Not needed yet. %> +<%# Intentionally blank template required by router for content generated by frontend. %> diff --git a/app/views/dashboard/password_reset.html.erb b/app/views/dashboard/password_reset.html.erb index 9046ef559..4d5af9468 100644 --- a/app/views/dashboard/password_reset.html.erb +++ b/app/views/dashboard/password_reset.html.erb @@ -1 +1 @@ -<%# Not needed yet. %> +<%# Intentionally blank template required by router for content generated by frontend. %> diff --git a/app/views/dashboard/tos_update.html.erb b/app/views/dashboard/tos_update.html.erb index 9046ef559..4d5af9468 100644 --- a/app/views/dashboard/tos_update.html.erb +++ b/app/views/dashboard/tos_update.html.erb @@ -1 +1 @@ -<%# Not needed yet. %> +<%# Intentionally blank template required by router for content generated by frontend. %> diff --git a/frontend/__test_support__/resource_index_builder.ts b/frontend/__test_support__/resource_index_builder.ts index b91850670..46a540b67 100644 --- a/frontend/__test_support__/resource_index_builder.ts +++ b/frontend/__test_support__/resource_index_builder.ts @@ -11,7 +11,7 @@ import { resourceReducer, emptyState } from "../resources/reducer"; import { resourceReady } from "../sync/actions"; import { threeWayComparison as c3 } from "../util/move"; import { defensiveClone } from "../util/util"; -import { chain } from "lodash"; +import { chain, groupBy } from "lodash"; export function fakeDevice(): TaggedDevice { return { "kind": "Device", @@ -420,7 +420,7 @@ const blankReg: TaggedRegimen = { * number of failed tests. To circumvent this, we "repair" faulty foreign keys * in TaggedResources. This applies to many legacy tests. - RC*/ function repairBrokeReferences(resources: TaggedResource[]): TaggedResource[] { - const table = chain(resources).groupBy(x => x.kind).value(); + const table = groupBy(resources, x => x.kind); resources.map(resource => { if (resource.kind === "FarmEvent") { // Find FarmEvents const { executable_type, executable_id } = resource.body; diff --git a/frontend/controls/controls.tsx b/frontend/controls/controls.tsx index 5857ecaa0..008b7843b 100644 --- a/frontend/controls/controls.tsx +++ b/frontend/controls/controls.tsx @@ -55,7 +55,7 @@ export class Controls extends React.Component { render() { const showWebcamWidget = !this.props.getWebAppConfigVal(BooleanSetting.hide_webcam_widget); - return + return {showWebcamWidget ? diff --git a/frontend/controls/move/motor_position_plot.tsx b/frontend/controls/move/motor_position_plot.tsx index 1eb114997..42acbb94f 100644 --- a/frontend/controls/move/motor_position_plot.tsx +++ b/frontend/controls/move/motor_position_plot.tsx @@ -164,7 +164,7 @@ const PlotLines = ({ locationData }: { locationData: BotLocationData }) => { export const MotorPositionPlot = (props: { locationData: BotLocationData }) => { return { +export class StepSizeSelector extends React.Component { cssForIndex(num: number) { const choices = this.props.choices; let css = "move-amount no-radius fb-button "; diff --git a/frontend/css/_index.scss b/frontend/css/_index.scss index 314ef873c..76ae07122 100644 --- a/frontend/css/_index.scss +++ b/frontend/css/_index.scss @@ -1,7 +1,7 @@ // Blueprint -// @import "~normalize.css"; @import "@blueprintjs/core/lib/css/blueprint.css"; @import "@blueprintjs/icons/lib/css/blueprint-icons.css"; +// Partials @import "animations"; @import "colors"; @import "fonts"; diff --git a/frontend/css/global.scss b/frontend/css/global.scss index 1b8ebc41b..1f8127bf3 100644 --- a/frontend/css/global.scss +++ b/frontend/css/global.scss @@ -402,7 +402,6 @@ fieldset { .webcam-stream-unavailable { position: relative; width: 100%; - height: 100%; } .webcam-stream-unavailable img { @@ -761,7 +760,7 @@ ul { } } -.farmware { +.farmware-page { button { margin: 0.5rem; } @@ -814,7 +813,7 @@ ul { word-wrap: break-word; } -.logs { +.logs-page { .row { @media screen and (max-width: 974px) { margin-left: 0; diff --git a/frontend/css/image_flipper.scss b/frontend/css/image_flipper.scss index 06a6d22b6..4ae29bfb8 100644 --- a/frontend/css/image_flipper.scss +++ b/frontend/css/image_flipper.scss @@ -1,5 +1,6 @@ .image-flipper { position: relative; + margin-top: 1rem; } .image-flipper-image { diff --git a/frontend/css/status_ticker.scss b/frontend/css/status_ticker.scss index cb87bcc70..d75c327c7 100644 --- a/frontend/css/status_ticker.scss +++ b/frontend/css/status_ticker.scss @@ -7,6 +7,7 @@ background: $black; opacity: 0.9; .bp3-collapse { + width: 100% !important; overflow-y: scroll !important; max-height: 20rem !important; } diff --git a/frontend/devices/connectivity/diagram.tsx b/frontend/devices/connectivity/diagram.tsx index 250a2c831..61f5668ce 100644 --- a/frontend/devices/connectivity/diagram.tsx +++ b/frontend/devices/connectivity/diagram.tsx @@ -142,7 +142,7 @@ export function ConnectivityDiagram(props: ConnectivityDiagramProps) { id="connectivity-diagram" width="100%" height="100%" - style={{ maxHeight: "300px" }} + style={{ maxHeight: "250px" }} viewBox="-100 -100 210 220"> diff --git a/frontend/devices/devices.tsx b/frontend/devices/devices.tsx index 6ed4489c4..ce77cdcc4 100644 --- a/frontend/devices/devices.tsx +++ b/frontend/devices/devices.tsx @@ -55,7 +55,7 @@ export class Devices extends React.Component { const botToMqttLastSeen = (botToMqtt && botToMqttStatus === "up") ? botToMqtt.at : ""; - return + return (item: CalendarOccurrence) => item.heading.toLowerCase().includes(term) @@ -31,9 +31,7 @@ export class PureFarmEvents innerRows = (items: CalendarOccurrence[]) => { - return chain(items) - .sortBy(x => x.sortKey) - .value() + return sortBy(items, x => x.sortKey) .filter(filterSearch(this.searchTerm)) .map((occur, index) => { const url = `/app/designer/farm_events/` diff --git a/frontend/farm_designer/index.tsx b/frontend/farm_designer/index.tsx index 6488c346c..87a0b55bd 100755 --- a/frontend/farm_designer/index.tsx +++ b/frontend/farm_designer/index.tsx @@ -1,5 +1,4 @@ import * as React from "react"; -import { Component, createElement } from "react"; import { connect } from "react-redux"; import { GardenMap } from "./map/garden_map"; import { Props, State, BotOriginQuadrant, isBotOriginQuadrant } from "./interfaces"; @@ -39,7 +38,7 @@ export const getGridSize = export const gridOffset: AxisNumberProperty = { x: 50, y: 50 }; @connect(mapStateToProps) -export class FarmDesigner extends Component> { +export class FarmDesigner extends React.Component> { initializeSetting = (name: keyof State, defaultValue: boolean): boolean => { @@ -93,7 +92,7 @@ export class FarmDesigner extends Component> { } childComponent(props: Props) { - return this.props.children || createElement(Plants, props); + return this.props.children || React.createElement(Plants, props); } get mapOnly() { diff --git a/frontend/farm_designer/map/layers/spread/spread_layer.tsx b/frontend/farm_designer/map/layers/spread/spread_layer.tsx index 07ef1f368..a97ccf13c 100644 --- a/frontend/farm_designer/map/layers/spread/spread_layer.tsx +++ b/frontend/farm_designer/map/layers/spread/spread_layer.tsx @@ -1,5 +1,4 @@ import * as React from "react"; -import { Component } from "react"; import { round, transformXY } from "../../util"; import { cachedCrop } from "../../../../open_farm/icons"; import { MapTransformProps, TaggedPlant } from "../../interfaces"; @@ -71,7 +70,7 @@ interface SpreadCircleState { } export class SpreadCircle extends - Component { + React.Component { state: SpreadCircleState = { spread: undefined }; componentWillMount = () => { diff --git a/frontend/farm_designer/search_selectors.ts b/frontend/farm_designer/search_selectors.ts index 5a32b52de..ac92df1d2 100644 --- a/frontend/farm_designer/search_selectors.ts +++ b/frontend/farm_designer/search_selectors.ts @@ -1,11 +1,11 @@ import { CropLiveSearchResult } from "./interfaces"; import { t } from "i18next"; import { DEFAULT_ICON } from "../open_farm/icons"; -import { startCase, chain } from "lodash"; +import { startCase, find } from "lodash"; export function findBySlug( crops: CropLiveSearchResult[], slug?: string): CropLiveSearchResult { - const crop = chain(crops).find((result) => result.crop.slug === slug).value(); + const crop = find(crops, result => result.crop.slug === slug); return crop || { crop: { name: startCase((slug || t("Name")).split("-").join(" ")), diff --git a/frontend/farmware/index.tsx b/frontend/farmware/index.tsx index 0dfaa0d8c..7ea0182d1 100644 --- a/frontend/farmware/index.tsx +++ b/frontend/farmware/index.tsx @@ -164,7 +164,7 @@ export class FarmwarePage extends React.Component { render() { const farmware = getFarmwareByName( this.props.farmwares, this.current || "take-photo"); - return + return ({ import * as React from "react"; import { mount, shallow } from "enzyme"; import { FrontPage, setField, PartialFormEvent } from "../front_page"; -import * as axios from "axios"; +import axios from "axios"; import { API } from "../../api"; import { Session } from "../../session"; import { success, error } from "farmbot-toastr"; @@ -61,7 +61,7 @@ describe("", () => { el.setState({ email: "foo@bar.io", loginPassword: "password" }); await el.instance().submitLogin(fakeEvent as FormEvent); expect(API.setBaseUrl).toHaveBeenCalled(); - expect(axios.default.post).toHaveBeenCalledWith( + expect(axios.post).toHaveBeenCalledWith( "://localhost:3000/api/tokens/", { user: { email: "foo@bar.io", password: "password" } }); expect(Session.replaceToken).toHaveBeenCalledWith("new data"); @@ -73,7 +73,7 @@ describe("", () => { el.setState({ email: "foo@bar.io", loginPassword: "password" }); await el.instance().submitLogin(fakeEvent as FormEvent); expect(API.setBaseUrl).toHaveBeenCalled(); - expect(axios.default.post).toHaveBeenCalledWith( + expect(axios.post).toHaveBeenCalledWith( "://localhost:3000/api/tokens/", { user: { email: "foo@bar.io", password: "password" } }); expect(Session.replaceToken).not.toHaveBeenCalled(); @@ -88,7 +88,7 @@ describe("", () => { el.setState({ email: "foo@bar.io", loginPassword: "password" }); await el.instance().submitLogin(fakeEvent as FormEvent); expect(API.setBaseUrl).toHaveBeenCalled(); - expect(axios.default.post).toHaveBeenCalledWith( + expect(axios.post).toHaveBeenCalledWith( "://localhost:3000/api/tokens/", { user: { email: "foo@bar.io", password: "password" } }); await expect(Session.replaceToken).not.toHaveBeenCalled(); @@ -106,7 +106,7 @@ describe("", () => { agreeToTerms: true }); await el.instance().submitRegistration(fakeEvent as FormEvent); - expect(axios.default.post).toHaveBeenCalledWith("usersPath", { + expect(axios.post).toHaveBeenCalledWith("usersPath", { user: { agree_to_terms: true, email: "foo@bar.io", name: "Foo Bar", password: "password", password_confirmation: "password" @@ -128,7 +128,7 @@ describe("", () => { agreeToTerms: true }); await el.instance().submitRegistration(fakeEvent as FormEvent); - await expect(axios.default.post).toHaveBeenCalledWith("usersPath", { + await expect(axios.post).toHaveBeenCalledWith("usersPath", { user: { agree_to_terms: true, email: "foo@bar.io", name: "Foo Bar", password: "password", password_confirmation: "password" @@ -141,12 +141,11 @@ describe("", () => { it("submits forgot password: success", async () => { mockAxiosResponse = Promise.resolve({ data: "" }); - debugger; const el = mount(); el.setState({ email: "foo@bar.io", activePanel: "forgotPassword" }); await el.instance().submitForgotPassword( fakeEvent as React.FormEvent); - await expect(axios.default.post).toHaveBeenCalledWith("resetPath", + await expect(axios.post).toHaveBeenCalledWith("resetPath", { email: "foo@bar.io" }); await expect(success).toHaveBeenCalledWith( "Email has been sent.", "Forgot Password"); @@ -159,7 +158,7 @@ describe("", () => { el.setState({ email: "foo@bar.io", activePanel: "forgotPassword" }); await el.instance().submitForgotPassword( fakeEvent as React.FormEvent); - await expect(axios.default.post).toHaveBeenCalledWith("resetPath", + await expect(axios.post).toHaveBeenCalledWith("resetPath", { email: "foo@bar.io" }); await expect(error).toHaveBeenCalledWith( expect.stringContaining("failure")); @@ -172,7 +171,7 @@ describe("", () => { el.setState({ email: "foo@bar.io", activePanel: "forgotPassword" }); await el.instance().submitForgotPassword( fakeEvent as React.FormEvent); - await expect(axios.default.post).toHaveBeenCalledWith("resetPath", + await expect(axios.post).toHaveBeenCalledWith("resetPath", { email: "foo@bar.io" }); await expect(error).toHaveBeenCalledWith(expect.stringContaining( "not associated with an account")); diff --git a/frontend/logs/index.tsx b/frontend/logs/index.tsx index 93b1e2509..d32dbb34a 100644 --- a/frontend/logs/index.tsx +++ b/frontend/logs/index.tsx @@ -78,7 +78,7 @@ export class Logs extends React.Component> { render() { const filterBtnColor = this.filterActive ? "green" : "gray"; - return + return

diff --git a/frontend/regimens/index.tsx b/frontend/regimens/index.tsx index cf282d089..ee15382a2 100644 --- a/frontend/regimens/index.tsx +++ b/frontend/regimens/index.tsx @@ -1,5 +1,4 @@ import * as React from "react"; -import { Component } from "react"; import { BulkScheduler } from "./bulk_scheduler/index"; import { RegimensList } from "./list/index"; import { RegimenEditor } from "./editor/index"; @@ -13,7 +12,7 @@ import { t } from "i18next"; import { ToolTips } from "../constants"; @connect(mapStateToProps) -export class Regimens extends Component { +export class Regimens extends React.Component { componentWillMount() { if (!this.props.current) { setActiveRegimenByName(); } } @@ -21,7 +20,7 @@ export class Regimens extends Component { render() { const { current, calendar } = this.props; const regimenSelected = current && isTaggedRegimen(current) && calendar; - return + return { - x.items = chain(x.items).sortBy(SORT_KEY).value(); + x.items = sortBy(x.items, SORT_KEY); return x; }); } @@ -102,10 +101,10 @@ const createRows = (index: ResourceIndex, dispatch: Function, regimen: TaggedReg const uuid = findId(index, "Sequence", item.sequence_id); const sequence = findSequence(index, uuid); const { time_offset } = item; - const d = duration(time_offset); + const d = moment.duration(time_offset); const { name } = sequence.body; const color = sequence.body.color || randomColor(); const hhmm = moment({ hour: d.hours(), minute: d.minutes() }).format(FMT); - const day = Math.floor(duration(time_offset).asDays()) + 1; + const day = Math.floor(moment.duration(time_offset).asDays()) + 1; return { name, hhmm, color, day, dispatch, regimen, item, sortKey: time_offset }; }; diff --git a/frontend/sequences/locals_list/location_form_list.ts b/frontend/sequences/locals_list/location_form_list.ts index c6fffe3a3..06d1f9929 100644 --- a/frontend/sequences/locals_list/location_form_list.ts +++ b/frontend/sequences/locals_list/location_form_list.ts @@ -8,7 +8,7 @@ import { TaggedTool, TaggedPoint } from "farmbot"; import { DropDownItem } from "../../ui"; import { Vector3 } from "farmbot/dist"; import { t } from "i18next"; -import { capitalize, chain } from "lodash"; +import { capitalize } from "lodash"; import { joinKindAndId } from "../../resources/reducer_support"; import { Point } from "farmbot/dist/resources/api_resources"; @@ -43,12 +43,12 @@ export const NAME_MAP: Record = { "Other": "Other", }; -const heading = (name: DropdownHeadingId) => ({ +const heading = (name: DropdownHeadingId): DropDownItem[] => ([{ label: t(NAME_MAP[name]), heading: true, value: 0, headingId: name -}); +}]); const ddiFrom = (points: TaggedPoint[], pointerType: PointerTypeName) => points .filter(x => x.body.pointer_type === pointerType) @@ -70,7 +70,7 @@ export function locationFormList(resources: ResourceIndex, .map(({ tool, location }) => formatTools(tool, location)) .filter(x => parseInt("" + x.value) > 0); const group = maybeGroup(!!displayGroups); - return chain(heading("Tool")) + return heading("Tool") .concat(toolDDI) .concat(group(everyPointDDI("Tool"))) .concat(group(everyPointDDI("ToolSlot"))) @@ -82,8 +82,7 @@ export function locationFormList(resources: ResourceIndex, .concat(group(everyPointDDI("GenericPointer"))) .concat(heading("Other")) .concat(additionalItems) - .concat(COORDINATE_DDI()) - .value(); + .concat(COORDINATE_DDI()); } /** Create drop down item with label; i.e., "Point/Plant (1, 2, 3)" */ diff --git a/frontend/sequences/sequences.tsx b/frontend/sequences/sequences.tsx index 456ce5b20..66eb4177b 100644 --- a/frontend/sequences/sequences.tsx +++ b/frontend/sequences/sequences.tsx @@ -22,7 +22,7 @@ export class Sequences extends React.Component { render() { const { sequence } = this.props; const sequenceSelected = sequence && isTaggedSequence(sequence); - return + return { +export class TileMoveAbsolute extends React.Component { get resources() { return this.props.resources; } get step() { return this.props.currentStep; } get tool(): TaggedTool | undefined { diff --git a/frontend/tools/index.tsx b/frontend/tools/index.tsx index b4ea2b30a..0ac312f1c 100644 --- a/frontend/tools/index.tsx +++ b/frontend/tools/index.tsx @@ -13,7 +13,7 @@ export class Tools extends React.Component> { () => this.setState({ [name]: !this.state[name] }); render() { - return + return {this.state.editingBays diff --git a/package.json b/package.json index e656f719b..fa6acb587 100644 --- a/package.json +++ b/package.json @@ -10,11 +10,12 @@ "coverage": "cat **/*lcov.info | ./node_modules/coveralls/bin/coveralls.js", "build": "TARGET=production echo Rick- fix this 30 jan", "start": "echo 'DEPRECATED. Remove `start` from npm scripts'", - "test-slow": "jest --coverage --ci --maxWorkers=6 --colors", + "test-slow": "jest --coverage --ci -w 6 --colors", "test": "jest --no-coverage --cache -w 5 --colors", - "typecheck": "./node_modules/.bin/tsc --noEmit --jsx preserve", + "typecheck": "./node_modules/typescript/bin/tsc --noEmit", "tslint": "./node_modules/tslint/bin/tslint --project .", - "sass-lint": "./node_modules/sass-lint/bin/sass-lint.js -c .sass-lint.yml -v -q" + "sass-lint": "./node_modules/sass-lint/bin/sass-lint.js -c .sass-lint.yml -v -q", + "sass-check": "./node_modules/sass/sass.js --no-source-map frontend/css/_index.scss sass.log" }, "keywords": [ "farmbot"