Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ commands:
- run:
name: Run JS tests
command: |
sudo docker compose run web npm run test-slow -- -c .circleci/jest-ci.config.js
sudo docker compose run web npm run test-slow -- -c .circleci/jest-ci.config.js -w 6
echo 'export COVERAGE_AVAILABLE=true' >> $BASH_ENV
lint-commands:
steps:
Expand Down
10 changes: 5 additions & 5 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,12 @@ GEM
google-apis-core (>= 0.15.0, < 2.a)
google-apis-storage_v1 (0.50.0)
google-apis-core (>= 0.15.0, < 2.a)
google-cloud-core (1.7.1)
google-cloud-core (1.8.0)
google-cloud-env (>= 1.0, < 3.a)
google-cloud-errors (~> 1.0)
google-cloud-env (2.2.1)
faraday (>= 1.0, < 3.a)
google-cloud-errors (1.4.0)
google-cloud-errors (1.5.0)
google-cloud-storage (1.55.0)
addressable (~> 2.8)
digest-crc (~> 0.4)
Expand Down Expand Up @@ -248,7 +248,7 @@ GEM
hashie (~> 4.1)
multi_json (~> 1.15)
racc (1.8.1)
rack (2.2.11)
rack (2.2.13)
rack-attack (6.7.0)
rack (>= 1.0, < 4)
rack-cors (2.0.2)
Expand Down Expand Up @@ -376,7 +376,7 @@ GEM
rails
warden (1.2.9)
rack (>= 2.0.9)
webmock (3.25.0)
webmock (3.25.1)
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
Expand Down Expand Up @@ -439,4 +439,4 @@ RUBY VERSION
ruby 3.3.7p123

BUNDLED WITH
2.6.2
2.6.5
13 changes: 11 additions & 2 deletions frontend/__test_support__/fake_designer_state.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DesignerState } from "../farm_designer/interfaces";
import { DesignerState, DrawnPointPayl } from "../farm_designer/interfaces";
import { HelpState } from "../help/reducer";
import { RunButtonMenuOpen } from "../sequences/interfaces";

