Merge branch 'bluewave-labs:master' into backend-completion

This commit is contained in:
Mohammad Khalilzadeh authored and GitHub committed 2024-07-05 09:20:24 +03:30
commit a7adb8c04b
18 files changed
+80 -120

No files matched your search

@@ -1,38 +0,0 @@
import SearchTextField from "../TextFields/Search/SearchTextField";
import "./index.css";
import HostsTable from "../HostsTable";
import Pagination from "../Pagination";
import PropTypes from "prop-types";
/**
* CurrentMonitors displays the current status of monitor
*
* @component
* @param {Array<Monitor>} monitors - An array of monitor objects to be displayed.
*/
const CurrentMonitors = ({ monitors }) => {
return (
<div className="current-monitors">
<div className="current-monitors-bar">
<div className="current-monitors-title-holder">
<div className="current-monitors-title">Current monitors</div>
<div className="current-monitors-counter">{monitors.length}</div>
</div>
<div className="current-monitors-search-bar">
<SearchTextField />
</div>
</div>
<div className="monitors-v-gaping"></div>
<HostsTable monitors={monitors} />
<div className="monitors-v-gaping"></div>
<Pagination />
</div>
);
};
CurrentMonitors.propTypes = {
monitors: PropTypes.arrayOf(PropTypes.object).isRequired,
};
export default CurrentMonitors;
@@ -1,6 +1,7 @@
import TabPanel from "@mui/lab/TabPanel";
import React, { useState } from "react";
import AnnouncementsDualButtonWithIcon from "../../Announcements/AnnouncementsDualButtonWithIcon/AnnouncementsDualButtonWithIcon";
// import AnnouncementsDualButtonWithIcon from "../../Announcements/AnnouncementsDualButtonWithIcon/AnnouncementsDualButtonWithIcon";
import AnnouncementsDualButtonWithIcon from "../../Toast/AnnouncementsDualButtonWithIcon/AnnouncementsDualButtonWithIcon";
import { useTheme } from "@emotion/react";
import { Box, Divider, Stack, Typography } from "@mui/material";
import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
+1 -1
View File
@@ -1,6 +1,6 @@
import PropTypes from "prop-types";
import ComplexAlert from "../../Components/Icons/ComplexAlert/ComplexAlert";
import AnnouncementsDualButtonWithIcon from "../../Components/Announcements/AnnouncementsDualButtonWithIcon/AnnouncementsDualButtonWithIcon";
import AnnouncementsDualButtonWithIcon from "./AnnouncementsDualButtonWithIcon/AnnouncementsDualButtonWithIcon";
import "react-toastify/dist/ReactToastify.css";
import { toast, ToastContainer } from "react-toastify";
import "./index.css";
@@ -1,65 +0,0 @@
import Button from "../../Components/Button";
import ServerStatus from "../../Components/Charts/Servers/ServerStatus";
import CurrentMonitors from "../../Components/CurrentMonitors";
import PropTypes from "prop-types";
import { useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
/**
* CurrentStats displays the current status of monitor
*
* @component
* @param {Array<Monitor>} monitors - An array of monitor objects to be displayed.
*/
const CurrentStats = ({ monitors }) => {
const navigate = useNavigate();
const authState = useSelector((state) => state.auth);
const up = monitors.reduce((acc, cur) => {
if (cur.checks.length > 0) {
return cur.checks[cur.checks.length - 1].status === true ? acc + 1 : acc;
}
return 0;
}, 0);
const down = monitors.reduce((acc, cur) => {
if (cur.checks.length > 0) {
return cur.checks[cur.checks.length - 1].status === false ? acc + 1 : acc;
}
return 0;
}, 0);
return (
<div>
<div className="monitors-gaps-medium"></div>
<div className="monitors-gaps-medium"></div>
<div className="monitors-bar">
<div className="monitors-bar-title">
Hello, {authState.user.firstname}
</div>
<Button
level="primary"
label="Create new monitor"
onClick={() => {
navigate("/monitors/create");
}}
sx={{ padding: "10px 20px", fontSize: "13px" }}
/>
</div>
<div className="monitors-gaps-medium"></div>
<div className="monitors-stats">
<ServerStatus title="Up" value={up} state="up" />
<ServerStatus title="Down" value={down} state="down" />
<ServerStatus title="Paused" value={0} state="pause" />
</div>
<div className="monitors-gaps-medium"></div>
<CurrentMonitors monitors={monitors} />
</div>
);
};
CurrentStats.propTypes = {
monitors: PropTypes.arrayOf(PropTypes.object).isRequired,
};
export default CurrentStats;
+2
View File
@@ -9,6 +9,7 @@
}
.monitors-bar {
margin-top: calc(2 * var(--env-var-spacing-2));
display: flex;
justify-content: space-between;
align-items: center;
@@ -20,6 +21,7 @@
}
.monitors-stats {
margin-top: var(--env-var-spacing-2);
display: flex;
gap: 24px;
}
+54 -7
View File
@@ -1,22 +1,69 @@
import CurrentStats from "./CurrentStats";
import "./index.css";
import "./monitors.css";
import { useEffect } from "react";
import { useSelector } from "react-redux";
import { useDispatch } from "react-redux";
import { useSelector, useDispatch } from "react-redux";
import { getMonitorsByUserId } from "../../Features/Monitors/monitorsSlice";
import { useNavigate } from "react-router-dom";
import Button from "../../Components/Button";
import ServerStatus from "../../Components/Charts/Servers/ServerStatus";
import SearchTextField from "../../Components/TextFields/Search/SearchTextField";
import HostsTable from "../../Components/HostsTable";
import Pagination from "../../Components/Pagination";
const Monitors = () => {
const navigate = useNavigate();
const monitorState = useSelector((state) => state.monitors);
const authstate = useSelector((state) => state.auth);
const authState = useSelector((state) => state.auth);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getMonitorsByUserId(authstate.authToken));
dispatch(getMonitorsByUserId(authState.authToken));
}, []);
const up = monitorState.monitors.reduce((acc, cur) => {
return cur.status === true ? acc + 1 : acc;
}, 0);
const down = monitorState.monitors.length - up;
return (
<div className="monitors">
<CurrentStats monitors={monitorState.monitors} />
<div className="monitors-bar">
<div className="monitors-bar-title">
Hello, {authState.user.firstname}
</div>
<Button
level="primary"
label="Create new monitor"
onClick={() => {
navigate("/monitors/create");
}}
sx={{ padding: "10px 20px", fontSize: "13px" }}
/>
</div>
<div className="monitors-stats">
<ServerStatus title="Up" value={up} state="up" />
<ServerStatus title="Down" value={down} state="down" />
<ServerStatus title="Paused" value={0} state="pause" />
</div>
<div className="current-monitors">
<div className="current-monitors-bar">
<div className="current-monitors-title-holder">
<div className="current-monitors-title">Current monitors</div>
<div className="current-monitors-counter">
{monitorState.monitors.length}
</div>
</div>
<div className="current-monitors-search-bar">
<SearchTextField />
</div>
</div>
<div className="monitors-v-gaping"></div>
<HostsTable monitors={monitorState.monitors} />
<div className="monitors-v-gaping"></div>
<Pagination />
</div>
</div>
);
};
@@ -1,4 +1,5 @@
.current-monitors {
margin-top: var(--env-var-spacing-2);
border: 1px solid #eaecf0;
padding: 40px;
border-radius: 4px;
+4 -4
View File
@@ -4,12 +4,12 @@ import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
import HelpOutlineIcon from "@mui/icons-material/HelpOutline";
import WebsiteTextField from "../../Components/TextFields/Website/WebsiteTextField";
import DescriptionTextField from "../../Components/TextFields/Description/DescriptionTextField";
import AnnouncementsDualButton from "../../Components/Announcements/AnnouncementsDualButton/AnnouncementsDualButton";
import AnnouncementsDualButtonWithIcon from "../../Components/Announcements/AnnouncementsDualButtonWithIcon/AnnouncementsDualButtonWithIcon";
import AnnouncementsDualButton from "../../Components/Toast/AnnouncementsDualButton/AnnouncementsDualButton";
import AnnouncementsDualButtonWithIcon from "../../Components/Toast/AnnouncementsDualButtonWithIcon/AnnouncementsDualButtonWithIcon";
import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
import ComplexAlert from "../../Components/Icons/ComplexAlert/ComplexAlert";
import AnnouncementsMessageBar from "../../Components/Announcements/AnnouncementsMessageBar/AnnouncementsMessageBar";
import AnnouncementUpdateSubscription from "../../Components/Announcements/AnnouncementUpdateSubscription/AnnouncementUpdateSubscription";
import AnnouncementsMessageBar from "../../Components/Toast/AnnouncementsMessageBar/AnnouncementsMessageBar";
import AnnouncementUpdateSubscription from "../../Components/Toast/AnnouncementUpdateSubscription/AnnouncementUpdateSubscription";
import PlayGroundCharts from "./PlayGround-Charts";
import PlayGroundPopupModals from "./PlayGround-Popup-Modals";
import PlayGroundTooltips from "./PlayGround-Tooltips";
+4
View File
@@ -214,6 +214,10 @@ const editMonitor = async (req, res, next) => {
try {
const editedMonitor = await req.db.editMonitor(req, res);
// Delete the old job(editedMonitor has the same ID as the old monitor)
await req.jobQueue.deleteJob(editedMonitor);
// Add the new job back to the queue
await req.jobQueue.addJob(editedMonitor._id, editedMonitor);
return res.status(200).json({
success: true,
msg: successMessages.MONITOR_EDIT,
+12 -4
View File
@@ -42,7 +42,9 @@ const insertUser = async (req, res) => {
}
const newUser = new UserModel(userData);
await newUser.save();
return await UserModel.findOne({ _id: newUser._id }).select("-password"); // .select() doesn't work with create, need to save then find
return await UserModel.findOne({ _id: newUser._id })
.select("-password")
.select("-profileImage"); // .select() doesn't work with create, need to save then find
} catch (error) {
if (error.code === DUPLICATE_KEY_CODE) {
throw new Error(errorMessages.DB_USER_EXISTS);
@@ -66,7 +68,9 @@ const getUserByEmail = async (req, res) => {
try {
// Need the password to be able to compare, removed .select()
// We can strip the hash before returing the user
const user = await UserModel.findOne({ email: req.body.email });
const user = await UserModel.findOne(
{ email: req.body.email }.select("-profileImage")
);
if (user) {
return user;
} else {
@@ -102,7 +106,9 @@ const updateUser = async (req, res) => {
candidateUserId,
candidateUser,
{ new: true } // Returns updated user instead of pre-update user
).select("-password");
)
.select("-password")
.select("-profileImage");
return updatedUser;
} catch (error) {
throw error;
@@ -190,7 +196,9 @@ const resetPassword = async (req, res) => {
// Fetch the user again without the password
const userWithoutPassword = await UserModel.findOne({
email: recoveryToken.email,
}).select("-password");
})
.select("-password")
.select("-profileImage");
return userWithoutPassword;
} else {
throw new Error(errorMessages.DB_USER_NOT_FOUND);