diff --git a/Client/src/Utils/Theme.js b/Client/src/Utils/Theme.js
index 60273cd95..f3ed11fc3 100644
--- a/Client/src/Utils/Theme.js
+++ b/Client/src/Utils/Theme.js
@@ -91,6 +91,7 @@ const theme = createTheme({
pY: "40px",
},
gap: {
+ xs: "4px",
small: "8px",
medium: "12px",
ml: "16px",
@@ -101,7 +102,7 @@ const theme = createTheme({
info: {
color: secondaryMain,
bg: otherColorsWhite,
- border: "#d0d5dd",
+ border: sectionBorder,
},
error: {
color: "#d92d20",
@@ -109,9 +110,9 @@ const theme = createTheme({
border: "#f04438",
},
warning: {
- color: "#f79009",
- bg: "#fffaef",
- border: "#fecf60"
+ color: "#DC6803",
+ bg: "#fffcf5",
+ border: "#fec84b",
},
},
});
diff --git a/Client/src/Utils/toastUtils.jsx b/Client/src/Utils/toastUtils.jsx
new file mode 100644
index 000000000..73c21c260
--- /dev/null
+++ b/Client/src/Utils/toastUtils.jsx
@@ -0,0 +1,44 @@
+import PropTypes from "prop-types";
+import { toast } from "react-toastify";
+import Alert from "../Components/Alert";
+
+/**
+ * @param {object} props
+ * @param {'info' | 'error' | 'warning'} - The variant of the alert (e.g., "info", "error").
+ * @param {string} props.title - The title of the alert.
+ * @param {string} props.body - The body/content of the alert.
+ * @param {boolean} props.hasIcon - Whether the alert should include an icon.
+ * @param {object} [props.config] - Additional configuration props for the toast.
+ */
+
+export const createToast = ({ variant, title, body, hasIcon, config = {} }) => {
+ const toastConfig = {
+ position: "bottom-right",
+ autoClose: 3000,
+ hideProgressBar: true,
+ closeButton: false,
+ ...config,
+ };
+
+ toast(
+ ({ closeToast }) => (
+
+ ),
+ toastConfig
+ );
+};
+
+createToast.propTypes = {
+ variant: PropTypes.oneOf(["info", "error", "warning"]).isRequired,
+ title: PropTypes.string,
+ body: PropTypes.string,
+ hasIcon: PropTypes.bool,
+ config: PropTypes.object,
+};
diff --git a/Client/src/index.css b/Client/src/index.css
index 4af5f4e84..674acc13e 100644
--- a/Client/src/index.css
+++ b/Client/src/index.css
@@ -59,6 +59,7 @@
--env-var-spacing-1: 12px;
--env-var-spacing-1-plus: 16px;
+ --env-var-spacing-1-minus: 10px;
--env-var-spacing-2: 24px;
--env-var-spacing-3: 32px;
--env-var-spacing-4: 40px;
@@ -124,6 +125,18 @@ button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
+.Toastify__toast-container {
+ width: auto;
+}
+.Toastify [class^="Toastify__toast"] {
+ padding: 0;
+ margin: 0;
+}
+.Toastify__toast{
+ min-height: 0;
+ border-radius: 4px;
+}
+
@media (prefers-color-scheme: light) {
:root {
color: #213547;
diff --git a/Server/controllers/authController.js b/Server/controllers/authController.js
index 184158e55..979a0b87e 100644
--- a/Server/controllers/authController.js
+++ b/Server/controllers/authController.js
@@ -60,6 +60,21 @@ const registerController = async (req, res, next) => {
return;
}
+ // Check if an admin user exists, if so, error
+ try {
+ const admin = await req.db.checkAdmin(req, res);
+ console.log(admin);
+ if (admin === true) {
+ throw new Error(errorMessages.AUTH_ADMIN_EXISTS);
+ }
+ } catch (error) {
+ console.log("WEEEEEEE", error.message);
+ error.service = SERVICE_NAME;
+ error.status = 403;
+ next(error);
+ return;
+ }
+
// Create a new user
try {
const newUser = await req.db.insertUser(req, res);
diff --git a/Server/controllers/monitorController.js b/Server/controllers/monitorController.js
index 3cb1711c7..52433c8d7 100644
--- a/Server/controllers/monitorController.js
+++ b/Server/controllers/monitorController.js
@@ -87,12 +87,6 @@ const getMonitorsByUserId = async (req, res, next) => {
const userId = req.params.userId;
const monitors = await req.db.getMonitorsByUserId(req, res);
- if (monitors && monitors.length === 0) {
- const err = new Error(errorMessages.MONITOR_GET_BY_USER_ID);
- err.status = 404;
- throw err;
- }
-
return res.json({
success: true,
msg: successMessages.MONITOR_GET_BY_USER_ID(userId),
diff --git a/Server/db/MongoDB.js b/Server/db/MongoDB.js
index 36741711c..9b5a485f8 100644
--- a/Server/db/MongoDB.js
+++ b/Server/db/MongoDB.js
@@ -293,19 +293,19 @@ const getMonitorById = async (req, res) => {
*/
const getMonitorsByUserId = async (req, res) => {
try {
- const limit = req.body.limit;
+ const limit = req.query.limit;
const monitors = await Monitor.find({ userId: req.params.userId });
// Map each monitor to include its associated checks
const monitorsWithChecks = await Promise.all(
monitors.map(async (monitor) => {
-
- if(limit) {
+ if (limit) {
// Checks are order oldest -> newest
- const checks = await Check.find({ monitorId: monitor._id }).sort({
- createdAt: 1,
- }).limit(limit);;
+ const checks = await Check.find({ monitorId: monitor._id })
+ .sort({
+ createdAt: 1,
+ })
+ .limit(limit);
return { ...monitor.toObject(), checks };
-
} else {
// Checks are order oldest -> newest
const checks = await Check.find({ monitorId: monitor._id }).sort({
diff --git a/Server/routes/monitorRoute.js b/Server/routes/monitorRoute.js
index d19aedad9..ae7a5852e 100644
--- a/Server/routes/monitorRoute.js
+++ b/Server/routes/monitorRoute.js
@@ -5,7 +5,7 @@ const Monitor = require("../models/Monitor");
router.get("/", monitorController.getAllMonitors);
router.get("/:monitorId", monitorController.getMonitorById);
-router.get("/user/:userId?limit", monitorController.getMonitorsByUserId);
+router.get("/user/:userId", monitorController.getMonitorsByUserId);
router.post("/", monitorController.createMonitor);
router.post(
diff --git a/Server/utils/messages.js b/Server/utils/messages.js
index aded84d59..787adc8f6 100644
--- a/Server/utils/messages.js
+++ b/Server/utils/messages.js
@@ -4,6 +4,7 @@ const errorMessages = {
UNKNOWN_ERROR: "An unknown error occurred",
// Auth Controller
UNAUTHORIZED: "Unauthorized access",
+ AUTH_ADMIN_EXISTS: "Admin already exists",
//Error handling middleware
UNKNOWN_SERVICE: "Unknown service",