diff --git a/.github/workflows/elasticlib-ci.yaml b/.github/workflows/elasticlib-ci.yaml
new file mode 100644
index 00000000..adfeb4db
--- /dev/null
+++ b/.github/workflows/elasticlib-ci.yaml
@@ -0,0 +1,32 @@
+name: ElasticLib
+
+on:
+ push:
+ branches: ["main"]
+ pull_request:
+ branches: ["main"]
+ workflow_dispatch:
+
+jobs:
+ wpiformat-analyze:
+ name: "Verify Formatting"
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ - name: Fetch all history and metadata
+ run: |
+ git checkout -b pr
+ git branch -f main origin/main
+ - name: Set up Python 3.8
+ uses: actions/setup-python@v5
+ with:
+ python-version: 3.8
+ - name: Install wpiformat
+ run: pip3 install wpiformat==2024.50
+ - name: Run wpiformat
+ run: wpiformat -f Elastic.java elasticlib.h elasticlib.cpp elasticlib.py
+ working-directory: ./elasticlib
+ - name: Check output
+ run: git --no-pager diff --exit-code HEAD
diff --git a/elasticlib/.styleguide b/elasticlib/.styleguide
index 425b8074..2301a18e 100644
--- a/elasticlib/.styleguide
+++ b/elasticlib/.styleguide
@@ -12,11 +12,19 @@ cppSrcFileInclude {
modifiableFileExclude {
gradle/
assets/
+ build/
+ linux/
macos/
windows/
- linux/
test_resources/
screenshots/
installer_setup_script.iss
README.md
}
+
+includeOtherLibs {
+ ^fmt/
+ ^networktables/
+ ^units/
+ ^wpi/
+}
diff --git a/elasticlib/Elastic.java b/elasticlib/Elastic.java
index d8ab4df0..b124759a 100644
--- a/elasticlib/Elastic.java
+++ b/elasticlib/Elastic.java
@@ -21,25 +21,25 @@ public final class Elastic {
private static final ObjectMapper objectMapper = new ObjectMapper();
/**
- * Sends an alert notification to the Elastic dashboard. The alert is serialized as a JSON string
+ * Sends an notification to the Elastic dashboard. The notification is serialized as a JSON string
* before being published.
*
- * @param alert the {@link ElasticNotification} object containing alert details
+ * @param notification the {@link Notification} object containing notification details
*/
- public static void sendAlert(ElasticNotification alert) {
+ public static void sendNotification(Notification notification) {
try {
- publisher.set(objectMapper.writeValueAsString(alert));
+ publisher.set(objectMapper.writeValueAsString(notification));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
/**
- * Represents a notification object to be sent to the Elastic dashboard. This object holds
+ * Represents an notification object to be sent to the Elastic dashboard. This object holds
* properties such as level, title, description, display time, and dimensions to control how the
- * alert is displayed on the dashboard.
+ * notification is displayed on the dashboard.
*/
- public static class ElasticNotification {
+ public static class Notification {
@JsonProperty("level")
private NotificationLevel level;
@@ -59,17 +59,17 @@ public static class ElasticNotification {
private double height;
/**
- * Creates a new ElasticNotification with all default parameters. This constructor is intended
+ * Creates a new Notification with all default parameters. This constructor is intended
* to be used with the chainable decorator methods
*
*
Title and description fields are empty.
*/
- public ElasticNotification() {
+ public Notification() {
this(NotificationLevel.INFO, "", "");
}
/**
- * Creates a new ElasticNotification with all properties specified.
+ * Creates a new Notification with all properties specified.
*
* @param level the level of the notification (e.g., INFO, WARNING, ERROR)
* @param title the title text of the notification
@@ -78,7 +78,7 @@ public ElasticNotification() {
* @param width the width of the notification display area
* @param height the height of the notification display area, inferred if below zero
*/
- public ElasticNotification(
+ public Notification(
NotificationLevel level,
String title,
String description,
@@ -94,32 +94,32 @@ public ElasticNotification(
}
/**
- * Creates a new ElasticNotification with default display time and dimensions.
+ * Creates a new Notification with default display time and dimensions.
*
* @param level the level of the notification
* @param title the title text of the notification
* @param description the descriptive text of the notification
*/
- public ElasticNotification(NotificationLevel level, String title, String description) {
+ public Notification(NotificationLevel level, String title, String description) {
this(level, title, description, 3000, 350, -1);
}
/**
- * Creates a new ElasticNotification with a specified display time and default dimensions.
+ * Creates a new Notification with a specified display time and default dimensions.
*
* @param level the level of the notification
* @param title the title text of the notification
* @param description the descriptive text of the notification
* @param displayTimeMillis the display time in milliseconds
*/
- public ElasticNotification(
+ public Notification(
NotificationLevel level, String title, String description, int displayTimeMillis) {
this(level, title, description, displayTimeMillis, 350, -1);
}
/**
- * Creates a new ElasticNotification with specified dimensions and default display time. If the
- * height is below zero, it is automatically inferred based on screen size.
+ * Creates a new Notification with specified dimensions and default display time. If the height
+ * is below zero, it is automatically inferred based on screen size.
*
* @param level the level of the notification
* @param title the title text of the notification
@@ -127,7 +127,7 @@ public ElasticNotification(
* @param width the width of the notification display area
* @param height the height of the notification display area, inferred if below zero
*/
- public ElasticNotification(
+ public Notification(
NotificationLevel level, String title, String description, double width, double height) {
this(level, title, description, 3000, width, height);
}
@@ -250,7 +250,7 @@ public double getHeight() {
* @param level the level to set the notification to
* @return the current notification
*/
- public ElasticNotification withLevel(NotificationLevel level) {
+ public Notification withLevel(NotificationLevel level) {
this.level = level;
return this;
}
@@ -261,7 +261,7 @@ public ElasticNotification withLevel(NotificationLevel level) {
* @param title the title to set the notification to
* @return the current notification
*/
- public ElasticNotification withTitle(String title) {
+ public Notification withTitle(String title) {
setTitle(title);
return this;
}
@@ -272,7 +272,7 @@ public ElasticNotification withTitle(String title) {
* @param description the description to set the notification to
* @return the current notification
*/
- public ElasticNotification withDescription(String description) {
+ public Notification withDescription(String description) {
setDescription(description);
return this;
}
@@ -283,7 +283,7 @@ public ElasticNotification withDescription(String description) {
* @param seconds the number of seconds to display the notification for
* @return the current notification
*/
- public ElasticNotification withDisplaySeconds(double seconds) {
+ public Notification withDisplaySeconds(double seconds) {
return withDisplayMilliseconds((int) Math.round(seconds * 1000));
}
@@ -293,7 +293,7 @@ public ElasticNotification withDisplaySeconds(double seconds) {
* @param displayTimeMillis the number of milliseconds to display the notification for
* @return the current notification
*/
- public ElasticNotification withDisplayMilliseconds(int displayTimeMillis) {
+ public Notification withDisplayMilliseconds(int displayTimeMillis) {
setDisplayTimeMillis(displayTimeMillis);
return this;
}
@@ -304,7 +304,7 @@ public ElasticNotification withDisplayMilliseconds(int displayTimeMillis) {
* @param width the width to set the notification to
* @return the current notification
*/
- public ElasticNotification withWidth(double width) {
+ public Notification withWidth(double width) {
setWidth(width);
return this;
}
@@ -315,7 +315,7 @@ public ElasticNotification withWidth(double width) {
* @param height the height to set the notification to
* @return the current notification
*/
- public ElasticNotification withHeight(double height) {
+ public Notification withHeight(double height) {
setHeight(height);
return this;
}
@@ -327,7 +327,7 @@ public ElasticNotification withHeight(double height) {
*
* @return the current notification
*/
- public ElasticNotification withAutomaticHeight() {
+ public Notification withAutomaticHeight() {
setHeight(-1);
return this;
}
@@ -342,7 +342,7 @@ public ElasticNotification withAutomaticHeight() {
*
* @return the current notification
*/
- public ElasticNotification withNoAutoDismiss() {
+ public Notification withNoAutoDismiss() {
setDisplayTimeMillis(0);
return this;
}
diff --git a/elasticlib/elasticlib.cpp b/elasticlib/elasticlib.cpp
new file mode 100644
index 00000000..065322a3
--- /dev/null
+++ b/elasticlib/elasticlib.cpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2023-2024 Gold87 and other Elastic contributors
+// This software can be modified and/or shared under the terms
+// defined by the Elastic license:
+// https://github.com/Gold872/elastic-dashboard/blob/main/LICENSE
+
+#include "elasticlib.h"
+
+#include
+
+#include
+#include
+#include
+#include
+
+namespace elastic {
+
+void SendNotification(const Notification& notification) {
+ static nt::StringTopic topic =
+ nt::NetworkTableInstance::GetDefault().GetStringTopic(
+ "/Elastic/RobotNotifications");
+ static nt::StringPublisher publisher =
+ topic.Publish({.sendAll = true, .keepDuplicates = true});
+
+ try {
+ // Convert Notification to JSON string
+ wpi::json jsonData;
+
+ if (notification.level == NotificationLevel::INFO) {
+ jsonData["level"] = "INFO";
+ } else if (notification.level == NotificationLevel::WARNING) {
+ jsonData["level"] = "WARNING";
+ } else if (notification.level == NotificationLevel::ERROR) {
+ jsonData["level"] = "ERROR";
+ } else {
+ jsonData["level"] = "UNKNOWN";
+ }
+
+ jsonData["title"] = notification.title;
+ jsonData["description"] = notification.description;
+ jsonData["displayTime"] = notification.displayTime.value();
+ jsonData["width"] = notification.width;
+ jsonData["height"] = notification.height;
+
+ // Publish the JSON string
+ publisher.Set(jsonData.dump());
+ } catch (const std::exception& e) {
+ fmt::println(stderr, "Error processing JSON: {}", e.what());
+ } catch (...) {
+ fmt::println(stderr, "Unknown error occurred while processing JSON.");
+ }
+}
+
+} // namespace elastic
diff --git a/elasticlib/elasticlib.h b/elasticlib/elasticlib.h
index 76854e88..d3697230 100644
--- a/elasticlib/elasticlib.h
+++ b/elasticlib/elasticlib.h
@@ -5,352 +5,52 @@
#pragma once
-#include
-#include
-#include
-
-#include
-#include
-#include
#include
-/**
- * @class Elastic
- * @brief Handles publishing notifications to the Elastic Robot Notifications
- * topic on NetworkTables.
- */
-class Elastic {
- public:
- /**
- * @struct Notification
- * @brief Represents a notification with various display properties.
- */
- struct Notification {
- /**
- * @enum Level
- * @brief Defines severity levels for notifications.
- */
- enum class Level { INFO, WARNING, ERROR };
-
- Notification() : level(Level::INFO), title(""), description("") {}
-
- /**
- * @brief Constructs a Notification with default display time and
- * dimensions.
- * @param level The severity level of the notification.
- * @param title The title of the notification.
- * @param description The description of the notification.
- */
- Notification(Level level, const std::string& title,
- const std::string& description)
- : level(level),
- title(title),
- description(description),
- displayTimeMillis(3000),
- width(350),
- height(-1) {}
-
- /**
- * @brief Constructs a Notification with specified display time.
- * @param level The severity level of the notification.
- * @param title The title of the notification.
- * @param description The description of the notification.
- * @param displayTimeInMillis Duration to display the notification, in
- * milliseconds.
- */
- Notification(Level level, const std::string& title,
- const std::string& description, int displayTimeInMillis)
- : level(level),
- title(title),
- description(description),
- displayTimeMillis(displayTimeInMillis),
- width(350),
- height(-1) {}
-
- /**
- * @brief Constructs a Notification with specified display time and
- * dimensions.
- * @param level The severity level of the notification.
- * @param title The title of the notification.
- * @param description The description of the notification.
- * @param displayTimeInMillis Duration to display the notification, in
- * milliseconds.
- * @param width Width of the notification display.
- * @param height Height of the notification display.
- */
- Notification(Level level, const std::string& title,
- const std::string& description, int displayTimeInMillis,
- double width, double height)
- : level(level),
- title(title),
- description(description),
- displayTimeMillis(displayTimeInMillis),
- width(width),
- height(height) {}
-
- /**
- * @brief Sets the notification level.
- * @param level The new severity level.
- */
- void SetLevel(Level level) { this->level = level; }
-
- /**
- * @brief Gets the notification level.
- * @return The current severity level.
- */
- Level GetLevel() const { return level; }
-
- /**
- * @brief Sets the title of the notification.
- * @param title The new title.
- */
- void SetTitle(const std::string& title) { this->title = title; }
-
- /**
- * @brief Gets the title of the notification.
- * @return The current title.
- */
- std::string GetTitle() const { return title; }
-
- /**
- * @brief Sets the description of the notification.
- * @param description The new description.
- */
- void SetDescription(const std::string& description) {
- this->description = description;
- }
-
- /**
- * @brief Gets the description of the notification.
- * @return The current description.
- */
- std::string GetDescription() const { return description; }
-
- /**
- * @brief Gets the display duration of the notification.
- * @return Display time in milliseconds.
- */
- int GetDisplayTimeMillis() const { return displayTimeMillis; }
-
- /**
- * @brief Sets the display duration of the notification.
- * @param newDisplayTimeMillis New display time in milliseconds.
- */
- void SetDisplayTimeMillis(int newDisplayTimeMillis) {
- this->displayTimeMillis = newDisplayTimeMillis;
- }
-
- void SetDisplayTimeSeconds(double seconds) {
- SetDisplayTimeMillis((int)std::round(seconds * 1000));
- }
+#include
- /**
- * @brief Gets the display width of the notification.
- * @return The width in pixels.
- */
- double GetWidth() const { return width; }
+namespace elastic {
- /**
- * @brief Sets the display width of the notification.
- * @param width The new width in pixels.
- */
- void SetWidth(double width) { this->width = width; }
-
- /**
- * @brief Gets the display height of the notification.
- * @return The height in pixels.
- */
- double GetHeight() const { return height; }
-
- /**
- * @brief Sets the display height of the notification.
- * @param height The new height in pixels.
- */
- void SetHeight(double height) { this->height = height; }
-
- /**
- * Modifies the notification's level and returns itself to allow for method
- * chaining.
- *
- * @param level The level to set the notification to.
- * @return A reference to the current notification.
- */
- Notification& WithLevel(Level level) {
- this->level = level;
- return *this;
- }
-
- /**
- * Modifies the notification's title and returns itself to allow for method
- * chaining.
- *
- * @param title The title to set the notification to.
- * @return A reference to the current notification.
- */
- Notification& WithTitle(const std::string& title) {
- SetTitle(title);
- return *this;
- }
-
- /**
- * Modifies the notification's description and returns itself to allow for
- * method chaining.
- *
- * @param description The description to set the notification to.
- * @return A reference to the current notification.
- */
- Notification& WithDescription(const std::string& description) {
- SetDescription(description);
- return *this;
- }
-
- /**
- * Modifies the notification's display time and returns itself to allow for
- * method chaining.
- *
- * @param seconds The number of seconds to display the notification for.
- * @return A reference to the current notification.
- */
- Notification& WithDisplaySeconds(double seconds) {
- return WithDisplayMilliseconds(
- static_cast(std::round(seconds * 1000)));
- }
-
- /**
- * Modifies the notification's display time and returns itself to allow for
- * method chaining.
- *
- * @param displayTimeMillis The number of milliseconds to display the
- * notification for.
- * @return A reference to the current notification.
- */
- Notification& WithDisplayMilliseconds(int displayTimeMillis) {
- SetDisplayTimeMillis(displayTimeMillis);
- return *this;
- }
-
- /**
- * Modifies the notification's width and returns itself to allow for method
- * chaining.
- *
- * @param width The width to set the notification to.
- * @return A reference to the current notification.
- */
- Notification& WithWidth(double width) {
- SetWidth(width);
- return *this;
- }
-
- /**
- * Modifies the notification's height and returns itself to allow for method
- * chaining.
- *
- * @param height The height to set the notification to.
- * @return A reference to the current notification.
- */
- Notification& WithHeight(double height) {
- SetHeight(height);
- return *this;
- }
+/**
+ * Defines severity levels for notifications.
+ */
+enum class NotificationLevel { INFO, WARNING, ERROR };
- /**
- * Modifies the notification's height and returns itself to allow for method
- * chaining.
- *
- * This will set the height to -1 to have it automatically determined by
- * the dashboard.
- *
- * @return A reference to the current notification.
- */
- Notification& WithAutomaticHeight() {
- SetHeight(-1);
- return *this;
- }
+/**
+ * Represents an notification with various display properties.
+ */
+struct Notification {
+ /// Set the display time to this value to disable the auto-dismiss behavior.
+ static constexpr units::millisecond_t NO_AUTO_DISMISS{0_s};
- /**
- * Modifies the notification to disable the auto-dismiss behavior.
- *
- *
This sets the display time to 0 milliseconds.
- *
- *
The auto-dismiss behavior can be re-enabled by setting the display
- * time to a number greater than 0.
- *
- * @return A reference to the current notification.
- */
- Notification& WithNoAutoDismiss() {
- SetDisplayTimeMillis(0);
- return *this;
- }
- /**
- * @brief Converts the notification to a JSON string for publishing.
- * @return JSON string representing the notification.
- */
- std::string ToJson() const {
- wpi::json jsonData;
- jsonData["level"] = LevelToString(level);
- jsonData["title"] = title;
- jsonData["description"] = description;
- jsonData["displayTime"] = displayTimeMillis;
- jsonData["width"] = width;
- jsonData["height"] = height;
- return jsonData.dump();
- }
+ // Set the height to this value to have the dashboard automatically determine
+ // the height.
+ static constexpr int AUTOMATIC_HEIGHT = -1;
- /**
- * @brief Converts a notification level to its string representation.
- * @param level The notification level.
- * @return The string representation of the level.
- */
- static std::string LevelToString(Level level) {
- switch (level) {
- case Level::INFO:
- return "INFO";
- case Level::WARNING:
- return "WARNING";
- case Level::ERROR:
- return "ERROR";
- default:
- return "UNKNOWN";
- }
- }
+ /// Notification severity level.
+ NotificationLevel level = NotificationLevel::INFO;
- private:
- Level level; ///< Notification severity level.
- std::string title; ///< Title of the notification.
- std::string description; ///< Description of the notification.
- int displayTimeMillis; ///< Display time in milliseconds.
- double width; ///< Display width in pixels.
- double height; ///< Display height in pixels.
- };
+ /// Title of the notification.
+ std::string title;
- /**
- * @brief Publishes a notification as a JSON string to the NetworkTables
- * topic.
- * @param alert The notification to send.
- */
- static void SendAlert(const Notification& alert) {
- try {
- std::string jsonString =
- alert.ToJson(); // Convert Notification to JSON string
- GetPublisher().Set(jsonString); // Publish the JSON string
- } catch (const std::exception& e) {
- std::cerr << "Error processing JSON: " << e.what() << std::endl;
- } catch (...) {
- std::cerr << "Unknown error occurred while processing JSON." << std::endl;
- }
- }
+ /// Description of the notification.
+ std::string description;
- private:
- static nt::StringPublisher& GetPublisher() {
- static nt::StringTopic topic =
- nt::NetworkTableInstance::GetDefault().GetStringTopic(
- "/Elastic/RobotNotifications");
+ /// Display time.
+ units::millisecond_t displayTime{3_s};
- static nt::StringPublisher publisher =
- topic.Publish({.sendAll = true, .keepDuplicates = true});
+ /// Display width in pixels.
+ int width = 350;
- return publisher;
- }
+ /// Display height in pixels.
+ int height = AUTOMATIC_HEIGHT;
};
-using ElasticNotification = Elastic::Notification;
+/**
+ * Publishes an notification as a JSON string to the NetworkTables topic.
+ *
+ * @param notification The notification to send.
+ */
+void SendNotification(const Notification& notification);
+
+} // namespace elastic
diff --git a/elasticlib/elasticlib.py b/elasticlib/elasticlib.py
index b9c160a8..566941c5 100644
--- a/elasticlib/elasticlib.py
+++ b/elasticlib/elasticlib.py
@@ -1,19 +1,17 @@
import json
-from typing import Dict
+from enum import Enum
+
from ntcore import NetworkTableInstance, PubSubOptions
-class ElasticNotification:
- """
- Represents a notification object to be sent to the Elastic dashboard.
- This object holds properties such as level, title, description, display time,
- and dimensions to control how the alert is displayed on the dashboard.
- """
+class NotificationLevel(Enum):
+ INFO = "INFO"
+ WARNING = "WARNING"
+ ERROR = "ERROR"
- class NotificationLevel:
- INFO = "INFO"
- WARNING = "WARNING"
- ERROR = "ERROR"
+
+class Notification:
+ """Represents an notification with various display properties."""
def __init__(
self,
@@ -42,299 +40,44 @@ def __init__(
self.width = width
self.height = height
- def to_dict(self) -> Dict[str, str | float | int | NotificationLevel]:
- """
- Converts the notification to a dictionary for JSON serialization.
-
- Returns:
- dict: A dictionary representation of the notification object.
- """
- return {
- "level": self.level,
- "title": self.title,
- "description": self.description,
- "displayTime": self.display_time,
- "width": self.width,
- "height": self.height,
- }
-
- def with_level(self, level: str):
- """
- Sets the notification level and returns the object for chaining.
-
- Args:
- level (str): The level to set the notification to.
-
- Returns:
- ElasticNotification: The current notification object with the updated level.
- """
- self.level = level
- return self
-
- def with_title(self, title: str):
- """
- Sets the title and returns the object for chaining.
-
- Args:
- title (str): The title to set for the notification.
-
- Returns:
- ElasticNotification: The current notification object with the updated title.
- """
- self.title = title
- return self
-
- def with_description(self, description: str):
- """
- Sets the description and returns the object for chaining.
-
- Args:
- description (str): The description to set for the notification.
-
- Returns:
- ElasticNotification: The current notification object with the updated description.
- """
- self.description = description
- return self
-
- def with_display_seconds(self, seconds: float):
- """
- Sets the display time in seconds and returns the object for chaining.
-
- Args:
- seconds (float): The number of seconds the notification should be displayed for.
-
- Returns:
- ElasticNotification: The current notification object with the updated display time.
- """
- self.display_time = int(round(seconds * 1000))
- return self
-
- def with_display_milliseconds(self, display_time: int):
- """
- Sets the display time in milliseconds and returns the object for chaining.
-
- Args:
- display_time (int): The display time in milliseconds.
-
- Returns:
- ElasticNotification: The current notification object with the updated display time.
- """
- self.display_time = display_time
- return self
-
- def with_width(self, width: float):
- """
- Sets the display width and returns the object for chaining.
-
- Args:
- width (float): The width to set for the notification.
-
- Returns:
- ElasticNotification: The current notification object with the updated width.
- """
- self.width = width
- return self
-
- def with_height(self, height: float):
- """
- Sets the display height and returns the object for chaining.
-
- Args:
- height (float): The height to set for the notification.
-
- Returns:
- ElasticNotification: The current notification object with the updated height.
- """
- self.height = height
- return self
-
- def with_automatic_height(self):
- """
- Sets the height to automatic and returns the object for chaining.
-
- Returns:
- ElasticNotification: The current notification object with automatic height.
- """
- self.height = -1
- return self
-
- def with_no_auto_dismiss(self):
- """
- Sets the display time to 0 to prevent automatic dismissal.
-
- This method prevents the notification from disappearing automatically.
-
- Returns:
- None
- """
- self.display_time = 0
-
- def get_level(self) -> str:
- """
- Returns the level of this notification.
-
- Returns:
- str: The current level of the notification.
- """
- return self.level
-
- def set_level(self, level: str):
- """
- Updates the level of this notification.
-
- Args:
- level (str): The level to set the notification to.
-
- Returns:
- None
- """
- self.level = level
-
- def get_title(self) -> str:
- """
- Returns the title of this notification.
-
- Returns:
- str: The current title of the notification.
- """
- return self.title
-
- def set_title(self, title: str):
- """
- Updates the title of this notification.
-
- Args:
- title (str): The title to set the notification to.
-
- Returns:
- None
- """
- self.title = title
-
- def get_description(self) -> str:
- """
- Returns the description of this notification.
-
- Returns:
- str: The current description of the notification.
- """
- return self.description
-
- def set_description(self, description: str):
- """
- Updates the description of this notification.
-
- Args:
- description (str): The description to set the notification to.
-
- Returns:
- None
- """
- self.description = description
-
- def get_display_time_millis(self) -> int:
- """
- Returns the number of milliseconds the notification is displayed for.
- Returns:
- int: The display time in milliseconds.
- """
- return self.display_time
+__topic = None
+__publisher = None
- def set_display_time_seconds(self, seconds: float):
- """
- Updates the display time of the notification in seconds.
-
- Args:
- seconds (float): The number of seconds to display the notification for.
-
- Returns:
- None
- """
- self.display_time = int(round(seconds * 1000))
-
- def set_display_time_millis(self, display_time_millis: int):
- """
- Updates the display time of the notification in milliseconds.
- Args:
- display_time_millis (int): The number of milliseconds to display the notification for.
-
- Returns:
- None
- """
- self.display_time = display_time_millis
-
- def get_width(self) -> float:
- """
- Returns the width of this notification.
-
- Returns:
- float: The current width of the notification.
- """
- return self.width
-
- def set_width(self, width: float):
- """
- Updates the width of this notification.
-
- Args:
- width (float): The width to set for the notification.
-
- Returns:
- None
- """
- self.width = width
-
- def get_height(self) -> float:
- """
- Returns the height of this notification.
-
- Returns:
- float: The current height of the notification.
- """
- return self.height
-
- def set_height(self, height: float):
- """
- Updates the height of this notification.
-
- Args:
- height (float): The height to set for the notification. If height is -1, it indicates automatic height.
-
- Returns:
- None
- """
- self.height = height
-
-
-class Elastic:
+def send_notification(notification: Notification):
"""
- A class responsible for sending alert notifications to the Elastic dashboard.
+ Sends an notification notification to the Elastic dashboard.
+ The notification is serialized as a JSON string before being published.
- This class uses NetworkTables to publish notifications to the dashboard.
- The alerts are serialized as JSON strings before being sent.
- """
-
- _topic = NetworkTableInstance.getDefault().getStringTopic(
- "/Elastic/RobotNotifications"
- )
- _publisher = _topic.publish(PubSubOptions(sendAll=True, keepDuplicates=True))
-
- @staticmethod
- def send_alert(alert: ElasticNotification):
- """
- Sends an alert notification to the Elastic dashboard.
- The alert is serialized as a JSON string before being published.
+ Args:
+ notification (ElasticNotification): The notification object containing the notification details.
- Args:
- alert (ElasticNotification): The notification object containing the alert details.
-
- Raises:
- Exception: If there is an error during serialization or publishing the alert.
- """
- try:
- Elastic._publisher.set(json.dumps(alert.to_dict()))
- except Exception as e:
- print(f"Error serializing alert: {e}")
+ Raises:
+ Exception: If there is an error during serialization or publishing the notification.
+ """
+ global __topic
+ global __publisher
+
+ if not __topic:
+ __topic = NetworkTableInstance.getDefault().getStringTopic(
+ "/Elastic/RobotNotifications"
+ )
+ if not __publisher:
+ __publisher = __topic.publish(PubSubOptions(sendAll=True, keepDuplicates=True))
+
+ try:
+ __publisher.set(
+ json.dumps(
+ {
+ "level": notification.level,
+ "title": notification.title,
+ "description": notification.description,
+ "displayTime": notification.display_time,
+ "width": notification.width,
+ "height": notification.height,
+ }
+ )
+ )
+ except Exception as e:
+ print(f"Error serializing notification: {e}")
diff --git a/lib/pages/dashboard_page.dart b/lib/pages/dashboard_page.dart
index c3a99a41..6ce6f336 100644
--- a/lib/pages/dashboard_page.dart
+++ b/lib/pages/dashboard_page.dart
@@ -12,6 +12,7 @@ import 'package:elegant_notification/elegant_notification.dart';
import 'package:elegant_notification/resources/stacked_options.dart';
import 'package:file_selector/file_selector.dart';
import 'package:flex_seed_scheme/flex_seed_scheme.dart';
+import 'package:http/http.dart';
import 'package:path/path.dart' as path;
import 'package:popover/popover.dart';
import 'package:screen_retriever/screen_retriever.dart';
@@ -20,6 +21,7 @@ import 'package:url_launcher/url_launcher.dart';
import 'package:window_manager/window_manager.dart';
import 'package:elastic_dashboard/services/app_distributor.dart';
+import 'package:elastic_dashboard/services/elastic_layout_downloader.dart';
import 'package:elastic_dashboard/services/hotkey_manager.dart';
import 'package:elastic_dashboard/services/ip_address_util.dart';
import 'package:elastic_dashboard/services/log.dart';
@@ -30,6 +32,7 @@ import 'package:elastic_dashboard/services/shuffleboard_nt_listener.dart';
import 'package:elastic_dashboard/services/update_checker.dart';
import 'package:elastic_dashboard/util/tab_data.dart';
import 'package:elastic_dashboard/widgets/custom_appbar.dart';
+import 'package:elastic_dashboard/widgets/dialog_widgets/dialog_dropdown_chooser.dart';
import 'package:elastic_dashboard/widgets/dialog_widgets/dialog_text_input.dart';
import 'package:elastic_dashboard/widgets/dialog_widgets/dialog_toggle_switch.dart';
import 'package:elastic_dashboard/widgets/dialog_widgets/layout_drag_tile.dart';
@@ -46,6 +49,7 @@ class DashboardPage extends StatefulWidget {
final NTConnection ntConnection;
final SharedPreferences preferences;
final UpdateChecker updateChecker;
+ final ElasticLayoutDownloader? layoutDownloader;
final Function(Color color)? onColorChanged;
final Function(FlexSchemeVariant variant)? onThemeVariantChanged;
@@ -55,6 +59,7 @@ class DashboardPage extends StatefulWidget {
required this.preferences,
required this.version,
required this.updateChecker,
+ this.layoutDownloader,
this.onColorChanged,
this.onThemeVariantChanged,
});
@@ -64,8 +69,11 @@ class DashboardPage extends StatefulWidget {
}
class _DashboardPageState extends State with WindowListener {
- late final SharedPreferences preferences = widget.preferences;
+ SharedPreferences get preferences => widget.preferences;
late final RobotNotificationsListener _robotNotificationListener;
+ late final ElasticLayoutDownloader _layoutDownloader;
+
+ bool _seenShuffleboardWarning = false;
final List _tabData = [];
@@ -164,6 +172,7 @@ class _DashboardPageState extends State with WindowListener {
});
},
onTabCreated: (tab) {
+ _showShuffleboardWarningMessage();
if (preferences.getBool(PrefKeys.layoutLocked) ??
Defaults.layoutLocked) {
return;
@@ -185,43 +194,47 @@ class _DashboardPageState extends State with WindowListener {
));
},
onWidgetAdded: (widgetData) {
+ _showShuffleboardWarningMessage();
if (preferences.getBool(PrefKeys.layoutLocked) ??
Defaults.layoutLocked) {
return;
}
- // Needs to be done in case if widget data gets erased by the listener
- Map widgetDataCopy = {};
-
- widgetData.forEach(
- (key, value) => widgetDataCopy.putIfAbsent(key, () => value));
+ // Needs to be converted into the tab json format
+ Map tabJson = {};
- List tabNamesList = _tabData.map((data) => data.name).toList();
+ String tabName = widgetData['tab'];
+ tabJson.addAll({'containers':