parcel migration cleanup

pull/1107/head
gabrielburnworth 2019-02-06 17:36:11 -08:00
parent 0176d7617f
commit 37047aef54
33 changed files with 100 additions and 76 deletions

View File

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

View File

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

View File

@ -1,10 +1,41 @@
<% if @already_registered %>
You have already verified your account.
Please <%= link_to "log in", "/" %>.
<% else %>
<p> You are now being <%= link_to "redirected", app_landing_page_path %>. </p>
<script>
localStorage.session = JSON.stringify(<%= raw @token %>)
window.location.replace("<%= app_landing_page_path %>");
</script>
<% end %>
<div id="root">
<div class="static-page">
<div class="all-content-wrapper">
<h1 class="text-center">
Account verification
</h1>
<br>
<div class="row">
<div class="col-xs-12">
<div class="widget-wrapper">
<div class="widget-header">
<h5>
<% if @already_registered %>
Already verified
<% else %>
Verification success
<% end %>
</h5>
</div>
<div class="widget-body">
<div class="row">
<div class="col-xs-12">
<% 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 %>.
<script>
localStorage.session = JSON.stringify(<%= raw @token %>);
window.location.replace("<%= app_landing_page_path %>");
</script>
<% end %>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -1 +1 @@
<%# Not needed yet. %>
<%# Intentionally blank template required by router for content generated by frontend. %>

View File

@ -1 +1 @@
<%# Not needed yet. %>
<%# Intentionally blank template required by router for content generated by frontend. %>

View File

@ -1 +1 @@
<%# Not needed yet. %>
<%# Intentionally blank template required by router for content generated by frontend. %>

View File

@ -1 +1 @@
<%# Not needed yet. %>
<%# Intentionally blank template required by router for content generated by frontend. %>

View File

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

View File

