From 45fa3756cf91cea07fc8093feea85952826ae10b Mon Sep 17 00:00:00 2001 From: Jr7468 Date: Tue, 28 Jan 2025 13:04:52 +0000 Subject: [PATCH 1/6] Add speed dial actions for bug reporting and feature requests --- .../CippComponents/CippSpeedDial.jsx | 222 ++++++++++++++++++ src/pages/_app.js | 15 ++ 2 files changed, 237 insertions(+) create mode 100644 src/components/CippComponents/CippSpeedDial.jsx diff --git a/src/components/CippComponents/CippSpeedDial.jsx b/src/components/CippComponents/CippSpeedDial.jsx new file mode 100644 index 000000000000..805ca4a66fe9 --- /dev/null +++ b/src/components/CippComponents/CippSpeedDial.jsx @@ -0,0 +1,222 @@ +import React, { useState, useEffect } from "react"; +import { + SpeedDial, + SpeedDialAction, + SpeedDialIcon, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Button, + Snackbar, + Alert, + CircularProgress, +} from "@mui/material"; +import { Close as CloseIcon } from "@mui/icons-material"; +import { useForm } from "react-hook-form"; +import { CippFormComponent } from "/src/components/CippComponents/CippFormComponent"; + +const CippSpeedDial = ({ + actions = [], + position = { bottom: 16, right: 16 }, + icon, + openIcon = , +}) => { + const [openDialogs, setOpenDialogs] = useState({}); + const [loading, setLoading] = useState(false); + const [showSnackbar, setShowSnackbar] = useState(false); + const [speedDialOpen, setSpeedDialOpen] = useState(false); + const [isHovering, setIsHovering] = useState(false); + const [snackbarMessage, setSnackbarMessage] = useState(""); + + const formControls = actions.reduce((acc, action) => { + if (action.form) { + acc[action.id] = useForm({ + mode: "onChange", + defaultValues: action.form.defaultValues || {}, + }); + } + return acc; + }, {}); + + const handleSpeedDialClose = () => { + if (!isHovering) { + setTimeout(() => { + setSpeedDialOpen(false); + }, 200); + } + }; + + const handleMouseEnter = () => { + setIsHovering(true); + setSpeedDialOpen(true); + }; + + const handleMouseLeave = () => { + setIsHovering(false); + handleSpeedDialClose(); + }; + + const handleDialogOpen = (actionId) => { + setOpenDialogs((prev) => ({ ...prev, [actionId]: true })); + }; + + const handleDialogClose = (actionId) => { + setOpenDialogs((prev) => ({ ...prev, [actionId]: false })); + }; + + const handleSubmit = async (actionId, data) => { + if (!actions.find((a) => a.id === actionId)?.onSubmit) return; + + setLoading(true); + try { + const action = actions.find((a) => a.id === actionId); + const result = await action.onSubmit(data); + + if (result.success) { + formControls[actionId]?.reset(); + handleDialogClose(actionId); + } + setSnackbarMessage(result.message); + setShowSnackbar(true); + } catch (error) { + console.error(`Error submitting ${actionId}:`, error); + setSnackbarMessage("An error occurred while submitting"); + setShowSnackbar(true); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + const handleClickOutside = (event) => { + if (speedDialOpen) { + const speedDial = document.querySelector('[aria-label="Navigation SpeedDial"]'); + if (speedDial && !speedDial.contains(event.target)) { + setSpeedDialOpen(false); + } + } + }; + + document.addEventListener("click", handleClickOutside); + return () => { + document.removeEventListener("click", handleClickOutside); + }; + }, [speedDialOpen]); + + return ( + <> + } + open={speedDialOpen} + onClose={handleSpeedDialClose} + onOpen={() => setSpeedDialOpen(true)} + onMouseEnter={handleMouseEnter} + onMouseLeave={handleMouseLeave} + > + {actions.map((action) => ( + { + if (action.form) { + handleDialogOpen(action.id); + } else if (action.onClick) { + action.onClick(); + } + setSpeedDialOpen(false); + }} + tooltipOpen + sx={{ + "&.MuiSpeedDialAction-fab": { + backgroundColor: "background.paper", + "&:hover": { + backgroundColor: "action.hover", + }, + }, + "& .MuiSpeedDialAction-staticTooltipLabel": { + cursor: "pointer", + whiteSpace: "nowrap", + marginRight: "10px", + padding: "6px 10px", + "&:hover": { + backgroundColor: "action.hover", + }, + }, + }} + /> + ))} + + + {actions + .filter((action) => action.form) + .map((action) => ( + handleDialogClose(action.id)} + maxWidth="md" + fullWidth + > + {action.form.title} + + + + + + + + + ))} + + setShowSnackbar(false)} + anchorOrigin={{ vertical: "bottom", horizontal: "center" }} + > + setShowSnackbar(false)} severity="success" sx={{ width: "100%" }}> + {snackbarMessage} + + + + ); +}; + +export default CippSpeedDial; diff --git a/src/pages/_app.js b/src/pages/_app.js index 702eb328927c..1dd1e6971768 100644 --- a/src/pages/_app.js +++ b/src/pages/_app.js @@ -36,6 +36,21 @@ const App = (props) => { const getLayout = Component.getLayout ?? ((page) => page); const preferredTheme = useMediaPredicate("(prefers-color-scheme: dark)") ? "dark" : "light"; + const speedDialActions = [ + { + id: "bug-report", + icon: , + name: "Report Bug", + href: "https://github.com/KelvinTegelaar/CIPP/issues/new?template=bug.yml", + }, + { + id: "feature-request", + icon: , + name: "Request Feature", + href: "https://github.com/KelvinTegelaar/CIPP/issues/new?template=feature.yml", + }, + ]; + return ( From 32cbe0277a43203638631961e22c77d4772f906b Mon Sep 17 00:00:00 2001 From: Jr7468 Date: Fri, 31 Jan 2025 08:48:00 +0000 Subject: [PATCH 2/6] Add Speed Dial component with help, bug report, and feedback actions --- src/pages/_app.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/pages/_app.js b/src/pages/_app.js index 1dd1e6971768..b4ac447e1829 100644 --- a/src/pages/_app.js +++ b/src/pages/_app.js @@ -20,6 +20,12 @@ import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns"; import TimeAgo from "javascript-time-ago"; import en from "javascript-time-ago/locale/en.json"; +import CippSpeedDial from 'src/components/CippComponents/CippSpeedDial' +import { + Help as HelpIcon, + BugReport as BugReportIcon, + Feedback as FeedbackIcon, +} from '@mui/icons-material' import React from "react"; TimeAgo.addDefaultLocale(en); @@ -84,6 +90,11 @@ const App = (props) => { {getLayout()} + } + position={{ bottom: 16, right: 16 }} + /> {settings?.showDevtools && ( From 205fa4ca188ecb9060b3420a0f9147062ecc97ee Mon Sep 17 00:00:00 2001 From: Jr7468 Date: Fri, 31 Jan 2025 08:50:04 +0000 Subject: [PATCH 3/6] Prettier fix --- src/pages/_app.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pages/_app.js b/src/pages/_app.js index b4ac447e1829..c4884343f139 100644 --- a/src/pages/_app.js +++ b/src/pages/_app.js @@ -20,12 +20,12 @@ import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns"; import TimeAgo from "javascript-time-ago"; import en from "javascript-time-ago/locale/en.json"; -import CippSpeedDial from 'src/components/CippComponents/CippSpeedDial' +import CippSpeedDial from "src/components/CippComponents/CippSpeedDial"; import { Help as HelpIcon, BugReport as BugReportIcon, Feedback as FeedbackIcon, -} from '@mui/icons-material' +} from "@mui/icons-material"; import React from "react"; TimeAgo.addDefaultLocale(en); @@ -90,11 +90,11 @@ const App = (props) => { {getLayout()} - } - position={{ bottom: 16, right: 16 }} - /> + } + position={{ bottom: 16, right: 16 }} + /> {settings?.showDevtools && ( From 65da8b660e90cc07a0e9dd46890ca5fb917d6ab0 Mon Sep 17 00:00:00 2001 From: Jr7468 Date: Fri, 31 Jan 2025 09:24:13 +0000 Subject: [PATCH 4/6] Tested and works properly on my Dev Env now! --- src/components/CippComponents/CippSpeedDial.jsx | 2 +- src/pages/_app.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/CippComponents/CippSpeedDial.jsx b/src/components/CippComponents/CippSpeedDial.jsx index 805ca4a66fe9..4313ace7a7ef 100644 --- a/src/components/CippComponents/CippSpeedDial.jsx +++ b/src/components/CippComponents/CippSpeedDial.jsx @@ -14,7 +14,7 @@ import { } from "@mui/material"; import { Close as CloseIcon } from "@mui/icons-material"; import { useForm } from "react-hook-form"; -import { CippFormComponent } from "/src/components/CippComponents/CippFormComponent"; +import { CippFormComponent } from "../../components/CippComponents/CippFormComponent"; const CippSpeedDial = ({ actions = [], diff --git a/src/pages/_app.js b/src/pages/_app.js index c4884343f139..b764d3f36c12 100644 --- a/src/pages/_app.js +++ b/src/pages/_app.js @@ -20,7 +20,7 @@ import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns"; import TimeAgo from "javascript-time-ago"; import en from "javascript-time-ago/locale/en.json"; -import CippSpeedDial from "src/components/CippComponents/CippSpeedDial"; +import CippSpeedDial from "../components/CippComponents/CippSpeedDial"; import { Help as HelpIcon, BugReport as BugReportIcon, From 6c432d3d77631c3cc94d15cd560c2456dd9ff70b Mon Sep 17 00:00:00 2001 From: Jr7468 Date: Fri, 31 Jan 2025 09:26:28 +0000 Subject: [PATCH 5/6] Add onClick handlers to Speed Dial GitHub links --- src/pages/_app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/_app.js b/src/pages/_app.js index b764d3f36c12..271c911a2c5b 100644 --- a/src/pages/_app.js +++ b/src/pages/_app.js @@ -48,12 +48,14 @@ const App = (props) => { icon: , name: "Report Bug", href: "https://github.com/KelvinTegelaar/CIPP/issues/new?template=bug.yml", + onClick: () => window.open("https://github.com/KelvinTegelaar/CIPP/issues/new?template=bug.yml", "_blank") }, { id: "feature-request", icon: , name: "Request Feature", href: "https://github.com/KelvinTegelaar/CIPP/issues/new?template=feature.yml", + onClick: () => window.open("https://github.com/KelvinTegelaar/CIPP/issues/new?template=feature.yml", "_blank") }, ]; From d6eaf09fef428c52f1565655b4b5548959c19e6e Mon Sep 17 00:00:00 2001 From: Jr7468 Date: Fri, 31 Jan 2025 14:19:04 +0000 Subject: [PATCH 6/6] Add Discord link to Speed Dial component --- public/discord-mark-blue.svg | 1 + src/pages/_app.js | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 public/discord-mark-blue.svg diff --git a/public/discord-mark-blue.svg b/public/discord-mark-blue.svg new file mode 100644 index 000000000000..4cadbc7f7ed3 --- /dev/null +++ b/public/discord-mark-blue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/pages/_app.js b/src/pages/_app.js index 271c911a2c5b..e520d50c5822 100644 --- a/src/pages/_app.js +++ b/src/pages/_app.js @@ -26,6 +26,8 @@ import { BugReport as BugReportIcon, Feedback as FeedbackIcon, } from "@mui/icons-material"; +import { SvgIcon } from "@mui/material"; +import discordIcon from "../../public/discord-mark-blue.svg"; import React from "react"; TimeAgo.addDefaultLocale(en); @@ -57,6 +59,16 @@ const App = (props) => { href: "https://github.com/KelvinTegelaar/CIPP/issues/new?template=feature.yml", onClick: () => window.open("https://github.com/KelvinTegelaar/CIPP/issues/new?template=feature.yml", "_blank") }, + { + id: "discord", + icon: ( + + + ), + name: "Join the Discord!", + href: "https://discord.gg/cyberdrain", + onClick: () => window.open("https://discord.gg/cyberdrain", "_blank") + }, ]; return (