Compare commits

..
399 Commits
Author SHA1 Message Date
Alex Holliday c5ba1b1dbe Merge remote-tracking branch 'upstream/master' 2025-01-23 07:12:35 -08:00
Alex Holliday 6f53c31e99 Merge branch 'master' of github.com:popnfresh234/bluewave-uptime 2025-01-23 07:06:14 -08:00
Alexander Holliday 986166e7a5 Merge pull request #1613 from renovate-bot/renovate/nodemailer-6.x-lockfile
fix(deps): update dependency nodemailer to v6.10.0
2025-01-23 07:02:55 -08:00
Alexander Holliday 0e14d8a52e Merge pull request #1614 from renovate-bot/renovate/bullmq-5.x
fix(deps): update dependency bullmq to v5.35.1
2025-01-23 07:02:32 -08:00
Mend Renovate 01592cf0f0 fix(deps): update dependency bullmq to v5.35.1 2025-01-23 13:37:56 +00:00
Mend Renovate ffffda7282 fix(deps): update dependency nodemailer to v6.10.0 2025-01-23 09:14:59 +00:00
Alexander Holliday d3ad898f73 Merge pull request #1611 from bluewave-labs/fix/maintenance-colors
Fix/maintenance colors
2025-01-22 12:45:10 -08:00
Alexander Holliday 027b331220 Merge pull request #1607 from bluewave-labs/fix/be/incidents
fix: be/incidents, resolves #1567
2025-01-22 12:44:14 -08:00
Alex Holliday 7b5d49c0e2 Fix maintenace table and colors 2025-01-22 12:40:29 -08:00
Alex Holliday bc8d43e222 Merge branch 'fix/be/incidents' into fix/maintenance-colors 2025-01-22 12:18:39 -08:00
Alex Holliday 1b31f9ac4c Remove console logs, update UI 2025-01-22 11:36:27 -08:00
Alex Holliday 15cd3b23c3 Add daterange prop 2025-01-22 11:13:44 -08:00
Alex Holliday 4268966b44 Add hour filter to incidents page 2025-01-22 11:10:09 -08:00
Alex Holliday f46f8cb12b Add hour filter to incidents page 2025-01-22 11:07:43 -08:00
Alex Holliday fc36da4f7b Add hour filters to check queries 2025-01-22 11:07:32 -08:00
Alex Holliday 2a74f2e8da remove seed from index 2025-01-22 11:06:39 -08:00
Alex Holliday 9ffe17e9eb add db utils 2025-01-22 08:29:38 -08:00
Alexander Holliday e4f2cfb978 Merge pull request #1609 from renovate-bot/renovate/mocha-11.x
chore(deps): update dependency mocha to v11.1.0
2025-01-22 07:20:53 -08:00
Alex Holliday 9a8ce41c95 add db utils for seeding db 2025-01-22 07:06:53 -08:00
Mend Renovate 90e697a1bd chore(deps): update dependency mocha to v11.1.0 2025-01-22 14:57:22 +00:00
Alexander Holliday 488e50ace5 Merge pull request #1608 from renovate-bot/renovate/bullmq-5.x
fix(deps): update dependency bullmq to v5.35.0
2025-01-22 06:56:36 -08:00
Mend Renovate 00e1286f24 fix(deps): update dependency bullmq to v5.35.0 2025-01-22 13:04:14 +00:00
Gorkem Cetin (BWL) fcd28afc97 Add github trending #1 badge 2025-01-22 01:38:07 -05:00
Alex Holliday 0d53a1e5fb Merge branch 'develop' into fix/be/incidents 2025-01-21 22:22:10 -08:00
Gorkem Cetin (BWL) c7b65e537a Update roadmap 2025-01-22 00:02:17 -05:00
Gorkem Cetin (BWL) 2c8e1c8444 Merge pull request #1606 from bluewave-labs/gorkem-bwl-patch-1
Update index.jsx
2025-01-21 20:21:09 -05:00
Gorkem Cetin (BWL) 9e9f5d435d Update index.jsx 2025-01-21 20:20:34 -05:00
Alex Holliday f5480cbfba Add default key to table rows 2025-01-21 15:39:49 -08:00
Alex Holliday 9535ffa192 Refactor Pagination component to accept a label to improve reusability. Use Pagination component with Incident table 2025-01-21 15:31:40 -08:00
Alex Holliday 4ed995692d Refactor incident endpoints to use aggregation 2025-01-21 15:30:51 -08:00
Alexander Holliday c4d223aee5 Merge pull request #1556 from bluewave-labs/fix/colors-general
Fix/colors general
2025-01-21 13:26:13 -08:00
Alex Holliday f8b3847577 Remove console log 2025-01-21 13:22:29 -08:00
Alex Holliday d92a477892 Add darker color to accent 2025-01-21 11:38:32 -08:00
Alex Holliday 6eedaa5ca0 various infra details page color fixes 2025-01-21 10:58:08 -08:00
Alex Holliday 239164e779 Fixed invisible text on login page 2025-01-21 10:57:53 -08:00
Alex Holliday 2070e24829 Fix gauge colors 2025-01-21 10:57:34 -08:00
Alex Holliday 8021786d0c fix gauge colors 2025-01-21 10:24:09 -08:00
Alex Holliday f68e885c88 status box fix 2025-01-21 10:20:43 -08:00
Alexander Holliday 0cfc041088 Merge pull request #1596 from renovate-bot/renovate/vite-5.x-lockfile
chore(deps): update dependency vite to v5.4.14
2025-01-21 07:04:22 -08:00
Alexander Holliday a53e0f7f20 Merge pull request #1601 from renovate-bot/renovate/material-ui-monorepo
fix(deps): update material-ui monorepo
2025-01-21 07:04:04 -08:00
Gorkem Cetin (BWL) 5fb748156f Delete guides directory as all documentation is kept in a separate repo now 2025-01-21 09:38:19 -05:00
Mend Renovate 9ebe9fe613 fix(deps): update material-ui monorepo 2025-01-21 13:40:22 +00:00
Mend Renovate 2b957e5cac chore(deps): update dependency vite to v5.4.14 2025-01-21 13:40:15 +00:00
Alex Holliday 8048dae81c color fixes 2025-01-20 15:26:15 -08:00
Alexander Holliday d91fe03acc Merge pull request #1591 from bluewave-labs/feat/be/consistent-response-middleare
feat: be/consistent response middleare
2025-01-20 11:48:40 -08:00
Alexander Holliday 8d148cd4bf Merge pull request #1587 from DMJain/develop
#1584 Removed Checkboxes for Notification : SMS & Multi Email
2025-01-20 11:03:57 -08:00
Alex Holliday 792b51b488 fix typos 2025-01-20 11:02:55 -08:00
Alexander Holliday 261d32e51e Merge pull request #1592 from renovate-bot/renovate/vite-5.x-lockfile
chore(deps): update dependency vite to v5.4.12
2025-01-20 06:56:13 -08:00
Alexander Holliday abb4a53816 Merge pull request #1594 from mertssmnoglu/fix/client-old-name
Implement new Checkmate logo to frontend
2025-01-20 06:55:03 -08:00
Mert Şişmanoğlu f73be34877 chore: Replace BlueWave Uptime logo with Checkmate logo across the pages
Signed-off-by: Mert Şişmanoğlu <mert190737fb@gmail.com>
2025-01-20 15:06:17 +03:00
Mert Şişmanoğlu 2cee0b4690 chore(client): Update checkmate favicon
Signed-off-by: Mert Şişmanoğlu <mert190737fb@gmail.com>
2025-01-20 15:05:21 +03:00
Darshan Jain 4ed6942d8b Merge branch 'issue#1584' into develop 2025-01-20 16:37:16 +05:30
Darshan Jain ed9a89b526 #1584 comments 2025-01-20 16:36:50 +05:30
Darshan Jain e99010e81d Merge branch 'develop' of https://github.com/DMJain/Checkmate into develop 2025-01-20 16:33:56 +05:30
Mend Renovate 36d20f90f6 Update dependency vite to v5.4.12 2025-01-20 09:45:16 +00:00
Darshan Jain d8b1d63faa commenting out checkboxs and input box instead of deleting for future implementations 2025-01-20 13:26:29 +05:30
Alex Holliday 9f43336a03 Use response handler in handleErrors middleare 2025-01-19 20:14:03 -08:00
Mert Şişmanoğlu 84dd4a49c9 fix: Update BlueWave Uptime references to Checkmate on the Client side and /index.html
Signed-off-by: Mert Şişmanoğlu <mert190737fb@gmail.com>
2025-01-20 02:48:26 +03:00
Alex Holliday e9eadfe838 use response middleware in StatusPageController 2025-01-19 12:05:45 -08:00
Alex Holliday 627c80581d use response middleware in SettingsController 2025-01-19 12:05:15 -08:00
Alex Holliday 3608eadb8c use response middleware in QueueController 2025-01-19 12:04:47 -08:00
Alex Holliday 378a190cd3 use response middleware in MonitorController 2025-01-19 12:01:27 -08:00
Darshan Jain f04cc6caf5 Merge branch 'bluewave-labs:develop' into develop 2025-01-19 23:40:59 +05:30
Darshan Jain 6ed8f93688 #1584 removed conditional input box for multi email 2025-01-19 23:35:01 +05:30
Alex Holliday f0bf680f19 use response middleware in MaintenanceWindowController 2025-01-19 10:01:48 -08:00
Darshan Jain 4d2c59b30c #1584 removed checkbox for incident notification: SMS, Multi Email 2025-01-19 23:30:08 +05:30
Alex Holliday e5f8d88c5a use response middleware in InviteController 2025-01-19 09:59:13 -08:00
Alex Holliday 0aaeeef113 remove unnecessary try/catch 2025-01-19 09:56:28 -08:00
Alex Holliday da89789a97 use response middleware in CheckController 2025-01-19 09:55:48 -08:00
Alex Holliday 252c16ac1b add a response middleware to enforce consistent API response 2025-01-19 09:53:03 -08:00
Alexander Holliday 5f9404178c Merge pull request #1574 from renovate-bot/renovate/dockerode-4.x
Update dependency dockerode to v4.0.4
2025-01-19 09:19:48 -08:00
Alexander Holliday 9b6e40fa34 Merge pull request #1575 from renovate-bot/renovate/material-ui-monorepo
Update material-ui monorepo to v7.24.0
2025-01-19 09:19:30 -08:00
Gorkem Cetin (BWL) 7abc2280af Update README.md 2025-01-19 01:29:03 -05:00
Gorkem Cetin (BWL) 8a356cf38d Map roadmap items to issues 2025-01-18 21:53:53 -05:00
Gorkem Cetin (BWL) cb1751f362 Update README.md 2025-01-18 14:07:35 -05:00
Gorkem Cetin (BWL) 0c7891f136 Update README.md 2025-01-18 13:21:19 -05:00
Mend Renovate 0bf1cbdfa9 Update material-ui monorepo to v7.24.0 2025-01-17 19:35:15 +00:00
Mend Renovate 866f89ef09 Update dependency dockerode to v4.0.4 2025-01-17 19:35:05 +00:00
Alexander Holliday ead3704173 Merge pull request #1563 from renovate-bot/renovate/bullmq-5.x
Update dependency bullmq to v5.34.10
2025-01-16 10:02:46 -08:00
Alexander Holliday b67f0bbfcd Merge pull request #1565 from renovate-bot/renovate/material-ui-monorepo
Update material-ui monorepo
2025-01-16 10:02:31 -08:00
Alexander Holliday 8d49ed50d8 Merge pull request #1572 from renovate-bot/renovate/npm-mongoose-vulnerability
Update dependency mongoose to v8.9.5 [SECURITY]
2025-01-16 10:02:16 -08:00
Mend Renovate 389ed2768a Update dependency mongoose to v8.9.5 [SECURITY] 2025-01-16 18:01:57 +00:00
Alexander Holliday d67acfe0ba Merge pull request #1571 from renovate-bot/renovate/react-router-monorepo
Update react-router monorepo to v6.28.2
2025-01-16 10:00:59 -08:00
Alexander Holliday d9a1f41b9d Merge pull request #1569 from not-Ryan/patch-1
Fix server is down mjml to show monitor name
2025-01-16 10:00:39 -08:00
Mend Renovate c073e086cb Update react-router monorepo to v6.28.2 2025-01-16 17:43:52 +00:00
Caio Cabral bc9d8f0b3c feat: fix INfrastructure counter 2025-01-15 19:34:49 -05:00
Caio Cabral ec94458de4 fix: Name on team table 2025-01-15 19:19:18 -05:00
Caio Cabral 8404cee349 refactor: change all selects instead of relying on sx 2025-01-15 19:16:33 -05:00
Caio Cabral 6864756552 feat: fix select 2025-01-15 19:13:34 -05:00
Caio Cabral 7d76aee647 feat: tabs 2025-01-15 18:58:44 -05:00
Caio Cabral 8661e8305d removing fixed height from css 2025-01-15 18:35:00 -05:00
Caio Cabral 851ad48b3e feat: Profile Panel buttons 2025-01-15 17:51:13 -05:00
Caio Cabral 53fcd5acc7 fix: pagespeed details 2025-01-15 08:07:48 -05:00
Caio Cabral 59f60d2184 fix inputs 2025-01-15 07:55:22 -05:00
notRyan 0345f06614 Fix server is down mjml to show monitor name
Was static google.com is now the monitor name in the header
2025-01-15 09:33:43 +01:00
Alexander Holliday aa852bd162 Merge pull request #1568 from bluewave-labs/hotfix/fe/maintenance-window-montior-list
hotfix: replace limit = -1 with limit = null
2025-01-14 22:24:31 -08:00
Alex Holliday 7e1b8df8fc replace limit = -1 with limit = null 2025-01-14 22:23:40 -08:00
Gorkem Cetin (BWL) f0aea3a534 Better screenshots 2025-01-14 23:11:44 -05:00
Caio Cabral b4ba9efd45 fix: table header color 2025-01-14 22:58:46 -05:00
Caio Cabral d09382bc71 fix: toast 2025-01-14 20:25:20 -05:00
Caio Cabral 8fe200fb8b feat: finished 2025-01-14 19:19:36 -05:00
Gorkem Cetin (BWL) 9538b5670f Update README.md 2025-01-14 18:57:15 -05:00
Caio Cabral 6cdac32bce feat: some colors fixed, table alignment 2025-01-14 18:54:00 -05:00
Mend Renovate bf74e8b64e Update material-ui monorepo 2025-01-14 21:11:41 +00:00
Mend Renovate c665a3777c Update dependency bullmq to v5.34.10 2025-01-14 17:55:00 +00:00
Alexander Holliday b599dcd68f Merge pull request #1560 from renovate-bot/renovate/eslint-plugin-react-7.x-lockfile
Update dependency eslint-plugin-react to v7.37.4
2025-01-14 09:54:36 -08:00
Alexander Holliday cfcaa0cbc5 Merge pull request #1555 from bluewave-labs/fix/fe/network-alerts
fix: fe axios error handler
2025-01-14 09:54:17 -08:00
Alexander Holliday 80ab5f0fd6 Merge pull request #1559 from bluewave-labs/fix/fe/has-monitors
fix: hasMonitors logic
2025-01-14 09:53:59 -08:00
Caio Cabral d54272ba30 cleaning unused code 2025-01-14 08:36:48 -05:00
Caio Cabral 5e9629ee29 fix: primary buttons 2025-01-14 08:09:03 -05:00
Caio Cabral 921fb6e458 spotted errors nd marked to be solved after merge 2025-01-14 07:59:08 -05:00
Gorkem Cetin (BWL) c46ef40cb7 Update README.md 2025-01-13 16:22:47 -05:00
Mend Renovate 701bcf3b68 Update dependency eslint-plugin-react to v7.37.4 2025-01-13 08:21:44 +00:00
Alex Holliday a7c99fcd58 fix hasMonitors logic 2025-01-12 17:18:50 -08:00
Caio Cabral 2ab6a578c3 merging 2025-01-12 13:33:11 -05:00
Caio Cabral a6eb97050b feat: finishing adjusting colors 2025-01-12 13:03:09 -05:00
Alex Holliday ef4b11c72b fix error handler 2025-01-12 09:51:25 -08:00
Caio Cabral e235279af0 feat: fix incident table 2025-01-12 12:35:14 -05:00
Caio Cabral 541a5b3f12 feat: fixing lots of colors 2025-01-12 12:28:13 -05:00
Alexander Holliday 0e443e4088 Merge pull request #1551 from renovate-bot/renovate/eslint-monorepo
Update eslint monorepo to v9.18.0
2025-01-12 09:17:42 -08:00
Alexander Holliday 2b61ff4fca Merge pull request #1553 from renovate-bot/renovate/eslint-plugin-react-refresh-0.x-lockfile
Update dependency eslint-plugin-react-refresh to v0.4.18
2025-01-12 09:17:27 -08:00
Alexander Holliday c171a718f4 Merge pull request #1554 from renovate-bot/renovate/bullmq-5.x
Update dependency bullmq to v5.34.9
2025-01-12 09:17:15 -08:00
Mend Renovate 2f2977cfac Update dependency bullmq to v5.34.9 2025-01-12 16:54:16 +00:00
Caio Cabral 61aaa8489a feat: simplify and adjust status label 2025-01-12 09:39:31 -05:00
Caio Cabral 5eca39cd04 feat: set accent color buttons hover colors 2025-01-12 08:33:33 -05:00
Caio Cabral 9fb6db6921 feat: excluding selected path from hover changes 2025-01-12 08:24:09 -05:00
Caio Cabral 46af783ce6 feat: colors for sidebar 2025-01-12 08:19:29 -05:00
Caio Cabral 5fcc87dab4 feat: all colors inside of sideBar 2025-01-11 18:06:47 -05:00
Caio Cabral 74c598e191 feat: changed a whole bunch of colors 2025-01-11 17:21:10 -05:00
Mend Renovate 3b9c747b76 Update dependency eslint-plugin-react-refresh to v0.4.18 2025-01-11 22:16:36 +00:00
Caio Cabral 3b1657c415 feat: changing background main for primary main 2025-01-11 16:53:00 -05:00
Caio Cabral c0df164e46 feat: changing background accent for tertiary main 2025-01-11 16:50:48 -05:00
Caio Cabral 6bb38c9339 feat: extract function 2025-01-11 16:40:07 -05:00
Caio Cabral b0aa5e64f4 feat: changing green for dark mode 2025-01-11 11:53:35 -05:00
Caio Cabral 059927cc20 feat: changing green for light mode 2025-01-11 11:49:02 -05:00
Caio Cabral 78340ce63b fix: logo 2025-01-11 10:06:31 -05:00
Caio Cabral 8cf28fe947 fix: label background color 2025-01-11 10:03:11 -05:00
Caio Cabral d027407562 fix percentage uptimePoor 2025-01-11 09:54:11 -05:00
Caio Cabral dbd351b2f1 fix many 2025-01-11 09:53:27 -05:00
Gorkem Cetin (BWL) 6542852634 Update README.md 2025-01-11 03:34:25 -05:00
Gorkem Cetin (BWL) 4fab3f8713 Delete grant_funding.md as we are referencing to https://checkmate.so 2025-01-11 02:32:49 -05:00
Gorkem Cetin (BWL) 4a655b0328 Newreleases.io + fix star numbers 2025-01-10 23:48:24 -05:00
Alexander Holliday e4f7d9eb7a Merge pull request #1552 from bluewave-labs/hotfix/be/default-sort-order
hotfix: add a default sort order if a field to sort by is not specified
2025-01-10 20:07:37 -08:00
Alex Holliday c61f08b31c Add a default sort order if a field to sort by is not specified 2025-01-10 20:06:01 -08:00
Mend Renovate 64deae1257 Update eslint monorepo to v9.18.0 2025-01-11 01:09:50 +00:00
Alexander Holliday 9c484a59d6 Merge pull request #1550 from bluewave-labs/fix/be/fe/search
fix: be/fe/search, resolves #1549
2025-01-10 13:45:55 -08:00
Alex Holliday cd14659a59 Use all monitors for search component instead of filtered monitors 2025-01-10 13:23:32 -08:00
Alex Holliday 367d3602c8 add array of all monitors to response for search 2025-01-10 13:23:19 -08:00
Alexander Holliday af8f3a0351 Merge pull request #1548 from bluewave-labs/fix/be/uptime-duration
fix: be/uptime duration
2025-01-10 12:14:33 -08:00
Alexander Holliday b8a6258402 Merge pull request #1542 from bluewave-labs/fix/be/jobqueue-scheduler
fix: use jobScheduler instead of deprecatred repeatable
2025-01-10 12:14:12 -08:00
Alex Holliday 12cc20a852 refactor uptime details query 2025-01-10 12:12:33 -08:00
Alex Holliday d495ca67e1 Merge branch 'fix/be/jobqueue-scheduler' into fix/be/uptime-duration 2025-01-10 09:48:53 -08:00
Alex Holliday 70898da69d Merge branch 'develop' into fix/be/uptime-duration 2025-01-10 09:48:10 -08:00
Alex Holliday 59c6f39ea9 Remove incomplete line 2025-01-10 09:46:22 -08:00
Alexander Holliday 50a7741dcc Merge pull request #1544 from renovate-bot/renovate/mongoose-8.x-lockfile
Update dependency mongoose to v8.9.4
2025-01-10 09:44:03 -08:00
Alexander Holliday a2102ca77a Merge pull request #1524 from jasneetsingh6114/feat/issue-1482
Inform Admin incase of server issue.
2025-01-10 09:43:46 -08:00
Alex Holliday cd3767a040 new duration algorithm 2025-01-09 20:50:08 -08:00
Mend Renovate 5bb1e64f25 Update dependency mongoose to v8.9.4 2025-01-09 23:07:07 +00:00
Jasneet Singh 74f23c1792 Address pr comments 2025-01-09 17:38:08 -05:00
Alex Holliday c1d6433e6c use jobScheduler instead of deprecatred repeatable 2025-01-09 12:01:51 -08:00
Alexander Holliday 2dfe5dec7c Merge pull request #1540 from renovate-bot/renovate/material-ui-monorepo
Update material-ui monorepo to v7.23.6
2025-01-09 10:53:30 -08:00
Alexander Holliday 5db231351e Merge pull request #1541 from bluewave-labs/hotfix/fe/be/incidents-page
hotfix: fe/be/incidents page
2025-01-09 10:53:14 -08:00
Caio Cabral 3787f9c288 feat: fix success grdient 2025-01-09 13:50:50 -05:00
Alex Holliday ef23648941 ommit checks from query if limit is null 2025-01-09 10:42:25 -08:00
Alex Holliday e8aecb4041 fix method name 2025-01-09 10:42:01 -08:00
Alex Holliday d76f02ba51 repalce limit param of -1 with null 2025-01-09 10:41:33 -08:00
Caio Cabral be144c5ed2 feat: search and actions 2025-01-09 12:32:54 -05:00
Caio Cabral 07641a2bd8 feat: fixing table 2025-01-09 12:19:28 -05:00
Mend Renovate 83b43d060a Update material-ui monorepo to v7.23.6 2025-01-09 15:21:09 +00:00
Caio Cabral 7686b1ecf5 fix: breadcrumbs 2025-01-09 08:40:25 -05:00
Caio Cabral 3ffcadc06e feat: setting new colors 2025-01-08 21:41:59 -05:00
Alexander Holliday 975e6d61b5 Merge pull request #1537 from bluewave-labs/hotfix/remove-missing-import
hotfix: remove missing import
2025-01-08 15:22:46 -08:00
Alex Holliday 6d82cb7eb2 remove missing import 2025-01-08 15:22:06 -08:00
Alexander Holliday 7a140e75f1 Merge pull request #1529 from renovate-bot/renovate/bullmq-5.x
Update dependency bullmq to v5.34.8
2025-01-08 15:15:09 -08:00
Alexander Holliday 51ab3487ee Merge pull request #1536 from bluewave-labs/fix/fe/debounce-search
fix: fix unnecessary rerenders
2025-01-08 15:14:48 -08:00
Alex Holliday de01a430a3 fix unnecessary rerenders 2025-01-08 15:13:35 -08:00
Alexander Holliday 5b1fbf8817 Merge pull request #1535 from bluewave-labs/hotfix/fe/be/filtering
hotfix: move filtering to the monitors facet
2025-01-08 14:18:45 -08:00
Alex Holliday 40fbe4a822 move filtering to the monitors facet 2025-01-08 14:17:29 -08:00
Alexander Holliday 75c6a6e024 Merge pull request #1534 from bluewave-labs/hotfix/fe/uptime-skeleton
hotfix: readd skeleton
2025-01-08 14:04:07 -08:00
Alex Holliday 62541f3fdd readd skeleton 2025-01-08 14:03:23 -08:00
Alexander Holliday b909210d21 Merge pull request #1533 from bluewave-labs/feat/be/unified-uptime-query
feat: be/unified uptime query
2025-01-08 13:53:29 -08:00
Alex Holliday de3a8be76c Use new query in Uptime page 2025-01-08 13:47:42 -08:00
Alex Holliday 7862f8d967 use new query in PageSpeed page 2025-01-08 13:47:20 -08:00
Alex Holliday bde4269fd1 use new query in infra page 2025-01-08 13:46:49 -08:00
Alex Holliday e616df2766 Remove unused thunks from uptime slice 2025-01-08 13:46:19 -08:00
Alex Holliday 1805ca8d17 Remove unnecessary params from getMonitorsByTeamId 2025-01-08 13:45:34 -08:00
Alex Holliday 979110dd77 Rewrite team monitors query 2025-01-08 13:44:24 -08:00
Alex Holliday 87f9c35c74 remove unused validation, update monitors by team ID validation 2025-01-08 13:42:43 -08:00
Alex Holliday 8f572ba01d Remove summary controller method, rewrite getMonitosByTeamId 2025-01-08 13:42:08 -08:00
Alex Holliday 7cfc06b2da Remove summary route 2025-01-08 13:40:57 -08:00
Alex Holliday 5da542b99e formatting 2025-01-08 12:01:43 -08:00
Alex Holliday cf5152d0ec remove unused dispatch from pagespeed 2025-01-08 12:01:28 -08:00
Alexander Holliday 61ee7a1059 Merge pull request #1532 from bluewave-labs/hotfix/fe/pagination
hotfix: use redux state for pagination
2025-01-08 11:55:14 -08:00
Alex Holliday 8d8082bb83 use redux state for pagination 2025-01-08 11:53:13 -08:00
Alexander Holliday ac839cae6c Merge pull request #1531 from bluewave-labs/fix/be/get-monitors-by-team-id-query
Fix/be/get monitors by team id query
2025-01-08 10:19:10 -08:00
Alex Holliday 2694f836c7 fix destructuring 2025-01-08 10:17:51 -08:00
Alex Holliday 35796dccd4 add normalize check 2025-01-08 10:06:50 -08:00
Alex Holliday ef56283fa9 Fix merge conflict, remove unused dispatch 2025-01-08 10:05:34 -08:00
Gorkem Cetin (BWL) dc43c0486c Add OpenSSF best practices badge 2025-01-08 01:22:33 -05:00
Mend Renovate dffbce1de1 Update dependency bullmq to v5.34.8 2025-01-08 05:48:23 +00:00
Alexander Holliday cac5dff694 Merge pull request #1526 from KalyanBhowmick/fix/be/incident-filter
Query updated for Incidents page filter
2025-01-07 21:47:50 -08:00
Kalyan Bhowmick 0e4cf8cded resolve query reverted 2025-01-08 10:30:22 +05:30
Caio Cabral db86753701 feat: updating texts 2025-01-07 21:27:52 -05:00
Alex Holliday a4989d3e95 Merge branch 'develop' into fix/be/get-monitors-by-team-id-query 2025-01-07 16:27:58 -08:00
Alex Holliday 0b803da5fb rewrite query to use aggregation pipeline 2025-01-07 16:27:35 -08:00
Alexander Holliday da9345abf5 Merge pull request #1528 from bluewave-labs/fix/fe/uptime-home
fix: fe/uptime home
2025-01-07 14:57:13 -08:00
Alexander Holliday 803a110345 Merge branch 'develop' into fix/fe/uptime-home 2025-01-07 14:57:03 -08:00
Alexander Holliday cba6734623 Merge pull request #1527 from bluewave-labs/fix/fe/simplify-monitor-summary
remove monitors from summary, unused
2025-01-07 14:54:52 -08:00
Alexander Holliday 4409afc0d0 Merge pull request #1523 from renovate-bot/renovate/bullmq-5.x
Update dependency bullmq to v5.34.7
2025-01-07 14:54:32 -08:00
Alex Holliday 787bb09235 fix pagination icon positioning 2025-01-07 14:52:10 -08:00
Alex Holliday 0cc5c732c7 Fix sort arrow positioning 2025-01-07 14:45:18 -08:00
Alex Holliday 1898880774 remove utility hook 2025-01-07 14:34:18 -08:00
Alex Holliday 89d0a74ade Use new table component, remove old table 2025-01-07 14:31:25 -08:00
Alex Holliday e070ef472e Create new UptimeDataTable component to hold search, table, and pagination 2025-01-07 14:30:27 -08:00
Alex Holliday 8bc05e4424 Rewrite uptime home page for simplicity, move queries to parent 2025-01-07 14:29:47 -08:00
Alex Holliday 37207da9fa Rename get method in network service 2025-01-07 14:28:46 -08:00
Alex Holliday 33b3143298 use correct name for redux action 2025-01-07 14:27:55 -08:00
Alex Holliday 290740d58e Add getting monitors by team id to redux slice to make use of loading state 2025-01-07 14:24:47 -08:00
Alex Holliday 741f0d1884 Merge branch 'develop' into fix/fe/uptime-home 2025-01-07 12:05:19 -08:00
Kalyan Bhowmick de513c226c Query updated for Incidents page filter 2025-01-07 23:48:12 +05:30
Alex Holliday e2d5388a30 remove monitors from summary, unused 2025-01-07 10:12:41 -08:00
Alexander Holliday 624ea50684 Merge pull request #1522 from bluewave-labs/fix/fe/uptime-details
Fix incorrect uptime check count, refactor out query pipelines
2025-01-06 16:35:23 -08:00
Mend Renovate 3ff9b19abf Update dependency bullmq to v5.34.7 2025-01-07 00:35:23 +00:00
Alexander Holliday 05bfbe2154 Merge pull request #1515 from bluewave-labs/feat/fe/reusable-data-table
feat: fe/reusable data table
2025-01-06 16:35:05 -08:00
Alexander Holliday a5aa00337a Merge pull request #1512 from bluewave-labs/fix/fe/charts-date-display
fix: fe/charts date display
2025-01-06 16:34:47 -08:00
Alex Holliday 9e1f50bc8e remove unused var 2025-01-06 15:24:16 -08:00
Alexander Holliday 36bbf5aba0 Merge pull request #1521 from bluewave-labs/hotfix/be/jobqueue-logging
hotfic: add more logging to jobqueue
2025-01-06 14:31:40 -08:00
Alex Holliday 299ae95a0d Add more logging to jobqueue 2025-01-06 14:30:48 -08:00
Alex Holliday ca42e2608f Fix incorrect uptime check count, refactor out query pipelines 2025-01-06 14:24:08 -08:00
Alexander Holliday dd5e14b6a5 Merge pull request #1505 from bluewave-labs/feat/devops/redis-health-check
feat: devops/add healthcheck to redis image
2025-01-06 14:08:28 -08:00
Jasneet Singh 4398010a9f Inform Admin incase of server issue. 2025-01-06 16:38:58 -05:00
Gorkem Cetin (BWL) 208677f9bc fix anyways 2025-01-06 13:57:24 -05:00
Gorkem Cetin (BWL) d600779432 Suggest watching 2025-01-06 13:57:06 -05:00
Alexander Holliday 303d3c5ba8 Merge pull request #1520 from bluewave-labs/hotfix/fe/validation
hotfix: make protocol optional for validation
2025-01-06 10:14:16 -08:00
Alex Holliday abe2544a2a make protocol optional for validation 2025-01-06 10:13:24 -08:00
Alexander Holliday 8045d2a17c Merge pull request #1516 from renovate-bot/renovate/dockerode-4.x
Update dependency dockerode to v4.0.3
2025-01-06 10:09:23 -08:00
Alexander Holliday 40b302fcf5 Merge pull request #1519 from bluewave-labs/hotfix/fe/monitor-validation
hotfix: fe/monitor validation, resolves #1518
2025-01-06 10:09:07 -08:00
Alex Holliday 21a33f8f37 Added source 2025-01-06 10:06:26 -08:00
Alex Holliday e2ce886a16 Update regex to avoid catastrophic backtracking 2025-01-06 10:05:53 -08:00
Gorkem Cetin (BWL) a9ceecbdb2 Update README.md 2025-01-06 04:46:28 -05:00
Gorkem Cetin (BWL) a74085abbe Fix screenshot 2025-01-06 04:42:56 -05:00
Gorkem Cetin (BWL) 99089ab103 Update README.md 2025-01-05 20:49:23 -05:00
Gorkem Cetin (BWL) 2a99c87ff2 Update README.md 2025-01-05 11:30:39 -05:00
Mend Renovate 09aa62d42e Update dependency dockerode to v4.0.3 2025-01-04 14:03:58 +00:00
Alexander Holliday 91a93bd8fb Merge pull request #1513 from renovate-bot/renovate/material-ui-monorepo
Update material-ui monorepo
2025-01-03 12:44:29 -08:00
Alexander Holliday 118796c4ef Merge pull request #1514 from rafeyrana/issue#1508
Left align Profile > Password components
2025-01-03 12:44:12 -08:00
Alex Holliday 8dd1dc8cca Removed unused BasicTable 2025-01-03 12:41:14 -08:00
Alex Holliday bd502a610a Move pagination components from Infrastrucutre directory to reusable table directory 2025-01-03 12:24:06 -08:00
Alex Holliday 447c9ce70b Use reuseable table in Uptime home page 2025-01-03 12:23:08 -08:00
Alex Holliday c504fbbad6 use reusable table in infrastructure page 2025-01-03 12:22:24 -08:00
Alex Holliday c69389db2c use reusable table in incidents page 2025-01-03 12:21:59 -08:00
Alex Holliday a053eebdb0 Use reusable table in team page 2025-01-03 12:21:33 -08:00
Alex Holliday 0c608fdc8e Fix conditional rendering of empty view 2025-01-03 12:09:05 -08:00
Rafey Rana 2c21a44e76 Left align Profile > Password components 2025-01-03 14:30:12 -05:00
Alex Holliday c6ef46133c safe data access, add default empty view 2025-01-03 11:17:55 -08:00
Alex Holliday c192d7024e Add empty view to table 2025-01-03 11:14:23 -08:00
Alex Holliday 3d067e8030 make config optional, safe SX access 2025-01-03 10:36:53 -08:00
Alex Holliday 83dc96887d Create a reusable table component 2025-01-03 10:31:38 -08:00
Mend Renovate 6b1d6b64d6 Update material-ui monorepo 2025-01-03 14:04:46 +00:00
Alex Holliday 032adb4a77 Refactor date format lookup to util functions, refactor x-axis for infra details charts 2025-01-02 14:22:31 -08:00
Alex Holliday ef13af3884 Update x-axis labels for uptime monitor details chart 2025-01-02 14:07:38 -08:00
Alexander Holliday 67749585e0 Merge pull request #1511 from bluewave-labs/hotfix/be/env-config
hotfix: fix env vars for settings service
2025-01-02 12:30:15 -08:00
Alex Holliday eee33e85c4 Remove superfluous dotenv from authController, add missing dotenv to settingsService 2025-01-02 12:27:19 -08:00
Alexander Holliday d46cc3d037 Merge pull request #1510 from bluewave-labs/feat/be/distributed-uptime
feat: be/distributed uptime
2025-01-02 12:08:27 -08:00
Alex Holliday 648d40648c move ngrok to dev dependencies 2025-01-02 12:06:01 -08:00
Alex Holliday 56cd3f5d9f update docs 2025-01-02 12:02:44 -08:00
Alex Holliday 74ec29fbc1 add routes to app 2025-01-02 12:02:28 -08:00
Alex Holliday ba7cb151a2 Add distributed uptime router 2025-01-02 11:47:09 -08:00
Alex Holliday 3b5a1827ad Add distributedUptimeController 2025-01-02 11:45:29 -08:00
Alex Holliday 71fd2fb5ef use ngrok 2025-01-02 11:40:26 -08:00
Alex Holliday b91cf296f1 add ngrok 2025-01-02 11:40:13 -08:00
Alex Holliday c284eafd63 update logs to standard 2025-01-02 11:39:53 -08:00
Alex Holliday 3fc5d7a336 udpate log to standard 2025-01-02 11:34:09 -08:00
Alex Holliday 3fb114f898 udpate log to standard 2025-01-02 11:33:57 -08:00
Alex Holliday 50e3e2b97c Add distributed http type to monitor 2025-01-02 11:27:05 -08:00
Alex Holliday 1303497947 Add distributed uptime model 2025-01-02 11:26:08 -08:00
Alexander Holliday 1e0102a5b4 Merge pull request #1507 from bluewave-labs/develop
develop -> master
2025-01-02 11:09:31 -08:00
Alexander Holliday 70ba745e07 Merge pull request #1506 from bluewave-labs/hotfix/fe/bad-merge
add missing auth headers to hardware-details request
2025-01-02 10:59:41 -08:00
Alex Holliday decda4450b add missing auth headers to hardware-details request 2025-01-02 10:58:55 -08:00
Alex Holliday 0583bcb0b1 Add healthcheck to redis image 2025-01-02 10:54:30 -08:00
Alexander Holliday 43ff7a4318 Merge pull request #1504 from bluewave-labs/hotfix/fe/bad-merge
Fix bad merge commit
2025-01-02 10:04:49 -08:00
Alex Holliday 30d8595cac Fix bad merge commit 2025-01-02 10:04:23 -08:00
Alexander Holliday 7b3a83a37f Merge pull request #1502 from bluewave-labs/fix/be/improved-jobqueue
fix: be/improved jobqueue
2025-01-02 09:59:04 -08:00
Alexander Holliday b7bd641c7f Merge pull request #1501 from bluewave-labs/fix/be/pagespeed-index
fix: add indices for PageSpeedCheck
2025-01-02 09:58:44 -08:00
Alexander Holliday 1ce3e227fc Merge pull request #1498 from bluewave-labs/feat/be/hardware-details
feat: be/hardware details
2025-01-02 09:58:28 -08:00
Alexander Holliday 25fd0f7055 Merge branch 'develop' into feat/be/hardware-details 2025-01-02 09:58:19 -08:00
Alexander Holliday f958424793 Merge pull request #1497 from bluewave-labs/feat/fe/uptime-details
feat: fe/uptime details
2025-01-02 09:57:30 -08:00
Gorkem Cetin (BWL) 2dbf324615 Update README.md 2025-01-02 08:20:49 -05:00
Alex Holliday 62d1d34937 better worker task handling, implement progress updates 2025-01-01 20:14:03 -08:00
Alex Holliday c11e412e81 fix init job queue method 2025-01-01 18:18:39 -08:00
Alex Holliday b332bed14e modify date format to ISO standard, remove toTimeStamp method 2025-01-01 17:27:12 -08:00
Alex Holliday e7cf127fde Fix tooltip and proptypes 2025-01-01 17:20:00 -08:00
Alex Holliday 69f7cf2ab1 fix check spread 2025-01-01 17:11:38 -08:00
Alex Holliday 86d11c7277 remove console.log 2025-01-01 17:11:26 -08:00
Alex Holliday dafdb03ce0 safe variable access 2025-01-01 17:06:49 -08:00
Alex Holliday 4c2a0fd2d3 Use initJobQueue method to initialize JobQueue, flush Redis DB on shutdown timeout 2025-01-01 13:33:01 -08:00
Alex Holliday e222b13b51 add separate queue for each monitor type 2025-01-01 13:32:18 -08:00
Alex Holliday 8fcbe43a9d Remove console log from hardware check module 2025-01-01 13:31:38 -08:00
Alex Holliday 48e8c29dd4 Add indices for PageSpeedCheck 2025-01-01 13:27:23 -08:00
Alex Holliday 6563cedf88 add jsdoc and validation 2025-01-01 09:08:07 -08:00
Alex Holliday c572096a50 safe data access 2025-01-01 09:02:21 -08:00
Alexander Holliday 67fe63c980 Merge pull request #1496 from renovate-bot/renovate/bullmq-5.x
fix(deps): update dependency bullmq to v5.34.6
2025-01-01 08:39:38 -08:00
Gorkem Cetin (BWL) ca258da7f0 Update README.md 2025-01-01 08:55:47 -05:00
Gorkem Cetin (BWL) 24f5c54fe5 Update README.md 2024-12-31 23:25:14 -05:00
Alex Holliday 180585806b Add last checked 2024-12-31 20:12:50 -08:00
Alex Holliday f176768b54 Refactor FE to use new query 2024-12-31 20:00:22 -08:00
Alex Holliday a3518e4462 add missing date range, add date range lookup 2024-12-31 20:00:02 -08:00
Alex Holliday cb425b2b3b Merge branch 'develop' into feat/be/hardware-details 2024-12-31 17:39:19 -08:00
Alex Holliday 2d9b4eaab6 write hardware monitor query 2024-12-31 17:39:02 -08:00
Alexander Holliday 350e560079 Merge pull request #1481 from bluewave-labs/fix/be/db-indices
fix: be/db indices
2024-12-31 17:38:29 -08:00
Alex Holliday 2a41642be7 add two mising date clauses to details query 2024-12-31 16:40:44 -08:00
Alex Holliday 58c416f909 use upchecksaggregate total checks instead of total checks 2024-12-31 16:40:16 -08:00
Alex Holliday e29b55408f Fixed color for upbarchart: 2024-12-31 16:39:50 -08:00
Alex Holliday 247bf44406 begin implementing aggregate query 2024-12-31 15:05:14 -08:00
Alex Holliday cf3305611f Add route and controller method for hardware details 2024-12-31 15:05:03 -08:00
Alex Holliday a466e91a45 remove old query 2024-12-31 13:46:56 -08:00
Alex Holliday 91b282e7d9 Refactor charts 2024-12-31 13:43:03 -08:00
Alex Holliday 17bd1f5286 Add temporary normalization functoins 2024-12-31 13:42:49 -08:00
Alex Holliday bbae5052c8 Add group checks to DB query 2024-12-31 13:42:25 -08:00
Gorkem Cetin (BWL) ee87a688ca Remove redundant pr template file 2024-12-31 16:34:55 -05:00
Gorkem Cetin (BWL) f8581a2da0 Create pull_request_template.md 2024-12-31 16:33:18 -05:00
Mend Renovate fabfbec329 fix(deps): update dependency bullmq to v5.34.6 2024-12-31 21:31:36 +00:00
Gorkem Cetin (BWL) 94e67f2377 Update grant_funding.md 2024-12-31 16:12:27 -05:00
Gorkem Cetin (BWL) 68ff079106 Fixes 2024-12-31 15:36:38 -05:00
Gorkem Cetin (BWL) e2c39bc293 Checkmate & Uprock grant funding call initial commit 2024-12-31 15:16:33 -05:00
Alex Holliday 7f601b1e11 rebuild query 2024-12-31 11:43:04 -08:00
Alexander Holliday 5567eec75d Merge pull request #1495 from renovate-bot/renovate/mongoose-8.x-lockfile
fix(deps): update dependency mongoose to v8.9.3
2024-12-31 10:12:14 -08:00
Alexander Holliday 11972c6c54 Merge pull request #1486 from mertssmnoglu/fix/server-lint-errors
fix(server-lint): Resolve lint errors in server-side test files
2024-12-31 10:09:49 -08:00
Alex Holliday 6f96e77fec modify query 2024-12-30 22:23:46 -08:00
Alex Holliday 3e995c82aa update response time gauge 2024-12-30 20:11:05 -08:00
Alex Holliday b5ceb5c4c1 Add timestamp method 2024-12-30 19:49:41 -08:00
Alex Holliday 853a28d316 migrate to new query 2024-12-30 19:49:28 -08:00
Alex Holliday d574faa7d8 Add groupUpChecks and groupDownChecks 2024-12-30 19:49:09 -08:00
Alex Holliday 107540b2a8 FE refactor 2024-12-30 16:07:28 -08:00
Alex Holliday e5181727fe Add netwokr request for uptime details 2024-12-30 14:58:20 -08:00
Alex Holliday 5391145a9a Add aggregate queries for uptime monitor stats 2024-12-30 14:57:19 -08:00
Alex Holliday 0551eb010d Add controller method for uptime details 2024-12-30 14:56:50 -08:00
Alex Holliday d9c583f972 Add a route for uptime details 2024-12-30 14:56:38 -08:00
Mend Renovate 566cd8538a fix(deps): update dependency mongoose to v8.9.3 2024-12-30 22:07:41 +00:00
Alexander Holliday 334e8c32f6 Merge pull request #1491 from rafeyrana/sidebar-button
Hamburger Icon button rounded
2024-12-30 10:21:48 -08:00
Rafey Rana 36ca55e2b6 code cleanup 2024-12-29 12:10:54 -05:00
Rafey Rana bf8fcadb4c Sidebar icon button rounded 2024-12-29 12:02:11 -05:00
Alexander Holliday 3e841b2e16 Merge pull request #1472 from aroy114/button
Red button mouse hover status has wrong color #1335
2024-12-29 08:59:59 -08:00
Alexander Holliday 811ccaeaf1 Merge pull request #1479 from bluewave-labs/feat/fe/tcp-port-monitoring
feat: fe/tcp port monitoring, resolves #1476
2024-12-29 08:58:05 -08:00
Alexander Holliday ba05405f82 Merge pull request #1478 from bluewave-labs/feat/be/tcp-port-monitoring
feat: be/tcp port monitoring, references #1476
2024-12-29 08:57:35 -08:00
Alexander Holliday 26f1c275df Merge pull request #1489 from aroy114/navbar
Clicking on settings shouldn't open the "Other" drawer, resolves #1485
2024-12-29 08:54:15 -08:00
Alexander Holliday 43b8a3cc6e Merge pull request #1487 from renovate-bot/renovate/fontsource-monorepo
fix(deps): update dependency @fontsource/roboto to v5.1.1
2024-12-29 08:48:34 -08:00
Anand Roy c2a178c99e fixed navbar links 2024-12-29 15:37:17 +00:00
Gorkem Cetin (BWL) d2ef1ab4bd I'll find a better design here with photos 2024-12-29 09:24:01 -05:00
Mend Renovate fee7997222 fix(deps): update dependency @fontsource/roboto to v5.1.1 2024-12-29 13:53:21 +00:00
Anand Roy 35697654b2 fixed variable 2024-12-29 13:37:23 +00:00
Mert Şişmanoğlu b9863e5eee chore(lint): Add chai globals to eslint config
- It will prevent ignore 'no-undef' errors for expect. We are globally registered the expect.
2024-12-29 14:41:42 +03:00
Mert Şişmanoğlu fcda60fe5b fix(test): Use 'npm run lint-fix' to fix 'mocha/no-mocha-arrows' like lint warnings
- ref: https://mochajs.org/#arrow-functions
2024-12-29 14:25:59 +03:00
Alex Holliday 0b5594f9c9 force index usage for getMonitorStatsById 2024-12-28 09:37:00 -08:00
Alex Holliday bdf23a45b7 Sync indices on startup 2024-12-28 09:35:34 -08:00
Alex Holliday ce3e7cf384 Add indices to HardwareCheck model 2024-12-28 09:35:00 -08:00
Alex Holliday 91e7229b23 Add indices to Check model 2024-12-28 09:34:27 -08:00
Gorkem Cetin (BWL) 319e6d6017 Add core maintainers 2024-12-28 00:43:27 -05:00
Alexander Holliday fab60f0da9 Merge pull request #1480 from bluewave-labs/hotfix/non-blocking-calls
hotfix: made adding jobs and scaling workers non-blocking
2024-12-27 14:02:18 -08:00
Alex Holliday d686a8de5e made adding jobs and scaling workers non-blocking 2024-12-27 14:00:47 -08:00
Alex Holliday bc748c57e5 Add port type to uptime queries 2024-12-27 11:17:25 -08:00
Alex Holliday ab27011b91 Add port option to create uptime monitors 2024-12-27 11:16:58 -08:00
Alex Holliday d27c44d498 Add validation for port to FE 2024-12-27 11:16:25 -08:00
Alex Holliday 004184b0f4 add port types to monitor operations on BE 2024-12-27 11:16:09 -08:00
Alex Holliday f155b8ceb8 Add validation and status messages 2024-12-27 10:49:54 -08:00
Alex Holliday 6ff1cd0b5d Add handling of ports to status service 2024-12-27 10:49:45 -08:00
Alex Holliday 9571af4dba Add port monitoring operation to network service 2024-12-27 10:49:31 -08:00
Alex Holliday 73994caa14 Add net module to network service 2024-12-27 10:49:06 -08:00
Alex Holliday 0a68611234 Add port type to Monitor 2024-12-27 10:48:44 -08:00
Alexander Holliday 955d3c6298 Merge pull request #1470 from bluewave-labs/feat/be/migrate-to-class
feat: be/migrate to class
2024-12-27 09:54:20 -08:00
Alexander Holliday bab0595834 Merge pull request #1477 from renovate-bot/renovate/material-ui-monorepo
fix(deps): update dependency @mui/x-data-grid to v7.23.5
2024-12-27 09:01:19 -08:00
Mend Renovate f32caeaea6 fix(deps): update dependency @mui/x-data-grid to v7.23.5 2024-12-27 16:57:37 +00:00
Alexander Holliday f37b5f4458 Merge pull request #1475 from bluewave-labs/hotfix/fe/details-certificiate
hotfix: fix certificate format
2024-12-26 12:27:13 -08:00
Alex Holliday fd21155209 fix certificate format 2024-12-26 12:26:06 -08:00
Alexander Holliday e2e155f1e6 Merge pull request #1473 from aroy114/certificate
Move certificate expiry to a card #1327
2024-12-26 12:18:39 -08:00
Anand Roy b708e7aa7d added year in the date 2024-12-26 19:16:24 +00:00
Alexander Holliday b7c5d75f31 Merge pull request #1471 from renovate-bot/renovate/bullmq-5.x
fix(deps): update dependency bullmq to v5.34.5
2024-12-26 07:30:56 -08:00
Mend Renovate 9182e2a3a3 fix(deps): update dependency bullmq to v5.34.5 2024-12-25 13:58:22 +00:00
Alex Holliday 83e489cfe5 Use service registry instead of adding services to request 2024-12-24 12:00:52 -08:00
Alex Holliday 139c1fd215 refactor middleware to use service registry 2024-12-24 12:00:36 -08:00
Alex Holliday 7f6e096491 refacgtor MongoDB to be class based 2024-12-24 11:59:18 -08:00
Alex Holliday 0861595d39 Refactor routers to be class based 2024-12-24 11:58:56 -08:00
Alex Holliday cc40bd6006 refactor controllers to be class based 2024-12-24 11:58:42 -08:00
Alex Holliday 8b0af64761 Add static name exports to all services 2024-12-24 11:58:26 -08:00
Alex Holliday 7c1442e32f Add a service registry 2024-12-24 11:56:08 -08:00
Alexander Holliday 2efd26da8d Merge pull request #1464 from renovate-bot/renovate/material-ui-monorepo
fix(deps): update material-ui monorepo
2024-12-24 07:13:18 -08:00
Alexander Holliday 169d58d0bd Merge pull request #1469 from renovate-bot/renovate/eslint-plugin-react-7.x-lockfile
chore(deps): update dependency eslint-plugin-react to v7.37.3
2024-12-24 07:13:05 -08:00
Mend Renovate 293bc12cef chore(deps): update dependency eslint-plugin-react to v7.37.3 2024-12-24 04:27:42 +00:00
Alexander Holliday fdcd0df126 Merge pull request #1465 from bluewave-labs/develop
Develop -> Master
2024-12-23 15:01:19 -08:00
Mend Renovate 3a4aa2f45f fix(deps): update material-ui monorepo 2024-12-23 18:43:38 +00:00
Gorkem Cetin (BWL) 0476644f44 Update for name changes 2024-12-13 22:43:54 -05:00
Alexander Holliday 5b9a159d86 Merge pull request #1287 from bluewave-labs/develop
Develop -> Master 2.0 release
2024-12-04 18:06:21 -08:00
Alexander Holliday 2a9db50e32 Merge pull request #1096 from bluewave-labs/develop
Develop -> Master
2024-10-30 10:25:31 +08:00
Alexander Holliday 79d0f00826 Merge pull request #1091 from bluewave-labs/develop
Develop -> Master
2024-10-30 09:59:35 +08:00
Dr. Gorkem Cetin 07e82edab7 GITBOOK-23: No subject 2024-10-11 02:46:44 +00:00
Dr. Gorkem Cetin ba0a19d5fe GITBOOK-22: No subject 2024-10-11 02:44:26 +00:00
Dr. Gorkem Cetin 88590301c0 GITBOOK-21: No subject 2024-10-11 02:36:23 +00:00
Alexander Holliday 7c5930faff Merge pull request #928 from bluewave-labs/develop
Develop -> Master
2024-10-11 10:06:17 +08:00
Alexander Holliday 99a9013526 Merge pull request #925 from bluewave-labs/develop
Develop -> Master
2024-10-11 09:39:48 +08:00
248 changed files with 9339 additions and 7672 deletions