Expand All @@ -20,7 +20,6 @@ export const fakeDesignerState = (): DesignerState => ({
bulkPlantSlug: undefined,
chosenLocation: { x: undefined, y: undefined, z: undefined },
drawnPoint: undefined,
drawnWeed: undefined,
openedSavedGarden: undefined,
tryGroupSortType: undefined,
editGroupAreaInMap: false,
Expand Down Expand Up @@ -63,3 +62,13 @@ export const fakeMenuOpenState = (): RunButtonMenuOpen => ({
component: undefined,
uuid: undefined,
});

export const fakeDrawnPoint = (): DrawnPointPayl => ({
name: "Fake Point",
cx: 10,
cy: 20,
r: 30,
color: "green",
z: 0,
at_soil_level: false,
});
51 changes: 37 additions & 14 deletions frontend/__tests__/hotkeys_test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,58 +12,80 @@ jest.mock("../api/crud", () => ({ save: jest.fn() }));
import React from "react";
import { shallow } from "enzyme";
import {
HotKey, HotKeys, HotKeysProps, hotkeysWithActions, toggleHotkeyHelpOverlay,
HotKey, HotKeys, HotKeysProps, hotkeysWithActions, HotkeysWithActionsProps,
toggleHotkeyHelpOverlay,
} from "../hotkeys";
import { sync } from "../devices/actions";
import { save } from "../api/crud";
import { Actions } from "../constants";
import { Path } from "../internal_urls";
import { mockDispatch } from "../__test_support__/fake_dispatch";
import {
fakeDesignerState, fakeDrawnPoint,
} from "../__test_support__/fake_designer_state";
import { resetDrawnPointDataAction } from "../points/create_points";

describe("hotkeysWithActions()", () => {
beforeEach(() => {
location.pathname = Path.mock(Path.designer());
});

const fakeProps = (): HotkeysWithActionsProps => ({
navigate: jest.fn(),
dispatch: jest.fn(),
designer: fakeDesignerState(),
slug: "",
});

it("has key bindings", () => {
const dispatch = jest.fn();
const navigate = jest.fn();
const hotkeys = hotkeysWithActions(navigate, dispatch, "");
const p = fakeProps();
const hotkeys = hotkeysWithActions(p);
expect(Object.values(hotkeys).length).toBe(8);
const e = {} as KeyboardEvent;

hotkeys[HotKey.save].onKeyDown?.(e);
expect(save).not.toHaveBeenCalled();
mockState.resources.consumers.sequences.current = "uuid";
const hotkeysSettingsPath = hotkeysWithActions(navigate, dispatch, "settings");
p.slug = "settings";
const hotkeysSettingsPath = hotkeysWithActions(p);
hotkeysSettingsPath[HotKey.save].onKeyDown?.(e);
expect(save).not.toHaveBeenCalled();
const hotkeysSequencesPath = hotkeysWithActions(
navigate, dispatch, "sequences");
p.slug = "sequences";
const hotkeysSequencesPath = hotkeysWithActions(p);
hotkeysSequencesPath[HotKey.save].onKeyDown?.(e);
expect(save).toHaveBeenCalledWith("uuid");

hotkeys[HotKey.sync].onKeyDown?.(e);
expect(dispatch).toHaveBeenCalledWith(sync());
expect(p.dispatch).toHaveBeenCalledWith(sync());

hotkeys[HotKey.navigateRight].onKeyDown?.(e);
expect(navigate).toHaveBeenCalledWith(Path.plants());
expect(p.navigate).toHaveBeenCalledWith(Path.plants());

hotkeys[HotKey.navigateLeft].onKeyDown?.(e);
expect(navigate).toHaveBeenCalledWith(Path.settings());
expect(p.navigate).toHaveBeenCalledWith(Path.settings());

hotkeys[HotKey.addPlant].onKeyDown?.(e);
expect(navigate).toHaveBeenCalledWith(Path.cropSearch());
expect(p.navigate).toHaveBeenCalledWith(Path.cropSearch());

hotkeys[HotKey.addEvent].onKeyDown?.(e);
expect(navigate).toHaveBeenCalledWith(Path.farmEvents("add"));
expect(p.navigate).toHaveBeenCalledWith(Path.farmEvents("add"));

const hotkeysWithDispatch =
hotkeysWithActions(navigate, mockDispatch(dispatch), "");
p.slug = "";
const dispatch = jest.fn();
p.dispatch = mockDispatch(dispatch);
const hotkeysWithDispatch = hotkeysWithActions(p);
hotkeysWithDispatch[HotKey.closePanel].onKeyDown?.(e);
expect(dispatch).toHaveBeenCalledWith({
type: Actions.SET_PANEL_OPEN, payload: false,
});

p.dispatch = jest.fn();
const point = fakeDrawnPoint();
point.cx = 1;
p.designer.drawnPoint = point;
const hotkeysWithDrawnPoint = hotkeysWithActions(p);
hotkeysWithDrawnPoint[HotKey.closePanel].onKeyDown?.(e);
expect(p.dispatch).toHaveBeenCalledWith(resetDrawnPointDataAction());
});
});

Expand All @@ -81,6 +103,7 @@ describe("<HotKeys />", () => {
const fakeProps = (): HotKeysProps => ({
dispatch: jest.fn(),
hotkeyGuide: false,
designer: fakeDesignerState(),
});

it("renders", () => {
Expand Down
4 changes: 3 additions & 1 deletion frontend/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,9 @@ export class RawApp extends React.Component<AppProps, {}> {
{(Path.equals("") || Path.equals(Path.app())) && isString(landingPage) &&
<Navigate to={landingPagePath(landingPage)} />}
{!syncLoaded && <LoadingPlant animate={this.props.animate} />}
<HotKeys dispatch={dispatch} hotkeyGuide={this.props.appState.hotkeyGuide} />
<HotKeys dispatch={dispatch}
hotkeyGuide={this.props.appState.hotkeyGuide}
designer={this.props.designer} />
{syncLoaded && <NavBar
designer={this.props.designer}
timeSettings={this.props.timeSettings}
Expand Down
1 change: 0 additions & 1 deletion frontend/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2440,7 +2440,6 @@ export enum Actions {
SET_SLUG_BULK = "SET_SLUG_BULK",
CHOOSE_LOCATION = "CHOOSE_LOCATION",
SET_DRAWN_POINT_DATA = "SET_DRAWN_POINT_DATA",
SET_DRAWN_WEED_DATA = "SET_DRAWN_WEED_DATA",
CHOOSE_SAVED_GARDEN = "CHOOSE_SAVED_GARDEN",
TRY_SORT_TYPE = "TRY_SORT_TYPE",
SET_SETTINGS_SEARCH_TERM = "SET_SETTINGS_SEARCH_TERM",
Expand Down
4 changes: 0 additions & 4 deletions frontend/css/_not_bootstrap.scss
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,6 @@ fieldset {
gap: 1rem;
}

.weed-detection-grid {
gap: 3rem;
}

.panel-title {
display: grid;
font-family: 'Inknut Antiqua', serif;
Expand Down
21 changes: 12 additions & 9 deletions frontend/css/farm_designer/farm_designer_panels.scss
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,18 @@
}

.grid-and-row-planting {
display: grid;
gap: 1rem;
position: relative;
.bp5-collapse-body {
display: grid;
gap: 1rem;
}
.fa-chevron-down,
.fa-chevron-up {
position: absolute;
right: 1rem;
top: 0.5rem;
font-size: 1.5rem;
}
h3 {
width: 100%;
text-align: center;
Expand Down Expand Up @@ -730,13 +740,6 @@
}
}
}
.title-help-icon:hover {
color: $dark_gray !important;
}
.title-help-text.open {
color: $dark_gray !important;
font-size: 1.2rem;
}
}
}

Expand Down
19 changes: 11 additions & 8 deletions frontend/css/global/tooltips.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,12 @@
.help-text-content {
font-size: 1.4rem;
a {
color: $off_white;
&:hover {
color: $white;
text-decoration: underline !important;
font-weight: normal !important;
}
.fa-external-link {
margin-left: 0.5rem;
margin: 0 0.5rem;
}
}
.markdown {
Expand All @@ -64,32 +63,36 @@

.title-help {
display: inline;
.title-help-icon {
margin-left: 1rem;
}
.title-help-text {
overflow: hidden;
max-height: 0;
color: transparent;
transition: all 0.5s ease;
transition-delay: 0.2s;
font-style: italic;
line-height: 2rem;
font-family: sans-serif;
.fa-external-link {
margin: 0 0.5rem;
}
a {
pointer-events: all;
}
a:link {
font-style: normal;
color: $black;
}
a:hover {
font-weight: 600;
color: $black;
text-decoration: underline;
color: unset; // sass-lint:disable-line variable-for-property
}
a:active {
color: $black;
}
&.open{
max-height: 16rem;
color: $black;
color: unset; // sass-lint:disable-line variable-for-property
transition: all 0.5s ease;
margin-bottom: 4rem;
}
Expand Down
13 changes: 6 additions & 7 deletions frontend/css/panels/photos.scss
Original file line number Diff line number Diff line change
Expand Up @@ -100,20 +100,22 @@
display: grid;
grid-template-columns: auto 1fr;
gap: 0.5rem;
align-items: baseline;
}
.title-help {
font-size: 1.3rem;
.fa-question-circle {
position: absolute;
top: -3rem;
top: -2.5rem;
right: 0;
font-size: 1.4rem;
margin-right: 0;
}
a {
text-decoration: none !important;
}
.fa-external-link {
margin-left: 1rem;
a:hover {
text-decoration: underline !important;
}
.update {
display: inline;
Expand All @@ -128,7 +130,7 @@
}
}
.title-help-text.open {
margin-bottom: 0;
margin-bottom: 1rem;
}
}
}
Expand All @@ -142,7 +144,4 @@
font-size: 1.2rem;
font-style: italic;
}
.camera-calibration-setting-grid {
grid-template-columns: 65% auto;
}
}
4 changes: 0 additions & 4 deletions frontend/css/panels/sequences.scss
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,6 @@
margin-bottom: 2.5rem;
padding-left: 0 !important;
}
.title-help-text {
padding-left: 15px;
padding-right: 15px;
}
}
.sequence-editor-content {
.sequence-description {
Expand Down
7 changes: 6 additions & 1 deletion frontend/devices/connectivity/connectivity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { FbosMetricHistoryTable } from "./fbos_metric_history_table";
import { Actions } from "../../constants";
import { forceOnline } from "../must_be_online";
import { isMobile } from "../../screen_size";
import { NavigationContext } from "../../routes_helpers";

export interface ConnectivityProps {
bot: BotState;
Expand Down Expand Up @@ -66,6 +67,10 @@ export class Connectivity
payload: key,
});

static contextType = NavigationContext;
context!: React.ContextType<typeof NavigationContext>;
navigate = this.context;

Realtime = () => {
const { informational_settings } = this.props.bot.hardware;
const {
Expand Down Expand Up @@ -157,7 +162,7 @@ export class Connectivity
<PortRow port={"80 - HTTP"} status={flags["botAPI"]} />
<PortRow port={"443 - HTTPS"} status={flags["botAPI"]} />
<PortRow port={"8883 - MQTT"} status={flags["botMQTT"]} />
<a onClick={docLinkClick("for-it-security-professionals")}>
<a onClick={docLinkClick("for-it-security-professionals", this.navigate)}>
<i className="fa fa-external-link" />
{t("Learn more about ports")}
</a>
Expand Down
4 changes: 2 additions & 2 deletions frontend/devices/connectivity/diagnosis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ export function Diagnosis(props: DiagnosisProps) {
<p>
{diagnosisMessage(getDiagnosisCode(props.statusFlags))}
</p>
<a onClick={docLinkClick("connecting-farmbot-to-the-internet")}>
<a onClick={docLinkClick("connecting-farmbot-to-the-internet", navigate)}>
<i className="fa fa-external-link" />
{t("Click here to learn more about connectivity codes.")}
</a>
<a onClick={docLinkClick("for-it-security-professionals")}>
<a onClick={docLinkClick("for-it-security-professionals", navigate)}>
<i className="fa fa-external-link" />
{t("Click here for document to show to your IT department.")}
</a>
Expand Down
Loading