diff --git a/.gitignore b/.gitignore index 6c9074e..b0ddd05 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ docs/.vitepress/dist docs/.vitepress/cache public/kanban.json +/logs # misc .DS_Store diff --git a/README.md b/README.md index 86b294c..6e80956 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,8 @@ Documentation · Try live demo · API Docs · - Roadmap + + Support ## ⭐ Features @@ -19,6 +20,7 @@ - Clean and easy to use UX/UI - Customizable themes/colors - Customizable user profiles +- Support for notifications ## 🚀 Getting Started diff --git a/app/components/home/menu/styles.scss b/app/components/home/menu/styles.scss index 94a1e94..cc932e4 100644 --- a/app/components/home/menu/styles.scss +++ b/app/components/home/menu/styles.scss @@ -1,4 +1,5 @@ -@import '../../../styles/global.scss'; +@use '../../../styles/breakpoints.scss' as *; +@use '../../../styles/pxToRem.scss' as *; .home-menu { display: flex; diff --git a/app/components/home/monitor/layout/card.scss b/app/components/home/monitor/layout/card.scss index d180b55..0c1bfcd 100644 --- a/app/components/home/monitor/layout/card.scss +++ b/app/components/home/monitor/layout/card.scss @@ -1,4 +1,4 @@ -@import '../../../../styles/global.scss'; +@use '../../../../styles/pxToRem.scss' as *; .home-monitor-container { width: pxToRem(250); diff --git a/app/components/home/monitor/layout/compact.scss b/app/components/home/monitor/layout/compact.scss index f90b871..d1e7de9 100644 --- a/app/components/home/monitor/layout/compact.scss +++ b/app/components/home/monitor/layout/compact.scss @@ -1,4 +1,4 @@ -@import '../../../../styles/global.scss'; +@use '../../../../styles/pxToRem.scss' as *; .home-monitor-container-compact { width: 100%; diff --git a/app/components/home/monitor/layout/list.scss b/app/components/home/monitor/layout/list.scss index 3d23d0d..4998b74 100644 --- a/app/components/home/monitor/layout/list.scss +++ b/app/components/home/monitor/layout/list.scss @@ -1,4 +1,5 @@ -@import '../../../../styles/global.scss'; +@use '../../../../styles/breakpoints.scss' as *; +@use '../../../../styles/pxToRem.scss' as *; .home-monitor-container-list { width: 100%; diff --git a/app/components/home/monitor/layout/table.scss b/app/components/home/monitor/layout/table.scss index 7f26607..49f2659 100644 --- a/app/components/home/monitor/layout/table.scss +++ b/app/components/home/monitor/layout/table.scss @@ -1,4 +1,5 @@ -@import '../../../../styles/global.scss'; +@use '../../../../styles/breakpoints.scss' as *; +@use '../../../../styles/pxToRem.scss' as *; .home-monitor-table-container-list { width: 100%; diff --git a/app/components/icons/index.jsx b/app/components/icons/index.jsx index 0dd568e..93f27d9 100644 --- a/app/components/icons/index.jsx +++ b/app/components/icons/index.jsx @@ -15,7 +15,7 @@ import { FiLayout } from 'react-icons/fi'; import { HiStatusOffline, HiStatusOnline } from 'react-icons/hi'; import { IoMdEyeOff, IoMdEye, IoMdClose, IoMdHelpCircle } from 'react-icons/io'; import { LiaSyncSolid } from 'react-icons/lia'; -import { MdEdit, MdErrorOutline } from 'react-icons/md'; +import { MdEdit, MdErrorOutline, MdNotifications } from 'react-icons/md'; import { FaCircleCheck, FaEllipsisVertical, @@ -24,6 +24,7 @@ import { FaTrashCan, } from 'react-icons/fa6'; import { IoArrowBack, IoColorPalette, IoGrid, IoReload } from 'react-icons/io5'; +import { RiStackFill } from 'react-icons/ri'; import StatusLogo from './statusLogo'; export { @@ -57,5 +58,7 @@ export { LiaSyncSolid, MdEdit, MdErrorOutline, + MdNotifications, + RiStackFill, StatusLogo, }; diff --git a/app/components/icons/statusLogo.jsx b/app/components/icons/statusLogo.jsx index 0d846b9..4a42a98 100644 --- a/app/components/icons/statusLogo.jsx +++ b/app/components/icons/statusLogo.jsx @@ -7,13 +7,11 @@ import useContextStore from '../../context'; const StatusLogo = ({ size = 250 }) => { const { - globalStore: { getAllMonitors }, + globalStore: { allMonitors }, } = useContextStore(); - const monitors = getAllMonitors(); - - const totalMonitors = monitors.length; - const offlineMonitors = monitors.filter( + const totalMonitors = allMonitors.length; + const offlineMonitors = allMonitors.filter( (monitor = {}) => monitor.heartbeats[0]?.isDown ).length; diff --git a/app/components/modal/monitor/configure.jsx b/app/components/modal/monitor/configure.jsx index 036bda2..62daff9 100644 --- a/app/components/modal/monitor/configure.jsx +++ b/app/components/modal/monitor/configure.jsx @@ -9,7 +9,10 @@ import MonitorPageInitial from './pages/initial'; import MonitorPageHttp from './pages/http'; import MonitorPageTcp from './pages/tcp'; import MonitorPageInterval from './pages/interval'; +import MonitorPageNotification from './pages/notification'; import useMonitorForm from '../../../hooks/useMonitorForm'; +import { Accordion, AccordionItem } from '../../ui/accordion'; +import MonitorHttpStatusCodes from './pages/http/statusCodes'; const MonitorConfigureModal = ({ closeModal, @@ -17,8 +20,12 @@ const MonitorConfigureModal = ({ handleMonitorSubmit, isEdit = false, }) => { - const { form, errors, inputs, handleActionButtons, handleInput } = - useMonitorForm(monitor, isEdit, closeModal, handleMonitorSubmit); + const { errors, inputs, handleActionButtons, handleInput } = useMonitorForm( + monitor, + isEdit, + closeModal, + handleMonitorSubmit + ); return ( @@ -26,50 +33,85 @@ const MonitorConfigureModal = ({ {isEdit ? 'Edit Monitor' : 'Add Monitor'} - {form.name === 'initial' && ( +
- )} - {form.name === 'http' && ( - - )} + {inputs.type === 'http' && ( + + )} - {form.name === 'tcp' && ( - - )} + {inputs.type === 'tcp' && ( + + )} +
+ + + - {form.name === 'interval' && ( - - )} + { + const { valid_status_codes = [] } = inputs; + const validStatusCodes = valid_status_codes.includes(code) + ? valid_status_codes.filter((id) => id !== code) + : valid_status_codes.concat(code); + handleInput('valid_status_codes', validStatusCodes); + }} + /> + + {errors.valid_status_codes && ( + + )} + + + +
+
+
+
- {form.actions.map((action) => ( - - {action} - - ))} + + Cancel + + + {isEdit ? 'Update' : 'Create'} +
); diff --git a/app/components/modal/monitor/pages/http/index.jsx b/app/components/modal/monitor/pages/http/index.jsx index 548ec48..f73ee9c 100644 --- a/app/components/modal/monitor/pages/http/index.jsx +++ b/app/components/modal/monitor/pages/http/index.jsx @@ -4,7 +4,6 @@ import PropTypes from 'prop-types'; // import local files import TextInput from '../../../../ui/input'; import MonitorHttpMethods from './methods'; -import MonitorHttpStatusCodes from './statusCodes'; const MonitorAddHttp = ({ inputs, errors, handleInput }) => { const handleMethodSelect = (method) => { @@ -12,7 +11,7 @@ const MonitorAddHttp = ({ inputs, errors, handleInput }) => { }; return ( -
+ <> { handleSelect={handleMethodSelect} /> {errors.method && ( - + )} - - { - const { valid_status_codes = [] } = inputs; - const validStatusCodes = valid_status_codes.includes(code) - ? valid_status_codes.filter((id) => id !== code) - : valid_status_codes.concat(code); - handleInput('valid_status_codes', validStatusCodes); - }} - /> - - {errors.valid_status_codes && ( - - )} -
+ ); }; diff --git a/app/components/modal/monitor/pages/http/methods.jsx b/app/components/modal/monitor/pages/http/methods.jsx index 67ad9af..7668970 100644 --- a/app/components/modal/monitor/pages/http/methods.jsx +++ b/app/components/modal/monitor/pages/http/methods.jsx @@ -13,7 +13,7 @@ const MonitorHttpMethods = ({ handleSelect, selectValue = defaultValue }) => { return ( <> - + - + { return ( -
+ <> { readOnly /> )} -
+ ); }; diff --git a/app/components/modal/monitor/pages/initial/type.jsx b/app/components/modal/monitor/pages/initial/type.jsx index ff4b1bc..46b6669 100644 --- a/app/components/modal/monitor/pages/initial/type.jsx +++ b/app/components/modal/monitor/pages/initial/type.jsx @@ -9,7 +9,7 @@ const MonitorInitialDropdown = ({ inputs, errors, handleInput }) => { const { dropdownIsOpen, toggleDropdown } = useDropdown(); return ( <> - + { {errors.type && ( -