@ -55,7 +55,7 @@ export class Controls extends React.Component<Props, {}> {
render() {
const showWebcamWidget =
!this.props.getWebAppConfigVal(BooleanSetting.hide_webcam_widget);
return <Page className="controls">
return <Page className="controls-page">
{showWebcamWidget
?
<Row>

View File

@ -164,7 +164,7 @@ const PlotLines = ({ locationData }: { locationData: BotLocationData }) => {
export const MotorPositionPlot = (props: { locationData: BotLocationData }) => {
return <svg
className="motor-position-plot-border"
style={{ marginTop: "2rem" }}
style={{ marginTop: "2rem", maxHeight: "250px" }}
width="100%"
height="100%"
viewBox={trim(`${-BORDER_WIDTH} ${-HEIGHT / 2 - BORDER_WIDTH}

View File

@ -1,9 +1,8 @@
import * as React from "react";
import { Component } from "react";
import { StepSizeSelectorProps } from "./interfaces";
import { first, last } from "lodash";
export class StepSizeSelector extends Component<StepSizeSelectorProps, {}> {
export class StepSizeSelector extends React.Component<StepSizeSelectorProps, {}> {
cssForIndex(num: number) {
const choices = this.props.choices;
let css = "move-amount no-radius fb-button ";

View File

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

View File

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

View File

@ -1,5 +1,6 @@
.image-flipper {
position: relative;
margin-top: 1rem;
}
.image-flipper-image {

View File

@ -7,6 +7,7 @@
background: $black;
opacity: 0.9;
.bp3-collapse {
width: 100% !important;
overflow-y: scroll !important;
max-height: 20rem !important;
}

View File

@ -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">
<g className="text"
dominantBaseline="middle">

View File

@ -55,7 +55,7 @@ export class Devices extends React.Component<Props, {}> {
const botToMqttLastSeen = (botToMqtt && botToMqttStatus === "up")
? botToMqtt.at
: "";
return <Page className="devices">
return <Page className="device-page">
<Row>
<Col xs={12} sm={6}>
<FarmbotOsSettings

View File

@ -1,7 +1,7 @@
import { Dictionary } from "farmbot/dist";
import { CalendarOccurrence, CalendarDay } from "../../interfaces";
import moment from "moment";
import { chain, sortBy } from "lodash";
import { sortBy } from "lodash";
export class Calendar {
/** We sort by this attribute. Left as const so that the compiler can catch
@ -47,7 +47,7 @@ export class Calendar {
items: sortBy(items, Calendar.SORT_KEY)
};
});
return chain(all).sortBy(Calendar.SORT_KEY).value();
return sortBy(all, Calendar.SORT_KEY);
}
findByDate(m: moment.Moment): CalendarOccurrence[] {

View File

@ -1,4 +1,3 @@
import { duration } from "moment";
import moment from "moment";
import { Moment, unitOfTime } from "moment";
import { range } from "lodash";
@ -77,7 +76,7 @@ export function farmEventIntervalSeconds(repeat: number, unit: TimeUnit) {
if ((unit === NEVER) || !(momentUnit)) {
return 0;
} else {
return duration(repeat, momentUnit).asSeconds();
return moment.duration(repeat, momentUnit).asSeconds();
}
}

View File

@ -12,7 +12,7 @@ import { DesignerNavTabs } from "../panel_header";
import { Link } from "../../link";
import { DesignerPanel, DesignerPanelContent } from "../plants/designer_panel";
import { EmptyStateWrapper, EmptyStateGraphic } from "../../ui/empty_state_wrapper";
import { chain, some, uniq, map } from "lodash";
import { some, uniq, map, sortBy } from "lodash";
const filterSearch = (term: string) => (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/`

View File

@ -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<Props, Partial<State>> {
export class FarmDesigner extends React.Component<Props, Partial<State>> {
initializeSetting =
(name: keyof State, defaultValue: boolean): boolean => {
@ -93,7 +92,7 @@ export class FarmDesigner extends Component<Props, Partial<State>> {
}
childComponent(props: Props) {
return this.props.children || createElement(Plants, props);
return this.props.children || React.createElement(Plants, props);
}
get mapOnly() {

View File

@ -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<SpreadCircleProps, SpreadCircleState> {
React.Component<SpreadCircleProps, SpreadCircleState> {
state: SpreadCircleState = { spread: undefined };
componentWillMount = () => {

View File

@ -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(" ")),

View File

@ -164,7 +164,7 @@ export class FarmwarePage extends React.Component<FarmwareProps, {}> {
render() {
const farmware = getFarmwareByName(
this.props.farmwares, this.current || "take-photo");
return <Page className="farmware">
return <Page className="farmware-page">
<Row>
<LeftPanel
className="farmware-list-panel"

View File

@ -28,7 +28,7 @@ jest.mock("../../api", () => ({
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("<FrontPage />", () => {
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("<FrontPage />", () => {
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("<FrontPage />", () => {
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("<FrontPage />", () => {
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("<FrontPage />", () => {
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("<FrontPage />", () => {
it("submits forgot password: success", async () => {
mockAxiosResponse = Promise.resolve({ data: "" });
debugger;
const el = mount<FrontPage>(<FrontPage />);
el.setState({ email: "foo@bar.io", activePanel: "forgotPassword" });
await el.instance().submitForgotPassword(
fakeEvent as React.FormEvent<HTMLFormElement>);
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("<FrontPage />", () => {
el.setState({ email: "foo@bar.io", activePanel: "forgotPassword" });
await el.instance().submitForgotPassword(
fakeEvent as React.FormEvent<HTMLFormElement>);
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("<FrontPage />", () => {
el.setState({ email: "foo@bar.io", activePanel: "forgotPassword" });
await el.instance().submitForgotPassword(
fakeEvent as React.FormEvent<HTMLFormElement>);
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"));

View File

@ -78,7 +78,7 @@ export class Logs extends React.Component<LogsProps, Partial<LogsState>> {
render() {
const filterBtnColor = this.filterActive ? "green" : "gray";
return <Page className="logs">
return <Page className="logs-page">
<Row>
<Col xs={10}>
<h3>

View File

@ -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<Props, {}> {
export class Regimens extends React.Component<Props, {}> {
componentWillMount() {
if (!this.props.current) { setActiveRegimenByName(); }
}
@ -21,7 +20,7 @@ export class Regimens extends Component<Props, {}> {
render() {
const { current, calendar } = this.props;
const regimenSelected = current && isTaggedRegimen(current) && calendar;
return <Page className="Regimen">
return <Page className="regimen-page">
<Row>
<LeftPanel
className="regimen-list-panel"

View File

@ -13,7 +13,6 @@ import {
findSequenceById
} from "../resources/selectors";
import { TaggedRegimen } from "farmbot";
import { duration } from "moment";
import moment from "moment";
import { ResourceIndex, UUID, VariableNameSet } from "../resources/interfaces";
import {
@ -21,7 +20,7 @@ import {
shouldDisplay as shouldDisplayFunc
} from "../util";
import { resourceUsageList } from "../resources/in_use";
import { groupBy, chain } from "lodash";
import { groupBy, chain, sortBy } from "lodash";
export function mapStateToProps(props: Everything): Props {
const { resources, dispatch, bot } = props;
@ -92,7 +91,7 @@ function generateCalendar(regimen: TaggedRegimen,
return days
.map(makeRows)
.map((x) => {
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 };
};

View File

@ -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<DropdownHeadingId, string> = {
"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)" */

View File

@ -22,7 +22,7 @@ export class Sequences extends React.Component<Props, {}> {
render() {
const { sequence } = this.props;
const sequenceSelected = sequence && isTaggedSequence(sequence);
return <Page className="Sequence">
return <Page className="sequence-page">
<Row>
<LeftPanel
className="sequence-list-panel"

View File

@ -1,6 +1,5 @@
import * as React from "react";
import { t } from "i18next";
import { Component } from "react";
import { StepParams } from "../interfaces";
import { MoveAbsState } from "../interfaces";
import {
@ -52,7 +51,7 @@ interface Args {
}
type LocationArg = "location" | "offset";
export class TileMoveAbsolute extends Component<StepParams, MoveAbsState> {
export class TileMoveAbsolute extends React.Component<StepParams, MoveAbsState> {
get resources() { return this.props.resources; }
get step() { return this.props.currentStep; }
get tool(): TaggedTool | undefined {

View File

@ -13,7 +13,7 @@ export class Tools extends React.Component<Props, Partial<ToolsState>> {
() => this.setState({ [name]: !this.state[name] });
render() {
return <Page className="tools">
return <Page className="tools-page">
<Row>
<Col sm={7}>
{this.state.editingBays

View File

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