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 .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.3.8
3.4.3
6 changes: 5 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
source "https://rubygems.org"
ruby "~> 3.3.8"
ruby "~> 3.4.3"

gem "rails", "~> 6"
gem "active_model_serializers"
Expand Down Expand Up @@ -28,6 +28,10 @@ gem "tzinfo-data" # For validation of user selected timezone names
gem "valid_url"
gem "thwait"
gem "lograge" # Used to filter repetitive RabbitMQ logs.
gem "drb"
gem "benchmark"
gem "ostruct"
gem "bigdecimal"

group :development, :test do
gem "climate_control"
Expand Down
21 changes: 14 additions & 7 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ GEM
amq-protocol (2.3.4)
base64 (0.2.0)
bcrypt (3.1.20)
benchmark (0.4.0)
bigdecimal (3.1.9)
builder (3.3.0)
bunny (2.24.0)
Expand Down Expand Up @@ -109,6 +110,7 @@ GEM
discard (1.4.0)
activerecord (>= 4.2, < 9.0)
docile (1.4.1)
drb (2.2.3)
e2mmap (0.1.0)
erubi (1.13.1)
factory_bot (6.5.1)
Expand All @@ -128,15 +130,15 @@ GEM
net-http (>= 0.5.0)
globalid (1.2.1)
activesupport (>= 6.1)
google-apis-core (0.17.0)
google-apis-core (0.18.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (~> 1.9)
httpclient (>= 2.8.3, < 3.a)
mini_mime (~> 1.0)
mutex_m
representable (~> 3.0)
retriable (>= 2.0, < 4.a)
google-apis-iamcredentials_v1 (0.23.0)
google-apis-iamcredentials_v1 (0.24.0)
google-apis-core (>= 0.15.0, < 2.a)
google-apis-storage_v1 (0.51.0)
google-apis-core (>= 0.15.0, < 2.a)
Expand Down Expand Up @@ -165,7 +167,7 @@ GEM
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
hashdiff (1.1.2)
hashdiff (1.2.0)
hashie (4.1.0)
httpclient (2.9.0)
mutex_m
Expand Down Expand Up @@ -227,6 +229,7 @@ GEM
racc (~> 1.4)
orm_adapter (0.5.0)
os (1.1.4)
ostruct (0.6.1)
passenger (6.0.27)
rack (>= 1.6.13)
rackup (>= 1.0.1)
Expand All @@ -245,7 +248,7 @@ GEM
hashie (~> 4.1)
multi_json (~> 1.15)
racc (1.8.1)
rack (2.2.14)
rack (2.2.16)
rack-attack (6.7.0)
rack (>= 1.0, < 4)
rack-cors (2.0.2)
Expand All @@ -270,7 +273,7 @@ GEM
bundler (>= 1.15.0)
railties (= 6.1.7.10)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.2.0)
rails-dom-testing (2.3.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
Expand Down Expand Up @@ -381,21 +384,24 @@ GEM
base64
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
zeitwerk (2.7.2)
zeitwerk (2.7.3)

PLATFORMS
aarch64-linux
x86_64-linux

DEPENDENCIES
active_model_serializers
benchmark
bigdecimal
bunny
climate_control
database_cleaner
delayed_job
delayed_job_active_record
devise
discard
drb
factory_bot_rails
faker
google-cloud-storage (~> 1.11)
Expand All @@ -405,6 +411,7 @@ DEPENDENCIES
logger
lograge
mutations
ostruct
passenger
pg
pry
Expand All @@ -431,7 +438,7 @@ DEPENDENCIES
webmock

RUBY VERSION
ruby 3.3.8p144
ruby 3.4.3p32

BUNDLED WITH
2.6.9
4 changes: 2 additions & 2 deletions docker_configs/api.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
FROM ruby:3.3.8
FROM ruby:3.4.3
RUN curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/apt.postgresql.org.gpg > /dev/null && \
sh -c '. /etc/os-release; echo $VERSION_CODENAME; echo "deb http://apt.postgresql.org/pub/repos/apt/ $VERSION_CODENAME-pgdg main" >> /etc/apt/sources.list.d/pgdg.list' && \
apt-get update -qq && apt-get install -y build-essential libpq-dev postgresql postgresql-contrib && \
mkdir -p /etc/apt/keyrings && \
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
sh -c 'echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" >> /etc/apt/sources.list.d/nodesource.list' && \
sh -c 'echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_24.x nodistro main" >> /etc/apt/sources.list.d/nodesource.list' && \
apt-get update -qq && \
sh -c 'echo "\nPackage: *\nPin: origin deb.nodesource.com\nPin-Priority: 700\n" >> /etc/apt/preferences' && \
apt-get install -y nodejs && \
Expand Down
9 changes: 9 additions & 0 deletions frontend/__test_support__/additional_mocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,12 @@ jest.mock("react-router", () => ({
Navigate: ({ to }: { to: string }) => <div>{mockNavigate(to)}</div>,
Outlet: jest.fn(() => <div />),
}));

jest.mock("delaunator", () => ({
__esModule: true,
default: {
from: jest.fn(() => ({
triangles: [0, 1, 2],
})),
},
}));
1 change: 1 addition & 0 deletions frontend/__test_support__/fake_designer_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export const fakeDesignerState = (): DesignerState => ({
distanceIndicator: "",
panelOpen: true,
threeDTopDownView: false,
threeDExaggeratedZ: false,
});

export const fakeHelpState = (): HelpState => ({
Expand Down
53 changes: 30 additions & 23 deletions frontend/__test_support__/three_d_mocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,40 @@ import {
import * as THREE from "three";
import React, { ReactNode } from "react";
import { TransitionFn, UseSpringProps } from "@react-spring/three";
import { ThreeElements } from "@react-three/fiber";
import { ThreeElements, ThreeEvent } from "@react-three/fiber";
import { Cloud, Clouds, Image, Tube } from "@react-three/drei";

const GroupForTests = (props: ThreeElements["group"]) =>
// @ts-expect-error Property does not exist on type JSX.IntrinsicElements
<group {...props} />;

type Event = ThreeEvent<PointerEvent>;

const MeshForTests = (props: ThreeElements["mesh"]) =>
// @ts-expect-error Property does not exist on type JSX.IntrinsicElements
<mesh {...props}
onPointerMove={(e: Event) =>
props.onPointerMove?.({
// @ts-expect-error: This spread always overwrites this property.
point: { x: 0, y: 0 },
...e,
})}
onClick={(e: Event) =>
props.onClick?.({
// @ts-expect-error: This spread always overwrites this property.
stopPropagation: jest.fn(),
// @ts-expect-error: This spread always overwrites this property.
point: { x: 0, y: 0 },
...e,
} as unknown as Event)}>
{props.name}
{props.children}
{/* @ts-expect-error Property does not exist on type JSX.IntrinsicElements */}
</mesh>;

jest.mock("../three_d_garden/components", () => ({
...jest.requireActual("../three_d_garden/components"),
Mesh: (props: ThreeElements["mesh"]) => <MeshForTests {...props} />,
Group: (props: ThreeElements["group"]) =>
props.visible === false
? <></>
Expand Down Expand Up @@ -61,8 +86,6 @@ jest.mock("@react-spring/three", () => ({
<div className={"animated"}>{children}</div>,
}));

type Event = React.MouseEvent<HTMLDivElement, MouseEvent>;

jest.mock("@react-three/drei", () => {
const useGLTF = jest.fn((key: string) => ({
[ASSETS.models.crossSlide]: {
Expand Down Expand Up @@ -581,6 +604,8 @@ jest.mock("@react-three/drei", () => {
useGLTF,
RoundedBox: ({ name }: { name: string }) =>
<div className={"cylinder"}>{name}</div>,
Plane: ({ name }: { name: string }) =>
<div className={"plane"}>{name}</div>,
Cylinder: ({ name }: { name: string }) =>
<div className={"cylinder"}>{name}</div>,
Torus: ({ name }: { name: string }) =>
Expand All @@ -591,26 +616,8 @@ jest.mock("@react-three/drei", () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Box: (props: any) =>
<div className={"box" + props.name} {...props}>{props.children}</div>,
Extrude: ({ name, onClick, onPointerMove }: {
name: string,
onClick: (event: Event) => void,
onPointerMove: (event: Event) => void,
}) =>
<div className={"extrude"}
onPointerMove={e =>
onPointerMove({
point: { x: 0, y: 0 },
...e,
} as unknown as Event)}
onClick={e =>
onClick({
// @ts-expect-error: This spread always overwrites this property.
stopPropagation: jest.fn(),
point: { x: 0, y: 0 },
...e,
} as unknown as Event)}>
{name}
</div>,
Extrude: ({ name }: { name: string }) =>
<div className={"extrude"}>{name}</div>,
Line: ({ name }: { name: string }) =>
<div className={"line"}>{name}</div>,
Trail: ({ name }: { name: string }) =>
Expand Down
1 change: 1 addition & 0 deletions frontend/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2487,6 +2487,7 @@ export enum Actions {
// 3D
SET_DISTANCE_INDICATOR = "SET_DISTANCE_INDICATOR",
TOGGLE_3D_TOP_DOWN_VIEW = "TOGGLE_3D_TOP_DOWN_VIEW",
TOGGLE_3D_EXAGGERATED_Z = "TOGGLE_3D_EXAGGERATED_Z",

// Regimens
PUSH_WEEK = "PUSH_WEEK",
Expand Down
5 changes: 4 additions & 1 deletion frontend/controls/controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ import { Navigate } from "react-router";
import { mapStateToProps } from "./state_to_props";

export const RawDesignerControls = (props: DesignerControlsProps) => {
props.dispatch({ type: Actions.OPEN_POPUP, payload: "controls" });
React.useEffect(() => {
props.dispatch({ type: Actions.OPEN_POPUP, payload: "controls" });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return <DesignerPanel panelName={"controls"} panel={Panel.Controls}>
<DesignerPanelContent panelName={"controls"}>
<Navigate to={Path.plants()} />
Expand Down
9 changes: 9 additions & 0 deletions frontend/farm_designer/__tests__/reducer_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,15 @@ describe("designer reducer", () => {
expect(newState.threeDTopDownView).toEqual(true);
});

it("sets exaggerated z", () => {
const action: ReduxAction<boolean> = {
type: Actions.TOGGLE_3D_EXAGGERATED_Z,
payload: true,
};
const newState = designer(oldState(), action);
expect(newState.threeDExaggeratedZ).toEqual(true);
});

it("sets panel open state", () => {
const action: ReduxAction<boolean> = {
type: Actions.SET_PANEL_OPEN,
Expand Down
1 change: 1 addition & 0 deletions frontend/farm_designer/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ export interface DesignerState {
distanceIndicator: string;
panelOpen: boolean;
threeDTopDownView: boolean;
threeDExaggeratedZ: boolean;
}

export type TaggedExecutable = TaggedSequence | TaggedRegimen;
Expand Down
5 changes: 5 additions & 0 deletions frontend/farm_designer/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export const initialState: DesignerState = {
distanceIndicator: "",
panelOpen: true,
threeDTopDownView: false,
threeDExaggeratedZ: false,
};

export const designer = generateReducer<DesignerState>(initialState)
Expand Down Expand Up @@ -244,6 +245,10 @@ export const designer = generateReducer<DesignerState>(initialState)
s.threeDTopDownView = payload;
return s;
})
.add<boolean>(Actions.TOGGLE_3D_EXAGGERATED_Z, (s, { payload }) => {
s.threeDExaggeratedZ = payload;
return s;
})
.add<boolean>(Actions.SET_PANEL_OPEN, (s, { payload }) => {
s.panelOpen = payload;
return s;
Expand Down
1 change: 1 addition & 0 deletions frontend/farm_designer/three_d_garden_map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const ThreeDGardenMap = (props: ThreeDGardenMapProps) => {
: "v1.7";

config.negativeZ = props.negativeZ;
config.exaggeratedZ = props.designer.threeDExaggeratedZ;

config.x = props.botPosition.x || 0;
config.y = props.botPosition.y || 0;
Expand Down
12 changes: 12 additions & 0 deletions frontend/three_d_garden/__tests__/components_test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import React from "react";
import { mount } from "enzyme";
import {
AmbientLight,
BoxGeometry,
DirectionalLight,
Group,
Mesh,
Expand All @@ -25,6 +26,17 @@ describe("<Group />", () => {
});
});

describe("<BoxGeometry />", () => {
const fakeProps = (): ThreeElements["boxGeometry"] => ({
name: "box",
});

it("adds props", () => {
const wrapper = mount(<BoxGeometry {...fakeProps()} />);
expect(wrapper.props().name).toEqual("box");
});
});

describe("<AmbientLight />", () => {
const fakeProps = (): ThreeElements["ambientLight"] => ({
intensity: 0.5,
Expand Down
23 changes: 23 additions & 0 deletions frontend/three_d_garden/__tests__/index_test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,29 @@ describe("<ThreeDGardenToggle />", () => {
});
});

it("disables exaggerated z", () => {
const p = fakeProps();
p.designer.threeDExaggeratedZ = true;
render(<ThreeDGardenToggle {...p} />);
const isoViewButton = screen.getByTitle("normal z");
fireEvent.click(isoViewButton);
expect(p.dispatch).toHaveBeenCalledWith({
type: Actions.TOGGLE_3D_EXAGGERATED_Z,
payload: false,
});
});

it("enables exaggerated z", () => {
const p = fakeProps();
render(<ThreeDGardenToggle {...p} />);
const topDownViewButton = screen.getByTitle("exaggerated z");
fireEvent.click(topDownViewButton);
expect(p.dispatch).toHaveBeenCalledWith({
type: Actions.TOGGLE_3D_EXAGGERATED_Z,
payload: true,
});
});

it("toggles 3D view", () => {
const p = fakeProps();
render(<ThreeDGardenToggle {...p} />);
Expand Down
Loading