diff --git a/app/serializers/base_point_serializer.rb b/app/serializers/base_point_serializer.rb
index 0f8fb4576..32380fd85 100644
--- a/app/serializers/base_point_serializer.rb
+++ b/app/serializers/base_point_serializer.rb
@@ -1,6 +1,24 @@
class BasePointSerializer < ApplicationSerializer
attributes :device_id, :name, :pointer_type, :meta, :x, :y, :z
+ # PROBLEM:
+ # * Users need a mutable way to mark a plant's creation time => `planted_at`
+ # * DB Admin needs to know the _real_ created_at time.
+ # * We can't change field names (or destroy data) that is in use by legacy devices
+ #
+ # SOLUTION:
+ # * Don't allow users to modify `created_at`
+ # * Provide `planted_at` if possible.
+ # * Always provide `planted_at` if it is available
+ # * Provide a read-only view of `created_at` if `planted_at` is `nil`
+ def planted_at
+ object.planted_at || object.created_at
+ end
+
+ def created_at
+ planted_at
+ end
+
def meta
object.meta || {}
end
diff --git a/frontend/constants.ts b/frontend/constants.ts
index 49bc3ffeb..ea11a3eb2 100644
--- a/frontend/constants.ts
+++ b/frontend/constants.ts
@@ -348,9 +348,6 @@ export namespace ToolTips {
For example, you can mark a plant as "planted" during a seeding
sequence or mark a weed as "removed" after removing it.`);
- export const REBOOT =
- trim(`Power cycle FarmBot's onboard computer.`);
-
export const SET_SERVO_ANGLE =
trim(`Move a servo to the provided angle. An angle of 90 degrees
corresponds to the servo midpoint (or, for a continuous rotation
@@ -362,6 +359,9 @@ export namespace ToolTips {
export const MOVE_TO_HOME =
trim(`Move FarmBot to home for the provided axis.`);
+ export const ASSERTION =
+ trim(`Evaluate Lua commands. For power users and software developers.`);
+
export const FIRMWARE_ACTION =
trim(`FarmBot OS or micro-controller firmware action.`);
@@ -740,6 +740,15 @@ export namespace Content {
encoders, stall detection, or endstops enabled for the chosen axis.
Enable endstops, encoders, or stall detection from the Device page for: `);
+ export const REBOOT_STEP =
+ trim(`Power cycle FarmBot's onboard computer.`);
+
+ export const SHUTDOWN_STEP =
+ trim(`Power down FarmBot's onboard computer.`);
+
+ export const ESTOP_STEP =
+ trim(`Unlocking a device requires user intervention.`);
+
export const IN_USE =
trim(`Used in another resource. Protected from deletion.`);
diff --git a/frontend/css/global.scss b/frontend/css/global.scss
index 9e1e23ae6..468e830dc 100644
--- a/frontend/css/global.scss
+++ b/frontend/css/global.scss
@@ -1314,6 +1314,24 @@ ul {
}
}
+.update-resource-step {
+ .custom-meta-field {
+ position: relative;
+ .fa-undo {
+ position: absolute;
+ top: 0.65rem;
+ right: 0.5rem;
+ color: $medium_light_gray;
+ &:hover {
+ color: $dark_gray;
+ }
+ }
+ }
+ .update-resource-pair {
+ margin-top: 1rem;
+ }
+}
+
.farmware-name-manual-input {
margin-top: 1rem;
}
diff --git a/frontend/css/steps.scss b/frontend/css/steps.scss
index d8dc65365..f62097440 100644
--- a/frontend/css/steps.scss
+++ b/frontend/css/steps.scss
@@ -136,6 +136,9 @@
&.reboot-step {
background: $brown;
}
+ &.shutdown-step {
+ background: $brown;
+ }
&.unknown-step {
background: $gray;
}
@@ -253,6 +256,9 @@
&.emergency-stop-step {
background: $light_red;
}
+ &.shutdown-step {
+ background: $light_brown;
+ }
&.reboot-step {
background: $light_brown;
}
diff --git a/frontend/devices/components/fbos_settings/__tests__/os_update_button_test.tsx b/frontend/devices/components/fbos_settings/__tests__/os_update_button_test.tsx
index d83f97440..5b3896b83 100644
--- a/frontend/devices/components/fbos_settings/__tests__/os_update_button_test.tsx
+++ b/frontend/devices/components/fbos_settings/__tests__/os_update_button_test.tsx
@@ -11,12 +11,15 @@ import { OsUpdateButton } from "../os_update_button";
import { OsUpdateButtonProps } from "../interfaces";
import { ShouldDisplay } from "../../../interfaces";
import { Content } from "../../../../constants";
+import { ConfigurationName } from "farmbot";
+
+const UPDATE_CHANNEL = "update_channel" as ConfigurationName;
describe("
{t("Version last seen")}: {fbos_version}
{t("Environment")}: {env}