No files matched your search

@@ -1,4 +1,4 @@
**(when sending your PR, only remove this line. Do not remove any lines below. Check all the items before sending your PR)**
**(when sending your PR, only remove this line. Do not remove any lines below. Check all the relevant items before sending your PR)**
## Describe your changes
+3 -3
View File
@@ -1,9 +1,9 @@
# Contributing to Uptime Manager application
# Contributing to Checkmate
First off, thanks for taking the time to contribute! ❤️
All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for different ways to help and details about how the Uptime Manager project handles them. Please make sure to read the relevant section before making your contribution. It will make it much easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. 🎉
All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for different ways to help and details about how the Checkmate project handles them. Please make sure to read the relevant section before making your contribution. It will make it much easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. 🎉
> And if you like the project, but don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about:
> - Star the project
@@ -77,7 +77,7 @@ Once it's filed:
This section guides you through submitting an enhancement suggestion for the application, **including completely new features and minor improvements to existing functionality**. Following these guidelines will help maintainers and the community understand your enhancements and find related suggestions.
- Make sure that you are using the latest version.
- Make sure you run the code locally. The Uptime Manager [documentation](https://bluewavelabs.gitbook.io/uptime-manager) covers it.
- Make sure you run the code locally. The Checkmate [documentation](https://bluewavelabs.gitbook.io/checkmate) covers it.
- Find out if the functionality is already covered, maybe by an individual configuration.
- Perform a [search](/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
- Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library.
+562 -418
View File
File diff suppressed because it is too large. Load diff
+5 -5
View File
@@ -14,12 +14,12 @@
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@fontsource/roboto": "^5.0.13",
"@mui/icons-material": "6.2.1",
"@mui/lab": "6.0.0-beta.20",
"@mui/material": "6.2.1",
"@mui/icons-material": "6.4.1",
"@mui/lab": "6.0.0-beta.24",
"@mui/material": "6.4.1",
"@mui/x-charts": "^7.5.1",
"@mui/x-data-grid": "7.23.3",
"@mui/x-date-pickers": "7.23.3",
"@mui/x-data-grid": "7.24.0",
"@mui/x-date-pickers": "7.24.0",
"@reduxjs/toolkit": "2.5.0",
"axios": "^1.7.4",
"dayjs": "1.11.13",
+48 -3
View File
@@ -1,4 +1,49 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="32" height="32" fill="#1570EF"/>
<path d="M21.8849 14.3622H19.2287C19.1529 13.9266 19.0133 13.5407 18.8097 13.2045C18.6061 12.8636 18.3527 12.5748 18.0497 12.3381C17.7467 12.1013 17.401 11.9238 17.0128 11.8054C16.6293 11.6823 16.215 11.6207 15.7699 11.6207C14.9792 11.6207 14.2784 11.8196 13.6676 12.2173C13.0568 12.6103 12.5786 13.188 12.233 13.9503C11.8873 14.7079 11.7145 15.6335 11.7145 16.7273C11.7145 17.84 11.8873 18.7775 12.233 19.5398C12.5833 20.2973 13.0616 20.8703 13.6676 21.2585C14.2784 21.642 14.9768 21.8338 15.7628 21.8338C16.1984 21.8338 16.6056 21.777 16.9844 21.6634C17.3679 21.545 17.7112 21.3722 18.0142 21.1449C18.322 20.9176 18.58 20.6383 18.7884 20.3068C19.0014 19.9754 19.1482 19.5966 19.2287 19.1705L21.8849 19.1847C21.7855 19.8759 21.5701 20.5246 21.2386 21.1307C20.9119 21.7367 20.4834 22.2718 19.9531 22.7358C19.4228 23.1951 18.8026 23.5549 18.0923 23.8153C17.3821 24.071 16.5938 24.1989 15.7273 24.1989C14.4489 24.1989 13.3078 23.9029 12.304 23.3111C11.3002 22.7192 10.5095 21.8646 9.93182 20.7472C9.35417 19.6297 9.06534 18.2898 9.06534 16.7273C9.06534 15.16 9.35653 13.8201 9.93892 12.7074C10.5213 11.59 11.3144 10.7353 12.3182 10.1435C13.322 9.55161 14.4583 9.25568 15.7273 9.25568C16.5369 9.25568 17.2898 9.36932 17.9858 9.59659C18.6818 9.82386 19.3021 10.1577 19.8466 10.598C20.3911 11.0336 20.8385 11.5687 21.1889 12.2031C21.544 12.8329 21.776 13.5526 21.8849 14.3622Z" fill="white"/>
<svg width="32" height="32" viewBox="0 0 600 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M218.252 79.2667L218.045 78.4143C218.712 77.617 219.642 77.5282 220.615 77.4361C224.829 77.0374 243.307 76.7077 246.676 77.418C248.299 77.76 249.661 78.5248 250.932 79.5734C254.845 82.8003 259.018 88.0302 262.403 91.9284C263.57 93.2734 264.805 95.1623 266.183 96.2584C268.203 99.7185 274.532 101.602 278.167 102.623C278.397 102.688 278.631 102.741 278.863 102.797C274.983 106.185 272.016 110.321 268.272 113.745C272.574 124.188 286.689 184.953 289.397 187.986C290.165 188.212 290.291 188.048 291.045 187.739C290.627 188.446 290.337 189.3 289.588 189.656L288.963 188.533C286.703 188.347 273.044 195.497 269.836 196.808C267.39 197.808 264.851 198.458 262.414 199.405C261.197 196.797 260.413 193.923 259.329 191.244C254.43 179.142 250.091 166.843 245.71 154.552C240.241 139.206 234.226 124.026 228.882 108.642C226.389 101.466 223.549 94.5009 220.953 87.3749C220.026 84.8301 219.72 81.4795 218.252 79.2667Z" fill="#3158B7"/>
<path d="M218.252 79.2667L218.045 78.4143C218.712 77.617 219.642 77.5282 220.615 77.4361C224.829 77.0374 243.307 76.7077 246.676 77.418C248.299 77.76 249.661 78.5248 250.932 79.5734C254.845 82.8003 259.018 88.0302 262.403 91.9284C263.57 93.2734 264.805 95.1623 266.183 96.2584C268.203 99.7185 274.532 101.602 278.167 102.623C278.397 102.688 278.631 102.741 278.863 102.797C274.983 106.185 272.016 110.321 268.272 113.745C266.08 111.774 263.588 110.159 261.208 108.427C256.477 104.982 251.692 101.649 246.906 98.282L233.54 88.9767C228.729 85.5908 223.823 81.3267 218.252 79.2667Z" fill="#73E4FA"/>
<path d="M299.595 19.4005C302.177 17.8183 305.226 16.8946 307.955 15.5556C310.387 14.3626 312.673 12.8604 315.15 11.7619C315.624 11.5519 315.886 11.4697 316.398 11.4844C315.732 13.7848 316.431 26.6622 316.441 30.2652C316.474 42.2192 316.084 54.2432 316.385 66.1867C316.416 67.4343 316.377 68.6301 316.847 69.8026C316.457 79.0631 316.718 88.4086 316.651 97.6808L316.423 172.062C316.376 177.75 316.385 183.438 316.448 189.125C316.469 192.585 316.902 196.888 316.126 200.243C316.055 199.033 315.728 197.334 316.025 196.183C315.86 197.435 315.463 198.762 315.391 200.002C315.283 201.847 315.798 203.719 315.391 205.559C314.431 204.554 313.43 203.906 312.592 202.729C308.228 196.602 310.556 194.07 301.963 190.683C299.704 189.793 293.054 186.88 291.045 187.739C290.291 188.048 290.165 188.212 289.397 187.986C286.689 184.953 272.574 124.188 268.272 113.745C272.016 110.321 274.983 106.185 278.863 102.797C278.631 102.741 278.397 102.688 278.167 102.623C274.532 101.602 268.203 99.7184 266.183 96.2583C269.435 97.3504 272.901 97.5882 276.304 97.6583C280.306 97.7408 283.403 97.3026 286.383 94.3544C288.086 92.669 289.516 90.6569 291.136 88.8839C293.303 86.512 296.041 84.1801 297.633 81.3777C300.012 77.1924 299.115 62.4967 299.219 57.0841C296.538 56.7086 293.912 56.806 291.218 56.6995C288.184 56.5796 285.396 56.0507 283.294 53.6585C280.886 50.9188 280.696 47.3466 281.035 43.8756C282.423 29.6657 295.122 37.239 298.804 33.8184C299.712 32.9739 299.469 21.618 299.595 19.4005Z" fill="#3D7ECD"/>
<path d="M362.288 269.421L362.773 270.062C364.332 274.37 365.193 279.073 366.359 283.516C368.419 291.371 370.61 299.194 372.793 307.015L395.769 388.039L411.304 442.863L415.766 458.213C416.528 460.836 417.569 463.467 417.96 466.175C417.89 466.842 418.03 466.869 417.485 467.324C413.349 466.406 409.11 465.92 404.942 465.147C396.892 463.653 388.881 461.984 380.817 460.552C380.516 459.221 380.489 457.712 380.305 456.347C379.896 453.327 379.359 450.33 378.694 447.356C376.712 438.738 374.16 430.227 372.075 421.626L351.327 334.35C349.071 324.725 347.019 314.981 344.607 305.405C342.561 297.284 340.078 289.201 338.622 280.946C339.912 280.649 340.991 280.35 342.142 279.684C345.072 278.136 348.264 277.064 351.221 275.536C354.9 273.636 358.345 270.649 362.288 269.421Z" fill="#73E4FA"/>
<path d="M316.398 11.4845C316.949 11.6168 317.496 11.7682 318.021 11.982C320.527 13.0022 322.595 14.8975 325.025 16.0401C326.641 16.7993 328.506 17.0278 330.066 17.9189C330.615 18.2326 331.175 18.6401 331.516 19.1833C333.638 22.5617 329.941 33.143 334.144 34.5595C335.071 34.872 336.309 34.7269 337.278 34.6636C342.517 34.3216 346.04 34.3235 349.065 39.1827C350.891 42.117 351.841 45.3207 350.982 48.7564C350.164 52.0314 347.831 55.4635 344.902 57.2399C344.309 57.5993 343.657 57.8308 343.003 58.0488C342.382 58.2541 341.729 58.4831 341.176 58.8402C339.34 60.0257 337.705 61.6472 335.85 62.8819C335.083 63.3916 333.536 63.9343 333.114 64.7163C333.015 64.8989 332.938 65.0921 332.849 65.2797C331.994 71.778 330.942 74.7954 335.242 80.4525C338.105 84.2196 345.676 93.407 349.248 96.0711C350.329 96.8768 351.548 97.3899 352.858 97.674C354.638 97.679 356.567 97.8353 358.319 97.4932C366.986 95.8002 372.945 85.6789 379.155 80.1412C380.557 78.8916 382.117 77.8947 383.974 77.4926C387.385 76.754 391.296 77.2429 394.773 77.2627C400.744 77.2966 406.631 77.1509 412.603 77.4939C413.066 77.8038 413.08 77.6663 413.16 78.1487C413.385 79.5036 412.832 81.0938 412.41 82.377C409.805 90.2864 406.49 98.1119 403.607 105.936L387.525 150.29C383.617 161.269 379.569 172.195 375.381 183.07C373.017 189.241 370.826 195.663 367.756 201.518C366.906 200.846 366.105 200.384 365.115 199.946C357.118 196.547 349.468 191.947 341.757 187.926C341.211 187.423 341.102 187.207 340.301 187.318C338.422 187.579 336.346 188.419 334.502 188.929C330.434 190.055 321.796 191.764 319.469 195.652C318.572 197.151 317.692 200.22 316.337 201.245C316.225 200.886 316.145 200.621 316.126 200.243C316.902 196.888 316.469 192.585 316.448 189.125C316.385 183.438 316.377 177.75 316.423 172.062L316.651 97.6809C316.718 88.4087 316.457 79.0632 316.847 69.8027C316.377 68.6302 316.416 67.4344 316.385 66.1868C316.084 54.2433 316.474 42.2193 316.441 30.2653C316.431 26.6623 315.732 13.7849 316.398 11.4845Z" fill="#73E4FA"/>
<path d="M332.127 57.4141C335.751 57.5106 339.378 57.8905 343.003 58.0488C342.382 58.2541 341.729 58.4831 341.176 58.8402C339.34 60.0257 337.705 61.6472 335.85 62.8819C335.083 63.3916 333.536 63.9343 333.114 64.7163C333.015 64.8989 332.938 65.0921 332.849 65.2797C332.684 62.6459 332.422 60.0356 332.127 57.4141Z" fill="black"/>
<path d="M352.858 97.674C354.638 97.679 356.567 97.8353 358.319 97.4932C366.986 95.8002 372.945 85.6789 379.155 80.1412C380.557 78.8916 382.117 77.8947 383.974 77.4926C387.385 76.754 391.296 77.2429 394.773 77.2627C400.744 77.2966 406.631 77.1509 412.603 77.4939C412.123 77.5931 411.776 77.6589 411.35 77.9133C409.284 79.1482 407.188 81.3404 405.081 82.7802C394.559 89.9716 384.283 97.4873 373.787 104.715C371.042 106.605 368.398 108.696 365.587 110.481C363.016 106.042 360.879 102.667 356.684 99.576C355.908 99.004 354.963 98.1848 354.042 97.8844C353.777 97.7979 353.467 97.7915 353.199 97.7482C353.084 97.7297 352.972 97.6988 352.858 97.674Z" fill="#4F91E0"/>
<path d="M316.847 69.8027C321.242 72.4105 326.84 79.7356 330.518 83.5726C335.063 88.3145 340.305 92.4625 345.078 96.9857C348.754 100.47 359.102 112.197 362.531 113.979C362.884 116.416 347.596 173.131 345.411 179.979C344.657 182.345 343.764 185.35 342.254 187.338C342.099 187.543 341.927 187.734 341.757 187.926C341.211 187.423 341.102 187.207 340.301 187.318C338.422 187.579 336.346 188.419 334.502 188.929C330.434 190.055 321.796 191.764 319.469 195.652C318.572 197.151 317.692 200.22 316.337 201.245C316.225 200.886 316.145 200.621 316.126 200.243C316.902 196.888 316.469 192.585 316.448 189.125C316.385 183.438 316.376 177.75 316.423 172.062L316.651 97.6809C316.718 88.4087 316.457 79.0632 316.847 69.8027Z" fill="#5BBFFC"/>
<path d="M316.126 200.243C316.145 200.621 316.225 200.886 316.337 201.245C317.692 200.22 318.572 197.151 319.469 195.652C321.796 191.764 330.434 190.055 334.502 188.929C336.346 188.419 338.422 187.579 340.301 187.318C341.102 187.207 341.211 187.423 341.757 187.926C349.468 191.947 357.118 196.547 365.115 199.946C366.105 200.384 366.906 200.846 367.756 201.518C367.27 202.637 366.763 203.747 366.234 204.848C365.063 207.595 364.344 210.137 363.459 212.952C367.613 213.364 371.797 213.297 375.966 213.194C386.171 213.341 399.134 211.56 407.006 219.438C408.262 220.694 409.583 222.077 410.315 223.707C411.447 228.7 410.939 234.09 410.692 239.173C410.661 239.285 410.628 239.397 410.599 239.511C410.317 240.612 410.264 241.816 409.76 242.846C408.269 245.89 403.918 248.67 401.099 250.509L397.101 250.535C392.229 251.156 386.936 250.764 382.02 250.742C380.258 252.242 379.572 253.4 379.015 255.621C375.623 257.067 372.349 258.186 368.836 259.31C366.357 260.996 362.191 264.345 361.869 267.495C361.803 268.145 361.893 268.578 362.175 269.155L362.288 269.421C358.345 270.649 354.9 273.636 351.221 275.536C348.264 277.064 345.072 278.136 342.142 279.684C340.991 280.35 339.912 280.649 338.622 280.946L338.374 280.965L337.631 281.175C336.996 280.978 336.122 280.707 335.64 280.22C335.013 279.586 332.112 273.818 330.826 272.131C327.237 267.42 322.458 264.909 316.638 264.129L316.192 264.037C314.993 265.535 316.083 270.149 315.579 272.213C315.076 269.916 316.559 267.352 315.272 265.334C314.562 264.951 314 264.949 313.234 265.15C310.643 265.828 308.244 267.144 305.601 267.663L305.359 267.78C304.526 268.174 303.726 268.445 302.836 268.679L302.422 268.516C302.97 267.994 303.581 267.707 304.249 267.371C303.346 267.089 302.592 267.405 301.795 267.828C300.798 268.358 299.724 269.109 298.638 269.418C296.45 270.04 293.748 268.782 292.771 271.723C291.539 275.429 292.836 276.598 289.342 279.245L289.264 279.106L289.746 279.665C289.922 279.642 290.098 279.617 290.274 279.596C290.788 279.534 291.072 279.562 291.552 279.784C283.761 280.886 276.08 271.943 269.481 268.727C269.532 267.685 269.414 267.036 268.848 266.155C266.793 262.951 261.551 259.21 258.011 257.869C256.773 257.4 255.382 257.17 254.087 256.899C250.725 256.497 247.482 255.358 244.173 254.665C241.651 254.137 239.029 253.962 236.466 253.728C236.969 252.907 236.631 251.749 236.978 250.742C234.444 250.731 231.884 250.523 229.351 250.403C226.903 249.086 224.175 246.485 222.644 244.15C220.166 240.368 220.112 229.455 221.195 225.05C221.962 221.93 223.946 219.508 226.648 217.845C227.525 217.021 228.391 216.267 229.547 215.874C232.606 214.832 236.233 214.827 239.433 214.547C243.327 214.206 247.238 213.733 251.141 213.538C256.502 213.269 261.883 213.36 267.25 213.257C267.293 213.167 267.345 213.08 267.378 212.986C268.103 210.948 263.421 201.839 262.414 199.405C264.851 198.458 267.39 197.808 269.836 196.808C273.044 195.497 286.703 188.347 288.963 188.533L289.588 189.656C290.337 189.3 290.627 188.446 291.045 187.739C293.054 186.88 299.704 189.793 301.963 190.683C310.556 194.07 308.228 196.602 312.592 202.729C313.43 203.906 314.431 204.554 315.391 205.559C315.798 203.719 315.283 201.847 315.391 200.002C315.463 198.762 315.86 197.435 316.025 196.183C315.728 197.334 316.055 199.033 316.126 200.243Z" fill="#73E4FA"/>
<path d="M226.648 217.845C227.525 217.021 228.391 216.267 229.547 215.874C232.606 214.832 236.233 214.827 239.433 214.547C243.327 214.206 247.238 213.733 251.141 213.538C256.502 213.269 261.883 213.36 267.25 213.257C273.5 213.971 279.834 213.445 286.108 213.605C286.028 213.626 285.948 213.648 285.867 213.666C283.762 214.153 281.367 213.997 279.208 214.037C272.251 214.165 265.326 213.83 258.375 213.88C253.031 213.919 247.886 214.67 242.578 215.017C240.895 215.127 236.024 214.805 235.01 216.105C234.814 216.356 234.778 216.499 234.672 216.773C235.26 217.358 235.736 217.319 236.534 217.341C240.179 217.439 243.921 217.212 247.585 217.238C254.057 217.283 260.516 217.54 266.99 217.551C270.978 217.557 278.548 217.235 282.283 217.919C273.611 218.558 264.721 217.948 256.023 218.03C249.71 217.873 243.396 217.847 237.081 217.954C233.732 217.991 229.946 218.398 226.648 217.845Z" fill="#4F91E0"/>
<path d="M321 196.5C321.019 196.878 320.86 194.141 320.972 194.5C322.327 193.475 318.572 197.151 319.469 195.652C321.796 191.764 330.434 190.055 334.502 188.929C336.346 188.419 338.422 187.579 340.301 187.318C341.102 187.207 341.211 187.423 341.757 187.926C349.468 191.947 357.118 196.547 365.115 199.946C366.105 200.384 366.906 200.846 367.756 201.518C367.27 202.637 366.763 203.747 366.234 204.848C365.063 207.595 364.344 210.137 363.459 212.952L361.76 212.951C346.809 213.807 331.759 213.014 316.787 213.074L315.391 205.559C315.798 203.719 315.283 201.847 315.391 200.002C315.463 198.762 315.835 196.752 316 195.5C315.5 195 323.374 191.757 321 196.5Z" fill="#3158B7"/>
<path d="M291.045 187.739C293.054 186.88 299.704 189.793 301.963 190.683C310.556 194.07 305.5 191.5 312.5 194.5C314 195 315.54 193.995 316.5 195L316.787 213.074C306.586 212.996 296.304 213.296 286.108 213.605C279.834 213.445 273.5 213.971 267.25 213.257C267.293 213.167 267.345 213.08 267.378 212.986C268.103 210.948 263.421 201.839 262.414 199.405C264.851 198.458 267.39 197.808 269.836 196.808C273.044 195.497 286.703 188.347 288.963 188.533L289.5 188.5C290.249 188.144 290.627 188.446 291.045 187.739Z" fill="#15337C"/>
<path d="M316.158 217.961C333.626 218.066 351.372 216.648 368.745 218.663C369.093 229.235 368.662 239.88 368.76 250.467L387.46 250.44C390.609 250.437 393.982 250.193 397.101 250.535C392.229 251.156 386.936 250.764 382.02 250.742L316.217 250.777C316.034 247.101 316.2 243.334 316.205 239.649C316.23 232.42 316.215 225.19 316.158 217.961Z" fill="#5BBFFC"/>
<path d="M229.351 250.403C226.903 249.086 224.175 246.485 222.644 244.15C220.166 240.368 220.112 229.455 221.195 225.05C221.962 221.93 223.946 219.508 226.648 217.845C229.946 218.398 233.732 217.991 237.081 217.954C243.396 217.847 249.71 217.873 256.023 218.03C264.721 217.948 273.611 218.558 282.283 217.919L316.158 217.961C316.215 225.19 316.23 232.42 316.205 239.649C316.2 243.334 316.034 247.101 316.217 250.777L382.02 250.742C380.258 252.242 379.572 253.4 379.015 255.621C375.623 257.067 372.349 258.186 368.836 259.31C366.357 260.996 362.191 264.345 361.869 267.495C361.803 268.145 361.893 268.578 362.175 269.155L362.288 269.421C358.345 270.649 354.9 273.636 351.221 275.536C348.264 277.064 345.072 278.136 342.142 279.684C340.991 280.35 339.912 280.649 338.622 280.946L338.374 280.965L337.631 281.175C336.996 280.978 336.122 280.707 335.64 280.22C335.013 279.586 332.112 273.818 330.826 272.131C327.237 267.42 322.458 264.909 316.638 264.129L316.192 264.037C314.993 265.535 316.083 270.149 315.579 272.213C315.076 269.916 316.559 267.352 315.272 265.334C314.562 264.951 314 264.949 313.234 265.15C310.643 265.828 308.244 267.144 305.601 267.663L305.359 267.78C304.526 268.174 303.726 268.445 302.836 268.679L302.422 268.516C302.97 267.994 303.581 267.707 304.249 267.371C303.346 267.089 302.592 267.405 301.795 267.828C300.798 268.358 299.724 269.109 298.638 269.418C296.45 270.04 293.748 268.782 292.771 271.723C291.539 275.429 292.836 276.598 289.342 279.245L289.264 279.106L289.746 279.665C289.922 279.642 290.098 279.617 290.274 279.596C290.788 279.534 291.072 279.562 291.552 279.784C283.761 280.886 276.08 271.943 269.481 268.727C269.532 267.685 269.414 267.036 268.848 266.155C266.793 262.951 261.551 259.21 258.011 257.869C256.773 257.4 255.382 257.17 254.087 256.899C250.725 256.497 247.482 255.358 244.173 254.665C241.651 254.137 239.029 253.962 236.466 253.728C236.969 252.907 236.631 251.749 236.978 250.742C234.444 250.731 231.884 250.523 229.351 250.403Z" fill="#3D7ECD"/>
<path d="M229.5 250.5C227.052 249.183 224.175 246.485 222.644 244.15C220.166 240.368 220.112 229.455 221.195 225.05C221.962 221.93 223.946 219.508 226.648 217.845C229.946 218.398 233.732 217.991 237.081 217.954C243.396 217.847 249.71 217.873 256.023 218.03C258.057 218.243 260.081 218.239 262.124 218.245C262.036 228.982 261.779 239.713 261.935 250.452C267.117 250.445 282.096 249.873 286.095 250.724C281.121 250.989 276.017 250.759 271.029 250.75C261.584 250.723 252.14 250.748 242.696 250.824C240.816 250.676 238.867 250.759 236.978 250.742C234.444 250.731 232.033 250.62 229.5 250.5Z" fill="#3158B7"/>
<path d="M242.696 250.824C252.14 250.748 261.584 250.723 271.029 250.75C276.017 250.759 281.121 250.989 286.095 250.724C296.126 250.796 306.188 250.976 316.217 250.777L382.02 250.742C380.258 252.242 379.572 253.4 379.015 255.621C375.623 257.067 372.349 258.186 368.836 259.31C366.357 260.996 362.191 264.345 361.869 267.495C361.803 268.145 361.893 268.578 362.175 269.155L362.288 269.421C358.345 270.649 354.9 273.636 351.221 275.536C348.264 277.064 345.072 278.136 342.142 279.684C340.991 280.35 339.912 280.649 338.622 280.946L338.374 280.965L337.631 281.175C336.996 280.978 336.122 280.707 335.64 280.22C335.013 279.586 332.112 273.818 330.826 272.131C327.237 267.42 322.458 264.909 316.638 264.129L316.192 264.037C314.993 265.535 316.083 270.149 315.579 272.213C315.076 269.916 316.559 267.352 315.272 265.334C314.562 264.951 314 264.949 313.234 265.15C310.643 265.828 308.244 267.144 305.601 267.663L305.359 267.78C304.526 268.174 303.726 268.445 302.836 268.679L302.422 268.516C302.97 267.994 303.581 267.707 304.249 267.371C303.346 267.089 302.592 267.405 301.795 267.828C300.798 268.358 299.724 269.109 298.638 269.418C296.45 270.04 293.748 268.782 292.771 271.723C291.539 275.429 292.836 276.598 289.342 279.245L289.264 279.106L289.746 279.665C289.922 279.642 290.098 279.617 290.274 279.596C290.788 279.534 291.072 279.562 291.552 279.784C283.761 280.886 276.08 271.943 269.481 268.727C269.532 267.685 269.414 267.036 268.848 266.155C266.793 262.951 261.551 259.21 258.011 257.869C256.773 257.4 255.382 257.17 254.087 256.899C250.725 256.497 247.482 255.358 244.173 254.665C241.651 254.137 239.029 253.962 236.466 253.728C236.969 252.907 236.631 251.749 236.978 250.742C238.867 250.759 240.816 250.676 242.696 250.824Z" fill="url(#paint0_linear_4222_6997)"/>
<path d="M236.978 250.742C238.867 250.759 240.816 250.676 242.696 250.824C242.881 250.874 243.066 250.928 243.252 250.974C245.298 251.479 247.92 251.212 250.051 251.224C248.443 251.53 247.073 251.291 245.943 252.702C245.85 253.55 245.913 253.633 246.31 254.399C248.336 255.702 252.778 255.161 254.087 256.899C250.725 256.497 247.482 255.358 244.173 254.665C241.651 254.137 239.029 253.962 236.466 253.728C236.969 252.907 236.631 251.749 236.978 250.742Z" fill="#15337C"/>
<path d="M315.839 263.948C315.537 262.501 315.708 261.013 315.229 259.629C314.46 258.966 313.976 259.049 312.984 258.933C313.102 258.884 313.213 258.814 313.338 258.787C315.769 258.246 325.519 258.983 328.801 258.983L357.499 259.017C359.803 259.006 366.156 258.505 368.097 258.96C368.485 259.051 368.546 259.119 368.836 259.31C366.357 260.996 362.191 264.345 361.869 267.495C361.803 268.145 361.893 268.578 362.175 269.155L362.288 269.421C358.345 270.649 354.9 273.636 351.221 275.536C348.264 277.064 345.072 278.136 342.142 279.684C340.991 280.35 339.912 280.649 338.622 280.946L338.374 280.965L337.631 281.175C336.996 280.978 336.122 280.707 335.64 280.22C335.013 279.586 332.112 273.818 330.826 272.131C327.237 267.42 322.458 264.909 316.638 264.129L316.192 264.037C314.993 265.535 316.083 270.149 315.579 272.213C315.076 269.916 316.559 267.352 315.272 265.334C314.562 264.951 314 264.949 313.234 265.15C310.643 265.828 308.244 267.144 305.601 267.663C307.941 265.704 312.848 264.583 315.839 263.948Z" fill="url(#paint1_linear_4222_6997)"/>
<path d="M334.406 268.36C340.718 267.927 347.148 267.514 353.456 268.191C355.699 268.431 360.368 269.793 362.175 269.155L362.288 269.421C358.345 270.649 354.9 273.636 351.221 275.536C348.264 277.064 345.072 278.136 342.142 279.684C340.991 280.35 339.912 280.649 338.622 280.946L338.374 280.965C338.013 279.917 337.843 278.75 337.605 277.665C336.155 274.684 336.233 271.392 334.406 268.36Z" fill="#4F91E0"/>
<path d="M337.605 277.665C338.101 277.244 338.105 277.263 338.759 277.253C340.026 277.925 341.077 278.732 342.142 279.684C340.991 280.35 339.912 280.649 338.622 280.946L338.374 280.965C338.013 279.917 337.843 278.75 337.605 277.665Z" fill="#5BBFFC"/>
<path d="M162.994 506.672C163.51 506.136 164.063 505.686 164.643 505.225C167.325 506.032 178.659 505.485 182.142 505.49L221.176 505.555C226.755 505.582 232.376 505.443 237.949 505.628C269.102 506.183 300.329 505.731 331.491 505.742L372.011 505.764C380.199 505.77 388.457 505.962 396.635 505.618C396.442 517.711 396.022 529.884 396.433 541.975C409.395 542.082 422.357 542.091 435.32 542.002C441.062 542.005 447.41 541.469 453.076 542.23C457.801 542.254 462.724 542.135 467.419 542.679C465.179 543.78 463.234 548.572 462.043 550.796V551.298L462.794 551.648C454.827 551.784 446.872 552.172 438.929 552.813C436.511 552.995 434.06 552.553 431.644 552.413C428.22 552.214 424.779 552.237 421.352 552.25C402.933 552.322 384.531 552.526 366.11 552.346L227.563 552.274C215.642 552.277 203.672 552.344 191.757 552.13C182.178 551.958 172.491 551.389 162.923 551.866C164.053 549.046 163.345 544.905 162.658 542.024C162.018 536.512 162.277 530.737 162.288 525.186C162.299 519.081 161.931 512.699 162.994 506.672Z" fill="#15337C"/>
<path d="M162.994 506.672C163.51 506.136 164.063 505.686 164.643 505.225C167.325 506.032 178.659 505.485 182.142 505.49L221.176 505.555C226.755 505.582 232.376 505.443 237.949 505.628C237.694 517.722 237.219 529.932 237.571 542.021L396.433 541.975C409.395 542.082 422.357 542.091 435.32 542.002C441.062 542.005 447.41 541.469 453.076 542.23C445.432 542.447 437.752 542.287 430.104 542.288L384.066 542.238L236.646 542.27L181.968 542.237C175.536 542.231 169.083 541.914 162.658 542.024C162.018 536.512 162.277 530.737 162.288 525.186C162.299 519.081 161.931 512.699 162.994 506.672Z" fill="#3158B7"/>
<path d="M237.949 505.628C269.102 506.183 300.329 505.731 331.491 505.742L372.011 505.764C380.199 505.77 388.457 505.962 396.635 505.618C396.442 517.711 396.022 529.884 396.433 541.975L237.571 542.021C237.219 529.932 237.694 517.722 237.949 505.628Z" fill="#3D7ECD"/>
<path d="M316.173 450.214L316.356 450.171C327.599 451.012 338.68 453.515 349.747 455.526C360.085 457.318 370.442 458.993 380.817 460.552C388.881 461.984 396.892 463.653 404.942 465.147C409.11 465.92 413.349 466.406 417.485 467.324C418.03 466.869 417.89 466.842 417.96 466.175C418.868 471.139 419.01 474.417 418.882 479.505C424.212 480.991 428.904 484.71 433.752 487.295L467.07 504.914C467.988 505.502 468.749 505.944 468.955 507.111C469.514 510.282 469.469 539.486 468.739 541.824C468.292 542.267 468.021 542.487 467.419 542.679C462.724 542.135 457.801 542.254 453.076 542.23C447.41 541.469 441.062 542.005 435.32 542.002C422.357 542.091 409.395 542.082 396.433 541.975C396.022 529.884 396.442 517.711 396.635 505.618C388.457 505.962 380.199 505.77 372.011 505.764L331.491 505.742C300.329 505.731 269.102 506.183 237.949 505.628C232.376 505.443 226.755 505.582 221.176 505.555L182.142 505.49C178.659 505.485 167.325 506.032 164.643 505.225C166.684 503.613 169.31 502.543 171.632 501.378C176.276 499.048 181.007 496.831 185.604 494.419C192.121 490.999 198.566 487.372 204.999 483.795C207.005 482.679 208.919 481.328 210.961 480.297C211.664 479.943 212.437 479.729 213.192 479.519C213.447 477.939 213.28 476.121 213.292 474.511C213.314 471.755 213.495 469.182 213.961 466.462C214.147 466.81 214.01 466.597 214.452 467.044C227.245 465.759 239.827 462.451 252.483 460.143C260.461 458.819 268.511 457.946 276.475 456.519L300.283 452.407C305.401 451.522 310.98 450.069 316.173 450.214Z" fill="#73E4FA"/>
<path d="M316.173 450.214L316.356 450.171C327.599 451.012 338.68 453.515 349.747 455.526C360.085 457.318 370.442 458.993 380.817 460.552C388.881 461.984 396.892 463.653 404.942 465.147C409.11 465.92 413.349 466.406 417.485 467.324C418.03 466.869 417.89 466.842 417.96 466.175C418.868 471.139 419.01 474.417 418.882 479.505C407.542 478.716 395.89 479.365 384.514 479.436C370.443 479.525 356.374 479.202 342.302 479.225L326.141 479.166C322.94 479.164 319.619 479.396 316.441 479.069C316.286 469.43 316.022 459.862 316.173 450.214Z" fill="#3D7ECD"/>
<path d="M467.07 504.914C467.988 505.502 468.749 505.944 468.955 507.111C469.514 510.282 469.469 539.486 468.739 541.824C468.292 542.267 468.021 542.487 467.419 542.679C462.724 542.135 457.801 542.254 453.076 542.23C447.41 541.469 441.062 542.005 435.32 542.002C422.357 542.091 409.395 542.082 396.433 541.975C396.022 529.884 396.442 517.711 396.635 505.618C399.774 505.933 403.063 505.785 406.221 505.786L422.299 505.784C435.31 505.785 448.476 506.228 461.464 505.68C463.339 505.6 465.314 505.634 467.07 504.914Z" fill="#5BBFFC"/>
<path d="M252.483 460.143C260.461 458.819 268.511 457.946 276.475 456.519L300.283 452.407C305.401 451.522 310.98 450.069 316.173 450.214C316.022 459.862 316.286 469.43 316.441 479.069C313.41 479.108 310.372 479.425 307.371 479.847C292.468 483.6 277.556 488.899 263.025 493.906C257.708 495.738 251.924 497.128 246.801 499.408C243.673 500.8 240.545 502.657 238.239 505.216L351.838 505.253L382.181 505.431C386.77 505.429 392.191 504.724 396.635 505.618C388.457 505.962 380.199 505.77 372.011 505.764L331.491 505.742C300.329 505.731 269.102 506.183 237.949 505.628C232.376 505.443 226.755 505.582 221.176 505.555L182.142 505.49C178.659 505.485 167.325 506.032 164.643 505.225C166.684 503.613 169.31 502.543 171.632 501.378C176.276 499.048 181.007 496.831 185.604 494.419C192.121 490.999 198.566 487.372 204.999 483.795C207.005 482.679 208.919 481.328 210.961 480.297C211.664 479.943 212.437 479.729 213.192 479.519C213.447 477.939 213.28 476.121 213.292 474.511C213.314 471.755 213.495 469.182 213.961 466.462C214.147 466.81 214.01 466.597 214.452 467.044C227.245 465.759 239.827 462.451 252.483 460.143Z" fill="url(#paint2_linear_4222_6997)"/>
<path d="M252.483 460.143C260.461 458.819 268.511 457.946 276.475 456.519L300.283 452.407C305.401 451.522 310.98 450.069 316.173 450.214C316.022 459.862 316.286 469.43 316.441 479.069C313.41 479.108 310.372 479.425 307.371 479.847C280.73 478.905 253.933 479.206 227.271 479.298C222.578 479.314 217.879 479.538 213.192 479.519C213.447 477.939 213.28 476.121 213.292 474.511C213.314 471.755 213.495 469.182 213.961 466.462C214.147 466.81 214.01 466.597 214.452 467.044C227.245 465.759 239.827 462.451 252.483 460.143Z" fill="#15337C"/>
<path d="M305.601 267.663C308.244 267.144 310.643 265.828 313.234 265.15C314 264.949 314.562 264.951 315.272 265.334C316.559 267.352 315.076 269.916 315.579 272.213C316.083 270.149 314.993 265.535 316.192 264.037L316.638 264.129C322.458 264.909 327.237 267.42 330.826 272.131C332.112 273.818 335.013 279.586 335.64 280.22C336.122 280.707 336.996 280.978 337.631 281.175L338.374 280.965L338.622 280.946C340.078 289.201 342.561 297.284 344.607 305.405C347.019 314.981 349.071 324.725 351.327 334.35L372.075 421.626C374.16 430.227 376.712 438.738 378.694 447.356C379.359 450.33 379.896 453.327 380.305 456.347C380.489 457.712 380.516 459.221 380.817 460.552C370.442 458.993 360.085 457.318 349.747 455.526C338.68 453.515 327.599 451.012 316.356 450.171L316.173 450.214C310.98 450.069 305.401 451.522 300.283 452.407L276.475 456.519C268.511 457.946 260.461 458.819 252.483 460.143C239.827 462.451 227.245 465.759 214.452 467.044C214.01 466.597 214.147 466.81 213.961 466.462C217.335 455.731 219.76 444.734 222.73 433.889L237.945 379.405L269.481 268.727C276.08 271.943 283.761 280.886 291.552 279.784C291.072 279.562 290.788 279.534 290.274 279.596C290.098 279.617 289.922 279.642 289.746 279.665L289.264 279.106L289.342 279.245C292.836 276.598 291.539 275.429 292.771 271.723C293.748 268.782 296.45 270.04 298.638 269.418C299.724 269.109 300.798 268.358 301.795 267.828C302.592 267.405 303.346 267.089 304.249 267.371C303.581 267.707 302.97 267.994 302.422 268.516L302.836 268.679C303.726 268.445 304.526 268.174 305.359 267.78L305.601 267.663Z" fill="#3D7ECD"/>
<path d="M213.961 466.462C217.335 455.731 219.76 444.734 222.73 433.889L237.945 379.405L269.481 268.727C276.08 271.943 283.761 280.886 291.552 279.784C294.318 279.786 297.526 280.103 300.239 279.671C302.32 279.34 293.35 281.165 295.5 281C292.765 282.129 294.815 282.321 291.94 282.461C291.8 282.468 291.66 282.481 291.519 282.489C291.435 282.494 291.35 282.496 291.266 282.5C290.329 287.67 289.473 292.882 288.349 298.015L265.21 399.097L256.243 437.602C255.364 441.302 250.844 457.078 251.4 459.744C251.766 459.902 252.097 460.037 252.483 460.143C239.827 462.451 227.245 465.759 214.452 467.044C214.01 466.597 214.147 466.81 213.961 466.462Z" fill="#3158B7"/>
<path d="M316.638 264.129C322.458 264.909 327.237 267.42 330.826 272.131C332.112 273.818 335.013 279.586 335.64 280.22C336.122 280.707 336.996 280.978 337.631 281.175L338.374 280.965L338.622 280.946C340.078 289.201 342.561 297.284 344.607 305.405C347.019 314.981 349.071 324.725 351.327 334.35L372.075 421.626C374.16 430.227 376.712 438.738 378.694 447.356C379.359 450.33 379.896 453.327 380.305 456.347C380.489 457.712 380.516 459.221 380.817 460.552C370.442 458.993 360.085 457.318 349.747 455.526C338.68 453.515 327.599 451.012 316.356 450.171L316.124 267.318C316.132 266.225 316.016 265.039 316.638 264.129Z" fill="#5BBFFC"/>
<path d="M162.602 542.012C222.681 542.667 282.903 542.133 343 542.146L421.144 542.172C436.934 542.179 452.86 542.406 468.631 542C468.259 556.284 468.631 576.5 466.168 585H164.5C162.602 574 162.11 556.297 162.602 542.012Z" fill="#2E57AB"/>
<path d="M263.193 261.724L235.532 253.517L232.5 252.5L229.5 250.5L402 250L377.5 261.724L364 275.5L339.134 284H289.345L269.731 271.69L263.193 261.724Z" fill="#2950B6"/>
<defs>
<linearGradient id="paint0_linear_4222_6997" x1="313.33" y1="251.065" x2="313.326" y2="279.202" gradientUnits="userSpaceOnUse">
<stop stop-color="#122869"/>
<stop offset="1" stop-color="#2950B6"/>
</linearGradient>
<linearGradient id="paint1_linear_4222_6997" x1="342.025" y1="256.698" x2="339.592" y2="280.614" gradientUnits="userSpaceOnUse">
<stop stop-color="#3052A7"/>
<stop offset="1" stop-color="#2671CE"/>
</linearGradient>
<linearGradient id="paint2_linear_4222_6997" x1="233.914" y1="479.018" x2="235.081" y2="504.885" gradientUnits="userSpaceOnUse">
<stop stop-color="#486DC9"/>
<stop offset="1" stop-color="#599BEA"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 29 KiB

+1
View File
@@ -40,6 +40,7 @@ function App() {
return {
body: {
backgroundImage: `radial-gradient(circle, ${palette.gradient.color1}, ${palette.gradient.color2}, ${palette.gradient.color3}, ${palette.gradient.color4}, ${palette.gradient.color5})`,
color: palette.primary.contrastText,
},
};
}}
+6 -3
View File
@@ -32,9 +32,12 @@ const icons = {
const Alert = ({ variant, title, body, isToast, hasIcon = true, onClick }) => {
const theme = useTheme();
/* TODO
This needs fixing. text bg and border not necessarilly exist. Probably text becomes contrastText. border becomes contrastText. bg becomes dark.
Check possible variants, see implementation in light and dark theme, and adjust */
const { text, bg, border } = theme.palette[variant];
Do we need other variants for alert?
*/
const text = theme.palette.secondary.contrastText;
const bg = theme.palette.secondary.main;
const border = theme.palette.secondary.contrastText;
const icon = icons[variant];
return (
+8 -2
View File
@@ -1,5 +1,6 @@
import PropTypes from "prop-types";
import { Box, Stack } from "@mui/material";
import { Box, Stack, useTheme } from "@mui/material";
// import useUtils from "../../Pages/Uptime/utils";
/**
* A component that renders a pulsating dot with a specified color.
@@ -15,6 +16,11 @@ import { Box, Stack } from "@mui/material";
*/
const PulseDot = ({ color }) => {
const theme = useTheme();
// const { statusToTheme } = useUtils();
/* TODO refactor so it gets status and gets theme color. Then uses theme.palette.[themeColor].lowContrast */
/* const themeColor = statusToTheme[status]; */
return (
<Stack
width="26px"
@@ -44,7 +50,7 @@ const PulseDot = ({ color }) => {
width: "7px",
height: "7px",
borderRadius: "50%",
backgroundColor: "white",
backgroundColor: theme.palette.accent.contrastText,
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
+6 -3
View File
@@ -32,13 +32,16 @@ const Avatar = ({ src, small, sx }) => {
return (
<MuiAvatar
alt={`${user?.firstName} ${user?.lastName}`}
/* TODO What is the /static/images/avatar/2.jpg ?*/
src={src ? src : user?.avatarImage ? image : "/static/images/avatar/2.jpg"}
sx={{
fontSize: small ? "16px" : "22px",
color: "white",
fontWeight: 400,
backgroundColor: theme.palette.primary.main, // Same BG color as checkmate BG in sidebar
color: theme.palette.accent.contrastText,
backgroundColor: theme.palette.accent.main, // Same BG color as checkmate BG in sidebar
display: "inline-flex",
/*
TODO not sure what this is for*/
"&::before": {
content: `""`,
position: "absolute",
@@ -54,7 +57,7 @@ const Avatar = ({ src, small, sx }) => {
}}
>
{user.firstName?.charAt(0)}
{user.lastName?.charAt(0) || ''}
{user.lastName?.charAt(0) || ""}
</MuiAvatar>
);
};
-130
View File
@@ -1,130 +0,0 @@
.MuiTable-root .host {
width: fit-content;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.MuiTable-root .host span {
font-size: 11px;
}
.MuiTable-root .label {
line-height: 1;
border-radius: var(--env-var-radius-2);
padding: 7px;
font-size: var(--env-var-font-size-small-plus);
}
.MuiPaper-root:has(table.MuiTable-root) {
box-shadow: none;
}
.MuiTable-root .MuiTableBody-root .MuiTableRow-root:last-child .MuiTableCell-root {
border: none;
}
.MuiTable-root .MuiTableHead-root .MuiTableCell-root,
.MuiTable-root .MuiTableBody-root .MuiTableCell-root {
font-size: var(--env-var-font-size-medium);
}
.MuiTable-root .MuiTableHead-root .MuiTableCell-root {
padding: var(--env-var-spacing-1);
font-weight: 500;
}
.MuiTable-root .MuiTableHead-root span {
display: inline-block;
height: 17px;
width: 20px;
overflow: hidden;
margin-bottom: -3px;
margin-left: 3px;
}
.MuiTable-root .MuiTableHead-root span svg {
width: 20px;
height: 20px;
}
.MuiTable-root .MuiTableBody-root .MuiTableCell-root {
padding: var(--env-var-spacing-1);
}
.MuiTable-root .MuiTableBody-root .MuiTableRow-root {
height: 50px;
}
.MuiPaper-root + .MuiPagination-root {
border-radius: var(--env-var-radius-1);
padding: var(--env-var-spacing-1-plus) var(--env-var-spacing-2);
}
.MuiPaper-root + .MuiPagination-root ul {
justify-content: center;
}
.MuiPaper-root + .MuiPagination-root button {
font-size: var(--env-var-font-size-medium);
font-weight: 500;
}
.MuiPaper-root + .MuiPagination-root ul li:first-child {
margin-right: auto;
}
.MuiPaper-root + .MuiPagination-root ul li:last-child {
margin-left: auto;
}
.MuiPaper-root + .MuiPagination-root ul li:first-child button {
padding: 0 var(--env-var-spacing-1) 0 var(--env-var-spacing-1-plus);
}
.MuiPaper-root + .MuiPagination-root ul li:last-child button {
padding: 0 var(--env-var-spacing-1-plus) 0 var(--env-var-spacing-1);
}
.MuiPaper-root + .MuiPagination-root ul li:first-child button::after,
.MuiPaper-root + .MuiPagination-root ul li:last-child button::before {
position: relative;
display: inline-block;
}
.MuiPaper-root + .MuiPagination-root ul li:first-child button::after {
content: "Previous";
margin-left: 15px;
}
.MuiPaper-root + .MuiPagination-root ul li:last-child button::before {
content: "Next";
margin-right: 15px;
}
.MuiPaper-root + .MuiPagination-root div.MuiPaginationItem-root {
user-select: none;
}
.MuiTablePagination-root p {
font-weight: 500;
font-size: var(--env-var-font-size-small-plus);
}
.MuiTablePagination-root .MuiTablePagination-select.MuiSelect-select {
text-align: left;
text-align-last: left;
}
.MuiTablePagination-root button {
min-width: 0;
padding: 4px;
margin-left: 5px;
}
.MuiTablePagination-root svg {
width: 22px;
height: 22px;
}
.MuiTablePagination-root .MuiSelect-icon {
width: 16px;
height: 16px;
top: 50%;
right: 8%;
transform: translateY(-50%);
}
.MuiTablePagination-root button.Mui-disabled {
opacity: 0.4;
}
.table-container .MuiTable-root .MuiTableHead-root .MuiTableCell-root {
text-transform: uppercase;
opacity: 0.8;
font-size: var(--env-var-font-size-small-plus);
font-weight: 400;
}
.monitors .MuiTableCell-root:not(:first-of-type):not(:last-of-type),
.monitors .MuiTableCell-root:not(:first-of-type):not(:last-of-type) {
padding-left: var(--env-var-spacing-1);
padding-right: var(--env-var-spacing-1);
}
+31 -6
View File
@@ -1,3 +1,8 @@
/* TODO
Should we delete this?
*/
import PropTypes from "prop-types";
import { useState, useEffect } from "react";
import { useTheme } from "@emotion/react";
@@ -201,7 +206,27 @@ const BasicTable = ({ data, paginated, reversed, table, emptyMessage = "No data"
return (
<>
<TableContainer component={Paper}>
<Table>
<Table
sx={{
"&.MuiTable-root :is(.MuiTableHead-root, .MuiTableBody-root) :is(th, td)": {
paddingLeft: theme.spacing(12),
},
"& th": {
backgroundColor: theme.palette.secondary.main,
color: theme.palette.secondary.contrastText,
/*
TODO all general styling for th should live here
*/
},
"& td": {
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastTextSecondary,
/*
TODO all general styling for td should live here
*/
},
}}
>
<TableHead>
<TableRow>
{data.cols.map((col) => (
@@ -251,7 +276,7 @@ const BasicTable = ({ data, paginated, reversed, table, emptyMessage = "No data"
px={theme.spacing(4)}
sx={{
"& p": {
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
},
}}
>
@@ -298,21 +323,21 @@ const BasicTable = ({ data, paginated, reversed, table, emptyMessage = "No data"
minWidth: theme.spacing(20),
textAlign: "left",
"&.Mui-focused > div": {
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
},
},
},
}}
sx={{
mt: theme.spacing(6),
color: theme.palette.text.secondary,
color: theme.palette.primary.contrastTextSecondary,
"& svg path": {
stroke: theme.palette.text.tertiary,
stroke: theme.palette.primary.contrastTextTertiary,
strokeWidth: 1.3,
},
"& .MuiSelect-select": {
border: 1,
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
},
}}
+2 -2
View File
@@ -1,9 +1,9 @@
.MuiBreadcrumbs-root {
height: 34px;
min-height: 34px;
}
.MuiBreadcrumbs-root svg {
width: 16px;
height: 16px;
min-height: 16px;
}
.MuiBreadcrumbs-root .MuiBreadcrumbs-li a {
font-size: var(--env-var-font-size-medium);
+7 -4
View File
@@ -28,13 +28,16 @@ const Breadcrumbs = ({ list }) => {
px={theme.spacing(2)}
py={theme.spacing(3.5)}
width="fit-content"
backgroundColor={theme.palette.background.fill}
backgroundColor={theme.palette.secondary.main}
borderRadius={theme.shape.borderRadius}
lineHeight="18px"
sx={{
"& .MuiBreadcrumbs-li a": {
transition: "background-color 0.2s ease-in-out, color 0.2s ease-in-out",
},
"& .MuiBreadcrumbs-li:not(:last-of-type):hover a": {
backgroundColor: theme.palette.other.fill,
opacity: 1,
backgroundColor: theme.palette.secondary.contrastText,
color: theme.palette.secondary.main,
},
}}
>
@@ -52,7 +55,7 @@ const Breadcrumbs = ({ list }) => {
opacity: 0.8,
textTransform: "capitalize",
"&, &:hover": {
color: theme.palette.text.tertiary,
color: theme.palette.secondary.contrastText,
},
}}
>
@@ -149,7 +149,7 @@ const CustomAreaChart = ({
/>
<CartesianGrid
stroke={theme.palette.border.light}
stroke={theme.palette.primary.lowContrast}
strokeWidth={1}
strokeOpacity={1}
fill="transparent"
@@ -180,7 +180,7 @@ const CustomAreaChart = ({
})}
{customTooltip ? (
<Tooltip
cursor={{ stroke: theme.palette.border.light }}
cursor={{ stroke: theme.palette.primary.lowContrast }}
content={customTooltip}
wrapperStyle={{ pointerEvents: "none" }}
/>
+19 -14
View File
@@ -39,12 +39,15 @@ const BarChart = ({ checks = [] }) => {
>
{checks.map((check, index) =>
check === "placeholder" ? (
/* TODO what is the purpose of this box? */
// CAIO_REVIEW the purpose of this box is to make sure there are always at least 25 bars
// even if there are less than 25 checks
<Box
key={`${check}-${index}`}
position="relative"
width={theme.spacing(4.5)}
height="100%"
backgroundColor={theme.palette.border.light}
backgroundColor={theme.palette.primary.lowContrast}
sx={{
borderRadius: theme.spacing(1.5),
}}
@@ -67,8 +70,8 @@ const BarChart = ({ checks = [] }) => {
height={theme.spacing(4)}
backgroundColor={
check.status
? theme.palette.success.main
: theme.palette.error.contrastText
? theme.palette.success.lowContrast
: theme.palette.error.lowContrast
}
sx={{ borderRadius: "50%" }}
/>
@@ -116,20 +119,22 @@ const BarChart = ({ checks = [] }) => {
"& .MuiTooltip-tooltip": {
backgroundColor: theme.palette.secondary.main,
border: 1,
borderColor: theme.palette.border.dark,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
boxShadow: theme.shape.boxShadow,
px: theme.spacing(4),
py: theme.spacing(2),
py: theme.spacing(3),
},
"& .MuiTooltip-tooltip p": {
/* TODO Font size should point to theme */
fontSize: 12,
color: theme.palette.text.tertiary,
color: theme.palette.secondary.contrastText,
fontWeight: 500,
},
"& .MuiTooltip-tooltip span": {
/* TODO Font size should point to theme */
fontSize: 11,
color: theme.palette.text.tertiary,
color: theme.palette.secondary.contrastText,
fontWeight: 600,
},
},
@@ -140,16 +145,14 @@ const BarChart = ({ checks = [] }) => {
position="relative"
width="9px"
height="100%"
backgroundColor={
check.status
? theme.palette.success.contrastText
: theme.palette.error.dark
}
backgroundColor={theme.palette.primary.lowContrast} // CAIO_REVIEW
sx={{
borderRadius: theme.spacing(1.5),
/*
TODO this doesn't seem to be used
"&:hover > .MuiBox-root": {
filter: "brightness(0.8)",
},
}, */
}}
>
<Box
@@ -158,7 +161,9 @@ const BarChart = ({ checks = [] }) => {
width="100%"
height={`${animate ? check.responseTime : 0}%`}
backgroundColor={
check.status ? theme.palette.success.main : theme.palette.error.main
check.status
? theme.palette.success.lowContrast
: theme.palette.error.lowContrast
}
sx={{
borderRadius: theme.spacing(1.5),
@@ -54,8 +54,8 @@ const CustomGauge = ({ progress = 0, radius = 70, strokeWidth = 15, threshold =
const fillColor =
progressWithinRange > threshold
? theme.palette.percentage.uptimePoor
: theme.palette.primary.main;
? theme.palette.error.lowContrast // CAIO_REVIEW
: theme.palette.accent.main; // CAIO_REVIEW
return (
<Box
@@ -70,7 +70,7 @@ const CustomGauge = ({ progress = 0, radius = 70, strokeWidth = 15, threshold =
>
<circle
className="radial-chart-base"
stroke={theme.palette.background.fill}
stroke={theme.palette.primary.lowContrast} // CAIO_REVIEW
strokeWidth={strokeWidth}
fill="none"
cx={totalSize / 2} // Center the circle
@@ -1,111 +0,0 @@
import { RadialBarChart, RadialBar, ResponsiveContainer } from "recharts";
import PropTypes from "prop-types";
import { useTheme } from "@emotion/react";
/* TODO delete component */
const MINIMUM_VALUE = 0;
const MAXIMUM_VALUE = 100;
const CHART_MAXIMUM_DATA = {
value: MAXIMUM_VALUE,
fill: "transparent",
};
const PROGRESS_THRESHOLD = 50;
const DEFAULT_WIDTH = 60;
const RADIUS_SIZE = "90%";
const START_ANGLE = 90;
const CHART_RANGE = 360;
const RADIAL_BAR_CHART_PROPS = {
innerRadius: RADIUS_SIZE,
outerRadius: RADIUS_SIZE,
barSize: 6,
startAngle: START_ANGLE,
endAngle: START_ANGLE - CHART_RANGE,
margin: { top: 0, right: 0, bottom: 0, left: 0 },
};
const RADIAL_BAR_PROPS = {
dataKey: "value",
cornerRadius: 8,
};
Gauge.propTypes = {
progressValue: PropTypes.number.isRequired,
width: PropTypes.number,
};
/**
* A circular gauge component that displays a progress value and text.
* The gauge fills based on the progress value and changes color at a 50% threshold.
*
* @component
* @param {Object} props - Component props
* @param {number} props.progressValue - The value to display in the gauge (0-100)
* @param {number} props.width - Width of the gauge container in pixels
* @returns {JSX.Element} A circular gauge chart with progress value and text
*
* @example
* <Gauge
* progressValue={75}
* width={200}
* />
*/
function Gauge({ progressValue, width = DEFAULT_WIDTH }) {
const theme = useTheme();
const myProgressValue = Math.max(MINIMUM_VALUE, Math.min(progressValue, MAXIMUM_VALUE));
const chartColor =
progressValue > PROGRESS_THRESHOLD
? theme.palette.primary.main
: theme.palette.percentage.uptimePoor;
const chartData = [
CHART_MAXIMUM_DATA,
{
value: myProgressValue,
fill: chartColor,
},
];
return (
<ResponsiveContainer
aspect={1}
width={width}
style={{ marginInline: "auto" }}
>
<RadialBarChart
{...RADIAL_BAR_CHART_PROPS}
data={chartData}
>
<RadialBar
{...RADIAL_BAR_PROPS}
fill={
progressValue > PROGRESS_THRESHOLD
? theme.palette.primary.main
: theme.palette.percentage.uptimePoor
}
background={{ fill: theme.palette.background.fill }}
label={{
position: "center",
content: () => (
<text
x="50%"
y="50%"
textAnchor="middle"
dominantBaseline="middle"
style={{
...theme.typography.body2,
fill: theme.typography.body2.color,
}}
>
{`${myProgressValue}%`}
</text>
),
}}
/>
</RadialBarChart>
</ResponsiveContainer>
);
}
export { Gauge };
@@ -13,20 +13,27 @@ import { useTheme } from "@emotion/react";
import { useMemo, useState } from "react";
import { useSelector } from "react-redux";
import { formatDateWithTz } from "../../../Utils/timeUtils";
import {
tooltipDateFormatLookup,
tickDateFormatLookup,
} from "../Utils/chartUtilFunctions";
import "./index.css";
const CustomToolTip = ({ active, payload, label }) => {
const CustomToolTip = ({ active, payload, label, dateRange }) => {
const format = tooltipDateFormatLookup(dateRange);
const uiTimezone = useSelector((state) => state.ui.timezone);
const theme = useTheme();
if (active && payload && payload.length) {
const responseTime = payload[0]?.payload?.originalAvgResponseTime
? payload[0]?.payload?.originalAvgResponseTime
: (payload[0]?.payload?.avgResponseTime ?? 0);
return (
<Box
className="area-tooltip"
sx={{
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
border: 1,
borderColor: theme.palette.border.dark,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
py: theme.spacing(2),
px: theme.spacing(4),
@@ -34,12 +41,12 @@ const CustomToolTip = ({ active, payload, label }) => {
>
<Typography
sx={{
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
fontSize: 12,
fontWeight: 500,
}}
>
{formatDateWithTz(label, "ddd, MMMM D, YYYY, h:mm A", uiTimezone)}
{formatDateWithTz(label, format, uiTimezone)}
</Typography>
<Box mt={theme.spacing(1)}>
<Box
@@ -56,7 +63,7 @@ const CustomToolTip = ({ active, payload, label }) => {
ml={theme.spacing(3)}
sx={{
"& span": {
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
fontSize: 11,
fontWeight: 500,
},
@@ -69,7 +76,7 @@ const CustomToolTip = ({ active, payload, label }) => {
Response Time
</Typography>{" "}
<Typography component="span">
{payload[0].payload.originalResponseTime}
{Math.floor(responseTime)}
<Typography
component="span"
sx={{ opacity: 0.8 }}
@@ -87,23 +94,35 @@ const CustomToolTip = ({ active, payload, label }) => {
return null;
};
const CustomTick = ({ x, y, payload, index }) => {
CustomToolTip.propTypes = {
active: PropTypes.bool,
payload: PropTypes.arrayOf(
PropTypes.shape({
value: PropTypes.number,
payload: PropTypes.shape({
_id: PropTypes.string,
avgResponseTime: PropTypes.number,
originalAvgResponseTime: PropTypes.number,
}),
})
),
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
dateRange: PropTypes.string,
};
const CustomTick = ({ x, y, payload, dateRange }) => {
const format = tickDateFormatLookup(dateRange);
const theme = useTheme();
const uiTimezone = useSelector((state) => state.ui.timezone);
// Render nothing for the first tick
if (index === 0) return null;
return (
<Text
x={x}
y={y + 10}
textAnchor="middle"
fill={theme.palette.text.tertiary}
fill={theme.palette.primary.contrastTextTertiary}
fontSize={11}
fontWeight={400}
>
{formatDateWithTz(payload?.value, "h:mm a", uiTimezone)}
{formatDateWithTz(payload?.value, format, uiTimezone)}
</Text>
);
};
@@ -113,13 +132,13 @@ CustomTick.propTypes = {
y: PropTypes.number,
payload: PropTypes.object,
index: PropTypes.number,
dateRange: PropTypes.string,
};
const MonitorDetailsAreaChart = ({ checks }) => {
const MonitorDetailsAreaChart = ({ checks, dateRange }) => {
const theme = useTheme();
const memoizedChecks = useMemo(() => checks, [checks[0]]);
const [isHovered, setIsHovered] = useState(false);
return (
<ResponsiveContainer
width="100%"
@@ -140,7 +159,7 @@ const MonitorDetailsAreaChart = ({ checks }) => {
onMouseLeave={() => setIsHovered(false)}
>
<CartesianGrid
stroke={theme.palette.border.light}
stroke={theme.palette.primary.lowContrast}
strokeWidth={1}
strokeOpacity={1}
fill="transparent"
@@ -156,38 +175,36 @@ const MonitorDetailsAreaChart = ({ checks }) => {
>
<stop
offset="0%"
stopColor={theme.palette.primary.main}
stopColor={theme.palette.accent.main}
stopOpacity={0.8}
/>
<stop
offset="100%"
stopColor={theme.palette.primary.light}
stopColor={theme.palette.accent.light}
stopOpacity={0}
/>
</linearGradient>
</defs>
<XAxis
stroke={theme.palette.border.dark}
dataKey="createdAt"
tick={<CustomTick />}
minTickGap={0}
stroke={theme.palette.primary.lowContrast}
dataKey="_id"
tick={<CustomTick dateRange={dateRange} />}
axisLine={false}
tickLine={false}
height={20}
interval="equidistantPreserveStart"
/>
<Tooltip
cursor={{ stroke: theme.palette.border.light }}
content={<CustomToolTip />}
cursor={{ stroke: theme.palette.primary.lowContrast }}
content={<CustomToolTip dateRange={dateRange} />}
wrapperStyle={{ pointerEvents: "none" }}
/>
<Area
type="monotone"
dataKey="responseTime"
stroke={theme.palette.primary.main}
dataKey="avgResponseTime"
stroke={theme.palette.accent.main} // CAIO_REVIEW
fill="url(#colorUv)"
strokeWidth={isHovered ? 2.5 : 1.5}
activeDot={{ stroke: theme.palette.background.main, r: 5 }}
activeDot={{ stroke: theme.palette.accent.main, r: 5 }} // CAIO_REVIEW
/>
</AreaChart>
</ResponsiveContainer>
@@ -196,17 +213,7 @@ const MonitorDetailsAreaChart = ({ checks }) => {
MonitorDetailsAreaChart.propTypes = {
checks: PropTypes.array,
dateRange: PropTypes.string,
};
CustomToolTip.propTypes = {
active: PropTypes.bool,
payload: PropTypes.arrayOf(
PropTypes.shape({
payload: PropTypes.shape({
originalResponseTime: PropTypes.number.isRequired,
}).isRequired,
})
),
label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
};
export default MonitorDetailsAreaChart;
@@ -0,0 +1,25 @@
export const tooltipDateFormatLookup = (dateRange) => {
const dateFormatLookup = {
day: "ddd. MMMM D, YYYY, hh:mm A",
week: "ddd. MMMM D, YYYY, hh:mm A",
month: "ddd. MMMM D, YYYY",
};
const format = dateFormatLookup[dateRange];
if (format === undefined) {
return "";
}
return format;
};
export const tickDateFormatLookup = (dateRange) => {
const tickFormatLookup = {
day: "h:mm A",
week: "MM/D, h:mm A",
month: "ddd. M/D",
};
const format = tickFormatLookup[dateRange];
if (format === undefined) {
return "";
}
return format;
};
@@ -4,7 +4,7 @@ import { useTheme } from "@mui/material";
import { Text } from "recharts";
import { formatDateWithTz } from "../../../Utils/timeUtils";
import { Box, Stack, Typography } from "@mui/material";
import { tickDateFormatLookup, tooltipDateFormatLookup } from "./chartUtilFunctions";
/**
* Custom tick component for rendering time with timezone.
*
@@ -15,20 +15,20 @@ import { Box, Stack, Typography } from "@mui/material";
* @param {number} props.index - The index of the tick.
* @returns {JSX.Element} The rendered tick component.
*/
export const TzTick = ({ x, y, payload, index }) => {
export const TzTick = ({ x, y, payload, index, dateRange }) => {
const theme = useTheme();
const uiTimezone = useSelector((state) => state.ui.timezone);
const format = tickDateFormatLookup(dateRange);
return (
<Text
x={x}
y={y + 10}
textAnchor="middle"
fill={theme.palette.text.tertiary}
fill={theme.palette.primary.contrastTextTertiary}
fontSize={11}
fontWeight={400}
>
{formatDateWithTz(payload?.value, "h:mm a", uiTimezone)}
{formatDateWithTz(payload?.value, format, uiTimezone)}
</Text>
);
};
@@ -38,6 +38,7 @@ TzTick.propTypes = {
y: PropTypes.number,
payload: PropTypes.object,
index: PropTypes.number,
dateRange: PropTypes.string,
};
/**
@@ -58,7 +59,7 @@ export const PercentTick = ({ x, y, payload, index }) => {
x={x - 20}
y={y}
textAnchor="middle"
fill={theme.palette.text.tertiary}
fill={theme.palette.primary.contrastTextTertiary}
fontSize={11}
fontWeight={400}
>
@@ -110,18 +111,21 @@ export const InfrastructureTooltip = ({
yIdx = -1,
yLabel,
dotColor,
dateRange,
}) => {
const uiTimezone = useSelector((state) => state.ui.timezone);
const theme = useTheme();
const format = tooltipDateFormatLookup(dateRange);
if (active && payload && payload.length) {
const [hardwareType, metric] = yKey.split(".");
return (
<Box
className="area-tooltip"
sx={{
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
border: 1,
borderColor: theme.palette.border.dark,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
py: theme.spacing(2),
px: theme.spacing(4),
@@ -129,12 +133,12 @@ export const InfrastructureTooltip = ({
>
<Typography
sx={{
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
fontSize: 12,
fontWeight: 500,
}}
>
{formatDateWithTz(label, "ddd, MMMM D, YYYY, h:mm A", uiTimezone)}
{formatDateWithTz(label, format, uiTimezone)}
</Typography>
<Box mt={theme.spacing(1)}>
<Box
@@ -151,7 +155,7 @@ export const InfrastructureTooltip = ({
ml={theme.spacing(3)}
sx={{
"& span": {
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
fontSize: 11,
fontWeight: 500,
},
@@ -163,7 +167,7 @@ export const InfrastructureTooltip = ({
>
{yIdx >= 0
? `${yLabel} ${getFormattedPercentage(payload[0].payload[hardwareType][yIdx][metric])}`
: `${yLabel} ${getFormattedPercentage(payload[0].payload[hardwareType][metric])}`}
: `${yLabel} ${getFormattedPercentage(payload[0].payload[yKey])}`}
</Typography>
</Stack>
</Box>
@@ -186,11 +190,20 @@ InfrastructureTooltip.propTypes = {
yIdx: PropTypes.number,
yLabel: PropTypes.string,
dotColor: PropTypes.string,
dateRange: PropTypes.string,
};
export const TemperatureTooltip = ({ active, payload, label, keys, dotColor }) => {
export const TemperatureTooltip = ({
active,
payload,
label,
keys,
dotColor,
dateRange,
}) => {
const uiTimezone = useSelector((state) => state.ui.timezone);
const theme = useTheme();
const format = tooltipDateFormatLookup(dateRange);
const formatCoreKey = (key) => {
return key.replace(/^core(\d+)$/, "Core $1");
};
@@ -199,9 +212,9 @@ export const TemperatureTooltip = ({ active, payload, label, keys, dotColor }) =
<Box
className="area-tooltip"
sx={{
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
border: 1,
borderColor: theme.palette.border.dark,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
py: theme.spacing(2),
px: theme.spacing(4),
@@ -209,12 +222,12 @@ export const TemperatureTooltip = ({ active, payload, label, keys, dotColor }) =
>
<Typography
sx={{
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
fontSize: 12,
fontWeight: 500,
}}
>
{formatDateWithTz(label, "ddd, MMMM D, YYYY, h:mm A", uiTimezone)}
{formatDateWithTz(label, format, uiTimezone)}
</Typography>
<Stack direction="column">
@@ -228,7 +241,7 @@ export const TemperatureTooltip = ({ active, payload, label, keys, dotColor }) =
ml={theme.spacing(3)}
sx={{
"& span": {
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
fontSize: 11,
fontWeight: 500,
},
@@ -274,4 +287,6 @@ TemperatureTooltip.propTypes = {
PropTypes.string,
PropTypes.number,
]),
dotColor: PropTypes.string,
dateRange: PropTypes.string,
};
+4 -1
View File
@@ -49,7 +49,10 @@ const Check = ({ text, noHighlightText, variant = "info", outlined = false }) =>
<Typography
component="span"
sx={{
color: variant === "info" ? theme.palette.text.tertiary : colors[variant],
color:
variant === "info"
? theme.palette.primary.contrastTextTertiary
: colors[variant],
opacity: 0.8,
}}
>
+5 -5
View File
@@ -5,10 +5,10 @@ const ConfigBox = styled(Stack)(({ theme }) => ({
flexDirection: "row",
justifyContent: "space-between",
gap: theme.spacing(20),
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
border: 1,
borderStyle: "solid",
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.spacing(2),
"& > *": {
paddingTop: theme.spacing(12),
@@ -18,7 +18,7 @@ const ConfigBox = styled(Stack)(({ theme }) => ({
flex: 0.7,
borderRight: 1,
borderRightStyle: "solid",
borderRightColor: theme.palette.border.light,
borderRightColor: theme.palette.primary.lowContrast,
paddingRight: theme.spacing(15),
paddingLeft: theme.spacing(15),
},
@@ -28,10 +28,10 @@ const ConfigBox = styled(Stack)(({ theme }) => ({
paddingLeft: theme.spacing(18),
},
"& h1, & h2": {
color: theme.palette.text.secondary,
color: theme.palette.primary.contrastTextSecondary,
},
"& p": {
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
},
}));
@@ -22,9 +22,9 @@ const GenericDialog = ({ title, description, open, onClose, theme, children }) =
left: "50%",
transform: "translate(-50%, -50%)",
width: 400,
bgcolor: theme.palette.background.main,
bgcolor: theme.palette.primary.main,
border: 1,
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
boxShadow: 24,
p: theme.spacing(15),
@@ -37,7 +37,7 @@ const GenericDialog = ({ title, description, open, onClose, theme, children }) =
id={titleId}
component="h2"
fontSize={16}
color={theme.palette.text.primary}
color={theme.palette.primary.contrastText}
fontWeight={600}
>
{title}
@@ -45,7 +45,7 @@ const GenericDialog = ({ title, description, open, onClose, theme, children }) =
{description && (
<Typography
id={descriptionId}
color={theme.palette.text.tertiary}
color={theme.palette.primary.contrastTextTertiary}
>
{description}
</Typography>
+1 -1
View File
@@ -12,7 +12,7 @@
width: max-content;
}
[class*="fallback__"] button.MuiButtonBase-root {
height: 34px;
min-height: 34px;
}
[class*="fallback__"] .check span.MuiTypography-root,
[class*="fallback__"] button.MuiButtonBase-root {
+3 -3
View File
@@ -40,7 +40,7 @@ const Fallback = ({ title, checks, link = "/", isAdmin, vowelStart = false }) =>
className="background-pattern-svg"
sx={{
"& svg g g:last-of-type path": {
stroke: theme.palette.border.light,
stroke: theme.palette.primary.lowContrast,
},
}}
>
@@ -54,7 +54,7 @@ const Fallback = ({ title, checks, link = "/", isAdmin, vowelStart = false }) =>
<Typography
component="h1"
marginY={theme.spacing(4)}
color={theme.palette.text.tertiary}
color={theme.palette.primary.contrastTextTertiary}
>
{vowelStart ? "An" : "A"} {title} is used to:
</Typography>
@@ -70,7 +70,7 @@ const Fallback = ({ title, checks, link = "/", isAdmin, vowelStart = false }) =>
{isAdmin && (
<Button
variant="contained"
color="primary"
color="accent"
sx={{ alignSelf: "center" }}
onClick={() => navigate(link)}
>
+4 -1
View File
@@ -6,16 +6,18 @@ import PropTypes from "prop-types";
*
* @param {Object} props - The properties passed to the Heading component.
* @param {('h1'|'h2'|'h3')} props.component - The heading level for the component.
* @param {Object} props.style - Custom styles to apply to the heading.
* @param {string} props.children - The content to display inside the heading.
* @returns {JSX.Element} The Typography component with specified heading properties.
*/
function Heading({ component, children }) {
function Heading({ component, style, children }) {
return (
<Typography
component={component}
variant="h2"
fontWeight={600}
style={style}
>
{children}
</Typography>
@@ -24,6 +26,7 @@ function Heading({ component, children }) {
Heading.propTypes = {
component: PropTypes.oneOf(["h1", "h2", "h3"]).isRequired,
style: PropTypes.object,
children: PropTypes.string.isRequired,
};
export { Heading };
@@ -16,7 +16,7 @@ import { BaseLabel } from "../Label";
const DEFAULT_CODE = 9999; // Default code for unknown status
const handleStatusCode = (status) => {
if (status >= 100 && status < 600) {
if (status) {
return status;
}
return DEFAULT_CODE;
@@ -30,32 +30,28 @@ const HttpStatusLabel = ({ status, customStyles }) => {
const theme = useTheme();
const colors = {
400: {
dotColor: theme.palette.warning.main,
bgColor: theme.palette.warning.dark,
borderColor: theme.palette.warning.light,
color: theme.palette.warning.main,
borderColor: theme.palette.warning.lowContrast,
},
500: {
dotColor: theme.palette.error.main,
bgColor: theme.palette.error.dark,
borderColor: theme.palette.error.light,
color: theme.palette.error.main,
borderColor: theme.palette.error.lowContrast,
},
default: {
dotColor: theme.palette.unresolved.main,
bgColor: theme.palette.unresolved.bg,
borderColor: theme.palette.unresolved.light,
color: theme.palette.primary.contrastText,
borderColor: theme.palette.primary.contrastText,
},
};
const statusCode = handleStatusCode(status);
const { borderColor, bgColor, dotColor } =
const { borderColor, color } =
colors[getRoundedStatusCode(statusCode)] || colors.default;
return (
<BaseLabel
label={String(statusCode)}
styles={{
color: dotColor,
backgroundColor: bgColor,
color: color,
borderColor: borderColor,
...customStyles,
}}
+3 -3
View File
@@ -48,9 +48,9 @@ const IconBox = styled(Box)(
position: "relative",
border: 1,
borderStyle: "solid",
borderColor: theme.palette.border.dark,
borderColor: theme.palette.primary.lowContrast,
borderRadius: borderRadius,
backgroundColor: theme.palette.background.accent,
backgroundColor: theme.palette.tertiary.main,
"& svg": {
position: "absolute",
top: "50%",
@@ -59,7 +59,7 @@ const IconBox = styled(Box)(
width: svgWidth,
height: svgHeight,
"& path": {
stroke: theme.palette.text.tertiary,
stroke: theme.palette.primary.contrastTextTertiary,
},
},
})
@@ -90,14 +90,14 @@ const Checkbox = ({
mr: theme.spacing(6),
},
"&:not(:has(.Mui-disabled)):hover": {
backgroundColor: theme.palette.background.accent,
backgroundColor: theme.palette.tertiary.main,
},
"& span.MuiTypography-root": {
fontSize: 13,
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
},
".MuiFormControlLabel-label.Mui-disabled": {
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
opacity: 0.25,
},
}}
+5 -5
View File
@@ -39,7 +39,7 @@ const ImageField = ({ id, src, loading, onChange }) => {
borderRadius: theme.shape.borderRadius,
borderColor: isDragging
? theme.palette.primary.main
: theme.palette.border.light,
: theme.palette.primary.lowContrast,
borderWidth: "2px",
transition: "0.2s",
"&:hover": {
@@ -86,7 +86,7 @@ const ImageField = ({ id, src, loading, onChange }) => {
sx={{
pointerEvents: "none",
borderRadius: theme.shape.borderRadius,
border: `solid ${theme.shape.borderThick}px ${theme.palette.border.light}`,
border: `solid ${theme.shape.borderThick}px ${theme.palette.primary.lowContrast}`,
boxShadow: theme.shape.boxShadow,
}}
>
@@ -94,7 +94,7 @@ const ImageField = ({ id, src, loading, onChange }) => {
</IconButton>
<Typography
component="h2"
color={theme.palette.text.tertiary}
color={theme.palette.primary.contrastTextTertiary}
>
<Typography
component="span"
@@ -108,7 +108,7 @@ const ImageField = ({ id, src, loading, onChange }) => {
</Typography>
<Typography
component="p"
color={theme.palette.text.tertiary}
color={theme.palette.primary.contrastTextTertiary}
sx={{ opacity: 0.6 }}
>
(maximum size: 3MB)
@@ -117,7 +117,7 @@ const ImageField = ({ id, src, loading, onChange }) => {
</Box>
<Typography
component="p"
color={theme.palette.text.tertiary}
color={theme.palette.primary.contrastTextTertiary}
sx={{ opacity: 0.6 }}
>
Supported formats: JPG, PNG
+3 -3
View File
@@ -43,7 +43,7 @@ const Radio = (props) => {
height: 16,
boxShadow: `inset 0 0 0 1px ${theme.palette.secondary.main}`,
"&:not(.Mui-checked)": {
boxShadow: `inset 0 0 0 1px ${theme.palette.text.primary}70`, // Use theme text color for the outline
boxShadow: `inset 0 0 0 1px ${theme.palette.primary.contrastText}70`, // Use theme text color for the outline
},
mt: theme.spacing(0.5),
}}
@@ -56,7 +56,7 @@ const Radio = (props) => {
<Typography
component="h6"
mt={theme.spacing(1)}
color={theme.palette.text.secondary}
color={theme.palette.primary.contrastTextSecondary}
>
{props.desc}
</Typography>
@@ -69,7 +69,7 @@ const Radio = (props) => {
m: theme.spacing(-2.5),
borderRadius: theme.shape.borderRadius,
"&:hover": {
backgroundColor: theme.palette.background.accent,
backgroundColor: theme.palette.tertiary.main,
},
"& .MuiButtonBase-root": {
p: 0,
+23 -9
View File
@@ -27,7 +27,7 @@ const SearchAdornment = () => {
width: 16,
height: 16,
"& path": {
stroke: theme.palette.text.tertiary,
stroke: theme.palette.primary.contrastTextTertiary,
strokeWidth: 1.2,
},
},
@@ -56,7 +56,6 @@ const Search = ({
disabled,
}) => {
const theme = useTheme();
return (
<Autocomplete
multiple={multiple}
@@ -80,7 +79,7 @@ const Search = ({
<Typography
component="h3"
fontSize={"var(--env-var-font-size-medium)"}
color={theme.palette.text.secondary}
color={theme.palette.primary.contrastTextSecondary}
fontWeight={500}
>
{label}
@@ -95,16 +94,24 @@ const Search = ({
}}
sx={{
"& fieldset": {
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
},
"& .MuiOutlinedInput-root:hover:not(:has(input:focus)):not(:has(textarea:focus)) fieldset":
{
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
},
"& .MuiOutlinedInput-root": {
paddingY: 0,
},
"& .MuiAutocomplete-tag": {
// CAIO_REVIEW
color: theme.palette.primary.contrastText,
backgroundColor: theme.palette.primary.lowContrast,
},
"& .MuiChip-deleteIcon": {
color: theme.palette.primary.contrastText, // CAIO_REVIEW
},
}}
/>
{error && (
@@ -132,6 +139,7 @@ const Search = ({
}
return filtered;
}}
getOptionKey={(option) => option.id}
renderOption={(props, option) => {
const { key, ...optionProps } = props;
return (
@@ -142,7 +150,7 @@ const Search = ({
option.noOptions
? {
pointerEvents: "none",
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
}
: {}
}
@@ -155,16 +163,22 @@ const Search = ({
popper: {
keepMounted: true,
sx: {
"& ul": { p: 2 },
"& ul": { p: 2, backgroundColor: theme.palette.primary.main },
"& li.MuiAutocomplete-option": {
color: theme.palette.text.secondary,
color: theme.palette.primary.contrastTextSecondary,
px: 4,
borderRadius: theme.shape.borderRadius,
},
"& .MuiAutocomplete-listbox .MuiAutocomplete-option[aria-selected='true'], & .MuiAutocomplete-listbox .MuiAutocomplete-option[aria-selected='true'].Mui-focused, & .MuiAutocomplete-listbox .MuiAutocomplete-option[aria-selected='true']:hover":
{
backgroundColor: theme.palette.background.fill,
backgroundColor: theme.palette.primary.lowContrast,
color: "red",
},
"& li.MuiAutocomplete-option:hover:not([aria-selected='true'])": {
color: theme.palette.primary.main,
backgroundColor: theme.palette.primary.contrastTextSecondary,
},
"& .MuiAutocomplete-noOptions": {
px: theme.spacing(6),
py: theme.spacing(5),
@@ -1,6 +1,6 @@
.select-wrapper .select-component > .MuiSelect-select {
padding: 0 10px;
height: 34px;
min-height: 34px;
display: flex;
align-items: center;
line-height: 1;
@@ -54,11 +54,11 @@ const Select = ({
const theme = useTheme();
const itemStyles = {
fontSize: "var(--env-var-font-size-medium)",
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
borderRadius: theme.shape.borderRadius,
margin: theme.spacing(2),
};
return (
<Stack
gap={theme.spacing(labelControlSpacing)}
@@ -67,7 +67,7 @@ const Select = ({
{label && (
<Typography
component="h3"
color={theme.palette.text.secondary}
color={theme.palette.primary.contrastTextSecondary}
fontWeight={500}
fontSize={13}
>
@@ -89,13 +89,13 @@ const Select = ({
minWidth: "125px",
"& fieldset": {
borderRadius: theme.shape.borderRadius,
borderColor: theme.palette.border.dark,
borderColor: theme.palette.primary.lowContrast,
},
"&:not(.Mui-focused):hover fieldset": {
borderColor: theme.palette.border.dark,
borderColor: theme.palette.primary.lowContrast,
},
"& svg path": {
fill: theme.palette.other.icon,
fill: theme.palette.primary.contrastTextTertiary,
},
...sx,
}}
@@ -12,15 +12,15 @@ export const HttpAdornment = ({ https }) => {
alignItems="center"
height="100%"
sx={{
borderRight: `solid 1px ${theme.palette.border.dark}`,
backgroundColor: theme.palette.background.accent,
borderRight: `solid 1px ${theme.palette.primary.lowContrast}`,
backgroundColor: theme.palette.tertiary.main,
pl: theme.spacing(6),
}}
>
<Typography
component="h5"
paddingRight={"var(--env-var-spacing-1-minus)"}
color={theme.palette.text.secondary}
color={theme.palette.primary.contrastTextSecondary}
sx={{ lineHeight: 1, opacity: 0.8 }}
>
{https ? "https" : "http"}://
@@ -41,7 +41,7 @@ export const PasswordEndAdornment = ({ fieldType, setFieldType }) => {
aria-label="toggle password visibility"
onClick={() => setFieldType(fieldType === "password" ? "text" : "password")}
sx={{
color: theme.palette.border.dark,
color: theme.palette.primary.lowContrast,
padding: theme.spacing(1),
"&:focus-visible": {
outline: `2px solid ${theme.palette.primary.main}`,
@@ -6,6 +6,19 @@ import PropTypes from "prop-types";
const getSx = (theme, type, maxWidth) => {
const sx = {
maxWidth: maxWidth,
"& .MuiOutlinedInput-root ": {
"&:hover .MuiOutlinedInput-notchedOutline": {
borderColor: theme.palette.primary.contrastText, // Adjust hover border color
},
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
borderColor: theme.palette.accent.main, // Adjust focus border color
},
"&.Mui-disabled .MuiOutlinedInput-notchedOutline": {
borderColor: theme.palette.primary.contrastText, // CAIO_REVIEW
opacity: 0.5,
},
},
"& .MuiFormHelperText-root": {
position: "absolute",
bottom: `-${theme.spacing(24)}`,
@@ -101,7 +114,7 @@ const TextInput = forwardRef(
<Typography
component="h3"
fontSize={"var(--env-var-font-size-medium)"}
color={theme.palette.text.secondary}
color={theme.palette.primary.contrastTextSecondary}
fontWeight={500}
>
{label}
+16 -37
View File
@@ -24,15 +24,15 @@ const BaseLabel = ({ label, styles, children }) => {
// Grab the default borderRadius from the theme to match button style
const { borderRadius } = theme.shape;
// Calculate padding for the label to mimic button. Appears to scale correctly, not 100% sure though.
const padding = theme.spacing(1 * 0.75, 2);
const padding = theme.spacing(3, 5);
return (
<Box
className="label"
sx={{
borderRadius: borderRadius,
border: `1px solid ${theme.palette.text.tertiary}`,
color: theme.palette.text.tertiary,
border: `1px solid ${theme.palette.primary.lowContrast}`,
color: theme.palette.primary.contrastText,
padding: padding,
...styles,
}}
@@ -87,7 +87,7 @@ const ColoredLabel = ({ label, color }) => {
const theme = useTheme();
// If an invalid color is passed, default to the labelGray color
if (typeof color !== "string" || !/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(color)) {
color = theme.palette.border.light;
color = theme.palette.primary.lowContrast;
}
// Calculate lighter shades for border and bg
@@ -122,53 +122,32 @@ ColoredLabel.propTypes = {
* <StatusLabel status="up" text="Active" />
*/
const statusToTheme = {
up: "success",
down: "error",
paused: "warning",
pending: "warning",
"cannot resolve": "error",
};
const StatusLabel = ({ status, text, customStyles }) => {
const theme = useTheme();
const colors = {
up: {
dotColor: theme.palette.success.main,
bgColor: theme.palette.success.contrastText /* dark */,
borderColor: theme.palette.success.main /* light */,
},
down: {
dotColor: theme.palette.error.main,
bgColor: theme.palette.error.dark,
borderColor: theme.palette.error.light,
},
paused: {
dotColor: theme.palette.warning.main,
bgColor: theme.palette.warning.dark,
borderColor: theme.palette.warning.light,
},
pending: {
dotColor: theme.palette.text.secondary,
bgColor: theme.palette.background.main,
borderColor: theme.palette.border.dark,
},
"cannot resolve": {
dotColor: theme.palette.unresolved.main,
bgColor: theme.palette.unresolved.bg,
borderColor: theme.palette.unresolved.light,
},
};
// Look up the color for the status
const { borderColor, bgColor, dotColor } = colors[status];
const themeColor = statusToTheme[status];
return (
<BaseLabel
label={text}
styles={{
color: dotColor,
backgroundColor: bgColor,
borderColor: borderColor,
color: theme.palette[themeColor].main,
borderColor: theme.palette[themeColor].lowContrast,
...customStyles,
}}
>
<Box
width={7}
height={7}
bgcolor={dotColor}
bgcolor={theme.palette[themeColor].lowContrast}
borderRadius="50%"
marginRight="5px"
/>
+5 -5
View File
@@ -16,24 +16,24 @@ const Link = ({ level, label, url }) => {
const levelConfig = {
primary: {},
secondary: {
color: theme.palette.text.secondary,
color: theme.palette.primary.contrastTextSecondary,
sx: {
":hover": {
color: theme.palette.text.secondary,
color: theme.palette.primary.contrastTextSecondary,
},
},
},
tertiary: {
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
sx: {
textDecoration: "underline",
textDecorationStyle: "dashed",
textDecorationColor: theme.palette.primary.main,
textUnderlineOffset: "1px",
":hover": {
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
textDecorationColor: theme.palette.primary.main,
backgroundColor: theme.palette.background.fill,
backgroundColor: theme.palette.primary.lowContrast,
},
},
},
+8 -9
View File
@@ -1,4 +1,3 @@
import React from "react";
import { useTheme } from "@emotion/react";
import PropTypes from "prop-types";
import { Box, IconButton, LinearProgress, Stack, Typography } from "@mui/material";
@@ -30,11 +29,11 @@ const ProgressUpload = ({ icon, label, size, progress = 0, onClick, error }) =>
height: "fit-content",
borderRadius: theme.shape.borderRadius,
border: 1,
borderColor: theme.palette.border.light,
backgroundColor: theme.palette.background.fill,
borderColor: theme.palette.primary.lowContrast,
backgroundColor: theme.palette.primary.lowContrast,
"&:has(.input-error)": {
borderColor: theme.palette.error.main,
backgroundColor: theme.palette.error.dark,
backgroundColor: theme.palette.error.lowContrast,
py: theme.spacing(4),
px: theme.spacing(8),
"& > .MuiStack-root > svg": {
@@ -60,9 +59,9 @@ const ProgressUpload = ({ icon, label, size, progress = 0, onClick, error }) =>
height: 30,
minWidth: 30,
border: 1,
borderColor: theme.palette.border.dark,
borderColor: theme.palette.primary.lowContrast,
borderRadius: 2,
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
"& svg": {
position: "absolute",
top: "50%",
@@ -71,7 +70,7 @@ const ProgressUpload = ({ icon, label, size, progress = 0, onClick, error }) =>
width: 23,
height: 23,
"& path": {
fill: theme.palette.other.icon,
fill: theme.palette.primary.contrastTextTertiary,
},
},
}}
@@ -90,7 +89,7 @@ const ProgressUpload = ({ icon, label, size, progress = 0, onClick, error }) =>
{error}
</Typography>
) : (
<Box color={theme.palette.text.tertiary}>
<Box color={theme.palette.primary.contrastTextTertiary}>
<Typography
component="h2"
mb={theme.spacing(1.5)}
@@ -148,7 +147,7 @@ const ProgressUpload = ({ icon, label, size, progress = 0, onClick, error }) =>
height: "10px",
borderRadius: theme.shape.borderRadius,
maxWidth: "500px",
backgroundColor: theme.palette.border.light,
backgroundColor: theme.palette.primary.lowContrast,
}}
/>
</Box>
@@ -7,9 +7,9 @@ import PropTypes from "prop-types";
const CustomStepIcon = (props) => {
const { completed, active } = props;
return completed ? (
<CheckCircle color="primary" />
<CheckCircle color="accent" />
) : (
<RadioButtonCheckedIcon color={active ? "primary" : "disabled"} />
<RadioButtonCheckedIcon color={active ? "accent" : "disabled"} />
);
};
+1
View File
@@ -1,3 +1,4 @@
/* TODO */
aside .MuiList-root svg {
width: 20px;
height: 20px;
+110 -59
View File
@@ -98,7 +98,7 @@ const PATH_MAP = {
pagespeed: "Dashboard",
infrastructure: "Dashboard",
account: "Account",
settings: "Other",
settings: "Settings",
};
/**
@@ -156,35 +156,105 @@ function Sidebar() {
}
}, [location]);
/* TODO refactor this, there are a some ternaries and comments in the return */
const iconColor = theme.palette.primary.contrastTextTertiary;
/* TODO refactor this, there are a some ternaries and comments in the return */
return (
<Stack
component="aside"
className={collapsed ? "collapsed" : "expanded"}
/* TODO general padding should be here */
py={theme.spacing(6)}
gap={theme.spacing(6)}
/* TODO set all style in this sx if possible (when general)
This is the top lever for styles
*/
sx={{
border: 1,
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
backgroundColor: theme.palette.background.main,
"& .selected-path, & .MuiListItemButton-root:hover": {
backgroundColor: theme.palette.background.accent,
"& :is(p, span, .MuiListSubheader-root)": {
/*
Text color for unselected menu items and menu headings
Secondary contrast text against main background
*/
color: theme.palette.primary.contrastTextSecondary,
},
"& .MuiList-root svg path": {
stroke: theme.palette.text.tertiary,
/* Menu Icons */
stroke: iconColor,
},
"& p, & span, & .MuiListSubheader-root": {
color: theme.palette.text.secondary,
"& .selected-path": {
/* Selected menu item */
backgroundColor: theme.palette.secondary.main,
"&:hover": {
backgroundColor: theme.palette.secondary.main,
},
"& .MuiListItemIcon-root svg path": {
/* Selected menu item icon */
stroke: theme.palette.secondary.contrastText,
},
"& .MuiListItemText-root :is(p, span)": {
/* Selected menu item text */
color: theme.palette.secondary.contrastText,
},
},
"& .MuiListItemButton-root:not(.selected-path)": {
transition: "background-color .3s",
" &:hover": {
/* Hovered menu item bg color */
backgroundColor: theme.palette.tertiary.main,
"& :is(p, span)": {
/* Hovered menu item text color */
color: theme.palette.tertiary.contrastText,
},
},
},
}}
>
<IconButton
sx={{
position: "absolute",
/* TODO 60 is a magic number. if logo chnges size this might break */
top: 60,
right: 0,
transform: `translate(50%, 0)`,
backgroundColor: theme.palette.tertiary.main,
border: 1,
borderColor: theme.palette.primary.lowContrast,
p: theme.spacing(2.5),
"& svg": {
width: theme.spacing(8),
height: theme.spacing(8),
"& path": {
/* TODO this should be set at the top level if possible */
stroke: theme.palette.primary.contrastTextSecondary,
},
},
"&:focus": { outline: "none" },
"&:hover": {
backgroundColor: theme.palette.primary.lowContrast,
borderColor: theme.palette.primary.lowContrast,
},
}}
onClick={() => {
setOpen((prev) =>
Object.fromEntries(Object.keys(prev).map((key) => [key, false]))
);
dispatch(toggleSidebar());
}}
>
{collapsed ? <ArrowRight /> : <ArrowLeft />}
</IconButton>
{/* TODO Alignment done using padding. Use single source of truth to that*/}
<Stack
pt={theme.spacing(6)}
pb={theme.spacing(12)}
pl={theme.spacing(8)}
>
{/* TODO Abstract logo into component */}
{/* TODO Turn logo into a link */}
<Stack
direction="row"
alignItems="center"
@@ -199,10 +269,11 @@ function Sidebar() {
minHeight={theme.spacing(16)}
pl="1px"
fontSize={18}
color="white"
color={theme.palette.accent.contrastText}
sx={{
position: "relative",
backgroundColor: theme.palette.primary.main,
backgroundColor: theme.palette.accent.main,
color: theme.palette.accent.contrastText,
borderRadius: theme.shape.borderRadius,
userSelect: "none",
}}
@@ -217,40 +288,7 @@ function Sidebar() {
Checkmate
</Typography>
</Stack>
<IconButton
sx={{
position: "absolute",
top: 60,
right: 0,
transform: `translate(50%, 0)`,
backgroundColor: theme.palette.background.fill,
border: 1,
borderColor: theme.palette.border.light,
p: theme.spacing(2.5),
"& svg": {
width: theme.spacing(8),
height: theme.spacing(8),
"& path": {
stroke: theme.palette.text.secondary,
},
},
"&:focus": { outline: "none" },
"&:hover": {
backgroundColor: theme.palette.border.light,
borderColor: theme.palette.border.light,
},
}}
onClick={() => {
setOpen((prev) =>
Object.fromEntries(Object.keys(prev).map((key) => [key, false]))
);
dispatch(toggleSidebar());
}}
>
{collapsed ? <ArrowRight /> : <ArrowLeft />}
</IconButton>
</Stack>
{/* menu */}
<List
component="nav"
aria-labelledby="nested-menu-subheader"
@@ -260,7 +298,8 @@ function Sidebar() {
component="div"
id="nested-menu-subheader"
sx={{
pt: theme.spacing(4),
py: theme.spacing(4),
/* TODO px should be centralized in container */
px: collapsed ? theme.spacing(2) : theme.spacing(4),
backgroundColor: "transparent",
}}
@@ -271,11 +310,12 @@ function Sidebar() {
sx={{
px: theme.spacing(6),
height: "100%",
overflow: "hidden",
/* overflow: "hidden", */
}}
>
{menu.map((item) =>
item.path ? (
/* If item has a path */
<Tooltip
key={item.path}
placement="right"
@@ -298,10 +338,12 @@ function Sidebar() {
className={location.pathname.includes(item.path) ? "selected-path" : ""}
onClick={() => navigate(`/${item.path}`)}
sx={{
height: "37px",
/*
TODO we do not need this height
minHeight: "37px", */
p: theme.spacing(5),
gap: theme.spacing(4),
borderRadius: theme.shape.borderRadius,
px: theme.spacing(4),
}}
>
<ListItemIcon sx={{ minWidth: 0 }}>{item.icon}</ListItemIcon>
@@ -309,7 +351,7 @@ function Sidebar() {
</ListItemButton>
</Tooltip>
) : collapsed ? (
/* TODO Do we ever get here? */
/* TODO Do we ever get here? If item does not have a path and collapsed state is true */
<React.Fragment key={item.name}>
<Tooltip
placement="right"
@@ -365,8 +407,9 @@ function Sidebar() {
MenuListProps={{ sx: { px: 1, py: 2 } }}
sx={{
ml: theme.spacing(8),
/* TODO what is this selection? */
"& .selected-path": {
backgroundColor: theme.palette.background.accent,
backgroundColor: theme.palette.tertiary.main,
},
}}
>
@@ -397,9 +440,10 @@ function Sidebar() {
sx={{
gap: theme.spacing(4),
opacity: 0.9,
/* TODO this has no effect? */
"& svg": {
"& path": {
stroke: theme.palette.other.icon,
stroke: theme.palette.primary.contrastTextTertiary,
strokeWidth: 1.1,
},
},
@@ -413,6 +457,7 @@ function Sidebar() {
</Menu>
</React.Fragment>
) : (
/* TODO Do we ever get here? If item does not have a path and collapsed state is false */
<React.Fragment key={item.name}>
<ListItemButton
onClick={() =>
@@ -474,7 +519,7 @@ function Sidebar() {
left: "-7px",
height: "100%",
borderLeft: 1,
borderLeftColor: theme.palette.other.line,
borderLeftColor: theme.palette.primary.lowContrast,
},
"&:last-child::before": {
height: "50%",
@@ -487,10 +532,11 @@ function Sidebar() {
height: "3px",
width: "3px",
borderRadius: "50%",
backgroundColor: theme.palette.other.line,
backgroundColor: theme.palette.primary.lowContrast,
},
"&.selected-path::after": {
backgroundColor: theme.palette.text.tertiary,
/* TODO what is this selector doing? */
backgroundColor: theme.palette.primary.contrastTextTertiary,
transform: "scale(1.2)",
},
}}
@@ -562,7 +608,7 @@ function Sidebar() {
marginLeft={"auto"}
columnGap={theme.spacing(2)}
>
<ThemeSwitch />
<ThemeSwitch color={iconColor} />
<Tooltip
title="Controls"
disableInteractive
@@ -572,12 +618,16 @@ function Sidebar() {
ml: "auto",
mr: "-8px",
"&:focus": { outline: "none" },
alignSelf: "center",
padding: "10px",
"& svg": {
width: "20px",
height: "20px",
width: "22px",
height: "22px",
},
"& svg path": {
stroke: theme.palette.other.icon,
/* Vertical three dots */
stroke: iconColor,
},
}}
onClick={(event) => openPopup(event, "logout")}
@@ -635,6 +685,7 @@ function Sidebar() {
</Box>
</MenuItem>
)}
{/* TODO Do we need two dividers? */}
{collapsed && <Divider />}
<Divider />
<MenuItem
@@ -644,7 +695,7 @@ function Sidebar() {
borderRadius: theme.shape.borderRadius,
pl: theme.spacing(4),
"& svg path": {
stroke: theme.palette.other.icon,
stroke: iconColor,
},
}}
>
+49 -11
View File
@@ -1,6 +1,7 @@
import { Box, Typography } from "@mui/material";
import { useTheme } from "@mui/material/styles";
import PropTypes from "prop-types";
import useUtils from "../../Pages/Uptime/utils";
/**
* StatBox Component
@@ -12,6 +13,8 @@ import PropTypes from "prop-types";
* @param {Object} props - The component props
* @param {string} props.heading - The primary heading/title of the statistic
* @param {string|React.ReactNode} props.subHeading - The value or description of the statistic
* @param {boolean} [props.gradient=false] - Determines if the box should have a gradient background
* @param {string} [props.status] - The status of the statistic
* @param {Object} [props.sx] - Additional custom styling to be applied to the box
*
* @example
@@ -26,35 +29,68 @@ import PropTypes from "prop-types";
* @returns {React.ReactElement} A styled box containing the statistic
*/
const StatBox = ({ heading, subHeading, sx }) => {
const StatBox = ({ heading, subHeading, gradient = false, status = "", sx }) => {
const theme = useTheme();
const { statusToTheme } = useUtils();
const themeColor = statusToTheme[status];
const statusBoxStyles = gradient
? {
background: `linear-gradient(to bottom right, ${theme.palette[themeColor].main} 30%, ${theme.palette[themeColor].lowContrast} 70%)`,
borderColor: theme.palette[themeColor].lowContrast,
}
: {
background: `linear-gradient(340deg, ${theme.palette.tertiary.main} 20%, ${theme.palette.primary.main} 45%)`,
borderColor: theme.palette.primary.lowContrast,
};
const headingStyles = gradient
? {
color: theme.palette[themeColor].contrastText,
}
: {
color: theme.palette.primary.contrastTextSecondary,
};
const spanFixedStyles = { marginLeft: theme.spacing(2), fontSize: 15 };
const detailTextStyles = gradient
? {
color: theme.palette[themeColor].contrastText,
"& span": {
color: theme.palette[themeColor].contrastText,
...spanFixedStyles,
},
}
: {
color: theme.palette.primary.contrastText,
"& span": {
color: theme.palette.primary.contrastTextTertiary,
...spanFixedStyles,
},
};
return (
<Box
sx={{
padding: `${theme.spacing(4)} ${theme.spacing(8)}`,
/* TODO why are we using width and min width here? */
minWidth: 200,
width: 225,
border: 1,
borderStyle: "solid",
borderColor: theme.palette.border.light,
borderRadius: 4,
backgroundColor: theme.palette.background.main,
background: `linear-gradient(340deg, ${theme.palette.background.accent} 20%, ${theme.palette.background.main} 45%)`,
...statusBoxStyles,
"& h2": {
/* TODO font size should come from theme */
fontSize: 13,
fontWeight: 500,
color: theme.palette.text.secondary,
textTransform: "uppercase",
...headingStyles,
},
"& p": {
fontSize: 18,
color: theme.palette.text.primary,
marginTop: theme.spacing(2),
"& span": {
color: theme.palette.text.tertiary,
marginLeft: theme.spacing(2),
fontSize: 15,
},
...detailTextStyles,
},
...sx,
}}
@@ -68,6 +104,8 @@ const StatBox = ({ heading, subHeading, sx }) => {
StatBox.propTypes = {
heading: PropTypes.string.isRequired,
subHeading: PropTypes.node.isRequired,
gradient: PropTypes.bool,
status: PropTypes.string,
sx: PropTypes.object,
};
@@ -28,8 +28,7 @@ const PasswordPanel = () => {
const theme = useTheme();
const dispatch = useDispatch();
const SPACING_GAP = theme.spacing(12);
const SPACING_GAP = theme.spacing(12);
//redux state
const { authToken, isLoading } = useSelector((state) => state.auth);
@@ -116,7 +115,7 @@ const PasswordPanel = () => {
value="password"
sx={{
"& h1, & input": {
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
},
}}
>
@@ -126,8 +125,7 @@ const PasswordPanel = () => {
noValidate
spellCheck="false"
gap={theme.spacing(26)}
maxWidth={"80ch"}
marginInline={"auto"}
maxWidth={"80ch"} // Keep maxWidth
>
<TextInput
type="text"
@@ -142,7 +140,7 @@ const PasswordPanel = () => {
direction="row"
justifyContent={"flex-start"}
alignItems={"center"}
gap={SPACING_GAP}
gap={SPACING_GAP}
flexWrap={"wrap"}
>
<Typography
@@ -166,8 +164,8 @@ const PasswordPanel = () => {
</Stack>
<Stack
direction="row"
alignItems={"center"}
gap={SPACING_GAP}
alignItems={"flex-start"}
gap={SPACING_GAP}
flexWrap={"wrap"}
>
<Typography
@@ -192,8 +190,8 @@ const PasswordPanel = () => {
</Stack>
<Stack
direction="row"
alignItems={"center"}
gap={SPACING_GAP}
alignItems={"flex-start"}
gap={SPACING_GAP}
flexWrap={"wrap"}
>
<Typography
@@ -230,7 +228,7 @@ const PasswordPanel = () => {
>
<LoadingButton
variant="contained"
color="primary"
color="accent"
type="submit"
loading={isLoading}
loadingIndicator="Saving..."
@@ -29,7 +29,7 @@ import Dialog from "../../Dialog";
const ProfilePanel = () => {
const theme = useTheme();
const dispatch = useDispatch();
const SPACING_GAP = theme.spacing(12);
//redux state
@@ -216,7 +216,7 @@ const ProfilePanel = () => {
value="profile"
sx={{
"& h1, & p, & input": {
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
},
}}
>
@@ -225,9 +225,13 @@ const ProfilePanel = () => {
className="edit-profile-form"
noValidate
spellCheck="false"
gap={SPACING_GAP}
gap={SPACING_GAP}
>
<Stack direction="row" gap={SPACING_GAP}>
<Stack
direction="row"
gap={SPACING_GAP}
>
{/* This 0.9 is a bit magic numbering, refactor */}
<Box flex={0.9}>
<Typography component="h1">First name</Typography>
</Box>
@@ -242,7 +246,10 @@ const ProfilePanel = () => {
flex={1}
/>
</Stack>
<Stack direction="row" gap={SPACING_GAP}>
<Stack
direction="row"
gap={SPACING_GAP}
>
<Box flex={0.9}>
<Typography component="h1">Last name</Typography>
</Box>
@@ -257,7 +264,10 @@ const ProfilePanel = () => {
flex={1}
/>
</Stack>
<Stack direction="row" gap={SPACING_GAP}>
<Stack
direction="row"
gap={SPACING_GAP}
>
<Stack flex={0.9}>
<Typography component="h1">Email</Typography>
<Typography
@@ -277,7 +287,10 @@ const ProfilePanel = () => {
flex={1}
/>
</Stack>
<Stack direction="row" gap={SPACING_GAP}>
<Stack
direction="row"
gap={SPACING_GAP}
>
<Stack flex={0.9}>
<Typography component="h1">Your photo</Typography>
<Typography
@@ -291,6 +304,7 @@ const ProfilePanel = () => {
direction="row"
alignItems="center"
flex={1}
gap={"8px"}
>
<Avatar
src={
@@ -300,18 +314,18 @@ const ProfilePanel = () => {
? localData.file
: ""
}
sx={{ mr: "8px" }}
sx={{ marginRight: "8px" }}
/>
<Button
variant="text"
color="info"
variant="contained" // CAIO_REIVEW
color="error"
onClick={handleDeletePicture}
>
Delete
</Button>
<Button
variant="text"
color="primary"
variant="contained" // CAIO_REVIEW
color="accent"
onClick={openPictureModal}
>
Update
@@ -332,7 +346,7 @@ const ProfilePanel = () => {
<Box width="fit-content">
<LoadingButton
variant="contained"
color="primary"
color="accent"
onClick={handleSaveProfile}
loading={isLoading}
loadingIndicator="Saving..."
@@ -348,7 +362,7 @@ const ProfilePanel = () => {
aria-hidden="true"
sx={{
marginY: theme.spacing(20),
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
}}
/>
{!user.role.includes("demo") && (
@@ -438,7 +452,7 @@ const ProfilePanel = () => {
</Button>
<Button
variant="contained"
color="primary"
color="accent"
onClick={handleUpdatePicture}
disabled={
(Object.keys(errors).length !== 0 && errors?.picture) ||
@@ -7,11 +7,10 @@ import { credentials } from "../../../Validation/validation";
import { networkService } from "../../../main";
import { createToast } from "../../../Utils/toastUtils";
import { useSelector } from "react-redux";
import BasicTable from "../../BasicTable";
import Select from "../../Inputs/Select";
import LoadingButton from "@mui/lab/LoadingButton";
import { GenericDialog } from "../../Dialog/genericDialog";
import DataTable from "../../Table/";
/**
* TeamPanel component manages the organization and team members,
* providing functionalities like renaming the organization, managing team members,
@@ -21,34 +20,47 @@ import { GenericDialog } from "../../Dialog/genericDialog";
*/
const TeamPanel = () => {
const roleMap = {
superadmin: "Super admin",
admin: "Admin",
user: "Team member",
demo: "Demo User",
};
const theme = useTheme();
const SPACING_GAP = theme.spacing(12);
const { authToken, user } = useSelector((state) => state.auth);
//TODO
// const [orgStates, setOrgStates] = useState({
// name: "Bluewave Labs",
// isEdit: false,
// });
const { authToken } = useSelector((state) => state.auth);
const [toInvite, setToInvite] = useState({
email: "",
role: ["0"],
});
const [tableData, setTableData] = useState({});
const [data, setData] = useState([]);
const [members, setMembers] = useState([]);
const [filter, setFilter] = useState("all");
const [isDisabled, setIsDisabled] = useState(true);
const [errors, setErrors] = useState({});
const [isSendingInvite, setIsSendingInvite] = useState(false);
const headers = [
{
id: "name",
content: "Name",
render: (row) => {
return (
<Stack>
<Typography color={theme.palette.primary.contrastTextSecondary}>
{row.firstName + " " + row.lastName}
</Typography>
<Typography>
Created {new Date(row.createdAt).toLocaleDateString()}
</Typography>
</Stack>
);
},
},
{ id: "email", content: "Email", render: (row) => row.email },
{
id: "role",
content: "Role",
render: (row) => row.role,
},
];
useEffect(() => {
const fetchTeam = async () => {
try {
@@ -67,6 +79,12 @@ const TeamPanel = () => {
}, [authToken]);
useEffect(() => {
const ROLE_MAP = {
superadmin: "Super admin",
admin: "Admin",
user: "Team member",
demo: "Demo User",
};
let team = members;
if (filter !== "all")
team = members.filter((member) => {
@@ -76,42 +94,14 @@ const TeamPanel = () => {
return member.role.includes(filter);
});
const data = {
cols: [
{ id: 1, name: "NAME" },
{ id: 2, name: "EMAIL" },
{ id: 3, name: "ROLE" },
],
rows: team?.map((member, idx) => {
const roles = member.role.map((role) => roleMap[role]).join(",");
return {
id: member._id,
data: [
{
id: idx,
data: (
<Stack>
<Typography color={theme.palette.text.secondary}>
{member.firstName + " " + member.lastName}
</Typography>
<Typography>
Created {new Date(member.createdAt).toLocaleDateString()}
</Typography>
</Stack>
),
},
{ id: idx + 1, data: member.email },
{
id: idx + 2,
data: roles,
},
],
};
}),
};
team = team.map((member) => ({
...member,
id: member._id,
role: member.role.map((role) => ROLE_MAP[role]).join(","),
}));
setData(team);
}, [filter, members]);
setTableData(data);
}, [filter, members, roleMap, theme]);
useEffect(() => {
setIsDisabled(Object.keys(errors).length !== 0 || toInvite.email === "");
}, [errors, toInvite.email]);
@@ -190,11 +180,11 @@ const TeamPanel = () => {
value="team"
sx={{
"& h1": {
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
},
"& .MuiTable-root .MuiTableBody-root .MuiTableCell-root, & .MuiTable-root p + p":
{
color: theme.palette.text.accent,
color: theme.palette.primary.contrastTextSecondary,
},
}}
>
@@ -242,18 +232,17 @@ const TeamPanel = () => {
<LoadingButton
loading={isSendingInvite}
variant="contained"
color="primary"
color="accent"
onClick={() => setIsOpen(true)}
>
Invite a team member
</LoadingButton>
</Stack>
<BasicTable
data={tableData}
paginated={false}
reversed={true}
table={"team"}
emptyMessage={"There are no team members with this role"}
<DataTable
headers={headers}
data={data}
config={{ emptyView: "There are no team members with this role" }}
/>
</Stack>
@@ -300,15 +289,15 @@ const TeamPanel = () => {
>
<LoadingButton
loading={isSendingInvite}
variant="text"
color="info"
variant="contained" // CAIO_REVIEW
color="error"
onClick={closeInviteModal}
>
Cancel
</LoadingButton>
<LoadingButton
variant="contained"
color="primary"
color="accent"
onClick={handleInviteMember}
loading={isSendingInvite}
disabled={isDisabled}
@@ -1,9 +1,9 @@
import PropTypes from "prop-types";
import { Box, Button } from "@mui/material";
import LeftArrowDouble from "../../../../../assets/icons/left-arrow-double.svg?react";
import RightArrowDouble from "../../../../../assets/icons/right-arrow-double.svg?react";
import LeftArrow from "../../../../../assets/icons/left-arrow.svg?react";
import RightArrow from "../../../../../assets/icons/right-arrow.svg?react";
import LeftArrowDouble from "../../../../assets/icons/left-arrow-double.svg?react";
import RightArrowDouble from "../../../../assets/icons/right-arrow-double.svg?react";
import LeftArrow from "../../../../assets/icons/left-arrow.svg?react";
import RightArrow from "../../../../assets/icons/right-arrow.svg?react";
TablePaginationActions.propTypes = {
count: PropTypes.number.isRequired,
@@ -2,14 +2,14 @@ import PropTypes from "prop-types";
import { useTheme } from "@emotion/react";
import { Stack, TablePagination, Typography } from "@mui/material";
import { TablePaginationActions } from "./Actions";
import SelectorVertical from "../../../../assets/icons/selector-vertical.svg?react";
import SelectorVertical from "../../../assets/icons/selector-vertical.svg?react";
Pagination.propTypes = {
monitorCount: PropTypes.number.isRequired, // Total number of items for pagination.
itemCount: PropTypes.number.isRequired, // Total number of items for pagination.
page: PropTypes.number.isRequired, // Current page index.
rowsPerPage: PropTypes.number.isRequired, // Number of rows displayed per page.
handleChangePage: PropTypes.func.isRequired, // Function to handle page changes.
handleChangeRowsPerPage: PropTypes.func.isRequired, // Function to handle changes in rows per page.
handleChangeRowsPerPage: PropTypes.func, // Function to handle changes in rows per page.
};
const ROWS_PER_PAGE_OPTIONS = [5, 10, 15, 25];
@@ -18,6 +18,7 @@ const ROWS_PER_PAGE_OPTIONS = [5, 10, 15, 25];
* Pagination component for table navigation with customized styling and behavior.
*
* @param {object} props - Component properties.
* @param {string} props.paginationLabel - Label for the pagination.
* @param {number} props.monitorCount - Total number of monitors to paginate.
* @param {number} props.page - Current page index (0-based).
* @param {number} props.rowsPerPage - Number of rows to display per page.
@@ -26,7 +27,8 @@ const ROWS_PER_PAGE_OPTIONS = [5, 10, 15, 25];
* @returns {JSX.Element} The Pagination component.
*/
function Pagination({
monitorCount,
paginationLabel,
itemCount,
page,
rowsPerPage,
handleChangePage,
@@ -35,7 +37,7 @@ function Pagination({
const theme = useTheme();
const start = page * rowsPerPage + 1;
const end = Math.min(page * rowsPerPage + rowsPerPage, monitorCount);
const end = Math.min(page * rowsPerPage + rowsPerPage, itemCount);
const range = `${start} - ${end}`;
return (
@@ -51,11 +53,11 @@ function Pagination({
variant="body2"
sx={{ opacity: 0.7 }}
>
Showing {range} of {monitorCount} monitor(s)
Showing {range} of {itemCount} {paginationLabel}
</Typography>
<TablePagination
component="div"
count={monitorCount}
count={itemCount}
page={page}
onPageChange={handleChangePage}
rowsPerPage={rowsPerPage}
@@ -92,20 +94,27 @@ function Pagination({
minWidth: theme.spacing(20),
textAlign: "left",
"&.Mui-focused > div": {
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
},
"& .MuiSelect-icon": {
// Add this style override
position: "absolute",
right: 0,
top: "50%",
transform: "translateY(-50%)",
},
},
},
}}
sx={{
color: theme.palette.text.secondary,
color: theme.palette.primary.contrastTextSecondary,
"& svg path": {
stroke: theme.palette.text.tertiary,
stroke: theme.palette.primary.contrastTextTertiary,
strokeWidth: 1.3,
},
"& .MuiSelect-select": {
border: 1,
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
},
}}
@@ -114,4 +123,4 @@ function Pagination({
);
}
export { Pagination };
export default Pagination;
+128
View File
@@ -0,0 +1,128 @@
import {
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
} from "@mui/material";
import PropTypes from "prop-types";
import { useTheme } from "@emotion/react";
/**
* @typedef {Object} Header
* @property {number|string} id - The unique identifier for the header.
* @property {React.ReactNode} content - The content to display in the header cell.
* @property {Function} render - A function to render the cell content for a given row.
*/
/**
* @typedef {Object} Config
* @property {Function} onRowClick - A function to be called when a row is clicked, receiving the row data as an argument.
* @property {Object} rowSX - Style object for the table row.
*/
/**
* DataTable component renders a table with headers and data.
*
* @param {Object} props - The component props.
* @param {Header[]} props.headers - An array of header objects, each containing an `id`, `content`, and `render` function.
* @param {Array} props.data - An array of data objects, each representing a row.
* @returns {JSX.Element} The rendered table component.
*/
const DataTable = ({ headers, data, config = { emptyView: "No data" } }) => {
const theme = useTheme();
if ((headers?.length ?? 0) === 0) {
return "No data";
}
return (
<TableContainer component={Paper}>
<Table
stickyHeader
sx={{
"&.MuiTable-root :is(.MuiTableHead-root, .MuiTableBody-root) :is(th, td)": {
paddingLeft: theme.spacing(8),
},
"& :is(th)": {
backgroundColor: theme.palette.secondary.main,
color: theme.palette.secondary.contrastText,
fontWeight: 600,
fontSize: "12px",
},
"& :is(td)": {
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastTextSecondary,
},
}}
>
<TableHead>
<TableRow>
{headers.map((header, index) => (
<TableCell
key={header.id}
align={index === 0 ? "left" : "center"}
>
{header.content}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{(data?.length ?? 0) === 0 ? (
<TableRow>
<TableCell
colSpan={headers.length}
align="center"
>
{config.emptyView}
</TableCell>
</TableRow>
) : (
data.map((row) => {
const key = row.id || row._id || Math.random();
return (
<TableRow
key={key}
sx={config?.rowSX ?? {}}
onClick={config?.onRowClick ? () => config.onRowClick(row) : null}
>
{headers.map((header, index) => {
return (
<TableCell
align={index === 0 ? "left" : "center"}
key={header.id}
>
{header.render(row)}
</TableCell>
);
})}
</TableRow>
);
})
)}
</TableBody>
</Table>
</TableContainer>
);
};
DataTable.propTypes = {
headers: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
content: PropTypes.node.isRequired,
render: PropTypes.func.isRequired,
})
).isRequired,
data: PropTypes.array.isRequired,
config: PropTypes.shape({
onRowClick: PropTypes.func.isRequired,
rowSX: PropTypes.object,
emptyView: PropTypes.node,
}),
};
export default DataTable;
@@ -35,12 +35,12 @@ const SunAndMoonIcon = () => {
cx="12"
cy="12"
r="6"
fill={theme.palette.text.secondary}
fill={theme.palette.primary.contrastTextSecondary}
mask="url(#moon-mask)"
/>
<g
className="sun-beams"
stroke={theme.palette.text.secondary}
stroke={theme.palette.primary.contrastTextSecondary}
>
<line
x1="12"
+5 -1
View File
@@ -15,7 +15,7 @@ import { useDispatch, useSelector } from "react-redux";
import { setMode } from "../../Features/UI/uiSlice";
import "./index.css";
const ThemeSwitch = ({ width = 48, height = 48 }) => {
const ThemeSwitch = ({ width = 48, height = 48, color }) => {
const mode = useSelector((state) => state.ui.mode);
const dispatch = useDispatch();
@@ -37,6 +37,10 @@ const ThemeSwitch = ({ width = 48, height = 48 }) => {
display: "flex",
alignItems: "center",
justifyContent: "center",
"& svg >:is(circle, g)": {
fill: color,
stroke: color,
},
}}
>
<SunAndMoonIcon />
@@ -40,7 +40,7 @@ export const checkEndpointResolution = createAsyncThunk(
const res = await networkService.checkEndpointResolution({
authToken: authToken,
monitorURL: monitorURL,
})
});
return res.data;
} catch (error) {
if (error.response && error.response.data) {
@@ -53,7 +53,7 @@ export const checkEndpointResolution = createAsyncThunk(
return thunkApi.rejectWithValue(payload);
}
}
)
);
export const getPagespeedMonitorById = createAsyncThunk(
"monitors/getMonitorById",
@@ -88,7 +88,6 @@ export const getPageSpeedByTeamId = createAsyncThunk(
teamId: user.teamId,
types: ["pagespeed"],
});
return res.data;
} catch (error) {
if (error.response && error.response.data) {
@@ -78,30 +78,6 @@ export const getUptimeMonitorById = createAsyncThunk(
}
);
export const getUptimeMonitorsByTeamId = createAsyncThunk(
"monitors/getMonitorsByTeamId",
async (token, thunkApi) => {
const user = jwtDecode(token);
try {
const res = await networkService.getMonitorsAndSummaryByTeamId({
authToken: token,
teamId: user.teamId,
types: ["http", "ping", "docker"],
});
return res.data;
} catch (error) {
if (error.response && error.response.data) {
return thunkApi.rejectWithValue(error.response.data);
}
const payload = {
status: false,
msg: error.message ? error.message : "Unknown error",
};
return thunkApi.rejectWithValue(payload);
}
}
);
export const updateUptimeMonitor = createAsyncThunk(
"monitors/updateMonitor",
async (data, thunkApi) => {
@@ -257,26 +233,6 @@ const uptimeMonitorsSlice = createSlice({
},
extraReducers: (builder) => {
builder
// *****************************************************
// Monitors by teamId
// *****************************************************
.addCase(getUptimeMonitorsByTeamId.pending, (state) => {
state.isLoading = true;
})
.addCase(getUptimeMonitorsByTeamId.fulfilled, (state, action) => {
state.isLoading = false;
state.success = action.payload.msg;
state.monitorsSummary = action.payload.data;
})
.addCase(getUptimeMonitorsByTeamId.rejected, (state, action) => {
state.isLoading = false;
state.success = false;
state.msg = action.payload
? action.payload.msg
: "Getting uptime monitors failed";
})
// *****************************************************
// Create Monitor
// *****************************************************
+1 -1
View File
@@ -14,7 +14,7 @@
margin-top: 50px;
}
.account button:not(.MuiIconButton-root) {
height: 34px;
min-height: 34px;
}
.account .field {
flex: 1;
+25 -12
View File
@@ -57,22 +57,27 @@ const Account = ({ open = "profile" }) => {
className="account"
px={theme.spacing(20)}
py={theme.spacing(12)}
backgroundColor={theme.palette.primary.main}
border={1}
borderColor={theme.palette.border.light}
borderColor={theme.palette.primary.lowContrast}
borderRadius={theme.shape.borderRadius}
backgroundColor={theme.palette.background.main}
>
<TabContext value={tab}>
<Box
sx={{
borderBottom: 1,
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
"& .MuiTabs-root": { height: "fit-content", minHeight: "0" },
}}
>
<TabList
onChange={handleTabChange}
aria-label="account tabs"
sx={{
"& .MuiTabs-indicator": {
backgroundColor: theme.palette.tertiary.contrastText,
},
}}
>
{tabList.map((label, index) => (
<Tab
@@ -84,21 +89,29 @@ const Account = ({ open = "profile" }) => {
tabIndex={index}
sx={{
fontSize: 13,
color: theme.palette.text.tertiary,
color: theme.palette.tertiary.contrastText,
backgroundColor: theme.palette.tertiary.main,
textTransform: "none",
minWidth: "fit-content",
minHeight: 0,
paddingLeft: 0,
paddingY: theme.spacing(4),
paddingY: theme.spacing(6),
fontWeight: 400,
marginRight: theme.spacing(8),
borderBottom: "2px solid transparent",
"&:focus": {
borderBottom: `2px solid ${theme.palette.border.light}`,
borderRight: `1px solid ${theme.palette.primary.lowContrast}`,
"&:first-child": { borderTopLeftRadius: "8px" },
"&:last-child": { borderTopRightRadius: "8px", borderRight: 0 },
"&:focus-visible": {
color: theme.palette.primary.contrastText,
borderColor: theme.palette.tertiary.contrastText,
borderRightColor: theme.palette.primary.lowContrast,
},
"&.Mui-selected": {
backgroundColor: theme.palette.secondary.main,
color: theme.palette.secondary.contrastText,
borderColor: theme.palette.secondary.contrastText,
borderRightColor: theme.palette.primary.lowContrast,
},
"&:hover": {
borderBottom: `2px solid ${theme.palette.border.light}`,
borderColor: theme.palette.primary.lowContrast,
},
}}
/>
+8 -7
View File
@@ -7,7 +7,7 @@ import { createToast } from "../../Utils/toastUtils";
import { forgotPassword } from "../../Features/Auth/authSlice";
import Background from "../../assets/Images/background-grid.svg?react";
import EmailIcon from "../../assets/icons/email.svg?react";
import Logo from "../../assets/icons/bwu-icon.svg?react";
import Logo from "../../assets/icons/checkmate-icon.svg?react";
import IconBox from "../../Components/IconBox";
import "./index.css";
@@ -94,7 +94,8 @@ const CheckEmail = () => {
fontWeight: 600,
fontSize: 22,
},
"& p": { color: theme.palette.text.accent, fontSize: 13.5 },
/* TODO font size from theme */
"& p": { color: theme.palette.primary.contrastTextSecondary, fontSize: 13.5 },
"& span": { fontSize: "inherit" },
}}
>
@@ -102,7 +103,7 @@ const CheckEmail = () => {
className="background-pattern-svg"
sx={{
"& svg g g:last-of-type path": {
stroke: theme.palette.border.light,
stroke: theme.palette.primary.lowContrast,
},
}}
>
@@ -115,7 +116,7 @@ const CheckEmail = () => {
gap={theme.spacing(4)}
>
<Logo style={{ borderRadius: theme.shape.borderRadius }} />
<Typography sx={{ userSelect: "none" }}>BlueWave Uptime</Typography>
<Typography sx={{ userSelect: "none" }}>Checkmate</Typography>
</Stack>
<Stack
width="100%"
@@ -129,8 +130,8 @@ const CheckEmail = () => {
"& > .MuiStack-root": {
border: 1,
borderRadius: theme.spacing(5),
borderColor: theme.palette.border.light,
backgroundColor: theme.palette.background.main,
borderColor: theme.palette.primary.lowContrast,
backgroundColor: theme.palette.primary.main,
padding: {
xs: theme.spacing(12),
sm: theme.spacing(20),
@@ -173,7 +174,7 @@ const CheckEmail = () => {
</Box>
<Button
variant="contained"
color="primary"
color="accent"
onClick={openMail}
sx={{
width: "100%",
+8 -7
View File
@@ -7,7 +7,7 @@ import { useEffect, useState } from "react";
import { credentials } from "../../Validation/validation";
import { useNavigate } from "react-router-dom";
import TextInput from "../../Components/Inputs/TextInput";
import Logo from "../../assets/icons/bwu-icon.svg?react";
import Logo from "../../assets/icons/checkmate-icon.svg?react";
import Key from "../../assets/icons/key.svg?react";
import Background from "../../assets/Images/background-grid.svg?react";
import LoadingButton from "@mui/lab/LoadingButton";
@@ -95,8 +95,9 @@ const ForgotPassword = () => {
fontSize: 21,
},
"& p": {
/* TODO font size from theme */
fontSize: 14,
color: theme.palette.text.accent,
color: theme.palette.primary.contrastTextSecondary,
},
}}
>
@@ -104,7 +105,7 @@ const ForgotPassword = () => {
className="background-pattern-svg"
sx={{
"& svg g g:last-of-type path": {
stroke: theme.palette.border.light,
stroke: theme.palette.primary.lowContrast,
},
}}
>
@@ -117,7 +118,7 @@ const ForgotPassword = () => {
gap={theme.spacing(4)}
>
<Logo style={{ borderRadius: theme.shape.borderRadius }} />
<Typography sx={{ userSelect: "none" }}>BlueWave Uptime</Typography>
<Typography sx={{ userSelect: "none" }}>Checkmate</Typography>
</Stack>
<Stack
width="100%"
@@ -131,8 +132,8 @@ const ForgotPassword = () => {
"& > .MuiStack-root": {
border: 1,
borderRadius: theme.spacing(5),
borderColor: theme.palette.border.light,
backgroundColor: theme.palette.background.main,
borderColor: theme.palette.primary.lowContrast,
backgroundColor: theme.palette.primary.main,
padding: {
xs: theme.spacing(12),
sm: theme.spacing(20),
@@ -186,7 +187,7 @@ const ForgotPassword = () => {
/>
<LoadingButton
variant="contained"
color="primary"
color="accent"
loading={isLoading}
disabled={errors.email !== undefined}
onClick={handleSubmit}
@@ -65,7 +65,7 @@ const EmailStep = ({ form, errors, onSubmit, onChange }) => {
>
<Button
variant="contained"
color="primary"
color="accent"
type="submit"
disabled={errors.email && true}
sx={{
@@ -24,7 +24,7 @@ const ForgotPasswordLabel = ({ email, errorEmail }) => {
</Typography>
<Typography
component="span"
color={theme.palette.primary.main}
color={theme.palette.accent.main}
ml={theme.spacing(2)}
sx={{ userSelect: "none" }}
onClick={handleNavigate}
@@ -91,7 +91,7 @@ const PasswordStep = ({ form, errors, onSubmit, onChange, onBack }) => {
</Button>
<LoadingButton
variant="contained"
color="primary"
color="accent"
type="submit"
loading={authState.isLoading}
disabled={errors.password && true}
+7 -6
View File
@@ -8,7 +8,7 @@ import { useDispatch, useSelector } from "react-redux";
import { createToast } from "../../../Utils/toastUtils";
import { networkService } from "../../../main";
import Background from "../../../assets/Images/background-grid.svg?react";
import Logo from "../../../assets/icons/bwu-icon.svg?react";
import Logo from "../../../assets/icons/checkmate-icon.svg?react";
import { logger } from "../../../Utils/Logger";
import "../index.css";
import EmailStep from "./Components/EmailStep";
@@ -145,7 +145,8 @@ const Login = () => {
fontWeight: 600,
fontSize: 28,
},
"& p": { fontSize: 14, color: theme.palette.text.accent },
/* TODO set font size from theme */
"& p": { fontSize: 14, color: theme.palette.primary.contrastTextSecondary },
"& span": { fontSize: "inherit" },
}}
>
@@ -153,7 +154,7 @@ const Login = () => {
className="background-pattern-svg"
sx={{
"& svg g g:last-of-type path": {
stroke: theme.palette.border.light,
stroke: theme.palette.primary.lowContrast,
},
}}
>
@@ -166,7 +167,7 @@ const Login = () => {
gap={theme.spacing(4)}
>
<Logo style={{ borderRadius: theme.shape.borderRadius }} />
<Typography sx={{ userSelect: "none" }}>BlueWave Uptime</Typography>
<Typography sx={{ userSelect: "none" }}>Checkmate</Typography>
</Stack>
<Stack
width="100%"
@@ -181,8 +182,8 @@ const Login = () => {
"& > .MuiStack-root": {
border: 1,
borderRadius: theme.spacing(5),
borderColor: theme.palette.border.light,
backgroundColor: theme.palette.background.main,
borderColor: theme.palette.primary.lowContrast,
backgroundColor: theme.palette.primary.main,
padding: {
xs: theme.spacing(12),
sm: theme.spacing(20),
@@ -6,7 +6,7 @@ import { clearAuthState } from "../../Features/Auth/authSlice";
import { clearUptimeMonitorState } from "../../Features/UptimeMonitors/uptimeMonitorsSlice";
import Background from "../../assets/Images/background-grid.svg?react";
import ConfirmIcon from "../../assets/icons/check-outlined.svg?react";
import Logo from "../../assets/icons/bwu-icon.svg?react";
import Logo from "../../assets/icons/checkmate-icon.svg?react";
import IconBox from "../../Components/IconBox";
import "./index.css";
@@ -31,14 +31,15 @@ const NewPasswordConfirmed = () => {
fontWeight: 600,
fontSize: 21,
},
"& p": { fontSize: 13.5, color: theme.palette.text.accent },
/* TODO font size from theme*/
"& p": { fontSize: 13.5, color: theme.palette.primary.contrastTextSecondary },
}}
>
<Box
className="background-pattern-svg"
sx={{
"& svg g g:last-of-type path": {
stroke: theme.palette.border.light,
stroke: theme.palette.primary.lowContrast,
},
}}
>
@@ -51,7 +52,7 @@ const NewPasswordConfirmed = () => {
gap={theme.spacing(4)}
>
<Logo style={{ borderRadius: theme.shape.borderRadius }} />
<Typography sx={{ userSelect: "none" }}>BlueWave Uptime</Typography>
<Typography sx={{ userSelect: "none" }}>Checkmate</Typography>
</Stack>
<Stack
width="100%"
@@ -65,8 +66,8 @@ const NewPasswordConfirmed = () => {
"& > .MuiStack-root": {
border: 1,
borderRadius: theme.spacing(5),
borderColor: theme.palette.border.light,
backgroundColor: theme.palette.background.main,
borderColor: theme.palette.primary.lowContrast,
backgroundColor: theme.palette.primary.main,
padding: {
xs: theme.spacing(12),
sm: theme.spacing(20),
@@ -103,7 +104,6 @@ const NewPasswordConfirmed = () => {
</Box>
<Button
variant="contained"
color="primary"
onClick={() => navigate("/uptime")}
sx={{
width: "100%",
+10 -9
View File
@@ -12,7 +12,7 @@ import { credentials } from "../../../Validation/validation";
import { createToast } from "../../../Utils/toastUtils";
import { register } from "../../../Features/Auth/authSlice";
import Background from "../../../assets/Images/background-grid.svg?react";
import Logo from "../../../assets/icons/bwu-icon.svg?react";
import Logo from "../../../assets/icons/checkmate-icon.svg?react";
import Mail from "../../../assets/icons/mail.svg?react";
import "../index.css";
@@ -50,7 +50,7 @@ const LandingPage = ({ isSuperAdmin, onSignup }) => {
"& svg": {
mr: theme.spacing(4),
"& path": {
stroke: theme.palette.other.icon,
stroke: theme.palette.primary.contrastTextTertiary,
},
},
"&:focus-visible": {
@@ -77,7 +77,7 @@ const LandingPage = ({ isSuperAdmin, onSignup }) => {
}}
sx={{
"&:hover": {
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
},
}}
>
@@ -95,7 +95,7 @@ const LandingPage = ({ isSuperAdmin, onSignup }) => {
}}
sx={{
"&:hover": {
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
},
}}
>
@@ -285,7 +285,8 @@ const Register = ({ isSuperAdmin }) => {
fontWeight: 600,
fontSize: 28,
},
"& p": { fontSize: 14, color: theme.palette.text.accent },
/* TODO set fontsize from theme */
"& p": { fontSize: 14, color: theme.palette.primary.contrastTextSecondary },
"& span": { fontSize: "inherit" },
}}
>
@@ -293,7 +294,7 @@ const Register = ({ isSuperAdmin }) => {
className="background-pattern-svg"
sx={{
"& svg g g:last-of-type path": {
stroke: theme.palette.border.light,
stroke: theme.palette.primary.lowContrast,
},
}}
>
@@ -306,7 +307,7 @@ const Register = ({ isSuperAdmin }) => {
gap={theme.spacing(4)}
>
<Logo style={{ borderRadius: theme.shape.borderRadius }} />
<Typography sx={{ userSelect: "none" }}>BlueWave Uptime</Typography>
<Typography sx={{ userSelect: "none" }}>Checkmate</Typography>
</Stack>
<Stack
width="100%"
@@ -320,8 +321,8 @@ const Register = ({ isSuperAdmin }) => {
"& > .MuiStack-root": {
border: 1,
borderRadius: theme.spacing(5),
borderColor: theme.palette.border.light,
backgroundColor: theme.palette.background.main,
borderColor: theme.palette.primary.lowContrast,
backgroundColor: theme.palette.primary.main,
padding: {
xs: theme.spacing(12),
sm: theme.spacing(20),
@@ -111,7 +111,7 @@ function StepOne({ form, errors, onSubmit, onChange, onBack }) {
</Button>
<Button
variant="contained"
color="primary"
color="accent"
type="submit"
disabled={(errors.firstName || errors.lastName) && true}
sx={{
@@ -134,7 +134,7 @@ function StepThree({ onSubmit, onBack }) {
mr: theme.spacing(3),
},
":focus-visible": {
outline: `2px solid ${theme.palette.primary.dark}`,
outline: `2px solid ${theme.palette.primary.lowContrast}`,
outlineOffset: "4px",
},
}}
@@ -145,7 +145,7 @@ function StepThree({ onSubmit, onBack }) {
<Button
type="submit"
variant="contained"
color="primary"
color="accent"
disabled={
form.password.length === 0 ||
form.confirm.length === 0 ||
@@ -93,7 +93,7 @@ function StepTwo({ form, errors, onSubmit, onChange, onBack }) {
</Button>
<Button
variant="contained"
color="primary"
color="accent"
onClick={onSubmit}
disabled={errors.email && true}
sx={{
+8 -7
View File
@@ -13,7 +13,7 @@ import TextInput from "../../Components/Inputs/TextInput";
import { PasswordEndAdornment } from "../../Components/Inputs/TextInput/Adornments";
import IconBox from "../../Components/IconBox";
import LockIcon from "../../assets/icons/lock.svg?react";
import Logo from "../../assets/icons/bwu-icon.svg?react";
import Logo from "../../assets/icons/checkmate-icon.svg?react";
import Background from "../../assets/Images/background-grid.svg?react";
import "./index.css";
import { useValidatePassword } from "./hooks/useValidatePassword";
@@ -74,8 +74,9 @@ const SetNewPassword = () => {
fontSize: 24,
},
"& p": {
/* TODO font size from theme */
fontSize: 14,
color: theme.palette.text.accent,
color: theme.palette.primary.contrastTextSecondary,
},
}}
>
@@ -83,7 +84,7 @@ const SetNewPassword = () => {
className="background-pattern-svg"
sx={{
"& svg g g:last-of-type path": {
stroke: theme.palette.border.light,
stroke: theme.palette.primary.lowContrast,
},
}}
>
@@ -96,7 +97,7 @@ const SetNewPassword = () => {
gap={theme.spacing(4)}
>
<Logo style={{ borderRadius: theme.shape.borderRadius }} />
<Typography sx={{ userSelect: "none" }}>BlueWave Uptime</Typography>
<Typography sx={{ userSelect: "none" }}>Checkmate</Typography>
</Stack>
<Stack
width="100%"
@@ -110,8 +111,8 @@ const SetNewPassword = () => {
"& > .MuiStack-root": {
border: 1,
borderRadius: theme.spacing(5),
borderColor: theme.palette.border.light,
backgroundColor: theme.palette.background.main,
borderColor: theme.palette.primary.lowContrast,
backgroundColor: theme.palette.primary.main,
padding: {
xs: theme.spacing(12),
sm: theme.spacing(20),
@@ -233,7 +234,7 @@ const SetNewPassword = () => {
</Box>
<LoadingButton
variant="contained"
color="primary"
color="accent"
loading={isLoading}
onClick={handleSubmit}
disabled={
@@ -16,7 +16,7 @@ const Empty = ({ styles, mode }) => {
</Box>
<Typography
textAlign="center"
color={theme.palette.text.secondary}
color={theme.palette.primary.contrastTextSecondary}
>
No incidents recorded yet.
</Typography>
@@ -1,20 +1,6 @@
import PropTypes from "prop-types";
import {
TableContainer,
Table,
TableHead,
TableRow,
TableCell,
TableBody,
Pagination,
PaginationItem,
Paper,
Typography,
Box,
} from "@mui/material";
import { Typography, Box } from "@mui/material";
import ArrowBackRoundedIcon from "@mui/icons-material/ArrowBackRounded";
import ArrowForwardRoundedIcon from "@mui/icons-material/ArrowForwardRounded";
import { useState, useEffect } from "react";
import { useSelector } from "react-redux";
import { networkService } from "../../../main";
@@ -27,8 +13,10 @@ import PlaceholderDark from "../../../assets/Images/data_placeholder_dark.svg?re
import { HttpStatusLabel } from "../../../Components/HttpStatusLabel";
import { Empty } from "./Empty/Empty";
import { IncidentSkeleton } from "./Skeleton/Skeleton";
import DataTable from "../../../Components/Table";
import Pagination from "../../../Components/Table/TablePagination";
const IncidentTable = ({ monitors, selectedMonitor, filter }) => {
const IncidentTable = ({ monitors, selectedMonitor, filter, dateRange }) => {
const uiTimezone = useSelector((state) => state.ui.timezone);
const theme = useTheme();
@@ -36,19 +24,10 @@ const IncidentTable = ({ monitors, selectedMonitor, filter }) => {
const mode = useSelector((state) => state.ui.mode);
const [checks, setChecks] = useState([]);
const [checksCount, setChecksCount] = useState(0);
const [paginationController, setPaginationController] = useState({
page: 0,
rowsPerPage: 14,
});
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
setPaginationController((prevPaginationController) => ({
...prevPaginationController,
page: 0,
}));
}, [filter, selectedMonitor]);
useEffect(() => {
const fetchPage = async () => {
if (!monitors || Object.keys(monitors).length === 0) {
@@ -63,10 +42,10 @@ const IncidentTable = ({ monitors, selectedMonitor, filter }) => {
teamId: user.teamId,
sortOrder: "desc",
limit: null,
dateRange: null,
dateRange,
filter: filter,
page: paginationController.page,
rowsPerPage: paginationController.rowsPerPage,
page: page,
rowsPerPage: rowsPerPage,
});
} else {
res = await networkService.getChecksByMonitor({
@@ -74,12 +53,13 @@ const IncidentTable = ({ monitors, selectedMonitor, filter }) => {
monitorId: selectedMonitor,
sortOrder: "desc",
limit: null,
dateRange: null,
dateRange,
filter: filter,
page: paginationController.page,
rowsPerPage: paginationController.rowsPerPage,
page,
rowsPerPage,
});
}
setChecks(res.data.data.checks);
setChecksCount(res.data.data.checksCount);
} catch (error) {
@@ -89,50 +69,61 @@ const IncidentTable = ({ monitors, selectedMonitor, filter }) => {
}
};
fetchPage();
}, [
authToken,
user,
monitors,
selectedMonitor,
filter,
paginationController.page,
paginationController.rowsPerPage,
]);
}, [authToken, user, monitors, selectedMonitor, filter, page, rowsPerPage, dateRange]);
const handlePageChange = (_, newPage) => {
setPaginationController({
...paginationController,
page: newPage - 1, // 0-indexed
});
setPage(newPage);
};
let paginationComponent = <></>;
if (checksCount > paginationController.rowsPerPage) {
paginationComponent = (
<Pagination
count={Math.ceil(checksCount / paginationController.rowsPerPage)}
page={paginationController.page + 1} //0-indexed
onChange={handlePageChange}
shape="rounded"
renderItem={(item) => (
<PaginationItem
slots={{
previous: ArrowBackRoundedIcon,
next: ArrowForwardRoundedIcon,
}}
{...item}
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(event.target.value);
};
const headers = [
{
id: "monitorName",
content: "Monitor Name",
render: (row) => monitors[row.monitorId]?.name ?? "N/A",
},
{
id: "status",
content: "Status",
render: (row) => {
const status = row.status === true ? "up" : "down";
return (
<StatusLabel
status={status}
text={status}
customStyles={{ textTransform: "capitalize" }}
/>
)}
sx={{ mt: "auto" }}
/>
);
}
);
},
},
{
id: "dateTime",
content: "Date & Time",
render: (row) => {
const formattedDate = formatDateWithTz(
row.createdAt,
"YYYY-MM-DD HH:mm:ss A",
uiTimezone
);
return formattedDate;
},
},
{
id: "statusCode",
content: "Status Code",
render: (row) => <HttpStatusLabel status={row.statusCode} />,
},
{ id: "message", content: "Message", render: (row) => row.message },
];
let sharedStyles = {
border: 1,
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
p: theme.spacing(30),
};
@@ -159,55 +150,25 @@ const IncidentTable = ({ monitors, selectedMonitor, filter }) => {
</Box>
<Typography
textAlign="center"
color={theme.palette.text.secondary}
color={theme.palette.primary.contrastTextSecondary}
>
The monitor you have selected has no recorded incidents yet.
</Typography>
</Box>
) : (
<>
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>Monitor Name</TableCell>
<TableCell>Status</TableCell>
<TableCell>Date & Time</TableCell>
<TableCell>Status Code</TableCell>
<TableCell>Message</TableCell>
</TableRow>
</TableHead>
<TableBody>
{checks.map((check) => {
const status = check.status === true ? "up" : "down";
const formattedDate = formatDateWithTz(
check.createdAt,
"YYYY-MM-DD HH:mm:ss A",
uiTimezone
);
return (
<TableRow key={check._id}>
<TableCell>{monitors[check.monitorId]?.name}</TableCell>
<TableCell>
<StatusLabel
status={status}
text={status}
customStyles={{ textTransform: "capitalize" }}
/>
</TableCell>
<TableCell>{formattedDate}</TableCell>
<TableCell>
<HttpStatusLabel status={check.statusCode} />
</TableCell>
<TableCell>{check.message}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
{paginationComponent}
<DataTable
headers={headers}
data={checks}
/>
<Pagination
paginationLabel="incidents"
itemCount={checksCount}
page={page}
rowsPerPage={rowsPerPage}
handleChangePage={handlePageChange}
handleChangeRowsPerPage={handleChangeRowsPerPage}
/>
</>
)}
</>
@@ -218,6 +179,7 @@ IncidentTable.propTypes = {
monitors: PropTypes.object.isRequired,
selectedMonitor: PropTypes.string.isRequired,
filter: PropTypes.string.isRequired,
dateRange: PropTypes.string.isRequired,
};
export default IncidentTable;
-11
View File
@@ -1,11 +0,0 @@
.incidents h1.MuiTypography-root {
font-size: var(--env-var-font-size-large);
font-weight: 600;
}
.incidents button.MuiButtonBase-root,
.incidents p.MuiTypography-root {
font-size: var(--env-var-font-size-medium);
}
.incidents button.MuiButtonBase-root {
height: 34px;
}
+117 -47
View File
@@ -8,7 +8,6 @@ import { useTheme } from "@emotion/react";
import Select from "../../Components/Inputs/Select";
import IncidentTable from "./IncidentTable";
import SkeletonLayout from "./skeleton";
import "./index.css";
const Incidents = () => {
const theme = useTheme();
@@ -21,6 +20,7 @@ const Incidents = () => {
// TODO do something with these filters
const [filter, setFilter] = useState("all");
const [dateRange, setDateRange] = useState("hour");
useEffect(() => {
const fetchMonitors = async () => {
@@ -29,7 +29,7 @@ const Incidents = () => {
const res = await networkService.getMonitorsByTeamId({
authToken: authState.authToken,
teamId: authState.user.teamId,
limit: -1,
limit: null,
types: null,
status: null,
checkOrder: null,
@@ -40,7 +40,6 @@ const Incidents = () => {
field: null,
order: null,
});
// Reduce to a lookup object for 0(1) lookup
if (res?.data?.data?.monitors?.length > 0) {
const monitorLookup = res.data.data.monitors.reduce((acc, monitor) => {
acc[monitor._id] = monitor;
@@ -56,7 +55,7 @@ const Incidents = () => {
}
};
fetchMonitors();
}, [authState]);
}, [authState, monitorId]);
useEffect(() => {}, [monitors]);
@@ -78,61 +77,132 @@ const Incidents = () => {
<>
<Stack
direction="row"
alignItems="center"
justifyContent="space-between"
gap={theme.spacing(6)}
>
<Typography
display="inline-block"
component="h1"
color={theme.palette.text.secondary}
<Stack
direction="row"
alignItems="center"
gap={theme.spacing(6)}
>
Incidents for
</Typography>
<Select
id="incidents-select-monitor"
placeholder="All servers"
value={selectedMonitor}
onChange={handleSelect}
items={Object.values(monitors)}
sx={{
backgroundColor: theme.palette.background.main,
}}
/>
<ButtonGroup
sx={{
ml: "auto",
"& .MuiButtonBase-root, & .MuiButtonBase-root:hover": {
borderColor: theme.palette.border.light,
},
}}
<Typography
display="inline-block"
component="h1"
color={theme.palette.primary.contrastTextSecondary}
>
Incidents for
</Typography>
<Select
id="incidents-select-monitor"
placeholder="All servers"
value={selectedMonitor}
onChange={handleSelect}
items={Object.values(monitors)}
sx={{
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastTextSecondary,
}}
/>
</Stack>
<Stack
direction="row"
alignItems="center"
gap={theme.spacing(6)}
>
<Button
variant="group"
filled={(filter === "all").toString()}
onClick={() => setFilter("all")}
<Typography
display="inline-block"
component="h1"
color={theme.palette.primary.contrastTextSecondary}
>
All
</Button>
<Button
variant="group"
filled={(filter === "down").toString()}
onClick={() => setFilter("down")}
Filter by:
</Typography>
<ButtonGroup
sx={{
ml: "auto",
"& .MuiButtonBase-root, & .MuiButtonBase-root:hover": {
borderColor: theme.palette.primary.lowContrast,
},
}}
>
Down
</Button>
<Button
variant="group"
filled={(filter === "resolve").toString()}
onClick={() => setFilter("resolve")}
<Button
variant="group"
filled={(filter === "all").toString()}
onClick={() => setFilter("all")}
>
All
</Button>
<Button
variant="group"
filled={(filter === "down").toString()}
onClick={() => setFilter("down")}
>
Down
</Button>
<Button
variant="group"
filled={(filter === "resolve").toString()}
onClick={() => setFilter("resolve")}
>
Cannot resolve
</Button>
</ButtonGroup>
</Stack>
<Stack
direction="row"
alignItems="center"
gap={theme.spacing(6)}
>
<Typography
display="inline-block"
component="h1"
color={theme.palette.primary.contrastTextSecondary}
>
Cannot Resolve
</Button>
</ButtonGroup>
Show:
</Typography>
<ButtonGroup
sx={{
ml: "auto",
"& .MuiButtonBase-root, & .MuiButtonBase-root:hover": {
borderColor: theme.palette.primary.lowContrast,
},
}}
>
<Button
variant="group"
filled={(dateRange === "hour").toString()}
onClick={() => setDateRange("hour")}
>
Last hour
</Button>
<Button
variant="group"
filled={(dateRange === "day").toString()}
onClick={() => setDateRange("day")}
>
Last day
</Button>
<Button
variant="group"
filled={(dateRange === "week").toString()}
onClick={() => setDateRange("week")}
>
Last week
</Button>
<Button
variant="group"
filled={(dateRange === "all").toString()}
onClick={() => setDateRange("all")}
>
All
</Button>
</ButtonGroup>
</Stack>
</Stack>
<IncidentTable
monitors={monitors}
selectedMonitor={selectedMonitor}
filter={filter}
dateRange={dateRange}
/>
</>
)}
@@ -407,7 +407,7 @@ const CreateInfrastructureMonitor = () => {
>
<LoadingButton
variant="contained"
color="primary"
color="accent"
onClick={handleCreateInfrastructureMonitor}
loading={monitorState?.isLoading}
>
@@ -19,7 +19,7 @@ const Empty = ({ styles }) => {
<Typography variant="h2">Your infrastructure dashboard will show here</Typography>
<Typography
textAlign="center"
color={theme.palette.text.secondary}
color={theme.palette.primary.contrastTextSecondary}
>
Hang tight! Data is loading
</Typography>
+119 -72
View File
@@ -1,7 +1,7 @@
import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";
import Breadcrumbs from "../../../Components/Breadcrumbs";
import { Stack, Box, Typography } from "@mui/material";
import { Button, ButtonGroup, Stack, Box, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import CustomGauge from "../../../Components/Charts/CustomGauge";
import AreaChart from "../../../Components/Charts/AreaChart";
@@ -13,9 +13,8 @@ import { useNavigate } from "react-router-dom";
import Empty from "./empty";
import { logger } from "../../../Utils/Logger";
import { formatDurationRounded, formatDurationSplit } from "../../../Utils/timeUtils";
import { TzTick, PercentTick } from "../../../Components/Charts/Utils/chartUtils";
import {
TzTick,
PercentTick,
InfrastructureTooltip,
TemperatureTooltip,
} from "../../../Components/Charts/Utils/chartUtils";
@@ -109,10 +108,10 @@ const BaseBox = ({ children, sx = {} }) => {
padding: `${theme.spacing(BASE_BOX_PADDING_VERTICAL)} ${theme.spacing(BASE_BOX_PADDING_HORIZONTAL)}`,
minWidth: 200,
width: 225,
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
border: 1,
borderStyle: "solid",
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
...sx,
}}
>
@@ -156,7 +155,7 @@ const GaugeBox = ({ value, heading, metricOne, valueOne, metricTwo, valueTwo })
<Box
sx={{
width: "100%",
borderTop: `1px solid ${theme.palette.border.light}`,
borderTop: `1px solid ${theme.palette.primary.lowContrast}`,
}}
>
<Stack
@@ -185,9 +184,11 @@ GaugeBox.propTypes = {
value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
heading: PropTypes.string.isRequired,
metricOne: PropTypes.string.isRequired,
valueOne: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
valueOne: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.element])
.isRequired,
metricTwo: PropTypes.string.isRequired,
valueTwo: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
valueTwo: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.element])
.isRequired,
};
/**
@@ -204,7 +205,7 @@ const InfrastructureDetails = () => {
];
const [monitor, setMonitor] = useState(null);
const { authToken } = useSelector((state) => state.auth);
const [dateRange, setDateRange] = useState("all");
const [dateRange, setDateRange] = useState("day");
const { statusColor, statusStyles, determineState } = useUtils();
// These calculations are needed because ResponsiveContainer
// doesn't take padding of parent/siblings into account
@@ -217,8 +218,9 @@ const InfrastructureDetails = () => {
(chartContainerHeight - totalChartContainerPadding - totalTypographyPadding) * 0.95;
// end height calculations
const buildStatBoxes = (checks, uptime) => {
let latestCheck = checks[0] ?? null;
const buildStatBoxes = (stats, uptime) => {
if (Object.keys(stats).length === 0) return [];
let latestCheck = stats?.aggregateData?.latestCheck ?? null;
if (latestCheck === null) return [];
// Extract values from latest check
@@ -311,8 +313,10 @@ const InfrastructureDetails = () => {
];
};
const buildGaugeBoxConfigs = (checks) => {
let latestCheck = checks[0] ?? null;
const buildGaugeBoxConfigs = (stats) => {
if (Object.keys(stats).length === 0) return [];
let latestCheck = stats?.aggregateData?.latestCheck ?? null;
if (latestCheck === null) return [];
// Extract values from latest check
@@ -359,27 +363,27 @@ const InfrastructureDetails = () => {
if (checks === null) return { temps: [], tempKeys: [] };
for (const check of checks) {
if (check?.cpu?.temperature?.length > numCores) {
numCores = check.cpu.temperature.length;
if (check?.avgTemperature?.length > numCores) {
numCores = check.avgTemperature.length;
break;
}
}
const temps = checks.map((check) => {
// If there's no data, set the temperature to 0
if (
check?.cpu?.temperature?.length === 0 ||
check?.cpu?.temperature === undefined ||
check?.cpu?.temperature === null
check?.avgTemperature?.length === 0 ||
check?.avgTemperature === undefined ||
check?.avgTemperature === null
) {
check.cpu.temperature = Array(numCores).fill(0);
check.avgTemperature = Array(numCores).fill(0);
}
const res = check?.cpu?.temperature?.reduce(
const res = check?.avgTemperature?.reduce(
(acc, cur, idx) => {
acc[`core${idx + 1}`] = cur;
return acc;
},
{
createdAt: check.createdAt,
_id: check._id,
}
);
return res;
@@ -389,7 +393,7 @@ const InfrastructureDetails = () => {
}
return {
tempKeys: Object.keys(temps[0] || {}).filter((key) => key !== "createdAt"),
tempKeys: Object.keys(temps[0] || {}).filter((key) => key !== "_id"),
temps,
};
};
@@ -397,90 +401,91 @@ const InfrastructureDetails = () => {
const buildAreaChartConfigs = (checks) => {
let latestCheck = checks[0] ?? null;
if (latestCheck === null) return [];
const reversedChecks = checks.toReversed();
const tempData = buildTemps(reversedChecks);
const { temps, tempKeys } = buildTemps(checks);
return [
{
type: "memory",
data: reversedChecks,
dataKeys: ["memory.usage_percent"],
data: checks,
dataKeys: ["avgMemoryUsage"],
heading: "Memory usage",
strokeColor: theme.palette.primary.main,
gradientStartColor: theme.palette.primary.main,
strokeColor: theme.palette.accent.main, // CAIO_REVIEW
gradientStartColor: theme.palette.accent.main, // CAIO_REVIEW
yLabel: "Memory usage",
yDomain: [0, 1],
yTick: <PercentTick />,
xTick: <TzTick />,
xTick: <TzTick dateRange={dateRange} />,
toolTip: (
<InfrastructureTooltip
dotColor={theme.palette.primary.main}
yKey={"memory.usage_percent"}
yKey={"avgMemoryUsage"}
yLabel={"Memory usage"}
dateRange={dateRange}
/>
),
},
{
type: "cpu",
data: reversedChecks,
dataKeys: ["cpu.usage_percent"],
data: checks,
dataKeys: ["avgCpuUsage"],
heading: "CPU usage",
strokeColor: theme.palette.success.main,
gradientStartColor: theme.palette.success.main,
yLabel: "CPU usage",
yDomain: [0, 1],
yTick: <PercentTick />,
xTick: <TzTick />,
xTick: <TzTick dateRange={dateRange} />,
toolTip: (
<InfrastructureTooltip
dotColor={theme.palette.success.main}
yKey={"cpu.usage_percent"}
yKey={"avgCpuUsage"}
yLabel={"CPU usage"}
dateRange={dateRange}
/>
),
},
{
type: "temperature",
data: tempData.temps,
dataKeys: tempData.tempKeys,
data: temps,
dataKeys: tempKeys,
strokeColor: theme.palette.error.main,
gradientStartColor: theme.palette.error.main,
heading: "CPU Temperature",
yLabel: "Temperature",
xTick: <TzTick />,
xTick: <TzTick dateRange={dateRange} />,
yDomain: [
0,
Math.max(
Math.max(
...tempData.temps.flatMap((t) => tempData.tempKeys.map((k) => t[k]))
) * 1.1,
Math.max(...temps.flatMap((t) => tempKeys.map((k) => t[k]))) * 1.1,
200
),
],
toolTip: (
<TemperatureTooltip
keys={tempData.tempKeys}
keys={tempKeys}
dotColor={theme.palette.error.main}
dateRange={dateRange}
/>
),
},
...(latestCheck?.disk?.map((disk, idx) => ({
...(latestCheck?.disks?.map((disk, idx) => ({
type: "disk",
data: reversedChecks,
data: checks,
diskIndex: idx,
dataKeys: [`disk[${idx}].usage_percent`],
dataKeys: [`disks[${idx}].usagePercent`],
heading: `Disk${idx} usage`,
strokeColor: theme.palette.warning.main,
gradientStartColor: theme.palette.warning.main,
yLabel: "Disk Usage",
yDomain: [0, 1],
yTick: <PercentTick />,
xTick: <TzTick />,
xTick: <TzTick dateRange={dateRange} />,
toolTip: (
<InfrastructureTooltip
dotColor={theme.palette.warning.main}
yKey={`disk.usage_percent`}
yKey={`disks.usagePercent`}
yLabel={"Disc usage"}
yIdx={idx}
dateRange={dateRange}
/>
),
})) || []),
@@ -491,15 +496,12 @@ const InfrastructureDetails = () => {
useEffect(() => {
const fetchData = async () => {
try {
const response = await networkService.getStatsByMonitorId({
const response = await networkService.getHardwareDetailsByMonitorId({
authToken: authToken,
monitorId: monitorId,
sortOrder: null,
limit: null,
dateRange: dateRange,
numToDisplay: 50,
normalize: false,
});
response.data.data;
setMonitor(response.data.data);
} catch (error) {
navigate("/not-found", { replace: true });
@@ -510,16 +512,17 @@ const InfrastructureDetails = () => {
}, [authToken, monitorId, dateRange, navigate]);
const statBoxConfigs = buildStatBoxes(
monitor?.checks ?? [],
monitor?.stats ?? {},
monitor?.uptimePercentage ?? "Unknown"
);
const gaugeBoxConfigs = buildGaugeBoxConfigs(monitor?.checks ?? []);
const areaChartConfigs = buildAreaChartConfigs(monitor?.checks ?? []);
const gaugeBoxConfigs = buildGaugeBoxConfigs(monitor?.stats ?? {});
const areaChartConfigs = buildAreaChartConfigs(monitor?.stats?.checks ?? []);
const lastChecked =
Date.now() - new Date(monitor?.stats?.aggregateData?.latestCheck?.createdAt);
return (
<Box>
<Breadcrumbs list={navList} />
{monitor?.checks?.length > 0 ? (
{monitor?.stats.checks?.length > 0 ? (
<Stack
direction="column"
gap={theme.spacing(10)}
@@ -545,10 +548,11 @@ const InfrastructureDetails = () => {
Checking every {formatDurationRounded(monitor?.interval)}
</Typography>
<Typography alignSelf="end">
Last checked {formatDurationSplit(monitor?.lastChecked).time}{" "}
{formatDurationSplit(monitor?.lastChecked).format} ago
Last checked {formatDurationSplit(lastChecked).time}{" "}
{formatDurationSplit(lastChecked).format} ago
</Typography>
</Stack>
<Stack
direction="row"
flexWrap="wrap"
@@ -561,21 +565,64 @@ const InfrastructureDetails = () => {
/>
))}
</Stack>
<Stack
direction="row"
gap={theme.spacing(8)}
>
{gaugeBoxConfigs.map((config) => (
<GaugeBox
key={`${config.type}-${config.diskIndex ?? ""}`}
value={config.value}
heading={config.heading}
metricOne={config.metricOne}
valueOne={config.valueOne}
metricTwo={config.metricTwo}
valueTwo={config.valueTwo}
/>
))}
{gaugeBoxConfigs.map((config) => {
return (
<GaugeBox
key={`${config.type}-${config.diskIndex ?? ""}`}
value={config.value}
heading={config.heading}
metricOne={config.metricOne}
valueOne={config.valueOne}
metricTwo={config.metricTwo}
valueTwo={config.valueTwo}
/>
);
})}
</Stack>
<Stack
direction="row"
justifyContent="space-between"
alignItems="flex-end"
gap={theme.spacing(8)}
mb={theme.spacing(8)}
>
<Typography variant="body2">
Showing statistics for past{" "}
{dateRange === "day"
? "24 hours"
: dateRange === "week"
? "7 days"
: "30 days"}
.
</Typography>
<ButtonGroup sx={{ height: 32 }}>
<Button
variant="group"
filled={(dateRange === "day").toString()}
onClick={() => setDateRange("day")}
>
Day
</Button>
<Button
variant="group"
filled={(dateRange === "week").toString()}
onClick={() => setDateRange("week")}
>
Week
</Button>
<Button
variant="group"
filled={(dateRange === "month").toString()}
onClick={() => setDateRange("month")}
>
Month
</Button>
</ButtonGroup>
</Stack>
<Stack
direction={"row"}
@@ -602,7 +649,7 @@ const InfrastructureDetails = () => {
height={areaChartHeight}
data={config.data}
dataKeys={config.dataKeys}
xKey="createdAt"
xKey="_id"
yDomain={config.yDomain}
customTooltip={config.toolTip}
xTick={config.xTick}
@@ -621,9 +668,9 @@ const InfrastructureDetails = () => {
<Empty
styles={{
border: 1,
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
p: theme.spacing(30),
}}
/>
@@ -83,7 +83,7 @@ const InfrastructureMenu = ({ monitor, isAdmin, updateCallback }) => {
outline: "none",
},
"& svg path": {
stroke: theme.palette.other.icon,
stroke: theme.palette.primary.contrastTextTertiary,
},
}}
ref={anchor}
+108 -173
View File
@@ -1,4 +1,4 @@
import { useEffect, useState } from "react";
import { useEffect, useState, useCallback } from "react";
import { useNavigate } from "react-router-dom";
import { /* useDispatch, */ useSelector } from "react-redux";
import { useTheme } from "@emotion/react";
@@ -8,23 +8,12 @@ import SkeletonLayout from "./skeleton";
import Fallback from "../../Components/Fallback";
// import GearIcon from "../../Assets/icons/settings-bold.svg?react";
import CPUChipIcon from "../../assets/icons/cpu-chip.svg?react";
import {
Box,
Button,
IconButton,
Paper,
Stack,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
} from "@mui/material";
import DataTable from "../../Components/Table";
import { Box, Button, IconButton, Stack } from "@mui/material";
import Breadcrumbs from "../../Components/Breadcrumbs";
import { StatusLabel } from "../../Components/Label";
import { Heading } from "../../Components/Heading";
import { Pagination } from "./components/TablePagination";
import Pagination from "../../Components/Table/TablePagination/index.jsx";
// import { getInfrastructureMonitorsByTeamId } from "../../Features/InfrastructureMonitors/infrastructureMonitorsSlice";
import { networkService } from "../../Utils/NetworkService.js";
import CustomGauge from "../../Components/Charts/CustomGauge/index.jsx";
@@ -32,42 +21,8 @@ import Host from "../Uptime/Home/host.jsx";
import { useIsAdmin } from "../../Hooks/useIsAdmin.js";
import { InfrastructureMenu } from "./components/Menu";
const columns = [
{ label: "Host" },
{ label: "Status" },
{ label: "Frequency" },
{ label: "CPU" },
{ label: "Mem" },
{ label: "Disk" },
{ label: "Actions" },
];
const BREADCRUMBS = [{ name: `infrastructure`, path: "/infrastructure" }];
/* TODO
Create reusable table component.
It should receive as a parameter the following object:
tableData = [
columns = [
{
id: example,
label: Example Extendable,
align: "center" | "left" (default)
}
],
rows: [
{
**Number of keys will be equal to number of columns**
key1: string,
key2: number,
key3: Component
}
]
]
Apply to Monitor Table, and Account/Team.
Analyze existing BasicTable
*/
/**
* This is the Infrastructure monitoring page. This is a work in progress
*
@@ -95,12 +50,13 @@ function Infrastructure() {
setRowsPerPage(parseInt(event.target.value));
setPage(0);
};
const [monitorState, setMonitorState] = useState({ monitors: [], total: 0 });
const [monitors, setMonitors] = useState([]);
const [summary, setSummary] = useState({});
const { authToken } = useSelector((state) => state.auth);
const user = jwtDecode(authToken);
const fetchMonitors = async () => {
const fetchMonitors = useCallback(async () => {
try {
setIsLoading(true);
const response = await networkService.getMonitorsByTeamId({
@@ -108,29 +64,23 @@ function Infrastructure() {
teamId: user.teamId,
limit: 1,
types: ["hardware"],
status: null,
checkOrder: "desc",
normalize: true,
page: page,
rowsPerPage: rowsPerPage,
});
setMonitorState({
monitors: response?.data?.data?.monitors ?? [],
total: response?.data?.data?.monitorCount ?? 0,
});
setMonitors(response?.data?.data?.filteredMonitors ?? []);
setSummary(response?.data?.data?.summary ?? {});
} catch (error) {
console.error(error);
} finally {
setIsLoading(false);
}
};
}, [page, rowsPerPage, authToken, user.teamId]);
useEffect(() => {
fetchMonitors();
}, [page, rowsPerPage]);
}, [fetchMonitors]);
const { determineState } = useUtils();
const { monitors, total: totalMonitors } = monitorState;
// do it here
function openDetails(id) {
navigate(`/infrastructure/${id}`);
@@ -139,6 +89,65 @@ function Infrastructure() {
fetchMonitors();
}
const headers = [
{
id: "host",
content: "Host",
render: (row) => (
<Host
title={row.name}
url={row.url}
percentage={row.uptimePercentage}
percentageColor={row.percentageColor}
/>
),
},
{
id: "status",
content: "Status",
render: (row) => (
<StatusLabel
status={row.status}
text={row.status}
/>
),
},
{
id: "frequency",
content: "Frequency",
render: (row) => (
<Stack
direction={"row"}
justifyContent={"center"}
alignItems={"center"}
gap=".25rem"
>
<CPUChipIcon
width={20}
height={20}
/>
{row.processor}
</Stack>
),
},
{ id: "cpu", content: "CPU", render: (row) => <CustomGauge progress={row.cpu} /> },
{ id: "mem", content: "Mem", render: (row) => <CustomGauge progress={row.mem} /> },
{ id: "disk", content: "Disk", render: (row) => <CustomGauge progress={row.disk} /> },
{
id: "actions",
content: "Actions",
render: (row) => (
<IconButton>
<InfrastructureMenu
monitor={row}
isAdmin={isAdmin}
updateCallback={handleActionMenuDelete}
/>
</IconButton>
),
},
];
const monitorsAsRows = monitors.map((monitor) => {
const processor =
((monitor.checks[0]?.cpu?.usage_frequency ?? 0) / 1000).toFixed(2) + " GHz";
@@ -151,12 +160,12 @@ function Infrastructure() {
.toString();
const percentageColor =
monitor.uptimePercentage < 0.25
? theme.palette.percentage.uptimePoor
? theme.palette.error.main
: monitor.uptimePercentage < 0.5
? theme.palette.percentage.uptimeFair
: monitor.uptimePercentage < 0.75
? theme.palette.percentage.uptimeGood
: theme.palette.percentage.uptimeExcellent;
: theme.palette.success.lowContrast;
return {
id: monitor._id,
name: monitor.name,
@@ -171,7 +180,7 @@ function Infrastructure() {
};
});
let isActuallyLoading = isLoading && monitorState.monitors?.length === 0;
let isActuallyLoading = isLoading && monitors?.length === 0;
return (
<Box
className="infrastructure-monitor"
@@ -179,17 +188,17 @@ function Infrastructure() {
':has(> [class*="fallback__"])': {
position: "relative",
border: 1,
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
borderStyle: "dashed",
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
overflow: "hidden",
},
}}
>
{isActuallyLoading ? (
<SkeletonLayout />
) : monitorState.monitors?.length !== 0 ? (
) : monitors?.length !== 0 ? (
<Stack gap={theme.spacing(8)}>
<Box>
<Breadcrumbs list={BREADCRUMBS} />
@@ -202,7 +211,7 @@ function Infrastructure() {
{isAdmin && (
<Button
variant="contained"
color="primary"
color="accent"
onClick={navigateToCreate}
sx={{ fontWeight: 500, whiteSpace: "nowrap" }}
>
@@ -225,117 +234,43 @@ function Infrastructure() {
}}
>
<Heading component="h2">Infrastructure monitors</Heading>
{/* TODO Correct the class current-monitors-counter, there are some unnecessary things there */}
{/* TODO Same as the one in UptimaDataTable. Create component */}
<Box
component="span"
className="current-monitors-counter"
color={theme.palette.text.primary}
border={1}
borderColor={theme.palette.border.light}
backgroundColor={theme.palette.background.accent}
color={theme.palette.tertiary.contrastText}
border={2}
borderColor={theme.palette.accent.main}
backgroundColor={theme.palette.tertiary.main}
sx={{
padding: ".25em .75em",
borderRadius: "50%",
fontSize: "12px",
fontWeight: 500,
}}
>
{totalMonitors}
{summary?.totalMonitors ?? 0}
</Box>
</Stack>
<TableContainer component={Paper}>
<Table stickyHeader>
<TableHead sx={{ backgroundColor: theme.palette.background.accent }}>
<TableRow>
{columns.map((column, index) => (
<TableCell
key={index}
align={index === 0 ? "left" : "center"}
sx={{
backgroundColor: theme.palette.background.accent,
}}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{monitorsAsRows.map((row) => {
return (
<TableRow
key={row.id}
onClick={() => openDetails(row.id)}
sx={{
cursor: "pointer",
"&:hover": {
backgroundColor: theme.palette.background.accent,
},
}}
>
{/* TODO iterate over column and get column id, applying row[column.id] */}
<TableCell>
<Host
title={row.name}
url={row.url}
percentage={row.uptimePercentage}
percentageColor={row.percentageColor}
/>
</TableCell>
<TableCell align="center">
<StatusLabel
status={row.status}
text={row.status}
/* Use capitalize inside of Status Label */
/* Update component so we don't need to pass text and status separately*/
customStyles={{ textTransform: "capitalize" }}
/>
</TableCell>
<TableCell align="center">
<Stack
direction={"row"}
justifyContent={"center"}
alignItems={"center"}
gap=".25rem"
>
<CPUChipIcon
width={20}
height={20}
/>
{row.processor}
</Stack>
</TableCell>
<TableCell align="center">
<CustomGauge progress={row.cpu} />
</TableCell>
<TableCell align="center">
<CustomGauge progress={row.mem} />
</TableCell>
<TableCell align="center">
<CustomGauge progress={row.disk} />
</TableCell>
<TableCell align="center">
{/* Get ActionsMenu from Monitor Table and create a component */}
<IconButton
sx={{
"& svg path": {
stroke: theme.palette.other.icon,
},
}}
>
<InfrastructureMenu
monitor={row}
isAdmin={isAdmin}
updateCallback={handleActionMenuDelete}
/>
{/* <GearIcon
width={20}
height={20}
/> */}
</IconButton>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<DataTable
config={{
/* TODO this behavior seems to be repeated. Put it on the root table? */
rowSX: {
cursor: "pointer",
"&:hover td": {
backgroundColor: theme.palette.tertiary.main,
transition: "background-color .3s ease",
},
},
onRowClick: (row) => openDetails(row.id),
}}
headers={headers}
data={monitorsAsRows}
/>
<Pagination
monitorCount={totalMonitors}
itemCount={summary?.totalMonitors ?? 0}
paginationLabel="monitors"
page={page}
rowsPerPage={rowsPerPage}
handleChangePage={handleChangePage}
+5 -5
View File
@@ -33,9 +33,9 @@ const IntegrationsComponent = ({ icon, header, info, onClick }) => {
pl={theme.spacing(12)}
height="100%"
border={1}
borderColor={theme.palette.border.light}
borderColor={theme.palette.primary.lowContrast}
borderRadius={theme.shape.borderRadius}
backgroundColor={theme.palette.background.main}
backgroundColor={theme.palette.primary.main}
>
{icon}
<Stack
@@ -54,7 +54,7 @@ const IntegrationsComponent = ({ icon, header, info, onClick }) => {
</Stack>
<Button
variant="contained"
color="primary"
color="accent"
onClick={onClick}
sx={{ alignSelf: "center" }}
disabled={true}
@@ -126,13 +126,13 @@ const Integrations = () => {
gap={theme.spacing(2)}
sx={{
"& h1, & p": {
color: theme.palette.text.secondary,
color: theme.palette.primary.contrastTextSecondary,
},
}}
>
<Typography component="h1">Integrations</Typography>
<Typography mb={theme.spacing(12)}>
Connect BlueWave Uptime to your favorite service.
Connect Checkmate to your favorite service.
</Typography>
<Grid
container
@@ -136,7 +136,7 @@ const CreateMaintenance = () => {
const response = await networkService.getMonitorsByTeamId({
authToken: authToken,
teamId: user.teamId,
limit: -1,
limit: null,
types: ["http", "ping", "pagespeed"],
});
const monitors = response.data.data.monitors;
@@ -360,7 +360,6 @@ const CreateMaintenance = () => {
<DatePicker
id="startDate"
disablePast
label="Date"
disableHighlightToday
value={form.startDate}
slots={{ openPickerIcon: CalendarIcon }}
@@ -374,17 +373,17 @@ const CreateMaintenance = () => {
flexDirection: "row-reverse",
},
"& input": {
height: 34,
minHeight: 34,
p: 0,
pr: theme.spacing(5),
},
"& fieldset": {
borderColor: theme.palette.border.dark,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
},
"&:not(:has(.Mui-disabled)):not(:has(.Mui-error)) .MuiOutlinedInput-root:not(:has(input:focus)):hover fieldset":
{
borderColor: theme.palette.border.dark,
borderColor: theme.palette.primary.lowContrast,
},
},
},
@@ -394,12 +393,36 @@ const CreateMaintenance = () => {
py: 0,
mr: 0,
"& path": {
stroke: theme.palette.other.icon,
stroke: theme.palette.primary.contrastTextTertiary,
strokeWidth: 1.1,
},
"&:hover": { backgroundColor: "transparent" },
},
},
// CAIO_REVIEW, entire popper
popper: {
sx: {
"& .MuiPickersDay-root": {
color: theme.palette.primary.contrastText,
"&.Mui-selected": {
backgroundColor: theme.palette.accent.main, // Selected day background
color: theme.palette.primary.contrastText, // Selected day text color
},
"&:hover": {
backgroundColor: theme.palette.accent.light, // Hover background
},
"&.Mui-disabled": {
color: theme.palette.primary.ContrastTextTertiary, // Disabled day color
},
},
"& .MuiDayCalendar-weekDayLabel": {
color: theme.palette.primary.contrastText,
},
"& .MuiPickersCalendarHeader-label": {
color: theme.palette.primary.contrastText,
},
},
},
}}
sx={{}}
onChange={(newDate) => {
@@ -439,17 +462,17 @@ const CreateMaintenance = () => {
flexDirection: "row-reverse",
},
"& input": {
height: 34,
minHeight: 34,
p: 0,
pl: theme.spacing(5),
},
"& fieldset": {
borderColor: theme.palette.border.dark,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
},
"&:not(:has(.Mui-disabled)):not(:has(.Mui-error)) .MuiOutlinedInput-root:not(:has(input:focus)):hover fieldset":
{
borderColor: theme.palette.border.dark,
borderColor: theme.palette.primary.lowContrast,
},
},
},
@@ -532,7 +555,7 @@ const CreateMaintenance = () => {
<LoadingButton
loading={isLoading}
variant="contained"
color="primary"
color="accent"
onClick={handleSubmit}
disabled={false}
>
@@ -95,7 +95,7 @@ const ActionsMenu = ({ /* isAdmin, */ maintenanceWindow, updateCallback }) => {
outline: "none",
},
"& svg path": {
stroke: theme.palette.other.icon,
stroke: theme.palette.primary.contrastTextTertiary,
},
}}
>
@@ -1,34 +1,16 @@
import PropTypes from "prop-types";
import {
TableContainer,
Table,
TableHead,
TableRow,
TableCell,
TableBody,
Paper,
Box,
TablePagination,
Stack,
Typography,
Button,
} from "@mui/material";
import { Box } from "@mui/material";
import DataTable from "../../../Components/Table";
import Pagination from "../../../Components/Table/TablePagination";
import ArrowDownwardRoundedIcon from "@mui/icons-material/ArrowDownwardRounded";
import ArrowUpwardRoundedIcon from "@mui/icons-material/ArrowUpwardRounded";
import ActionsMenu from "./ActionsMenu";
import { useState, useEffect, memo, useCallback, useRef } from "react";
import { memo } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useTheme } from "@emotion/react";
import LeftArrowDouble from "../../../assets/icons/left-arrow-double.svg?react";
import RightArrowDouble from "../../../assets/icons/right-arrow-double.svg?react";
import LeftArrow from "../../../assets/icons/left-arrow.svg?react";
import RightArrow from "../../../assets/icons/right-arrow.svg?react";
import SelectorVertical from "../../../assets/icons/selector-vertical.svg?react";
import { formatDurationRounded } from "../../../Utils/timeUtils";
import { StatusLabel } from "../../../Components/Label";
import { setRowsPerPage } from "../../../Features/UI/uiSlice";
import dayjs from "dayjs";
/**
* Component for pagination actions (first, previous, next, last).
*
@@ -41,65 +23,6 @@ import dayjs from "dayjs";
*
* @returns {JSX.Element} Pagination actions component.
*/
const TablePaginationActions = (props) => {
const { count, page, rowsPerPage, onPageChange } = props;
const handleFirstPageButtonClick = (event) => {
onPageChange(event, 0);
};
const handleBackButtonClick = (event) => {
onPageChange(event, page - 1);
};
const handleNextButtonClick = (event) => {
onPageChange(event, page + 1);
};
const handleLastPageButtonClick = (event) => {
onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
};
return (
<Box sx={{ flexShrink: 0, ml: "24px" }}>
<Button
variant="group"
onClick={handleFirstPageButtonClick}
disabled={page === 0}
aria-label="first page"
>
<LeftArrowDouble />
</Button>
<Button
variant="group"
onClick={handleBackButtonClick}
disabled={page === 0}
aria-label="previous page"
>
<LeftArrow />
</Button>
<Button
variant="group"
onClick={handleNextButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="next page"
>
<RightArrow />
</Button>
<Button
variant="group"
onClick={handleLastPageButtonClick}
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
aria-label="last page"
>
<RightArrowDouble />
</Button>
</Box>
);
};
TablePaginationActions.propTypes = {
count: PropTypes.number.isRequired,
page: PropTypes.number.isRequired,
rowsPerPage: PropTypes.number.isRequired,
onPageChange: PropTypes.func.isRequired,
};
const MaintenanceTable = ({
page,
@@ -111,13 +34,102 @@ const MaintenanceTable = ({
updateCallback,
}) => {
const { rowsPerPage } = useSelector((state) => state.ui.maintenance);
const theme = useTheme();
console.log(rowsPerPage);
const dispatch = useDispatch();
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
dispatch(
setRowsPerPage({
value: parseInt(event.target.value, 10),
table: "maintenance",
})
);
setPage(0);
};
const headers = [
{
id: "name",
content: (
<Box onClick={() => handleSort("name")}>
Maintenance Window Name
<span
style={{
visibility: sort.field === "name" ? "visible" : "hidden",
}}
>
{sort.order === "asc" ? (
<ArrowUpwardRoundedIcon />
) : (
<ArrowDownwardRoundedIcon />
)}
</span>
</Box>
),
render: (row) => row.name,
},
{
id: "status",
content: (
<Box onClick={() => handleSort("status")}>
{" "}
Status
<span
style={{
visibility: sort.field === "active" ? "visible" : "hidden",
}}
>
{sort.order === "asc" ? (
<ArrowUpwardRoundedIcon />
) : (
<ArrowDownwardRoundedIcon />
)}
</span>
</Box>
),
render: (row) => {
const status = row.active ? "up" : "paused";
const text = row.active ? "active" : "paused";
return (
<StatusLabel
status={status}
text={text}
customStyles={{ textTransform: "capitalize" }}
/>
);
},
},
{
id: "nextWindow",
content: "Next window",
render: (row) => {
return getTimeToNextWindow(row.start, row.end, row.repeat);
},
},
{
id: "repeat",
content: "Repeat",
render: (row) => {
return row.repeat === 0 ? "N/A" : formatDurationRounded(row.repeat);
},
},
{
id: "actions",
content: "Actions",
render: (row) => (
<ActionsMenu
maintenanceWindow={row}
updateCallback={updateCallback}
/>
),
},
];
const getTimeToNextWindow = (startTime, endTime, repeat) => {
//1. Advance time closest to next window as possible
const now = dayjs();
@@ -153,26 +165,6 @@ const MaintenanceTable = ({
}
};
const handleChangeRowsPerPage = (event) => {
dispatch(
setRowsPerPage({
value: parseInt(event.target.value, 10),
table: "maintenance",
})
);
setPage(0);
};
/**
* Helper function to calculate the range of displayed rows.
* @returns {string}
*/
const getRange = () => {
let start = page * rowsPerPage + 1;
let end = Math.min(page * rowsPerPage + rowsPerPage, maintenanceWindowCount);
return `${start} - ${end}`;
};
const handleSort = async (field) => {
let order = "";
if (sort.field !== field) {
@@ -183,165 +175,21 @@ const MaintenanceTable = ({
setSort({ field, order });
};
console.log(handleChangePage);
return (
<>
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell
sx={{ cursor: "pointer" }}
onClick={() => handleSort("name")}
>
<Box>
Maintenance Window Name
<span
style={{
visibility: sort.field === "name" ? "visible" : "hidden",
}}
>
{sort.order === "asc" ? (
<ArrowUpwardRoundedIcon />
) : (
<ArrowDownwardRoundedIcon />
)}
</span>
</Box>
</TableCell>
<TableCell
sx={{ cursor: "pointer" }}
onClick={() => handleSort("status")}
>
{" "}
<Box width="max-content">
{" "}
Status
<span
style={{
visibility: sort.field === "active" ? "visible" : "hidden",
}}
>
{sort.order === "asc" ? (
<ArrowUpwardRoundedIcon />
) : (
<ArrowDownwardRoundedIcon />
)}
</span>
</Box>
</TableCell>
<TableCell>Next Window</TableCell>
<TableCell>Repeat</TableCell>
<TableCell>Actions</TableCell>
</TableRow>
</TableHead>
<TableBody>
{maintenanceWindows.map((maintenanceWindow) => {
const text = maintenanceWindow.active ? "active" : "paused";
const status = maintenanceWindow.active ? "up" : "paused";
return (
<TableRow key={maintenanceWindow._id}>
<TableCell>{maintenanceWindow.name}</TableCell>
<TableCell>
<StatusLabel
status={status}
text={text}
customStyles={{ textTransform: "capitalize" }}
/>
</TableCell>
<TableCell>
{getTimeToNextWindow(
maintenanceWindow.start,
maintenanceWindow.end,
maintenanceWindow.repeat
)}
</TableCell>
<TableCell>
{maintenanceWindow.repeat === 0
? "N/A"
: formatDurationRounded(maintenanceWindow.repeat)}
</TableCell>
<TableCell>
<ActionsMenu
maintenanceWindow={maintenanceWindow}
updateCallback={updateCallback}
/>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<Stack
direction="row"
alignItems="center"
justifyContent="space-between"
px={theme.spacing(4)}
>
<Typography
px={theme.spacing(2)}
variant="body2"
sx={{ opacity: 0.7 }}
>
Showing {getRange()} of {maintenanceWindowCount} maintenance window(s)
</Typography>
<TablePagination
component="div"
count={maintenanceWindowCount}
page={page}
onPageChange={handleChangePage}
rowsPerPage={rowsPerPage}
rowsPerPageOptions={[5, 10, 15, 25]}
onRowsPerPageChange={handleChangeRowsPerPage}
ActionsComponent={TablePaginationActions}
labelRowsPerPage="Rows per page"
labelDisplayedRows={({ page, count }) =>
`Page ${page + 1} of ${Math.max(0, Math.ceil(count / rowsPerPage))}`
}
slotProps={{
select: {
MenuProps: {
keepMounted: true,
disableScrollLock: true,
PaperProps: {
className: "pagination-dropdown",
sx: {
mt: 0,
mb: theme.spacing(2),
},
},
transformOrigin: { vertical: "bottom", horizontal: "left" },
anchorOrigin: { vertical: "top", horizontal: "left" },
sx: { mt: theme.spacing(-2) },
},
inputProps: { id: "pagination-dropdown" },
IconComponent: SelectorVertical,
sx: {
ml: theme.spacing(4),
mr: theme.spacing(12),
minWidth: theme.spacing(20),
textAlign: "left",
"&.Mui-focused > div": {
backgroundColor: theme.palette.background.main,
},
},
},
}}
sx={{
mt: theme.spacing(6),
color: theme.palette.text.secondary,
"& svg path": {
stroke: theme.palette.text.tertiary,
strokeWidth: 1.3,
},
"& .MuiSelect-select": {
border: 1,
borderColor: theme.palette.border.light,
borderRadius: theme.shape.borderRadius,
},
}}
/>
</Stack>
<DataTable
headers={headers}
data={maintenanceWindows}
/>
<Pagination
itemCount={maintenanceWindowCount}
page={page}
rowsPerPage={rowsPerPage}
handleChangePage={handleChangePage}
handleChangeRowsPerPage={handleChangeRowsPerPage}
/>
</>
);
};
+3 -3
View File
@@ -51,10 +51,10 @@ const Maintenance = () => {
':has(> [class*="fallback__"])': {
position: "relative",
border: 1,
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
borderStyle: "dashed",
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
overflow: "hidden",
},
}}
@@ -70,7 +70,7 @@ const Maintenance = () => {
<Breadcrumbs list={[{ name: "maintenance", path: "/maintenance" }]} />
<Button
variant="contained"
color="primary"
color="accent"
onClick={() => {
navigate("/maintenance/create");
}}
+1 -1
View File
@@ -58,7 +58,7 @@ const NotFound = ({ title = DefaultValue.title, desc = DefaultValue.desc }) => {
<Typography variant="body1">{desc}</Typography>
<Button
variant="contained"
color="primary"
color="accent"
sx={{ mt: theme.spacing(10) }}
onClick={() => navigate("/")}
>
@@ -249,7 +249,7 @@ const PageSpeedConfigure = () => {
width: 4,
height: 4,
borderRadius: "50%",
backgroundColor: theme.palette.text.tertiary,
backgroundColor: theme.palette.primary.contrastTextTertiary,
opacity: 0.8,
left: -10,
top: "50%",
@@ -276,7 +276,7 @@ const PageSpeedConfigure = () => {
"& svg": {
mr: theme.spacing(2),
"& path": {
stroke: theme.palette.other.icon,
stroke: theme.palette.primary.contrastTextTertiary,
strokeWidth: 0.1,
},
},
@@ -319,7 +319,7 @@ const PageSpeedConfigure = () => {
gap={theme.spacing(20)}
sx={{
".MuiInputBase-root:has(> .Mui-disabled)": {
backgroundColor: theme.palette.background.accent,
backgroundColor: theme.palette.tertiary.main,
},
}}
>
@@ -426,7 +426,7 @@ const PageSpeedConfigure = () => {
loading={isLoading}
type="submit"
variant="contained"
color="primary"
color="accent"
onClick={handleSave}
sx={{ px: theme.spacing(12) }}
>
@@ -179,7 +179,7 @@ const CreatePageSpeed = () => {
className="create-monitor"
sx={{
"& h1": {
color: theme.palette.text.primary,
color: theme.palette.primary.contrastText,
},
}}
>
@@ -207,7 +207,7 @@ const CreatePageSpeed = () => {
component="span"
fontSize="inherit"
fontWeight="inherit"
color={theme.palette.text.secondary}
color={theme.palette.primary.contrastTextSecondary}
>
PageSpeed monitor
</Typography>
@@ -337,7 +337,7 @@ const CreatePageSpeed = () => {
>
<LoadingButton
variant="contained"
color="primary"
color="accent"
onClick={handleCreateMonitor}
disabled={!Object.values(errors).every((value) => value === undefined)}
loading={isLoading}
@@ -18,7 +18,7 @@ const config = {
seo: {
id: "seo",
text: "SEO",
color: "unresolved",
color: "secondary",
},
performance: {
id: "performance",
@@ -33,7 +33,7 @@ const config = {
accessibility: {
id: "accessibility",
text: "accessibility",
color: "primary",
color: "accent",
},
};
@@ -54,9 +54,9 @@ const CustomToolTip = ({ active, payload, label, config }) => {
return (
<Box
sx={{
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
border: 1,
borderColor: theme.palette.border.dark,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
py: theme.spacing(2),
px: theme.spacing(4),
@@ -64,7 +64,7 @@ const CustomToolTip = ({ active, payload, label, config }) => {
>
<Typography
sx={{
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
fontSize: 12,
fontWeight: 500,
}}
@@ -86,7 +86,7 @@ const CustomToolTip = ({ active, payload, label, config }) => {
mt={theme.spacing(1)}
sx={{
"& span": {
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
fontSize: 11,
fontWeight: 500,
},
@@ -186,7 +186,7 @@ const CustomTick = ({ x, y, payload, index }) => {
x={x}
y={y + 8}
textAnchor="middle"
fill={theme.palette.text.tertiary}
fill={theme.palette.primary.contrastTextTertiary}
fontSize={11}
fontWeight={400}
>
@@ -238,14 +238,14 @@ const PagespeedDetailsAreaChart = ({ data, interval, metrics }) => {
onMouseLeave={() => setIsHovered(false)}
>
<CartesianGrid
stroke={theme.palette.border.light}
stroke={theme.palette.primary.lowContrast}
strokeWidth={1}
strokeOpacity={1}
fill="transparent"
vertical={false}
/>
<XAxis
stroke={theme.palette.border.dark}
stroke={theme.palette.primary.lowContrast}
dataKey="createdAt"
tick={<CustomTick />}
axisLine={false}
@@ -255,13 +255,14 @@ const PagespeedDetailsAreaChart = ({ data, interval, metrics }) => {
interval="equidistantPreserveStart"
/>
<Tooltip
cursor={{ stroke: theme.palette.border.light }}
cursor={{ stroke: theme.palette.primary.lowContrast }}
content={<CustomToolTip config={filteredConfig} />}
/>
<defs>
{Object.values(filteredConfig).map(({ id, color }) => {
/* TODO not working? */
const startColor = theme.palette[color].main;
const endColor = theme.palette[color].light;
const endColor = theme.palette[color].lowContrast;
return (
<linearGradient
@@ -289,7 +290,7 @@ const PagespeedDetailsAreaChart = ({ data, interval, metrics }) => {
{Object.keys(filteredConfig).map((key) => {
const { color } = filteredConfig[key];
const strokeColor = theme.palette[color].main;
const bgColor = theme.palette.background.main;
const bgColor = theme.palette.primary.main;
return (
<Area
@@ -126,29 +126,29 @@ const PieChart = ({ audits }) => {
if (value >= 90 && value <= 100)
return {
stroke: theme.palette.success.main,
strokeBg: theme.palette.success.light,
strokeBg: theme.palette.success.lowContrast,
text: theme.palette.success.contrastText,
bg: theme.palette.success.light,
bg: theme.palette.success.lowContrast,
};
else if (value >= 50 && value < 90)
return {
stroke: theme.palette.warning.main,
strokeBg: theme.palette.warning.light,
strokeBg: theme.palette.warning.lowContrast,
text: theme.palette.warning.contrastText,
bg: theme.palette.warning.dark,
bg: theme.palette.warning.lowContrast,
};
else if (value >= 0 && value < 50)
return {
stroke: theme.palette.error.contrastText,
strokeBg: theme.palette.error.light,
strokeBg: theme.palette.error.lowContrast,
text: theme.palette.error.contrastText,
bg: theme.palette.error.dark,
bg: theme.palette.error.lowContrast,
};
return {
stroke: theme.palette.unresolved.main,
strokeBg: theme.palette.unresolved.light,
text: theme.palette.unresolved.main,
bg: theme.palette.unresolved.bg,
stroke: theme.palette.tertiary.contrastText,
strokeBg: theme.palette.tertiary.contrastText,
text: theme.palette.tertiary.contrastText,
bg: theme.palette.tertiary.main,
};
};
+1 -1
View File
@@ -1,5 +1,5 @@
.page-speed-details button.MuiButtonBase-root {
height: 34px;
min-height: 34px;
}
.page-speed-details .MuiPieArcLabel-root {
+5 -5
View File
@@ -151,7 +151,7 @@ const PageSpeedDetails = () => {
width: 4,
height: 4,
borderRadius: "50%",
backgroundColor: theme.palette.text.tertiary,
backgroundColor: theme.palette.primary.contrastTextTertiary,
opacity: 0.8,
left: -9,
top: "50%",
@@ -175,7 +175,7 @@ const PageSpeedDetails = () => {
"& svg": {
mr: theme.spacing(3),
"& path": {
stroke: theme.palette.other.icon,
stroke: theme.palette.primary.contrastTextTertiary,
},
},
}}
@@ -372,7 +372,7 @@ const PageSpeedDetails = () => {
? theme.palette.warning.main
: score >= 0
? theme.palette.error.contrastText
: theme.palette.unresolved.main;
: theme.palette.tertiary.main;
// Find the position where the number ends and the unit begins
const match = audit.displayValue.match(/(\d+\.?\d*)\s*([a-zA-Z]+)/);
@@ -393,7 +393,7 @@ const PageSpeedDetails = () => {
gap={theme.spacing(4)}
p={theme.spacing(3)}
border={1}
borderColor={theme.palette.border.light}
borderColor={theme.palette.primary.lowContrast}
borderRadius={4}
>
<Box>
@@ -410,7 +410,7 @@ const PageSpeedDetails = () => {
component="span"
fontSize={14}
fontWeight={500}
color={theme.palette.text.primary}
color={theme.palette.primary.contrastText}
>
{value}
<Typography
@@ -6,17 +6,17 @@ export const ChartBox = styled(Stack)(({ theme }) => ({
minWidth: 250,
border: 1,
borderStyle: "solid",
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
borderRadius: 4,
borderTopRightRadius: 16,
borderBottomRightRadius: 16,
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
"& h2": {
color: theme.palette.text.secondary,
color: theme.palette.primary.contrastTextSecondary,
fontSize: 15,
fontWeight: 500,
},
"& p": { color: theme.palette.text.tertiary },
"& p": { color: theme.palette.primary.contrastTextTertiary },
"& > :nth-of-type(1)": {
gridColumn: 1,
gridRow: 1,
@@ -31,10 +31,10 @@ export const ChartBox = styled(Stack)(({ theme }) => ({
padding: theme.spacing(8),
borderLeft: 1,
borderLeftStyle: "solid",
borderLeftColor: theme.palette.border.light,
borderLeftColor: theme.palette.primary.lowContrast,
borderRadius: 16,
backgroundColor: theme.palette.background.main,
background: `linear-gradient(325deg, ${theme.palette.background.accent} 20%, ${theme.palette.background.main} 45%)`,
backgroundColor: theme.palette.primary.main,
background: `linear-gradient(325deg, ${theme.palette.tertiary.main} 20%, ${theme.palette.primary.main} 45%)`,
},
"& path": {
transition: "stroke-width 400ms ease",
+25 -20
View File
@@ -23,9 +23,9 @@ const CustomToolTip = ({ payload }) => {
return (
<Box
sx={{
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
border: 1,
borderColor: theme.palette.border.dark,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
py: theme.spacing(2),
px: theme.spacing(4),
@@ -33,7 +33,7 @@ const CustomToolTip = ({ payload }) => {
>
<Typography
sx={{
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
fontSize: 12,
fontWeight: 500,
}}
@@ -52,7 +52,7 @@ const CustomToolTip = ({ payload }) => {
mt={theme.spacing(1)}
sx={{
"& span": {
color: theme.palette.text.tertiary,
color: theme.palette.primary.contrastTextTertiary,
fontSize: 11,
fontWeight: 500,
},
@@ -81,6 +81,7 @@ CustomToolTip.propTypes = {
payload: PropTypes.array,
};
/* TODO separate utils in folder*/
/**
* Processes the raw data to include a score for each entry.
* @param {Array<Object>} data - The raw data array.
@@ -104,6 +105,7 @@ const processData = (data) => {
return formattedData;
};
/* TODO separate component*/
/**
* Renders an area chart displaying page speed scores.
* @param {Object} props
@@ -114,7 +116,9 @@ const processData = (data) => {
const PagespeedAreaChart = ({ data, status }) => {
const theme = useTheme();
const [isHovered, setIsHovered] = useState(false);
const { pagespeedStyles } = useUtils();
const { statusToTheme } = useUtils();
const themeColor = statusToTheme[status];
const formattedData = processData(data);
@@ -134,14 +138,14 @@ const PagespeedAreaChart = ({ data, status }) => {
onMouseLeave={() => setIsHovered(false)}
>
<CartesianGrid
stroke={theme.palette.border.light}
stroke={theme.palette.primary.lowContrast}
strokeWidth={1}
strokeOpacity={1}
fill="transparent"
vertical={false}
/>
<Tooltip
cursor={{ stroke: theme.palette.border.light }}
cursor={{ stroke: theme.palette.primary.lowContrast }}
content={<CustomToolTip />}
/>
<defs>
@@ -154,24 +158,24 @@ const PagespeedAreaChart = ({ data, status }) => {
>
<stop
offset="0%"
stopColor={pagespeedStyles[status].stroke}
stopColor={theme.palette[themeColor].lowContrast}
stopOpacity={0.8}
/>
<stop
offset="100%"
stopColor={pagespeedStyles[status].light}
stopColor={theme.palette[themeColor].main}
stopOpacity={0}
/>
</linearGradient>
</defs>
<Area
dataKey="score"
stroke={pagespeedStyles[status].stroke}
stroke={theme.palette[themeColor].lowContrast}
strokeWidth={isHovered ? 2.5 : 1.5}
fill={`url(#pagespeed-chart-${status})`}
activeDot={{
stroke: pagespeedStyles[status].light,
fill: pagespeedStyles[status].stroke,
stroke: theme.palette[themeColor].main,
fill: theme.palette[themeColor].lowContrast,
r: 4.5,
}}
/>
@@ -192,6 +196,7 @@ PagespeedAreaChart.propTypes = {
status: PropTypes.string.isRequired,
};
/* TODO separate component */
/**
* Renders a card displaying monitor details and an area chart.
* @param {Object} props
@@ -215,9 +220,9 @@ const Card = ({ monitor }) => {
p={theme.spacing(8)}
onClick={() => navigate(`/pagespeed/${monitor._id}`)}
border={1}
borderColor={theme.palette.border.light}
borderColor={theme.palette.primary.lowContrast}
borderRadius={theme.shape.borderRadius}
backgroundColor={theme.palette.background.main}
backgroundColor={theme.palette.primary.main}
sx={{
display: "grid",
gridTemplateColumns: "34px 2fr 1fr",
@@ -225,7 +230,7 @@ const Card = ({ monitor }) => {
gridTemplateRows: "34px 1fr 3fr",
cursor: "pointer",
"&:hover": {
backgroundColor: theme.palette.background.accent,
backgroundColor: theme.palette.tertiary.main,
},
"& path": {
transition: "stroke-width 400ms ease",
@@ -267,7 +272,7 @@ const Card = ({ monitor }) => {
sx={{ gridColumnStart: 1, gridColumnEnd: 4 }}
>
<PagespeedAreaChart
data={monitor.checks}
data={monitor.checks.slice().reverse()}
status={monitorState}
/>
</Box>
@@ -278,8 +283,8 @@ const Card = ({ monitor }) => {
px={theme.spacing(4)}
borderTop={1}
borderRight={1}
borderColor={theme.palette.border.light}
backgroundColor={theme.palette.background.accent}
borderColor={theme.palette.primary.lowContrast}
backgroundColor={theme.palette.tertiary.main}
sx={{
pointerEvents: "none",
userSelect: "none",
@@ -289,7 +294,7 @@ const Card = ({ monitor }) => {
>
<Typography
fontSize={11}
color={theme.palette.text.accent}
color={theme.palette.primary.contrastTextSecondary}
>
Checking every{" "}
{(() => {
@@ -299,7 +304,7 @@ const Card = ({ monitor }) => {
<Typography
component="span"
fontSize={12}
color={theme.palette.text.primary}
color={theme.palette.primary.contrastText}
>
{time}{" "}
</Typography>
+1 -1
View File
@@ -4,5 +4,5 @@
font-size: var(--env-var-font-size-small);
}
.page-speed:not(:has([class*="fallback__"])) button {
height: 34px;
min-height: 34px;
}
+12 -20
View File
@@ -1,8 +1,7 @@
import { Box, Button, Grid, Stack } from "@mui/material";
import { useEffect, useState } from "react";
import { useTheme } from "@emotion/react";
import { useDispatch, useSelector } from "react-redux";
import { getPageSpeedByTeamId } from "../../Features/PageSpeedMonitor/pageSpeedMonitorSlice";
import { useSelector } from "react-redux";
import Fallback from "../../Components/Fallback";
import "./index.css";
import { useNavigate } from "react-router";
@@ -15,16 +14,12 @@ import { Heading } from "../../Components/Heading";
import { useIsAdmin } from "../../Hooks/useIsAdmin";
const PageSpeed = () => {
const theme = useTheme();
const dispatch = useDispatch();
const navigate = useNavigate();
const isAdmin = useIsAdmin();
const { user, authToken } = useSelector((state) => state.auth);
const [isLoading, setIsLoading] = useState(true);
const [monitors, setMonitors] = useState([]);
const [monitorCount, setMonitorCount] = useState(0);
useEffect(() => {
dispatch(getPageSpeedByTeamId(authToken));
}, [authToken, dispatch]);
const [summary, setSummary] = useState({});
useEffect(() => {
const fetchMonitors = async () => {
@@ -35,18 +30,15 @@ const PageSpeed = () => {
teamId: user.teamId,
limit: 10,
types: ["pagespeed"],
status: null,
checkOrder: "desc",
normalize: true,
page: null,
rowsPerPage: null,
filter: null,
field: null,
order: null,
});
if (res?.data?.data?.monitors) {
setMonitors(res.data.data.monitors);
setMonitorCount(res.data.data.monitorCount);
if (res?.data?.data?.filteredMonitors) {
setMonitors(res.data.data.filteredMonitors);
setSummary(res.data.data.summary);
}
} catch (error) {
console.log(error);
@@ -68,10 +60,10 @@ const PageSpeed = () => {
':has(> [class*="fallback__"])': {
position: "relative",
border: 1,
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
borderStyle: "dashed",
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
overflow: "hidden",
},
}}
@@ -91,7 +83,7 @@ const PageSpeed = () => {
{isAdmin && (
<Button
variant="contained"
color="primary"
color="accent"
onClick={() => navigate("/pagespeed/create")}
sx={{ fontWeight: 500, whiteSpace: "nowrap" }}
>
@@ -113,12 +105,12 @@ const PageSpeed = () => {
<Box
component="span"
className="current-monitors-counter"
color={theme.palette.text.primary}
color={theme.palette.primary.contrastText}
border={1}
borderColor={theme.palette.border.light}
backgroundColor={theme.palette.background.accent}
borderColor={theme.palette.primary.lowContrast}
backgroundColor={theme.palette.tertiary.main}
>
{monitorCount}
{summary?.totalMonitors ?? 0}
</Box>
</Stack>
<Grid
+1 -1
View File
@@ -13,7 +13,7 @@
font-weight: 600;
}
.settings button {
height: 34px;
min-height: 34px;
}
.settings span.MuiTypography-root {
opacity: 0.6;
+4 -4
View File
@@ -266,7 +266,7 @@ const Settings = () => {
open={isOpen.deleteStats}
theme={theme}
title="Do you want to clear all stats?"
description="Once deleted, this monitor cannot be retrieved."
description="Once deleted, your monitors cannot be retrieved."
onCancel={() => setIsOpen(deleteStatsMonitorsInitState)}
confirmationButtonLabel="Yes, clear all stats"
onConfirm={handleClearStats}
@@ -279,7 +279,7 @@ const Settings = () => {
<Box>
<Typography component="h1">Demo monitors</Typography>
<Typography sx={{ mt: theme.spacing(2) }}>
Here you can add and remove demo monitors
Here you can add and remove demo monitors.
</Typography>
</Box>
<Stack gap={theme.spacing(20)}>
@@ -287,7 +287,7 @@ const Settings = () => {
<Typography>Add demo monitors</Typography>
<LoadingButton
variant="contained"
color="primary"
color="accent"
loading={isLoading || authIsLoading || checksIsLoading}
onClick={handleInsertDemoMonitors}
sx={{ mt: theme.spacing(4) }}
@@ -346,7 +346,7 @@ const Settings = () => {
loading={isLoading || authIsLoading || checksIsLoading}
disabled={Object.keys(errors).length > 0}
variant="contained"
color="primary"
color="accent"
sx={{ px: theme.spacing(12), mt: theme.spacing(20) }}
onClick={handleSave}
>
+2 -2
View File
@@ -12,10 +12,10 @@ const Status = () => {
':has(> [class*="fallback__"])': {
position: "relative",
border: 1,
borderColor: theme.palette.border.light,
borderColor: theme.palette.primary.lowContrast,
borderRadius: theme.shape.borderRadius,
borderStyle: "dashed",
backgroundColor: theme.palette.background.main,
backgroundColor: theme.palette.primary.main,
overflow: "hidden",
},
}}
+10 -11
View File
@@ -11,7 +11,6 @@ import {
updateUptimeMonitor,
pauseUptimeMonitor,
getUptimeMonitorById,
getUptimeMonitorsByTeamId,
deleteUptimeMonitor,
} from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
import TextInput from "../../../Components/Inputs/TextInput";
@@ -157,7 +156,6 @@ const Configure = () => {
const action = await dispatch(updateUptimeMonitor({ authToken, monitor: monitor }));
if (action.meta.requestStatus === "fulfilled") {
createToast({ body: "Monitor updated successfully!" });
dispatch(getUptimeMonitorsByTeamId(authToken));
} else {
createToast({ body: "Failed to update monitor." });
}
@@ -276,7 +274,7 @@ const Configure = () => {
width: 4,
height: 4,
borderRadius: "50%",
backgroundColor: theme.palette.text.tertiary,
backgroundColor: theme.palette.primary.contrastTextTertiary,
opacity: 0.8,
left: -10,
top: "50%",
@@ -307,7 +305,7 @@ const Configure = () => {
width: 22,
height: 22,
"& path": {
stroke: theme.palette.text.tertiary,
stroke: theme.palette.primary.contrastTextTertiary,
strokeWidth: 1.7,
},
},
@@ -378,14 +376,15 @@ const Configure = () => {
</Box>
<Stack gap={theme.spacing(6)}>
<Typography component="p">When there is a new incident,</Typography>
<Checkbox
{/* {Leaving components commented for future funtionality implimentation} */}
{/* <Checkbox
id="notify-sms"
label="Notify via SMS (coming soon)"
isChecked={false}
value=""
onChange={() => logger.warn("disabled")}
isDisabled={true}
/>
/> */}
<Checkbox
id="notify-email-default"
label={`Notify via email (to ${user.email})`}
@@ -397,15 +396,15 @@ const Configure = () => {
value={user?.email}
onChange={(event) => handleChange(event)}
/>
<Checkbox
{/* <Checkbox
id="notify-email"
label="Also notify via email to multiple addresses (coming soon)"
isChecked={false}
value=""
onChange={() => logger.warn("disabled")}
isDisabled={true}
/>
{monitor?.notifications?.some(
/> */}
{/* {monitor?.notifications?.some(
(notification) => notification.type === "emails"
) ? (
<Box mx={theme.spacing(16)}>
@@ -422,7 +421,7 @@ const Configure = () => {
</Box>
) : (
""
)}
)} */}
</Stack>
</ConfigBox>
<ConfigBox>
@@ -446,7 +445,7 @@ const Configure = () => {
>
<LoadingButton
variant="contained"
color="primary"
color="accent"
loading={isLoading}
sx={{ px: theme.spacing(12) }}
onClick={handleSubmit}
+40 -13
View File
@@ -50,10 +50,15 @@ const CreateMonitor = () => {
placeholder: "abc123",
namePlaceholder: "My Container",
},
port: {
label: "URL to monitor",
placeholder: "localhost",
namePlaceholder: "Localhost:5173",
},
};
const { user, authToken } = useSelector((state) => state.auth);
const { monitors, isLoading } = useSelector((state) => state.uptimeMonitors);
const { isLoading } = useSelector((state) => state.uptimeMonitors);
const dispatch = useDispatch();
const navigate = useNavigate();
const theme = useTheme();
@@ -82,6 +87,7 @@ const CreateMonitor = () => {
monitor.type === "http"
? `http${https ? "s" : ""}://` + monitor.url
: monitor.url,
port: monitor.type === "port" ? monitor.port : undefined,
name: monitor.name === "" ? monitor.url : monitor.name,
type: monitor.type,
interval: monitor.interval * MS_PER_MINUTE,
@@ -102,16 +108,16 @@ const CreateMonitor = () => {
}
if (monitor.type === "http") {
const checkEndpointAction = await dispatch(
checkEndpointResolution({ authToken, monitorURL: form.url })
);
if (checkEndpointAction.meta.requestStatus === "rejected") {
createToast({
body: "The endpoint you entered doesn't resolve. Check the URL again.",
});
setErrors({ url: "The entered URL is not reachable." });
return;
}
// const checkEndpointAction = await dispatch(
// checkEndpointResolution({ authToken, monitorURL: form.url })
// );
// if (checkEndpointAction.meta.requestStatus === "rejected") {
// createToast({
// body: "The endpoint you entered doesn't resolve. Check the URL again.",
// });
// setErrors({ url: "The entered URL is not reachable." });
// return;
// }
}
form = {
@@ -199,7 +205,7 @@ const CreateMonitor = () => {
}
};
fetchMonitor();
}, [monitorId, authToken, monitors, dispatch, navigate]);
}, [monitorId, authToken, dispatch, navigate]);
return (
<Box className="create-monitor">
@@ -252,11 +258,23 @@ const CreateMonitor = () => {
error={errors["url"] ? true : false}
helperText={errors["url"]}
/>
<TextInput
type="number"
id="monitor-port"
label="Port to monitor"
placeholder="5173"
value={monitor.port}
onChange={(event) => handleChange(event, "port")}
error={errors["port"] ? true : false}
helperText={errors["port"]}
hidden={monitor.type !== "port"}
/>
<TextInput
type="text"
id="monitor-name"
label="Display name"
isOptional={true}
placeholder={monitorTypeMaps[monitor.type].namePlaceholder || ""}
value={monitor.name}
onChange={(event) => handleChange(event, "name")}
error={errors["name"] ? true : false}
@@ -321,6 +339,15 @@ const CreateMonitor = () => {
checked={monitor.type === "docker"}
onChange={(event) => handleChange(event, "type")}
/>
<Radio
id="monitor-checks-port"
title="Port monitoring"
desc="Check whether your port is open or not."
size="small"
value="port"
checked={monitor.type === "port"}
onChange={(event) => handleChange(event, "type")}
/>
{errors["type"] ? (
<Box className="error-container">
<Typography
@@ -375,7 +402,7 @@ const CreateMonitor = () => {
>
<LoadingButton
variant="contained"
color="primary"
color="accent"
onClick={handleCreateMonitor}
disabled={!Object.values(errors).every((value) => value === undefined)}
loading={isLoading}
@@ -0,0 +1,42 @@
import PropTypes from "prop-types";
import { useSelector } from "react-redux";
import { formatDateWithTz } from "../../../../Utils/timeUtils";
const CustomLabels = ({ x, width, height, firstDataPoint, lastDataPoint, type }) => {
const uiTimezone = useSelector((state) => state.ui.timezone);
const dateFormat = type === "day" ? "MMM D, h:mm A" : "MMM D";
return (
<>
<text
x={x}
y={height}
dy={-3}
textAnchor="start"
fontSize={11}
>
{formatDateWithTz(firstDataPoint._id, dateFormat, uiTimezone)}
</text>
<text
x={width}
y={height}
dy={-3}
textAnchor="end"
fontSize={11}
>
{formatDateWithTz(lastDataPoint._id, dateFormat, uiTimezone)}
</text>
</>
);
};
CustomLabels.propTypes = {
x: PropTypes.number.isRequired,
width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
firstDataPoint: PropTypes.object.isRequired,
lastDataPoint: PropTypes.object.isRequired,
type: PropTypes.string.isRequired,
};
export default CustomLabels;
@@ -0,0 +1,92 @@
import { memo, useState } from "react";
import { useTheme } from "@mui/material";
import { ResponsiveContainer, BarChart, XAxis, Bar, Cell } from "recharts";
import PropTypes from "prop-types";
import CustomLabels from "./CustomLabels";
const DownBarChart = memo(({ monitor, type, onBarHover }) => {
const theme = useTheme();
const [chartHovered, setChartHovered] = useState(false);
const [hoveredBarIndex, setHoveredBarIndex] = useState(null);
return (
<ResponsiveContainer
width="100%"
minWidth={250}
height={155}
>
<BarChart
width="100%"
height="100%"
data={monitor.groupedDownChecks}
onMouseEnter={() => {
setChartHovered(true);
onBarHover({ time: null, totalChecks: 0 });
}}
onMouseLeave={() => {
setChartHovered(false);
setHoveredBarIndex(null);
onBarHover(null);
}}
>
<XAxis
stroke={theme.palette.primary.lowContrast}
height={15}
tick={false}
label={
<CustomLabels
x={0}
y={0}
width="100%"
height="100%"
firstDataPoint={monitor.groupedDownChecks?.[0] ?? {}}
lastDataPoint={
monitor.groupedDownChecks?.[monitor.groupedDownChecks.length - 1] ?? {}
}
type={type}
/>
}
/>
<Bar
dataKey="avgResponseTime"
maxBarSize={7}
background={{ fill: "transparent" }}
>
{monitor.groupedDownChecks.map((entry, index) => {
return (
<Cell
key={`cell-${entry.time}`}
fill={
hoveredBarIndex === index
? theme.palette.error.main
: chartHovered
? theme.palette.error.light // CAIO_REVIEW
: theme.palette.error.main
}
onMouseEnter={() => {
setHoveredBarIndex(index);
onBarHover(entry);
}}
onMouseLeave={() => {
setHoveredBarIndex(null);
onBarHover({ time: null, totalChecks: 0 });
}}
/>
);
})}
</Bar>
</BarChart>
</ResponsiveContainer>
);
});
DownBarChart.displayName = "DownBarChart";
DownBarChart.propTypes = {
monitor: PropTypes.shape({
groupedDownChecks: PropTypes.arrayOf(PropTypes.object),
}),
type: PropTypes.string,
onBarHover: PropTypes.func,
};
export default DownBarChart;
@@ -0,0 +1,117 @@
import PropTypes from "prop-types";
import { useTheme } from "@mui/material";
import { ResponsiveContainer, RadialBarChart, RadialBar, Cell } from "recharts";
const ResponseGaugeChart = ({ avgResponseTime }) => {
const theme = useTheme();
let max = 1000; // max ms
const data = [
{ response: max, fill: "transparent", background: false },
{ response: avgResponseTime, background: true },
];
let responseTime = Math.floor(avgResponseTime);
let responseProps =
responseTime <= 200
? {
category: "Excellent",
main: theme.palette.success.main,
bg: theme.palette.success.contrastText,
}
: responseTime <= 500
? {
category: "Fair",
main: theme.palette.success.main,
bg: theme.palette.success.contrastText,
}
: responseTime <= 600
? {
category: "Acceptable",
main: theme.palette.warning.main,
bg: theme.palette.warning.lowContrast,
}
: {
category: "Poor",
main: theme.palette.error.main,
bg: theme.palette.error.contrastText,
};
return (
<ResponsiveContainer
width="100%"
minWidth={210}
height={155}
>
<RadialBarChart
width="100%"
height="100%"
cy="89%"
data={data}
startAngle={180}
endAngle={0}
innerRadius={100}
outerRadius={150}
>
<text
x={0}
y="100%"
dx="5%"
dy={-2}
textAnchor="start"
fontSize={11}
>
low
</text>
<text
x="100%"
y="100%"
dx="-3%"
dy={-2}
textAnchor="end"
fontSize={11}
>
high
</text>
<text
x="50%"
y="45%"
textAnchor="middle"
dominantBaseline="middle"
fontSize={18}
fontWeight={400}
>
{responseProps.category}
</text>
<text
x="50%"
y="55%"
textAnchor="middle"
dominantBaseline="hanging"
fontSize={25}
>
<tspan fontWeight={600}>{responseTime}</tspan> <tspan opacity={0.8}>ms</tspan>
</text>
<RadialBar
background={{ fill: responseProps.bg }}
clockWise
dataKey="response"
stroke="none"
>
<Cell
fill="transparent"
background={false}
barSize={0}
/>
<Cell fill={responseProps.main} />
</RadialBar>
</RadialBarChart>
</ResponsiveContainer>
);
};
ResponseGaugeChart.propTypes = {
avgResponseTime: PropTypes.number.isRequired,
};
export default ResponseGaugeChart;
Loaded 100 of 248 files, more files were not shown because too many files have changed in this diff. Show more