Compare commits

...
Author SHA1 Message Date
Claude e4d2abd496 Add PropTypes and improve key handling in DockerContainersTable
Improvements:
- Add PropTypes validation for component props (containers, errors, captureVersion)
- Use composite key for ports map instead of index for better React reconciliation
- Ensures type safety and follows codebase PropTypes conventions

This improves code quality and prevents potential runtime issues.
2025-11-15 22:54:27 +00:00
Claude 8f3edac281 Fix DockerContainersTable to use Checkmate theme palette colors
Replace MUI shorthand color strings with proper Checkmate theme palette paths:
- color="textSecondary" → theme.palette.primary.contrastTextTertiary
- color="error.main" → theme.palette.error.main
- color="warning.main" → theme.palette.warning.main
- color="success.main" → theme.palette.success.main

This ensures consistent theming across the application and follows Checkmate component standards.
2025-11-15 22:48:45 +00:00
Claude fd9d265d23 Fix UX issues and improve Docker monitoring user experience
Critical fixes:
1. Monitor type detection on edit
   - When editing a Docker monitor, type is now correctly detected from monitor object
   - Previously defaulted to "hardware" causing incorrect form fields to show
   - Fix: Detect type from query params on create, from monitor.type on edit

2. Default interval for Docker monitors
   - Docker monitors now default to 30 seconds (0.5 minutes) on creation
   - Hardware monitors remain at 15 seconds (0.25 minutes)
   - Pass monitorType to initializeInfrastructureMonitorForCreate

3. Type-aware fallback links
   - Hardware tab empty state: links to /infrastructure/create?type=hardware
   - Docker tab empty state: links to /infrastructure/create?type=docker
   - Ensures correct form is shown when creating from empty state

UX improvements:
4. Enhanced error messaging in Docker container table
   - Differentiate between "No containers" vs "Docker daemon unavailable"
   - Show error details when Capture API fails
   - Display critical errors (docker.client) with red background
   - Show partial error messages when some containers fail to inspect

5. Display Capture metadata
   - Show Capture version in container table header
   - Display error count when errors are present (⚠ N error(s) encountered)
   - Help users identify API issues vs legitimate empty states

6. Improved empty state handling
   - "Docker daemon unavailable" - when Docker socket unreachable on Capture server
   - "No containers found" - when Capture is working but no containers exist
   - "Partial data available" - when some containers failed to inspect
   - Show specific error messages from Capture API

These changes improve the user experience when:
- Editing existing Docker monitors (correct form fields shown)
- Creating Docker monitors (proper default interval)
- Troubleshooting Capture API issues (clear error messages)
- Understanding container availability (version info, error details)
2025-11-15 22:42:02 +00:00
Claude 0a90a30045 Complete Docker monitoring integration with Capture API
This commit completes the Docker container monitoring feature using Capture API.

Frontend changes:
- Updated Infrastructure create/edit form to support Docker monitors
  - Conditional UI based on monitor type (hardware vs docker)
  - Docker-specific labels and placeholders
  - Capture server URL field (e.g., http://192.168.1.100:59232)
  - API secret field for Bearer token authentication
  - Enforced 30-second minimum polling interval for Docker
  - Conditionally hide hardware thresholds for Docker monitors

- Updated useInfrastructureSubmit hook
  - Accept monitorType parameter (hardware or docker)
  - Build form with type-specific fields
  - Only add thresholds for hardware monitors
  - Submit with correct monitor type to backend

- Created DockerContainersTable component
  - Displays all containers from Capture API response
  - Shows: container name, ID, status, health, image, uptime, ports
  - Color-coded status indicators (green=healthy, yellow=warning, red=error)
  - Formats uptime/downtime duration
  - Handles empty state gracefully

- Updated Infrastructure Details page
  - Conditionally render Docker container table for docker monitors
  - Keep existing hardware metrics (gauges, charts) for hardware monitors
  - Hide network tab for Docker monitors (not applicable)
  - Display container data from latest check

Implementation complete and ready for testing.
2025-11-15 22:33:05 +00:00
Claude 0f3c81c052 Add Docker monitoring integration with Capture API (partial implementation)
Backend changes:
- Update Check model to store Docker container data (container_id, status, health, ports, etc.)
- Refactor networkService to support both local Docker and remote Capture API
  - requestLocalDocker: Existing local Docker socket monitoring
  - requestCaptureDocker: New Capture API endpoint integration
  - requestDocker: Routes based on URL pattern (http/https vs container name)
- Update statusService to handle Docker check data storage
- Enforce proper error handling for Capture API (401, 404, 500, 207 responses)

Frontend changes:
- Add Hardware/Docker tabs to Infrastructure page
- Add query parameter support for monitor type selection
- Prepare form for Docker monitor creation (partial)

Status: Backend complete, frontend in progress
Next: Complete Docker monitor form, add container table component, test end-to-end
2025-11-15 22:27:31 +00:00
Claude 2d58facb97 Add comprehensive architecture documentation for Docker monitoring integration
Generated detailed architecture guide covering:
- Project structure and technology stack
- Monitor types and implementation patterns
- Database schema and models
- API patterns and endpoints
- Job scheduling and polling mechanisms
- Frontend components and UI structure
- Authentication and configuration flow

This documentation supports the Docker monitoring integration with Capture API.
2025-11-14 18:51:28 +00:00
Alexander Holliday 57ceac0c24 Merge pull request #3064 from bluewave-labs/statusPage-bars-centred-fix
Status page bars centred fix
2025-11-12 11:02:32 -08:00
Sajan a526bc5a3e Revert changes to lock files 2025-11-12 12:06:34 -06:00
Alexander Holliday fac4516353 Merge pull request #3058 from yuracoff18/doccumentation-fix-and-problem-solving-contributing
Fix the location from the docker images installation and addition of …
2025-11-12 09:21:37 -08:00
Alexander Holliday 4db13fb924 Update CONTRIBUTING.md 2025-11-12 09:21:02 -08:00
Sajan c97ee22e66 Move status validation inside the block 2025-11-12 10:54:55 -06:00
Sajan 98737f92af Add validation for the status prop 2025-11-12 10:34:22 -06:00
Sajan 74637f9d2a Remove fontSize 2025-11-12 10:21:26 -06:00
Sajan 69dbc2fe7a Move up/down chips next to the monitor name 2025-11-12 09:58:38 -06:00
Sajan d157e200f6 Use flex-end instead of right 2025-11-11 10:58:30 -06:00
Sajan 594540cff5 Fix centering issue for status page bars 2025-11-11 10:46:34 -06:00
Sajan 8e47e8cd3d fix formatting issue 2025-11-11 09:26:18 -06:00
Gorkem Cetin (BWL) c5d7625a06 Update installation instructions in README
Removed 'Coolify' from the list of alternatives for Checkmate installation.
2025-11-10 06:11:50 -05:00
Yura 7763c5e288 Fix the location from the docker images installation and addition of a solution from a problem i saw while installing the front 2025-11-09 01:15:05 -05:00
Yura 957988d977 Fix the location from the docker images installation and addition of a solution from a problem i saw while installing the front 2025-11-09 01:08:56 -05:00
Yura 0c04c06d4e centred the bars in status page UI 2025-11-09 00:45:33 -05:00
Yura a7ef014b92 centred the bars in status page UI 2025-11-09 00:41:02 -05:00
Yura 3822d971cb centred the bars in status page UI 2025-11-09 00:28:14 -05:00
Alexander Holliday 7cb985116e Merge pull request #3050 from TudorGR/chore/status-page-include-game-type-3048
feat: include game monitor type in status page monitor selection
2025-11-03 09:20:29 -08:00
Alexander Holliday 2297494d21 Merge pull request #3055 from matserix/develop
feat(kubernetes): support Storage Classes other than 'gp3'
2025-11-03 09:19:54 -08:00
matserix 19a61b6ce4 fix: update installation guide and values for MongoDB and Redis storage classes 2025-11-03 01:10:45 +01:00
matserix 492aed200a feat: support Storage Classes other than 'gp3' 2025-11-03 00:44:57 +01:00
Alexander Holliday be2f33b5d1 Merge pull request #3052 from bluewave-labs/fix/addjob
fix missing param
2025-10-30 10:58:45 -07:00
Alex Holliday 5d48cecee8 fix missing param 2025-10-30 10:57:48 -07:00
Gorkem Cetin (BWL) f0bfe1a152 Merge pull request #3049 from magicpages/detailed-response-times
fix: use sentence case for tooltip labels
2025-10-30 10:38:39 -04:00
Tudor Gradinaru d2ff386f97 feat: include game monitor type in status page monitor selection 2025-10-30 11:37:43 +02:00
Jannis Fedoruk-Betschki 42eaa75437 fix: use sentence case for tooltip labels 2025-10-30 07:25:48 +01:00
Alexander Holliday 7fb4e75956 Merge pull request #3047 from magicpages/detailed-response-times
feat: add detailed response time breakdown in Response Times table
2025-10-29 19:11:08 -07:00
Jannis Fedoruk-Betschki 87c549960e fix: use array parameter instead of closure for i18n-safe bold styling 2025-10-29 20:33:14 +01:00
Jannis Fedoruk-Betschki 4ac0f1e87f feat: add detailed response time breakdown in Response Times table 2025-10-29 20:22:57 +01:00
Alexander Holliday 5465bee630 Merge pull request #3046 from bluewave-labs/feat/cleanup
prune
2025-10-29 10:04:11 -07:00
Alex Holliday 60a3d46e59 prune 2025-10-29 10:03:16 -07:00
Gorkem Cetin (BWL) e100d54eed Simplify README by removing redundant content
Removed redundant section about Checkmate's codebase walkthrough and dataflow simulation tutorial.
2025-10-29 07:28:09 -04:00
Gorkem Cetin (BWL) 848d50ec43 Merge pull request #3043 from Abdullah85MBA/codecanvas-diagram-1761668096103
Added interactive CodeCanvas diagram for Checkmate
2025-10-29 07:26:29 -04:00
Alexander Holliday a9a8686295 Merge pull request #3044 from bluewave-labs/fix/cache-dns
add cacheable dns, stagger start times
2025-10-29 01:17:22 -07:00
Alex Holliday 30a9309bd8 add cacheable dns, stagger start times 2025-10-28 22:41:05 -07:00
Abi ab64cd192b Updated Readme screenshot 2025-10-28 12:29:59 -04:00
Abi 5fc2c8c14b Add CodeCanvas diagram to README 2025-10-28 12:15:26 -04:00
Abi ea7ce450f1 Merge develop into codecanvas-diagram-1761668096103 to sync with upstream 2025-10-28 12:15:00 -04:00
Abi ce77b43705 CodeCanvas: Save 2025-10-28 12:14:58 -04:00
Alexander Holliday bd2ba804ee Merge pull request #3040 from bluewave-labs/feat/bump-version
bump version
2025-10-27 10:30:23 -07:00
Alexander Holliday bd75f7b0fc Merge pull request #3041 from bluewave-labs/translation-update-80
🌐 Updated Translations from POEditor
2025-10-27 10:30:07 -07:00
GitHub Action 32e4f7514d feat: translations updated from POEditor 2025-10-27 17:29:47 +00:00
Alex Holliday c9e1d35daf bump version 2025-10-27 10:27:45 -07:00
Alexander Holliday 3be6ae91f2 Merge pull request #3039 from bluewave-labs/fix/bump-scheduler
bump-scheduler
2025-10-27 09:46:23 -07:00
Alex Holliday 931104fbcf type error 2025-10-27 09:45:21 -07:00
Alex Holliday 1d5cec94a5 bump-scheduler 2025-10-27 09:42:27 -07:00
Alexander Holliday faeec01a6d Merge pull request #3029 from LinPr/fix
fix/v1: Remove unnecessary import
2025-10-27 09:37:38 -07:00
Alexander Holliday b8db987579 Merge pull request #3037 from TudorGR/feat/matrix-notifications
feat: Add Matrix notification support
2025-10-27 09:36:09 -07:00
Tudor Gradinaru 1fad85d48d feat: Add Matrix notification support Fixes #3034 2025-10-25 18:35:15 +03:00
Alexander Holliday eb70c9f5f0 Merge pull request #3036 from TudorGR/feature/add-monitor-name-to-notification-title
feat: Add monitor name to notification titles
2025-10-23 09:38:29 -07:00
Tudor Gradinaru ce025df7b7 feat: Add monitor name to notification titles 2025-10-23 15:32:29 +03:00
Alexander Holliday daf5797fed Merge pull request #3031 from bluewave-labs/translation-update-79
🌐 Updated Translations from POEditor
2025-10-20 10:36:43 -07:00
GitHub Action 0baa7d9891 feat: translations updated from POEditor 2025-10-20 17:36:14 +00:00
Gorkem Cetin (BWL) f6cd0f668f Merge pull request #3028 from bluewave-labs/feat/remove-unused-css-variables
Got an OK from Owaise.
2025-10-20 09:22:52 -04:00
LinPr 9ae83cc34d fix/v1: remove unnecessary import 2025-10-20 14:22:20 +08:00
gorkem-bwlandClaude 06ebb76948 chore: remove 13 unused CSS variables from index.css
Removed the following unused CSS variables that were leftovers from when
the project switched to the MUI theme system:

- --env-var-radius-1
- --env-var-width-1
- --env-var-width-3
- --env-var-height-1
- --env-var-spacing-3
- --env-var-spacing-4
- --env-var-spacing-5
- --env-var-img-width-1
- --env-var-img-width-2
- --env-var-img-width-3
- --env-var-default-1
- --env-var-default-2
- --env-var-shadow-1

These variables are not referenced anywhere in the codebase. The project
now uses MUI theme configuration (theme.spacing(), theme.palette.*)
instead of CSS variables for styling.

Kept 19 CSS variables that are still actively used during the migration
to pure MUI theme.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-19 23:18:50 -04:00
Alexander Holliday 3a8ba154b2 Merge pull request #2992 from AlexHladin/chore/drop-nodemon
chore: drop nodemon
2025-10-17 20:03:45 -07:00
Alexander Holliday 089801109e Merge pull request #3018 from bluewave-labs/v2-select-component
Add Select component v2 with TypeScript and improved code efficiency
2025-10-14 13:24:33 -07:00
karenvicent a8a4b5c2b4 Merge branch 'develop' into v2-select-component 2025-10-14 15:58:52 -04:00
Alexander Holliday 089bda2de0 Merge pull request #3023 from bluewave-labs/fix/v2-utils
move v2 utils to v2 dir
2025-10-14 12:45:34 -07:00
Alex Holliday e18e2e26da move v2 utils to v2 dir 2025-10-14 12:45:11 -07:00
karenvicent 104cf194ac fix create more specific component 2025-10-14 12:22:20 -04:00
Alexander Holliday de7cdb4aef Merge pull request #3019 from bluewave-labs/feature/monitor-grouping-backend
feat: Add monitor grouping functionality (Backend)
2025-10-14 09:05:34 -07:00
gorkem-bwlandClaude 6bdf9891e8 Fix server formatting issues
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 21:51:06 -04:00
gorkem-bwlandClaude 27d37ece7d feat: Add monitor grouping functionality to backend
- Add optional 'group' field to Monitor schema with trimming and validation
- Add group validation to Joi schemas for create and edit monitor endpoints
- Add GET /api/v1/monitors/team/groups endpoint to fetch unique groups
- Implement case-insensitive group filtering in database layer
- Support for organizing monitors into collapsible groups

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 21:11:20 -04:00
karenvicent b9afca3608 Merge branch 'develop' into v2-select-component 2025-10-09 18:25:38 -04:00
karenvicent b796464241 select component V2 2025-10-09 18:16:25 -04:00
Alexander Holliday 97a14ed926 Merge pull request #3017 from bluewave-labs/fix/v2/sticky-sidebar
fix/v2: sticky sidebar
2025-10-09 14:00:35 -07:00
Alex Holliday 5018c56d0d stikcy sidebar 2025-10-09 14:00:04 -07:00
Alexander Holliday c7799ca7dc Merge pull request #3016 from bluewave-labs/fix/v2/normalization
Fix/v2/normalization
2025-10-09 13:56:10 -07:00
Alex Holliday 78b5cc9c6f ts 2025-10-09 13:55:39 -07:00
Alex Holliday ab3e6cdff9 normalzie on FE 2025-10-09 13:53:34 -07:00
Alexander Holliday 1cc01e6952 Merge pull request #3015 from bluewave-labs/feat/v2/fallbacks
feat/v2: add fallbacks
2025-10-09 12:46:19 -07:00
Alex Holliday fb90f193b1 add fallbacks 2025-10-09 12:44:27 -07:00
Alexander Holliday 1bacab89bb Merge pull request #3014 from bluewave-labs/fix/v2/auth-pages
fix/v2: add missing auth elements
2025-10-09 11:07:43 -07:00
Alex Holliday 7378f2e33b add missing auth elements 2025-10-09 11:06:34 -07:00
Alexander Holliday d0bb2b2ad5 Merge pull request #3013 from bluewave-labs/fix/network-timing
fix network timing for port and docker
2025-10-09 09:35:41 -07:00
Alex Holliday 376da7c70e fix network timing for port and docker 2025-10-09 09:33:14 -07:00
Alexander Holliday d58e5cf7ee Merge pull request #3012 from bluewave-labs/fix/keep-previous-data
fix/v2: add keep previous data
2025-10-08 15:29:41 -07:00
Alex Holliday e02eb2e30c add keep previous data 2025-10-08 15:27:53 -07:00
Alexander Holliday c4906d069a Merge pull request #3009 from bluewave-labs/feat/v2-implement-actions
update usePatch, implement actions
2025-10-08 15:00:43 -07:00
Alex Holliday d4ed535454 update prod env 2025-10-08 14:52:21 -07:00
Alex Holliday f9d0ab5e07 update usePatch, implement actions 2025-10-08 14:28:51 -07:00
Alexander Holliday 0a5efc75cd Merge pull request #3008 from bluewave-labs/feat/v2/uptime-details
feat/v2/uptime details
2025-10-08 13:48:05 -07:00
Alex Holliday aae1fefb31 add checks endpoint 2025-10-08 13:45:07 -07:00
Alex Holliday 86bb28e239 pagination 2025-10-08 13:44:41 -07:00
Alex Holliday 16b68b3d00 rever types 2025-10-07 15:46:35 -07:00
Alex Holliday a700f446fd add header 2025-10-07 15:46:09 -07:00
Alex Holliday 2246f227d1 30m -> 2h 2025-10-07 14:45:07 -07:00
Alex Holliday 29fbf0a362 charts 2025-10-07 14:44:55 -07:00
Alex Holliday 8a1fc94c31 stat boxes 2025-10-06 15:08:55 -07:00
Alex Holliday abadc99bf1 status 2025-10-06 13:59:31 -07:00
Alexander Holliday 7af7647bbf Merge pull request #2999 from bluewave-labs/feat-allow-admin-change-passwords
Add superadmin password reset functionality for team members
2025-10-06 12:52:46 -07:00
karenvicent 9a24090337 fix variable name 2025-10-06 15:43:17 -04:00
karenvicent d81a4ef0ee fix user service 2025-10-06 15:15:56 -04:00
Alexander Holliday cfb1830b55 Merge pull request #3005 from bluewave-labs/feat/v2/uptime
Feat/v2/uptime
2025-10-06 11:48:39 -07:00
Alex Holliday f7c094317a remove unused 2025-10-06 11:43:13 -07:00
Alex Holliday 56e0ac9640 actions menu 2025-10-06 11:40:08 -07:00
Alex Holliday 61651a0f4d action menu 2025-10-06 11:34:29 -07:00
Alex Holliday 7c3a05077c tooltip 2025-10-06 10:56:29 -07:00
Gorkem Cetin (BWL) 2d29bce97b Update CONTRIBUTING.md 2025-10-06 12:35:23 -04:00
Alexander Holliday 4f45baab00 Merge pull request #3003 from evermos/develop
Add Affinity, Tolerations, Request limit
2025-10-06 09:00:57 -07:00
Alexander Holliday 6def64d38e Merge pull request #3004 from bluewave-labs/fix/incident/numbers
Fix: Total Incident Number
2025-10-06 08:58:23 -07:00
Br0wnHammer 32b31076e6 Fix: Total Incident Number 2025-10-06 20:14:21 +05:30
ariretiarno 91a4911d42 protocol 2025-10-05 22:49:20 +07:00
ariretiarno 7298faac2b protocol 2025-10-05 22:47:48 +07:00
ariretiarno 711253beb2 affinity request limit 2025-10-05 22:36:39 +07:00
ariretiarno a380389386 ingress server 2025-10-05 22:25:33 +07:00
Alex Holliday f6b97c691e iniital uptime 2025-10-03 15:40:53 -07:00
karenvicent f31ff994fe fix errors 2025-10-03 17:11:05 -04:00
Alexander Holliday a46ef5c9dd Merge pull request #3001 from bluewave-labs/fix/v2/text-input
theme update
2025-10-03 12:57:33 -07:00
Alex Holliday 0018c452bb theme update 2025-10-03 12:56:52 -07:00
Alexander Holliday 6c6fc28f6e Merge pull request #3000 from bluewave-labs/feat/v2/create/uptime
feat/v2/create/uptime
2025-10-03 12:50:31 -07:00
Alex Holliday 575cf31c78 add typescript dev dep 2025-10-03 12:49:51 -07:00
Alex Holliday 938d9b6642 feat/v2/uptime/create 2025-10-03 12:45:21 -07:00
Gorkem Cetin (BWL) 9d68d35ca8 Merge pull request #2996 from JithendraKavala/docs/imporove-contributing-setup-instructions
docs: improve local development setup instructions in CONTRIBUTING.md
2025-10-03 15:34:18 -04:00
Alexander Holliday 8033eea267 Merge pull request #2997 from a-y-a-n-das/fix-week-datestring
fix(chart): correct 'week' date string format in chart aggregation
2025-10-02 13:35:40 -07:00
Alexander Holliday 469c4d7e99 Merge pull request #2994 from VivekKavala/fix-inaccurate-ping-times
fix: Correct inaccurate ping response times
2025-10-02 13:34:11 -07:00
karenvicent 5159d43cad fix save button validation 2025-10-02 15:40:21 -04:00
karenvicent c5bbb7aa2c Merge branch 'develop' into feat-allow-admin-change-passwords 2025-10-02 15:20:32 -04:00
karenvicent 4317d1a47e chace password by superadmin 2025-10-02 15:19:42 -04:00
a-y-a-n-das a1c04ba35e fixed the format 2025-10-02 20:43:00 +05:30
Alexander Holliday 95ad3e71ca Merge pull request #2987 from bluewave-labs/feat/v2/components
feat: move components to v1 and v2 dirs
2025-10-02 17:22:20 +05:30
AlexHladin 8bf3875d9a chore: add engines section to package.json 2025-10-02 14:17:23 +03:00
jithendra Kavala 080a33fac7 docs: improve local development setup instructions in CONTRIBUTING.md 2025-10-02 13:51:30 +05:30
Vivek Kavala 851d722746 fix: remove manual response time calculation in favor of library-native timing
The manual timing calculations were adding Node.js processing overhead
and were less accurate than the native timing provided by the respective
libraries (ping, got, etc.). Now using response.time from each library
for more accurate network response time measurements.
2025-10-02 12:46:51 +05:30
AlexHladin 3b22ce75db chore: drop nodemon 2025-10-02 00:47:11 +03:00
Alexander Holliday 5dbfb3b8c5 Merge pull request #2991 from bluewave-labs/feat/v2/sidebar
feat: v2/sidebar
2025-10-01 13:58:26 -07:00
Alex Holliday 735054b4e1 remove unused error 2025-10-01 13:57:04 -07:00
Alex Holliday 3ae2f857d4 add v2 sidebar 2025-10-01 13:55:32 -07:00
Alexander Holliday 220abb8579 Merge pull request #2989 from evermos/helmchart
helm chart
2025-10-01 13:34:50 -07:00
karenvicent 468a67f937 git stash push -m "work in progress" 2025-10-01 12:49:48 -04:00
Muhamad Ari Retiarno 99b3e3c516 Merge pull request #1 from evermos/helmchart
Helmchart
2025-10-01 11:06:47 +07:00
ariretiarno 8d48b2cc8a client host 2025-10-01 09:33:32 +07:00
ariretiarno d63731fced client host 2025-10-01 09:22:42 +07:00
ariretiarno 7a352cdcb3 client host 2025-10-01 09:16:45 +07:00
ariretiarno 4744c05f07 pvc 2025-09-30 11:35:14 +07:00
ariretiarno c6cf7a4639 helm chart 2025-09-30 11:30:21 +07:00
ariretiarno 7f2318da01 helm chart 2025-09-30 11:28:22 +07:00
Alex Holliday fc9018e314 Add collapse button and logo 2025-09-27 15:47:56 -07:00
Alexander Holliday c30d6019df Merge pull request #2987 from bluewave-labs/feat/v2/components
feat: move components to v1 and v2 dirs
2025-09-27 14:58:11 -07:00
Alex Holliday b57ed47592 remove mode prop 2025-09-27 14:57:55 -07:00
Alexander Holliday 6234be17cd Merge pull request #2986 from bluewave-labs/feat/v2/root/layout
feat/v2/root/layout
2025-09-27 14:55:17 -07:00
Alex Holliday 5cab842f0a move components to v1 and v2 dirs 2025-09-27 14:54:55 -07:00
Alex Holliday ca84c60614 Merge branch 'feat/v2/root/layout' of github.com:bluewave-labs/checkmate into feat/v2/root/layout 2025-09-27 14:48:44 -07:00
Alex Holliday 09fbc6b0b2 remove unused mode 2025-09-27 14:48:05 -07:00
Alexander Holliday f8b1998564 Merge branch 'develop' into feat/v2/root/layout 2025-09-27 14:43:18 -07:00
Alex Holliday 4d254b004d add gitignore 2025-09-27 14:38:14 -07:00
Alex Holliday 1d5f2427ed add root layout 2025-09-26 16:01:05 -07:00
Alexander Holliday 0249f89a8c Merge pull request #2984 from bluewave-labs/feat/v2/router
move v2 routes to v2 router
2025-09-26 15:33:23 -07:00
Alex Holliday ce0aaa7ac7 move v2 routes to v2 router 2025-09-26 15:31:55 -07:00
Alexander Holliday b7db3f96ba Merge pull request #2983 from bluewave-labs/feat/v2/register
add v2 register page
2025-09-26 15:25:41 -07:00
Alex Holliday ad5ab82c3b add v2 register page 2025-09-26 15:23:56 -07:00
Alexander Holliday 0567569faa Merge pull request #2982 from bluewave-labs/feat/v2/theme
feat: add typography to theme, change UsePost return type
2025-09-26 15:23:23 -07:00
Alex Holliday a8f111b399 generic return type 2025-09-26 15:22:15 -07:00
Alex Holliday 7c2f789a31 add typography to theme, change UsePost return type 2025-09-26 15:19:35 -07:00
Alexander Holliday 77c76b6b6d Merge pull request #2981 from bluewave-labs/feat/v2/auth/login
feat/v2/auth/login
2025-09-26 14:49:21 -07:00
Alex Holliday 60a90ce424 node types 2025-09-26 14:36:15 -07:00
Alex Holliday 3f581ae1b0 esm safe path 2025-09-26 14:32:16 -07:00
Alex Holliday 277aff3898 remove unused 2025-09-26 14:22:25 -07:00
Alex Holliday 0c5b9a863b add loading 2025-09-26 14:16:59 -07:00
Alex Holliday cb1e10f0a9 add v2 login page 2025-09-25 16:06:52 -07:00
Alexander Holliday 659162d60c Merge pull request #2980 from bluewave-labs/feat/typescript-config
Add typescript config, move to v1 dir
2025-09-25 10:23:15 -07:00
Alex Holliday 28ef465b3a update action name 2025-09-25 10:22:47 -07:00
Alex Holliday e29f7af858 add client build check 2025-09-25 10:21:31 -07:00
Alex Holliday 17b84cbe8a format 2025-09-25 10:19:08 -07:00
Alex Holliday 4d89213e1c Add typescript config, move to v1 dir 2025-09-25 10:11:41 -07:00
Alexander Holliday 879cbb8886 Merge pull request #2979 from bluewave-labs/fix/start-v2-queue
create and start v2 queue
2025-09-25 09:47:21 -07:00
Alex Holliday 5957479d03 express type 2025-09-25 09:46:11 -07:00
Alexander Holliday d7bc9bdb90 Merge pull request #2978 from bluewave-labs/feat/v2/routes
add v2 routes, controllers
2025-09-25 09:43:54 -07:00
Alex Holliday 811a6bf222 create and start v2 queue 2025-09-25 09:38:41 -07:00
Alex Holliday 6d0c560948 add v2 routes, controllers 2025-09-24 15:55:09 -07:00
Alexander Holliday f4b76baaa2 Merge pull request #2977 from bluewave-labs/feat/v2/services
feat/v2/services
2025-09-24 14:21:28 -07:00
Alex Holliday 76f4e974db dev types 2025-09-24 14:20:30 -07:00
Alex Holliday 66e5441bdf fix import path 2025-09-23 15:23:20 -07:00
Alex Holliday 68f4adfbfe add v2 services 2025-09-23 15:22:08 -07:00
Alexander Holliday 35a712eafb Merge pull request #2976 from bluewave-labs/feat/v2/models
feat: add v2 models
2025-09-23 14:57:03 -07:00
Alex Holliday 2d12fbdff1 fix notification schema 2025-09-23 14:56:02 -07:00
Alex Holliday c0ff162ed9 remove v2 files 2025-09-23 14:46:32 -07:00
Alex Holliday 059408f098 add v2 models 2025-09-23 14:40:57 -07:00
Alexander Holliday b118a321b9 Merge pull request #2975 from bluewave-labs/feat/v1/structure
feat/v1/structure
2025-09-23 14:25:46 -07:00
Alex Holliday b3b6f1d834 move all v1 files to v1 dirs 2025-09-23 14:23:45 -07:00
Alex Holliday 1383d8b59a add workflow 2025-09-23 14:12:17 -07:00
Alex Holliday 990aed9f2e Revert "Merge pull request #2973 from bluewave-labs/feat/v2/auth"
This reverts commit 72882fded9, reversing
changes made to bfb299cfca.
2025-09-23 14:05:23 -07:00
Alex Holliday 003d419a64 Revert "Merge pull request #2974 from bluewave-labs/fix/cleanup"
This reverts commit 7368cb2567, reversing
changes made to 72882fded9.
2025-09-23 14:05:16 -07:00
Alexander Holliday 7368cb2567 Merge pull request #2974 from bluewave-labs/fix/cleanup
move v1 to v1 dir, add build workflow
2025-09-23 12:00:06 -07:00
Alex Holliday f945a27011 move v1 to v1 dir, add build workflow 2025-09-23 11:59:02 -07:00
Alexander Holliday 72882fded9 Merge pull request #2973 from bluewave-labs/feat/v2/auth
feat: v2/auth
2025-09-23 11:45:39 -07:00
Alex Holliday 0030394008 add migrations table 2025-09-23 11:34:25 -07:00
Alexander Holliday bfb299cfca Merge pull request #2972 from bluewave-labs/fix/update-docker-files
fix/update docker files
2025-09-23 11:01:19 -07:00
Alexander Holliday b06d5c10ea Merge pull request #2971 from bluewave-labs/feat/v2-controllers
Feat/v2 controllers
2025-09-23 11:00:40 -07:00
Alexander Holliday 2a0d4195a1 Merge pull request #2970 from bluewave-labs/feat/v2-routes
feat: v2 routes
2025-09-23 11:00:18 -07:00
Alex Holliday 11ff99613a implement auth routes, add user migration 2025-09-22 15:56:41 -07:00
Alex Holliday 0b646ee64f update docker files to build 2025-09-22 13:26:45 -07:00
Alex Holliday 23126a92cd move v1 controllers to v1 dir 2025-09-22 13:04:45 -07:00
Alex Holliday f767125acd tsx, tpyescript 2025-09-22 13:03:54 -07:00
Alex Holliday d8ed9abebf add gitignore 2025-09-22 12:53:44 -07:00
613 changed files with 27903 additions and 12220 deletions

No files matched your search

+40
View File
@@ -0,0 +1,40 @@
name: Build Check (Client & Server)
on:
pull_request:
workflow_dispatch:
jobs:
build-client:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 22
- name: Install client dependencies
working-directory: client
run: npm install
- name: Check client build
working-directory: client
run: npm run build
build-server:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 22
- name: Install server dependencies
working-directory: server
run: npm install
- name: Check server build
working-directory: server
run: npm run build
+1
View File
@@ -88,3 +88,4 @@ jobs:
docker compose down
docker compose pull
docker compose up -d
docker system prune -af
+3 -1
View File
@@ -1 +1,3 @@
.vscode
.idea
.vscode
.VSCodeCounter
+993
View File
@@ -0,0 +1,993 @@
# Checkmate Codebase Architecture - Docker Monitoring Integration Guide
## 1. PROJECT STRUCTURE
### Directory Layout
```
Checkmate/
├── server/ # Backend Node.js/Express
│ ├── src/
│ │ ├── db/v1|v2/ # Database (MongoDB)
│ │ ├── service/v1|v2/ # Business logic
│ │ ├── routes/v1|v2/ # API routes
│ │ ├── controllers/v1|v2/ # HTTP request handlers
│ │ ├── middleware/v1/ # Express middleware
│ │ ├── config/ # Service initialization
│ │ ├── validation/ # Input validation
│ │ └── utils/ # Helper functions
│ └── package.json # Dependencies (Node >=20)
├── client/ # Frontend React + TypeScript
│ ├── src/
│ │ ├── Components/v1|v2/ # UI Components
│ │ ├── Pages/v1|v2/ # Page layouts
│ │ ├── Hooks/ # React hooks (data fetching)
│ │ ├── Features/ # Redux slices
│ │ └── Utils/ # Utilities & API client
│ └── package.json # React, Vite, MUI
└── docker/ # Deployment configs
```
### Technology Stack
**Backend:**
- Express 4.19 (HTTP server)
- MongoDB 8.3 (database)
- Mongoose (ODM)
- BullMQ 5.41 (job queue) - V2 only
- super-simple-scheduler 1.4 (job scheduling) - V1
- Dockerode 4.0.6 (Docker API client)
- JWT authentication
- Winston (logging)
**Frontend:**
- React 18.3 + TypeScript
- Vite (build tool)
- MUI v6 (Material-UI)
- Redux Toolkit (state management)
- Axios (HTTP client)
- React Router (navigation)
- i18next (internationalization)
**Architectures:**
- V1: Simpler, SuperSimpleQueue-based job scheduling
- V2: TypeScript-based, BullMQ, more structured (in development)
---
## 2. MONITOR TYPES & IMPLEMENTATION
### Supported Monitor Types
Defined in `/server/src/db/v1/models/Monitor.js` line 46:
```javascript
type: {
enum: ["http", "ping", "pagespeed", "hardware", "docker", "port", "game"],
required: true
}
```
### How Monitor Types Are Handled
#### Request Dispatch (NetworkService)
**Location:** `/server/src/service/v1/infrastructure/networkService.js` (580 lines)
Entry point: `requestStatus(monitor)` - Routes to type-specific handlers:
```javascript
async requestStatus(monitor) {
switch(monitor.type) {
case "ping": return await this.requestPing(monitor);
case "http": return await this.requestHttp(monitor);
case "pagespeed": return await this.requestPageSpeed(monitor);
case "hardware": return await this.requestHardware(monitor);
case "docker": return await this.requestDocker(monitor);
case "port": return await this.requestPort(monitor);
case "game": return await this.requestGame(monitor);
}
}
```
#### DOCKER IMPLEMENTATION (Lines 289-383)
```javascript
async requestDocker(monitor) {
// Uses Dockerode to connect to /var/run/docker.sock
const docker = new this.Docker({
socketPath: "/var/run/docker.sock",
handleError: true,
});
// Container matching (priority-based):
// 1. Exact full ID match (64-char)
// 2. Exact name match (case-insensitive)
// 3. Partial ID match (backwards compatibility)
// Returns: { status: bool, code: int, message: string, responseTime: ms }
}
```
**Docker Monitor Storage:**
- `monitor.url`: Container ID or name (e.g., "my-app" or "a1b2c3d4...")
- `monitor.port`: Not used for Docker
- Returns: Only status and response time (no detailed metrics)
#### HARDWARE IMPLEMENTATION (Lines 279-287)
```javascript
async requestHardware(monitor) {
return await this.requestHttp(monitor); // Delegates to HTTP!
}
```
Hardware monitors send HTTP requests to Capture API endpoint with secret authentication.
### Hardware/Docker Check Data Structure
**Location:** `/server/src/db/v1/models/Check.js` (176 lines)
Check schema includes:
```javascript
// Common fields
monitorId, teamId, type, status, responseTime, message
// Hardware/Docker specific (capture data):
cpu: {
physical_core, logical_core, frequency, temperature[],
free_percent, usage_percent
},
memory: {
total_bytes, available_bytes, used_bytes, usage_percent
},
disk: [{
read_speed_bytes, write_speed_bytes,
total_bytes, free_bytes, usage_percent
}],
host: { os, platform, kernel_version },
errors: [{ metric[], err }],
capture: { version, mode },
net: [{ name, bytes_sent, bytes_recv, ... }]
```
**TTL:** Auto-deletes after 30 days
**Indexes:** monitorId, type, status, updatedAt (optimized for queries)
---
## 3. DATABASE SCHEMA
### Core Models
#### Monitor Model
**File:** `/server/src/db/v1/models/Monitor.js` (208 lines)
```javascript
{
userId: ObjectId (immutable, required),
teamId: ObjectId (immutable, required),
name: String (required),
description: String,
type: String (enum: http|ping|pagespeed|hardware|docker|port|game),
url: String (required) // container name/ID for docker
port: Number,
interval: Number (ms, default: 60000),
isActive: Boolean (default: true),
status: Boolean, // Current up/down
statusWindow: [Boolean], // Last N checks
statusWindowSize: Number (default: 5),
statusWindowThreshold: Number (default: 60),
// Hardware/Docker thresholds
thresholds: {
usage_cpu: Number (0-1),
usage_memory: Number (0-1),
usage_disk: Number (0-1),
usage_temperature: Number
},
// Notification thresholds
alertThreshold: Number (default: 5),
cpuAlertThreshold, memoryAlertThreshold, diskAlertThreshold, tempAlertThreshold,
// Relationships
notifications: [ObjectId], // refs to Notification model
// Advanced
secret: String, // For Capture API auth
ignoreTlsErrors: Boolean,
jsonPath: String,
expectedValue: String,
matchMethod: String (equal|include|regex),
gameId: String,
group: String (max 50 chars),
// Computed
uptimePercentage: Number,
timestamps: true // createdAt, updatedAt
}
// Indexes
MonitorSchema.index({ teamId: 1, type: 1 });
// Pre-hooks
pre("findOneAndDelete"): Deletes checks, stats, removes from status pages
pre("deleteMany"): Cascade deletes
pre("save"): Syncs alertThresholds
pre("findOneAndUpdate"): Updates thresholds
```
#### Check Model
**File:** `/server/src/db/v1/models/Check.js`
```javascript
{
monitorId: ObjectId (ref: Monitor, immutable, indexed),
teamId: ObjectId (ref: Team, immutable, indexed),
type: String (enum: http|ping|pagespeed|hardware|docker|port|game, indexed),
status: Boolean (indexed),
responseTime: Number,
timings: Object,
statusCode: Number,
message: String,
// Acknowledgment
ack: Boolean (default: false),
ackAt: Date,
// Hardware fields (see above)
cpu, memory, disk[], host, errors[], capture, net[]
// PageSpeed only
accessibility, bestPractices, seo, performance, audits,
// Expiry
expiry: Date (TTL index: 30 days),
timestamps: true
}
// Indexes
CheckSchema.index({ updatedAt: 1 });
CheckSchema.index({ monitorId: 1, updatedAt: 1 });
CheckSchema.index({ monitorId: 1, updatedAt: -1 });
CheckSchema.index({ teamId: 1, updatedAt: -1 });
```
#### MonitorStats Model
**File:** `/server/src/db/v1/models/MonitorStats.js`
```javascript
{
monitorId: ObjectId (ref: Monitor, immutable, indexed),
avgResponseTime: Number,
totalChecks: Number,
totalUpChecks: Number,
totalDownChecks: Number,
uptimePercentage: Number,
lastCheckTimestamp: Number,
lastResponseTime: Number,
timeOfLastFailure: Number,
timestamps: true
}
```
### Database Access Layer
**Location:** `/server/src/db/v1/modules/`
- `MonitorModule.js` (593 lines) - Monitor CRUD + aggregations
- `CheckModule.js` - Check recording
- `MonitorModuleQueries.js` - MongoDB aggregation pipelines
**Key Methods:**
```javascript
// Creation
Monitor.createMonitor({ body, teamId, userId })
Monitor.createBulkMonitors(monitors)
// Retrieval
Monitor.getMonitorById(id)
Monitor.getMonitorsByTeamId()
Monitor.getMonitorStatsById()
Monitor.getHardwareDetailsById()
// Updates
Monitor.updateMonitor(id, updateData)
// Deletions
Monitor.deleteMonitor(id)
```
---
## 4. API PATTERNS
### REST Endpoint Structure
**Base:** `/api/v1/`
#### Monitor Routes
**File:** `/server/src/routes/v1/monitorRoute.js`
```
GET /monitors getAllMonitors
POST /monitors createMonitor
DELETE /monitors deleteAllMonitors (superadmin)
GET /monitors/:monitorId getMonitorById
PUT /monitors/:monitorId editMonitor (admin)
DELETE /monitors/:monitorId deleteMonitor (admin)
GET /monitors/team getMonitorsByTeamId
GET /monitors/team/with-checks getMonitorsWithChecksByTeamId
GET /monitors/team/summary getMonitorsSummaryByTeamId
GET /monitors/team/groups getGroupsByTeamId
GET /monitors/stats/:monitorId getMonitorStatsById
GET /monitors/uptime/details/:monitorId getUptimeDetailsById
GET /monitors/hardware/details/:monitorId getHardwareDetailsById
POST /monitors/pause/:monitorId pauseMonitor (admin)
POST /monitors/demo addDemoMonitors
POST /monitors/bulk createBulkMonitors (CSV upload)
POST /monitors/test-email sendTestEmail
GET /monitors/games getAllGames
GET /monitors/certificate/:monitorId fetchCertificate
```
#### Check Routes
**File:** `/server/src/routes/v1/checkRoute.js`
```
GET /checks/:monitorId getChecksByMonitorId
GET /checks/team/:teamId getChecksByTeamId
GET /checks/:monitorId/:checkId getCheckById
PUT /checks/:checkId updateCheck (ack)
```
### Request/Response Pattern
**Create Monitor Request:**
```javascript
POST /api/v1/monitors
Authorization: Bearer <JWT>
Content-Type: application/json
{
name: "My Docker Container",
description: "Monitors app container",
type: "docker",
url: "my-app-container", // Container name
interval: 60000, // 1 minute
isActive: true,
secret: "api-key-for-capture", // If using hardware monitoring
notifications: ["notif-id-1"],
thresholds: {
usage_cpu: 0.8, // 80%
usage_memory: 0.9, // 90%
usage_disk: 0.95
},
alertThreshold: 5, // Consecutive failures
statusWindowSize: 5, // Last 5 checks
statusWindowThreshold: 60 // % threshold
}
Response 200:
{
data: {
_id: "monitor-id",
name: "My Docker Container",
type: "docker",
status: true,
interval: 60000,
...
},
msg: "Monitor created successfully"
}
```
**Edit Monitor Request:**
```javascript
PUT /api/v1/monitors/:monitorId
{
name: "Updated Name",
interval: 120000,
thresholds: { usage_cpu: 0.85 },
// Partial updates allowed
}
```
### Authentication & Authorization
**JWT Middleware:** `/server/src/middleware/v1/verifyJWT.js`
- Header: `Authorization: Bearer <token>`
- Validates signature using `jwtSecret` from AppSettings
- Extracts user info: `req.user = { userId, teamId, role, ... }`
**Role-Based Access:**
```javascript
// isAllowed middleware checks req.user.role
router.post("/monitors", isAllowed(["admin", "superadmin"]), createMonitor);
router.delete("/monitors/:monitorId", isAllowed(["admin", "superadmin"]), deleteMonitor);
```
### Validation
**File:** `/server/src/validation/joi.js`
```javascript
const createMonitorBodyValidation = joi.object({
name: joi.string().required(),
description: joi.string().required(),
type: joi.string().required(),
url: joi.string().required(),
interval: joi.number(),
port: joi.number(),
thresholds: joi.object().keys({
usage_cpu: joi.number(),
usage_memory: joi.number(),
usage_disk: joi.number(),
usage_temperature: joi.number(),
}),
notifications: joi.array().items(joi.string()),
secret: joi.string(),
// ... more fields
});
```
---
## 5. POLLING/JOBS IMPLEMENTATION
### Job Queue Architecture
#### V1: SuperSimpleScheduler (Production)
**Files:**
- `/server/src/service/v1/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js`
- `/server/src/service/v1/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js`
**Job Lifecycle:**
1. **Initialization** (on server startup):
```javascript
// Load all monitors from DB
const monitors = await db.monitorModule.getAllMonitors();
for (const monitor of monitors) {
// Add job with random offset (0-100ms)
this.addJob(monitor._id, monitor);
}
// Register job template
scheduler.addTemplate("monitor-job", this.helper.getMonitorJob());
```
2. **Job Template** (executed per interval):
```javascript
getMonitorJob = () => {
return async (monitor) => {
// Check maintenance window
if (await this.isInMaintenanceWindow(monitorId, teamId)) {
return; // Skip
}
// Execute monitor check
const networkResponse = await this.networkService.requestStatus(monitor);
// Update monitor status
const { monitor: updated, statusChanged } =
await this.statusService.updateStatus(networkResponse);
// Send notifications if status changed
if (statusChanged) {
await this.notificationService.handleNotifications({
...networkResponse,
monitor: updated,
prevStatus,
statusChanged
});
}
};
};
```
3. **Job Control:**
```javascript
// Add job
addJob(monitorId, monitor) {
scheduler.addJob({
id: monitorId.toString(),
template: "monitor-job",
repeat: monitor.interval, // Milliseconds
active: monitor.isActive,
data: monitor.toObject()
});
}
// Pause/Resume
pauseJob(monitor) { scheduler.pauseJob(monitor._id); }
resumeJob(monitor) { scheduler.resumeJob(monitor._id); }
// Update interval
updateJob(monitor) {
scheduler.updateJob(monitor._id, {
repeat: monitor.interval,
data: monitor.toObject()
});
}
// Delete
deleteJob(monitor) { scheduler.removeJob(monitor._id); }
```
#### V2: BullMQ (TypeScript, Planned)
**Files:**
- `/server/src/service/v2/infrastructure/JobQueue.ts`
- `/server/src/service/v2/infrastructure/JobGenerator.ts`
**Key Differences:**
- Uses Redis backing store
- TypeScript interfaces (type safety)
- More robust queue management
- Cleanup jobs for orphaned checks
```typescript
// Cleanup job runs every 24 hours
scheduler.addJob({
id: "cleanup-orphaned-checks",
template: "cleanup-job",
repeat: 24 * 60 * 60 * 1000,
active: true
});
```
### Monitor Execution Flow
```
Monitor Created/Updated
↓
MonitorService.createMonitor()
↓
jobQueue.addJob(monitor)
↓
Job scheduled at interval
↓
[Job Execution]
├─ Check maintenance window
├─ NetworkService.requestStatus(monitor)
│ └─ Routes to type handler (requestDocker, requestHttp, etc)
├─ Create Check record (database)
├─ StatusService.updateMonitorStatus()
│ └─ Updates Monitor.status field
├─ MonitorStatsService.updateStats()
├─ If status changed → NotificationService.handleNotifications()
└─ Job completes / reschedules for next interval
```
### Status Update Logic
**Location:** `/server/src/service/v1/infrastructure/statusService.js`
```javascript
async updateStatus(networkResponse) {
// networkResponse = { monitorId, type, status, code, message, responseTime }
// 1. Create Check record
const check = await Check.create({
monitorId, teamId, type, status,
responseTime, statusCode: code, message
});
// 2. Get previous status
const prevStatus = monitor.status;
// 3. Apply statusWindow logic (sliding window of checks)
monitor.statusWindow.push(status);
if (monitor.statusWindow.length > monitor.statusWindowSize) {
monitor.statusWindow.shift();
}
// 4. Determine if DOWN (majority of window is false)
const downCount = monitor.statusWindow.filter(s => !s).length;
const isDown = (downCount / monitor.statusWindowSize) >
(monitor.statusWindowThreshold / 100);
monitor.status = isDown ? false : true;
// 5. Return status change info
return {
monitor: await monitor.save(),
statusChanged: prevStatus !== monitor.status,
prevStatus
};
}
```
---
## 6. FRONTEND COMPONENTS
### Monitor Management Pages
#### Infrastructure Monitors (Hardware/Docker)
**Location:** `/client/src/Pages/v1/Infrastructure/`
```
Infrastructure/
├── Create/
│ ├── index.jsx (Main form - 10K lines)
│ ├── Components/
│ │ ├── MonitorStatusHeader.jsx
│ │ ├── MonitorActionButtons.jsx
│ │ └── CustomAlertsSection.jsx
│ └── hooks/
│ ├── useInfrastructureMonitorForm.jsx
│ ├── useValidateInfrastructureForm.jsx
│ └── useInfrastructureSubmit.jsx
├── Details/
├── Monitors/
│ └── Components/
│ └── MonitorsTable.jsx
```
#### Form Structure (useInfrastructureMonitorForm hook)
```javascript
const [infrastructureMonitor, setInfrastructureMonitor] = useState({
url: "", // Container name/IP
name: "", // Display name
notifications: [], // Notification IDs
interval: 0.25, // Minutes (0.25 = 15s, 1 = 60s)
// Threshold toggles
cpu: false,
usage_cpu: "", // Percentage
memory: false,
usage_memory: "",
disk: false,
usage_disk: "",
temperature: false,
usage_temperature: "",
secret: "", // Capture API secret
statusWindowSize: 5,
statusWindowThreshold: 60
});
```
**Frequency Options:**
```javascript
[
{ _id: 0.25, name: "15 Seconds" },
{ _id: 0.5, name: "30 Seconds" },
{ _id: 1, name: "1 Minute" },
{ _id: 2, name: "2 Minutes" },
{ _id: 5, name: "5 Minutes" },
{ _id: 10, name: "10 Minutes" }
]
```
#### Form Submission (useInfrastructureSubmit hook)
```javascript
// Converts frontend form → backend model
const finalForm = {
url: `http${https ? "s" : ""}://` + infrastructureMonitor.url,
name: infrastructureMonitor.name || infrastructureMonitor.url,
interval: infrastructureMonitor.interval * 60000, // Convert to ms
type: "hardware", // Always "hardware" for infrastructure monitors
// Thresholds (convert % to decimal 0-1)
thresholds: {
...(cpu ? { usage_cpu: usage_cpu / 100 } : {}),
...(memory ? { usage_memory: usage_memory / 100 } : {}),
...(disk ? { usage_disk: usage_disk / 100 } : {}),
...(temperature ? { usage_temperature: usage_temperature / 100 } : {})
},
notifications: infrastructureMonitor.notifications
};
// API call
isCreate ?
await createMonitor({ monitor: finalForm, redirect: "/infrastructure" }) :
await updateMonitor({ monitor: finalForm, redirect: "/infrastructure" });
```
### Monitor Display Components
#### Monitor Status Component
**Location:** `/client/src/Components/v2/Monitors/MonitorStatus.tsx`
Displays:
- Status indicator (up/down)
- Response time
- Last check time
- Incident badges
#### Monitoring Hooks
**Location:** `/client/src/Hooks/v1/monitorHooks.js`
```javascript
// Fetch monitors
useFetchMonitorsByTeamId({ types, limit, page, ... })
useFetchMonitorsWithSummary({ types, monitorUpdateTrigger })
useFetchMonitorsWithChecks({ types, limit, ... })
// Fetch individual monitor
useFetchHardwareMonitorById({ monitorId, updateTrigger })
useFetchStatsByMonitorId({ monitorId, dateRange, ... })
// Manage monitors
useCreateMonitor() // POST /monitors
useUpdateMonitor() // PUT /monitors/:id
useDeleteMonitor() // DELETE /monitors/:id
usePauseMonitor() // POST /monitors/pause/:id
```
### Network Service (API Client)
**Location:** `/client/src/Utils/NetworkService.js` (1157 lines)
```javascript
// Constructor
constructor(store, dispatch, navigate) {
// Axios instance with:
// - Bearer token injection
// - Language header
// - 401 redirect to login
// - Network error handling
}
// Monitor endpoints
async createMonitor(config) {
return this.axiosInstance.post(`/monitors`, config.monitor);
}
async updateMonitor(config) {
return this.axiosInstance.put(`/monitors/${config.monitorId}`, config.monitor);
}
async getMonitorsByTeamId(config) {
// Query params: limit, types[], page, rowsPerPage, filter, field, order
return this.axiosInstance.get(`/monitors/team?...`);
}
async getHardwareDetailsByMonitorId(config) {
return this.axiosInstance.get(`/monitors/hardware/details/${config.monitorId}`);
}
async getStatsByMonitorId(config) {
// Query params: sortOrder, limit, dateRange, numToDisplay, normalize
return this.axiosInstance.get(`/monitors/stats/${config.monitorId}?...`);
}
```
---
## 7. AUTHENTICATION & API KEYS
### User Authentication (JWT)
**Registration/Login:**
```javascript
// POST /auth/register
{
firstName: "John",
lastName: "Doe",
email: "john@example.com",
password: "SecurePass123!"
}
Response:
{
user: { _id, email, role, teamId, ... },
token: "eyJhbGciOiJIUzI1NiIs..." // JWT
}
```
**Token Storage:** Redux store (`Features/Auth/authSlice`)
**Token Injection:** Automatic by NetworkService
```javascript
config.headers.Authorization = `Bearer ${authToken}`;
```
### Monitor-Specific Authentication
#### For Hardware/Docker Monitors via Capture API
Monitors can have a `secret` field for authenticating requests to the Capture API:
```javascript
{
type: "hardware",
url: "http://192.168.1.100:3000", // Capture endpoint
secret: "api-key-12345", // Passed to Capture API
thresholds: { ... }
}
```
**Implementation:** The secret is stored in the Monitor model and could be:
1. Sent as HTTP header: `Authorization: Bearer <secret>`
2. Sent as query param: `?secret=<secret>`
3. Sent in request body for POST requests
---
## 8. CONFIGURATION & USER SETTINGS
### Global Settings
**Model:** `/server/src/db/v1/models/AppSettings.js`
```javascript
{
jwtSecret: String, // For signing JWTs
sslCertificate: String, // SSL cert content
smtpConfig: Object, // Email settings
globalThresholds: { // Default thresholds
cpu: Number,
memory: Number,
disk: Number,
temperature: Number
},
siteTitle: String,
defaultLanguage: String,
maintenanceMode: Boolean
}
```
**Fetching Settings:**
```javascript
// Frontend
useFetchGlobalSettings()
→ NetworkService.getGlobalSettings()
→ GET /settings
// Backend
SettingsService.loadSettings()
→ Loads from AppSettings collection
```
### Monitor Configuration UI Flow
1. **Create Page:** `/infrastructure/create`
- Fetch global settings for default thresholds
- Form includes:
- Monitor name
- URL/Container name
- Interval (dropdown)
- CPU/Memory/Disk/Temp thresholds (checkboxes + inputs)
- Notification channels (multi-select)
- Secret (if using Capture API)
2. **Edit Page:** `/infrastructure/configure/:monitorId`
- Load existing monitor data
- Update form fields
- Save changes with PUT request
3. **Details Page:** `/infrastructure/:monitorId`
- Display monitor stats
- Show uptime graph
- List recent checks
- Status history
### Team-Based Isolation
**Access Control:**
```javascript
// All queries filtered by teamId
await Monitor.find({ teamId: req.user.teamId });
// verifyTeamAccess middleware
await verifyTeamAccess(req.user.teamId, req.params.monitorId);
```
---
## KEY PATTERNS FOR DOCKER MONITORING INTEGRATION
### 1. Adding Docker Monitor Type
Already supported! Located in:
- `Monitor.schema` type enum ✓
- `NetworkService.requestDocker()` ✓
- `Check.schema` with type ✓
### 2. Docker-Specific Data Collection
Currently: Only status + response time
**To Add Detailed Metrics:**
- Extend `Check.schema` with Docker stats fields
- Modify `NetworkService.requestDocker()` to call `container.stats()`
- Stream stats to `Check.docker` field
### 3. Capture API Integration (Hardware Monitoring)
**Flow:**
```
Monitor with type="hardware" and url="http://capture-endpoint"
↓
NetworkService.requestHardware()
↓ (delegates to)
NetworkService.requestHttp()
↓
Expects JSON response: { cpu, memory, disk, net, ... }
↓
Check record stores full payload in hardware fields
```
### 4. Database Queries
**Get hardware checks:**
```javascript
Check.find({
monitorId: id,
type: "hardware",
createdAt: { $gte: startDate, $lte: endDate }
})
.sort({ createdAt: -1 })
.limit(100)
```
### 5. UI Display
- Stats dashboard: `/infrastructure/:monitorId`
- Uptime details: `/monitor/uptime/details/:monitorId`
- Hardware details: `/monitor/hardware/details/:monitorId`
---
## SERVICE ARCHITECTURE
### Service Registry Pattern
**Location:** `/server/src/service/v1/system/serviceRegistry.js`
```javascript
// Singleton pattern
ServiceRegistry.set(serviceName, serviceInstance);
const service = ServiceRegistry.get(serviceName);
```
### Service Dependencies
**Initialization:** `/server/src/config/services.js`
```javascript
// Infrastructure services
new NetworkService({
axios, got, https, jmespath, GameDig, ping,
logger, http, Docker, // ← Docker client injected
net, stringService, settingsService
})
// Business services
new MonitorService({
db, settingsService, jobQueue,
stringService, emailService, logger
})
```
---
## KEY FILES SUMMARY
| Component | File | Lines | Purpose |
|-----------|------|-------|---------|
| Monitor Model | `server/src/db/v1/models/Monitor.js` | 209 | Schema, hooks |
| Check Model | `server/src/db/v1/models/Check.js` | 177 | Check records, TTL |
| NetworkService | `server/src/service/v1/infrastructure/networkService.js` | 580 | Type handlers |
| MonitorService | `server/src/service/v1/business/monitorService.js` | 277 | CRUD, validation |
| MonitorModule | `server/src/db/v1/modules/monitorModule.js` | 593 | DB queries |
| JobQueue | `server/src/service/v1/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js` | 177 | Job scheduling |
| MonitorController | `server/src/controllers/v1/monitorController.js` | 475 | HTTP handlers |
| MonitorRoute | `server/src/routes/v1/monitorRoute.js` | 61 | Endpoint definitions |
| Frontend Hooks | `client/src/Hooks/v1/monitorHooks.js` | 500+ | Data fetching |
| NetworkService (FE) | `client/src/Utils/NetworkService.js` | 1157 | API client |
| Form Hook | `client/src/Pages/v1/Infrastructure/Create/hooks/useInfrastructureMonitorForm.jsx` | 97 | Form state |
---
## DEPLOYMENT & DOCKER INTEGRATION
### Docker-Compose Setup
**Files:** `/docker/dev/docker-compose.yaml`, `/docker/prod/docker-compose.yaml`
**Volumes for Docker Monitoring:**
```yaml
volumes:
- /var/run/docker.sock:/var/run/docker.sock # Required for Dockerode
```
### Environment Variables
**Backend (.env):**
```
MONGODB_URI=mongodb://mongo:27017/checkmate
JWT_SECRET=your-secret-key
NODE_ENV=production|development
PORT=5000
```
**Frontend (.env):**
```
VITE_APP_API_BASE_URL=http://localhost:5000/api/v1
```
+166 -12
View File
@@ -6,7 +6,7 @@ We truly appreciate all kinds of contributions — code, ideas, translations or
Before you start, please take a moment to read the relevant section. It helps us review and accept contributions faster, and makes the whole process smoother for everyone. 💚
PS: **We work closely with contributors on our [Discord channel](https://discord.com/invite/NAb6H3UTjK)**. You’ll find community members, core maintainers, and first-timers helping each other out.
PS: **We work closely with contributors on our [Discord channel](https://discord.com/invite/NAb6H3UTjK)**. You'll find community members, core maintainers, and first-timers helping each other out.
---
@@ -32,12 +32,12 @@ PS: **We work closely with contributors on our [Discord channel](https://discord
### Get help or ask a question?
Ask anything in our [Discord server](https://discord.com/invite/NAb6H3UTjK) — we’re friendly and happy to help. [Our core contributors](https://github.com/bluewave-labs/checkmate?tab=readme-ov-file#-contributing) are active and ready to support you. You can also use [GitHub Discussions](https://github.com/bluewave-labs/Checkmate/discussions) section to ask your questions.
Ask anything in our [Discord server](https://discord.com/invite/NAb6H3UTjK) — we're friendly and happy to help. [Our core contributors](https://github.com/bluewave-labs/checkmate?tab=readme-ov-file#-contributing) are active and ready to support you. You can also use [GitHub Discussions](https://github.com/bluewave-labs/Checkmate/discussions) section to ask your questions.
### Report a bug?
1. Search [existing issues](https://github.com/bluewave-labs/checkmate/issues).
2. If it’s not listed, open a **new issue**.
2. If it's not listed, open a **new issue**.
3. Include as much detail as possible: what happened, what you expected, and steps to reproduce. Logs and screenshots help.
### Suggest a new feature?
@@ -48,19 +48,175 @@ Ask anything in our [Discord server](https://discord.com/invite/NAb6H3UTjK) —
### Set up Checkmate locally?
Frontend & backend:
#### Prerequisites
- Node.js (with npm)
- Docker
- Git
#### Step 1: Clone the Repository
```bash
git clone https://github.com/bluewave-labs/Checkmate.git
cd Checkmate
```
#### Step 2: Set Up Docker Containers (MongoDB)
Navigate to the Docker dev directory:
```bash
cd docker/dev
```
Build the Docker images:
```bash
./build_images.sh
```
Run MongoDB container:
```bash
docker run -d -p 27017:27017 -v uptime_mongo_data:/data/db --name uptime_database_mongo mongo:6.0
```
Navigate back to the root directory:
```bash
cd ../..
```
#### Step 3: Set Up the Backend (Server)
Navigate to the server directory:
```bash
cd server
```
Install dependencies:
```bash
npm install
```
Create a `.env` file in the `server` directory with the following minimum required configuration:
```env
CLIENT_HOST="http://localhost:5173"
JWT_SECRET="my_secret_key_change_this"
DB_CONNECTION_STRING="mongodb://localhost:27017/uptime_db"
TOKEN_TTL="99d"
ORIGIN="localhost"
LOG_LEVEL="debug"
```
**Environment Variables Explained:**
- `CLIENT_HOST`: Frontend URL (default: http://localhost:5173)
- `JWT_SECRET`: Secret key for JWT tokens (change to something secure)
- `DB_CONNECTION_STRING`: MongoDB connection URL
- `ORIGIN`: Origin for CORS purposes
- `TOKEN_TTL`: Token time to live (in vercel/ms format)
- `LOG_LEVEL`: Debug level (debug, info, warn, error)
Start the backend server:
```bash
npm run dev
```
By default, the frontend expects the backend on `http://localhost:3001`. Update configs if needed.
The server will run at `http://localhost:52345`.
#### Step 4: Set Up the Frontend (Client)
Open a new terminal window and navigate to the client directory from the root:
```bash
cd client
```
Install dependencies:
```bash
npm install
```
Create a `.env` file in the `client` directory:
```env
VITE_APP_API_BASE_URL="http://localhost:52345/api/v1"
VITE_APP_LOG_LEVEL="debug"
```
**Environment Variables Explained:**
- `VITE_APP_API_BASE_URL`: Backend API URL
- `VITE_APP_LOG_LEVEL`: Log level (none, error, warn, debug, info)
Start the frontend:
```bash
npm run dev
```
The client will run at `http://localhost:5173`.
#### Step 5: Access the Application
Open your browser and navigate to:
- **Frontend**: http://localhost:5173
- **Backend API**: http://localhost:52345
- **API Documentation**: http://localhost:52345/api-docs
#### Managing Docker Containers
Stop containers:
```bash
docker stop uptime_database_mongo
```
Start containers:
```bash
docker start uptime_database_mongo
```
Remove containers (if needed):
```bash
docker rm uptime_database_mongo
```
#### Troubleshooting
**Port already in use:**
- Check if another service is using ports 5173, 52345, 27017, or 6379
- Stop the conflicting service or change the port in `.env` files
**MongoDB connection issues:**
- Verify container is running: `docker ps`
- Check container logs: `docker logs uptime_database_mongo`
**Module not found errors:**
- Ensure you ran `npm install` in both `client` and `server` directories
**Need more help?**
- Check the [full documentation](https://docs.checkmate.so)
- Ask on [Discord](https://discord.com/invite/NAb6H3UTjK)
### Start contributing code?
1. Pick or open an issue (check `good-first-issue`s first)
2. (optional but highly suggested) Read a detailed structure of [Checkmate](https://deepwiki.com/bluewave-labs/Checkmate) if you would like to deep dive into the architecture.
3. Ask to be assigned. If there is alrady someone assigned and it's been more than 7 days, you can raise the flag and ask to be assigned as well.
3. Ask to be assigned. If there is already someone assigned and it's been more than 7 days, you can raise the flag and ask to be assigned as well.
4. Create a branch from `develop`.
5. Write your code.
6. Run and test locally.
@@ -75,6 +231,7 @@ Docs live in [checkmate-documentation](https://github.com/bluewave-labs/checkmat
### Help with translations?
We use [PoEditor](https://poeditor.com) for translations. You can:
- [Sign up and join your language team](https://poeditor.com/join/project/lRUoGZFCsJ).
- Translate UI strings.
- Ask questions on Discord in the relevant #translations channel.
@@ -84,6 +241,7 @@ Make sure all new UI strings in code use `t('key')`.
### Submit a pull request?
Follow the [pull request checklist](#pull-request-checklist). Your PR should:
- Be focused on one issue.
- Be tested locally.
- Use our linting and translation rules.
@@ -123,7 +281,6 @@ If one or more of these are missing, we may ask you to update your pull request
## Branching model
- Code contributions should go to the `develop` branch.
- `master` is used for stable releases.
- Use descriptive branch names, like `fix/login-error` or `feat/add-alerts`.
@@ -137,13 +294,10 @@ If one or more of these are missing, we may ask you to update your pull request
## Thank you
Thanks for making Checkmate better. We mean it. Whether it’s your first pull request or your 50th, we’re excited to build with you.
Thanks for making Checkmate better. We mean it. Whether it's your first pull request or your 50th, we're excited to build with you.
PS: feel free to introduce yourself on [Discord](https://discord.gg/YOUR-DISCORD-LINK) and say hi.
PS: feel free to introduce yourself on [Discord](https://discord.gg/NAb6H3UTjK) and say hi.
-- Checkmate team
Also make sure you read the [document about how to make a good pull request](/PULLREQUESTS.md).
+11325
View File
File diff suppressed because it is too large. Load diff
+2 -1
View File
@@ -52,7 +52,7 @@ Usage instructions can be found [here](https://docs.checkmate.so/checkmate-2.1).
See installation instructions in [Checkmate documentation portal](https://docs.checkmate.so/checkmate-2.1/users-guide/quickstart).
Alternatively, you can also use [Coolify](https://coolify.io/), [Elestio](https://elest.io/open-source/checkmate), [K8s](./charts/helm/checkmate/INSTALLATION.md), [Sive Host](https://sive.host) (South Africa) or [Pikapods](https://www.pikapods.com/) to quickly spin off a Checkmate instance. If you would like to monitor your server infrastructure, you'll need [Capture agent](https://github.com/bluewave-labs/capture). Capture repository also contains the installation instructions.
Alternatively, you can also use [Elestio](https://elest.io/open-source/checkmate), [K8s](./charts/helm/checkmate/INSTALLATION.md), [Sive Host](https://sive.host) (South Africa) or [Pikapods](https://www.pikapods.com/) to quickly spin off a Checkmate instance. If you would like to monitor your server infrastructure, you'll need [Capture agent](https://github.com/bluewave-labs/capture). Capture repository also contains the installation instructions.
### Using a Custom CA
@@ -162,6 +162,7 @@ Here's how you can contribute:
4. Open an issue if you believe you've encountered a bug.
5. Check for good-first-issue's if you are a newcomer.
6. Make a pull request to add new features/make quality-of-life improvements/fix bugs.
7. Check out this interactive walkthrough of the `Checkmate` codebase on CodeCanvas [here](https://www.code-canvas.com/?session=unauthenticatedGithub&repo=Checkmate&owner=bluewave-labs&branch=develop&OnboardingTutorial=true). To refine existing dataflow simulation or create new ones, follow the quick tutorial [here](https://docs.code-canvas.com/updating-diagram).
<a href="https://github.com/bluewave-labs/checkmate/graphs/contributors">
<img src="https://contrib.rocks/image?repo=bluewave-labs/checkmate" />
+4
View File
@@ -21,6 +21,10 @@ cd checkmate/charts/helm/checkmate
Edit `values.yaml` to update:
- `client.ingress.host` and `server.ingress.host` with your domain names
- `server.protocol` (usually http or https)
- **If upgrading**: Migrate persistence settings from flat structure to nested:
- Old: `persistence.mongodbSize` → New: `persistence.mongo.size`
- Old: `persistence.redisSize` → New: `persistence.redis.size`
- Add: `persistence.mongo.storageClass` and `persistence.redis.storageClass` (leave empty for default)
- Secrets under the `secrets` section (`JWT_SECRET`, email credentials, API keys, etc.) — replace all change_me values
### 3. Deploy the Helm chart
@@ -1,17 +1,25 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: client
name: checkmate-client
spec:
replicas: 1
selector:
matchLabels:
app: client
app: checkmate-client
template:
metadata:
labels:
app: client
app: checkmate-client
spec:
{{- with .Values.client.affinity }}
affinity:
{{- tpl ( . | toYaml) $ | nindent 8 }}
{{- end }}
{{- with .Values.client.tolerations }}
tolerations:
{{- tpl ( . | toYaml) $ | nindent 8 }}
{{- end }}
containers:
- name: client
image: {{ .Values.client.image }}
@@ -20,3 +28,17 @@ spec:
env:
- name: UPTIME_APP_API_BASE_URL
value: "{{ .Values.server.protocol }}://{{ .Values.server.ingress.host }}/api/v1"
- name: UPTIME_APP_CLIENT_HOST
value: "{{ .Values.client.protocol }}://{{ .Values.client.ingress.host }}"
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/conf.d/default.conf
subPath: default.conf
{{- with .Values.client.resources }}
resources:
{{- tpl ( . | toYaml) $ | nindent 12 }}
{{- end }}
volumes:
- name: config-volume
configMap:
name: checkmate-server-nginx-cm
@@ -2,10 +2,15 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: client-ingress
name: checkmate-client-ingress
{{- if .Values.client.ingress.annotations }}
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
{{- range $key, $value := .Values.client.ingress.annotations }}
{{ $key }}: {{ $value | quote }}
{{- end }}
{{- end }}
spec:
ingressClassName: {{ .Values.client.ingress.className }}
rules:
- host: {{ .Values.client.ingress.host }}
http:
@@ -14,7 +19,7 @@ spec:
pathType: Prefix
backend:
service:
name: client
name: checkmate-client
port:
number: {{ .Values.client.port }}
{{- end }}
@@ -1,9 +1,9 @@
apiVersion: v1
kind: Service
metadata:
name: client
name: checkmate-client
spec:
selector:
app: client
app: checkmate-client
ports:
- port: {{ .Values.client.port }}
@@ -1,27 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongodb
spec:
replicas: 1
selector:
matchLabels:
app: mongodb
template:
metadata:
labels:
app: mongodb
spec:
containers:
- name: mongodb
image: {{ .Values.mongodb.image }}
ports:
- containerPort: {{ .Values.mongodb.port }}
command: ["mongod", "--quiet", "--bind_ip_all"]
volumeMounts:
- name: mongodb-data
mountPath: /data/db
volumes:
- name: mongodb-data
persistentVolumeClaim:
claimName: mongodb-pvc
@@ -1,10 +0,0 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongodb-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .Values.persistence.mongodbSize }}
@@ -1,9 +1,9 @@
apiVersion: v1
kind: Service
metadata:
name: mongodb
name: checkmate-mongodb
spec:
selector:
app: mongodb
app: checkmate-mongodb
ports:
- port: {{ .Values.mongodb.port }}
@@ -0,0 +1,44 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: checkmate-mongodb
spec:
replicas: 1
selector:
matchLabels:
app: checkmate-mongodb
template:
metadata:
labels:
app: checkmate-mongodb
spec:
{{- with .Values.mongodb.affinity }}
affinity:
{{- tpl ( . | toYaml) $ | nindent 8 }}
{{- end }}
{{- with .Values.mongodb.tolerations }}
tolerations:
{{- tpl ( . | toYaml) $ | nindent 8 }}
{{- end }}
containers:
- name: mongodb
image: {{ .Values.mongodb.image }}
ports:
- containerPort: {{ .Values.mongodb.port }}
command: ["mongod", "--quiet", "--bind_ip_all"]
volumeMounts:
- name: checkmate-mongo-persistent-storage
mountPath: /data/db
{{- with .Values.mongodb.resources }}
resources:
{{- tpl ( . | toYaml) $ | nindent 12 }}
{{- end }}
volumeClaimTemplates:
- metadata:
name: checkmate-mongo-persistent-storage
spec:
storageClassName: {{ .Values.persistence.mongo.storageClass | quote }}
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: {{ .Values.persistence.mongo.size | default "5Gi" | quote }}
@@ -1,26 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: {{ .Values.redis.image }}
ports:
- containerPort: {{ .Values.redis.port }}
volumeMounts:
- name: redis-data
mountPath: /data
volumes:
- name: redis-data
persistentVolumeClaim:
claimName: redis-pvc
@@ -1,10 +0,0 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .Values.persistence.redisSize }}
@@ -1,9 +1,11 @@
{{- if .Values.redis.enabled }}
apiVersion: v1
kind: Service
metadata:
name: redis
name: checkmate-redis
spec:
selector:
app: redis
app: checkmate-redis
ports:
- port: {{ .Values.redis.port }}
{{- end }}
@@ -0,0 +1,33 @@
{{- if .Values.redis.enabled }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: checkmate-redis
spec:
replicas: 1
selector:
matchLabels:
app: checkmate-redis
template:
metadata:
labels:
app: checkmate-redis
spec:
containers:
- name: redis
image: {{ .Values.redis.image }}
ports:
- containerPort: {{ .Values.redis.port }}
volumeMounts:
- name: redis-data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: checkmate-redis-persistent-storage
spec:
storageClassName: {{ .Values.persistence.redis.storageClass | quote }}
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: {{ .Values.persistence.redis.size | default "1Gi" | quote }}
{{- end }}
@@ -4,10 +4,6 @@
{{- fail "secrets.JWT_SECRET must be overridden and cannot be 'change_me'" }}
{{- end }}
{{- if or (not $secrets.REFRESH_TOKEN_SECRET) (eq $secrets.REFRESH_TOKEN_SECRET "change_me") }}
{{- fail "secrets.REFRESH_TOKEN_SECRET must be overridden and cannot be 'change_me'" }}
{{- end }}
apiVersion: v1
kind: Secret
metadata:
@@ -1,17 +1,25 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: server
name: checkmate-server
spec:
replicas: 1
selector:
matchLabels:
app: server
app: checkmate-server
template:
metadata:
labels:
app: server
app: checkmate-server
spec:
{{- with .Values.server.affinity }}
affinity:
{{- tpl ( . | toYaml) $ | nindent 8 }}
{{- end }}
{{- with .Values.server.tolerations }}
tolerations:
{{- tpl ( . | toYaml) $ | nindent 8 }}
{{- end }}
containers:
- name: server
image: {{ .Values.server.image }}
@@ -20,3 +28,10 @@ spec:
envFrom:
- secretRef:
name: checkmate-secrets
{{- with .Values.server.resources }}
resources:
{{- tpl ( . | toYaml) $ | nindent 12 }}
{{- end }}
env:
- name: CLIENT_HOST
value: "{{ .Values.client.protocol }}://{{ .Values.client.ingress.host }}"
@@ -2,24 +2,31 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: server-ingress
name: checkmate-server-ingress
{{- if .Values.server.ingress.annotations }}
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "http://{{ .Values.client.ingress.host }},https://{{ .Values.client.ingress.host }}"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, PUT, POST, DELETE, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
{{- range $key, $value := .Values.server.ingress.annotations }}
{{ $key }}: {{ $value | quote }}
{{- end }}
{{- end }}
{{/*#annotations:
#nginx.ingress.kubernetes.io/rewrite-target: /
#nginx.ingress.kubernetes.io/enable-cors: "true"
#nginx.ingress.kubernetes.io/cors-allow-origin: "http://{{ .Values.client.ingress.host }},https://{{ .Values.client.ingress.host }}"
#nginx.ingress.kubernetes.io/cors-allow-methods: "GET, PUT, POST, DELETE, PATCH, OPTIONS"
#nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization"
#nginx.ingress.kubernetes.io/cors-allow-credentials: "true"*/}}
spec:
ingressClassName: {{ .Values.server.ingress.className }}
rules:
- host: {{ .Values.server.ingress.host }}
http:
paths:
- path: /
- path: /api/v1
pathType: Prefix
backend:
service:
name: server
name: checkmate-server
port:
number: {{ .Values.server.port }}
{{- end }}
@@ -0,0 +1,41 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: checkmate-server-nginx-cm
data:
default.conf: |
server {
listen 80;
listen [::]:80;
server_name checkmate-demo.bluewavelabs.ca;
server_tokens off;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
# location /api/ {
# proxy_pass http://{{ .Values.server.ingress.host }}:5000/api/;
# proxy_http_version 1.1;
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# }
location /api-docs/ {
proxy_pass http://{{ .Values.server.ingress.host }}:5000/api-docs/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
@@ -1,9 +1,9 @@
apiVersion: v1
kind: Service
metadata:
name: server
name: checkmate-server
spec:
selector:
app: server
app: checkmate-server
ports:
- port: {{ .Values.server.port }}
+29 -18
View File
@@ -1,41 +1,52 @@
client:
image: ghcr.io/bluewave-labs/checkmate-client:v2.3
image: ghcr.io/bluewave-labs/checkmate-client:v3.2.0
port: 80
protocol: http
ingress:
enabled: true
host: change_me
className: nginx
annotations: {}
server:
image: ghcr.io/bluewave-labs/checkmate-backend:v2.3
image: ghcr.io/bluewave-labs/checkmate-backend:v3.2.0
port: 52345
protocol: change_me
protocol: http
ingress:
enabled: true
host: change_me
className: nginx
annotations: {}
redis:
enabled: false
image: redis:7.2
port: 6379
mongodb:
image: mongo:7.0
image: ghcr.io/bluewave-labs/checkmate-mongo:v3.2.0
port: 27017
secrets:
JWT_SECRET: change_me
REFRESH_TOKEN_SECRET: change_me
SYSTEM_EMAIL_ADDRESS: test@example.com
SYSTEM_EMAIL_PASSWORD: change_me
SYSTEM_EMAIL_HOST: smtp.example.com
SYSTEM_EMAIL_PORT: "587"
PAGESPEED_API_KEY: change_me
DB_CONNECTION_STRING: mongodb://mongodb:27017/uptime_db
REDIS_HOST: redis
REDIS_PORT: "6379"
DB_TYPE: MongoDB
TOKEN_TTL: 99d
REFRESH_TOKEN_TTL: 99d
# REFRESH_TOKEN_SECRET: change_me
# SYSTEM_EMAIL_ADDRESS: test@example.com
# SYSTEM_EMAIL_PASSWORD: change_me
# SYSTEM_EMAIL_HOST: smtp.example.com
# SYSTEM_EMAIL_PORT: "587"
# PAGESPEED_API_KEY: change_me
DB_CONNECTION_STRING: mongodb://checkmate-mongodb.namespace.svc:27017/uptime_db
CLIENT_HOST: change_me
# REDIS_HOST: redis
# REDIS_PORT: "6379"
# DB_TYPE: MongoDB
# TOKEN_TTL: 99d
# REFRESH_TOKEN_TTL: 99d
persistence:
mongodbSize: 5Gi
redisSize: 1Gi
mongo:
size: 5Gi
storageClass: ""
redis:
size: 1Gi
storageClass: ""
+1
View File
@@ -1,3 +1,4 @@
VITE_APP_API_BASE_URL=UPTIME_APP_API_BASE_URL
VITE_APP_API_V2_BASE_URL=UPTIME_APP_API_V2_BASE_URL
VITE_APP_CLIENT_HOST=UPTIME_APP_CLIENT_HOST
VITE_APP_LOG_LEVEL=UPTIME_APP_LOG_LEVEL
+141 -1
View File
@@ -11,6 +11,7 @@
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@hello-pangea/dnd": "^18.0.0",
"@hookform/resolvers": "5.2.2",
"@mui/icons-material": "6.4.11",
"@mui/lab": "6.0.0-dev.240424162023-9968b4889d",
"@mui/material": "6.4.11",
@@ -21,11 +22,14 @@
"dayjs": "1.11.13",
"flag-icons": "7.3.2",
"html2canvas": "^1.4.1",
"human-interval": "2.0.1",
"i18next": "25.4.2",
"joi": "17.13.3",
"mui-color-input": "^6.0.0",
"pretty-ms": "9.3.0",
"react": "18.3.1",
"react-dom": "^18.2.0",
"react-hook-form": "7.63.0",
"react-i18next": "^15.4.0",
"react-icons": "5.5.0",
"react-redux": "9.2.0",
@@ -34,9 +38,12 @@
"react-toastify": "^10.0.5",
"recharts": "2.15.2",
"redux-persist": "6.0.0",
"vite-plugin-svgr": "^4.2.0"
"swr": "2.3.6",
"vite-plugin-svgr": "^4.2.0",
"zod": "4.1.11"
},
"devDependencies": {
"@types/node": "24.5.2",
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
"@vitejs/plugin-react": "^4.2.1",
@@ -45,6 +52,7 @@
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.6",
"prettier": "^3.3.3",
"typescript": "5.9.3",
"vite": "6.3.6"
}
},
@@ -653,6 +661,18 @@
"react-dom": "^18.0.0 || ^19.0.0"
}
},
"node_modules/@hookform/resolvers": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.2.2.tgz",
"integrity": "sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA==",
"license": "MIT",
"dependencies": {
"@standard-schema/utils": "^0.3.0"
},
"peerDependencies": {
"react-hook-form": "^7.55.0"
}
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
@@ -2107,6 +2127,16 @@
"integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
"license": "MIT"
},
"node_modules/@types/node": {
"version": "24.5.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.2.tgz",
"integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.12.0"
}
},
"node_modules/@types/parse-json": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
@@ -2991,6 +3021,15 @@
"node": ">=0.4.0"
}
},
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
@@ -4082,6 +4121,15 @@
"node": ">=8.0.0"
}
},
"node_modules/human-interval": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/human-interval/-/human-interval-2.0.1.tgz",
"integrity": "sha512-r4Aotzf+OtKIGQCB3odUowy4GfUDTy3aTWTfLd7ZF2gBCy3XW3v/dJLRefZnOFFnjqs5B1TypvS8WarpBkYUNQ==",
"license": "MIT",
"dependencies": {
"numbered": "^1.1.0"
}
},
"node_modules/i18next": {
"version": "25.4.2",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.4.2.tgz",
@@ -4916,6 +4964,12 @@
"integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
"license": "MIT"
},
"node_modules/numbered": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/numbered/-/numbered-1.1.0.tgz",
"integrity": "sha512-pv/ue2Odr7IfYOO0byC1KgBI10wo5YDauLhxY6/saNzAdAs0r1SotGCPzzCLNPL0xtrAwWRialLu23AAu9xO1g==",
"license": "MIT"
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -5131,6 +5185,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/parse-ms": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz",
"integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -5258,6 +5324,21 @@
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/pretty-ms": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz",
"integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==",
"license": "MIT",
"dependencies": {
"parse-ms": "^4.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@@ -5343,6 +5424,22 @@
"react": "^18.3.1"
}
},
"node_modules/react-hook-form": {
"version": "7.63.0",
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.63.0.tgz",
"integrity": "sha512-ZwueDMvUeucovM2VjkCf7zIHcs1aAlDimZu2Hvel5C5907gUzMpm4xCrQXtRzCvsBqFjonB4m3x4LzCFI1ZKWA==",
"license": "MIT",
"engines": {
"node": ">=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/react-hook-form"
},
"peerDependencies": {
"react": "^16.8.0 || ^17 || ^18 || ^19"
}
},
"node_modules/react-i18next": {
"version": "15.5.1",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.5.1.tgz",
@@ -6141,6 +6238,19 @@
"integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==",
"license": "MIT"
},
"node_modules/swr": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/swr/-/swr-2.3.6.tgz",
"integrity": "sha512-wfHRmHWk/isGNMwlLGlZX5Gzz/uTgo0o2IRuTMcf4CPuPFJZlq0rDaKUx+ozB5nBOReNV1kiOyzMfj+MBMikLw==",
"license": "MIT",
"dependencies": {
"dequal": "^2.0.3",
"use-sync-external-store": "^1.4.0"
},
"peerDependencies": {
"react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/text-segmentation": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
@@ -6289,6 +6399,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/typescript": {
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"devOptional": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/unbox-primitive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
@@ -6308,6 +6432,13 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/undici-types": {
"version": "7.12.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz",
"integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==",
"devOptional": true,
"license": "MIT"
},
"node_modules/update-browserslist-db": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
@@ -6639,6 +6770,15 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/zod": {
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.1.11.tgz",
"integrity": "sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
}
}
}
+11 -11
View File
@@ -5,8 +5,8 @@
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"build-dev": "vite build --mode development",
"build": "tsc -b && vite build",
"build-dev": "tsc -b && vite build --mode development",
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
"format": "prettier --write .",
@@ -16,6 +16,7 @@
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@hello-pangea/dnd": "^18.0.0",
"@hookform/resolvers": "5.2.2",
"@mui/icons-material": "6.4.11",
"@mui/lab": "6.0.0-dev.240424162023-9968b4889d",
"@mui/material": "6.4.11",
@@ -26,11 +27,14 @@
"dayjs": "1.11.13",
"flag-icons": "7.3.2",
"html2canvas": "^1.4.1",
"human-interval": "2.0.1",
"i18next": "25.4.2",
"joi": "17.13.3",
"mui-color-input": "^6.0.0",
"pretty-ms": "9.3.0",
"react": "18.3.1",
"react-dom": "^18.2.0",
"react-hook-form": "7.63.0",
"react-i18next": "^15.4.0",
"react-icons": "5.5.0",
"react-redux": "9.2.0",
@@ -39,17 +43,12 @@
"react-toastify": "^10.0.5",
"recharts": "2.15.2",
"redux-persist": "6.0.0",
"vite-plugin-svgr": "^4.2.0"
},
"unusedDepencies": {
"@solana/wallet-adapter-base": "0.9.25",
"@solana/wallet-adapter-material-ui": "0.16.35",
"@solana/wallet-adapter-react": "0.15.37",
"@solana/wallet-adapter-react-ui": "0.9.37",
"@solana/wallet-adapter-wallets": "0.19.34",
"@solana/web3.js": "1.98.0"
"swr": "2.3.6",
"vite-plugin-svgr": "^4.2.0",
"zod": "4.1.11"
},
"devDependencies": {
"@types/node": "24.5.2",
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
"@vitejs/plugin-react": "^4.2.1",
@@ -58,6 +57,7 @@
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.6",
"prettier": "^3.3.3",
"typescript": "5.9.3",
"vite": "6.3.6"
}
}
+6 -11
View File
@@ -9,8 +9,7 @@ import { CssBaseline, GlobalStyles } from "@mui/material";
import { logger } from "./Utils/Logger"; // Import the logger
import { networkService } from "./main";
import { Routes } from "./Routes";
import WalletProvider from "./Components/WalletProvider";
import AppLayout from "./Components/Layouts/AppLayout";
import AppLayout from "@/Components/v1/Layouts/AppLayout";
function App() {
const mode = useSelector((state) => state.ui.mode);
@@ -24,16 +23,12 @@ function App() {
}, []);
return (
/* Extract Themeprovider, baseline and global styles to Styles */
<ThemeProvider theme={mode === "light" ? lightTheme : darkTheme}>
<WalletProvider>
<CssBaseline />
<AppLayout>
<Routes />
</AppLayout>
<ToastContainer />
</WalletProvider>
<CssBaseline />
<AppLayout>
<Routes />
</AppLayout>
<ToastContainer />
</ThemeProvider>
);
}
@@ -2,17 +2,17 @@
import IconButton from "@mui/material/IconButton";
import Menu from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem";
import Settings from "../../assets/icons/settings-bold.svg?react";
import Dialog from "../../Components/Dialog";
import Settings from "../../../assets/icons/settings-bold.svg?react";
import Dialog from "../Dialog/index.jsx";
// Utils
import { useState } from "react";
import { useTheme } from "@emotion/react";
import { useNavigate } from "react-router-dom";
import { createToast } from "../../Utils/toastUtils";
import { createToast } from "../../../Utils/toastUtils.jsx";
import PropTypes from "prop-types";
import { usePauseMonitor, useDeleteMonitor } from "../../Hooks/monitorHooks";
import { usePauseMonitor, useDeleteMonitor } from "../../../Hooks/v1/monitorHooks.js";
const ActionsMenu = ({
monitor,
@@ -1,6 +1,6 @@
import LeftArrow from "../../assets/icons/left-arrow.svg?react";
import LeftArrowDouble from "../../assets/icons/left-arrow-double.svg?react";
import LeftArrowLong from "../../assets/icons/left-arrow-long.svg?react";
import LeftArrow from "../../../assets/icons/left-arrow.svg?react";
import LeftArrowDouble from "../../../assets/icons/left-arrow-double.svg?react";
import LeftArrowLong from "../../../assets/icons/left-arrow-long.svg?react";
import PropTypes from "prop-types";
const ArrowLeft = ({ type, color = "#667085", ...props }) => {
@@ -1,5 +1,5 @@
import RightArrow from "../../assets/icons/right-arrow.svg?react";
import RightArrowDouble from "../../assets/icons/right-arrow-double.svg?react";
import RightArrow from "../../../assets/icons/right-arrow.svg?react";
import RightArrowDouble from "../../../assets/icons/right-arrow-double.svg?react";
import PropTypes from "prop-types";
const ArrowRight = ({ type, color = "#667085", ...props }) => {
@@ -2,7 +2,7 @@ import PropTypes from "prop-types";
import { Box, Breadcrumbs as MUIBreadcrumbs } from "@mui/material";
import { useTheme } from "@emotion/react";
import { useNavigate } from "react-router-dom";
import ArrowRight from "../ArrowRight";
import ArrowRight from "../ArrowRight/index.jsx";
import "./index.css";
/**
@@ -61,7 +61,7 @@ import {
Tooltip,
ResponsiveContainer,
} from "recharts";
import { createGradient } from "../Utils/gradientUtils";
import { createGradient } from "../Utils/gradientUtils.jsx";
import PropTypes from "prop-types";
import { useTheme } from "@mui/material";
import { useId } from "react";
@@ -1,6 +1,6 @@
import { useTheme } from "@emotion/react";
import { Box, Stack, Tooltip, Typography } from "@mui/material";
import { formatDateWithTz } from "../../../Utils/timeUtils";
import { formatDateWithTz } from "../../../../Utils/timeUtils.js";
import { useEffect, useState } from "react";
import "./index.css";
import { useSelector } from "react-redux";
@@ -2,7 +2,7 @@
import { Typography, Stack } from "@mui/material";
import PropTypes from "prop-types";
import { useTheme } from "@emotion/react";
import IconBox from "../../IconBox";
import IconBox from "../../IconBox/index.jsx";
/**
* `EmptyView` is a functional React component that displays an empty state view with an optional icon, header, and message.
@@ -1,7 +1,7 @@
import { Stack, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import IconBox from "../../IconBox";
import EmptyView from "./EmptyView";
import IconBox from "../../IconBox/index.jsx";
import EmptyView from "./EmptyView.jsx";
import PropTypes from "prop-types";
const ChartBox = ({
@@ -5,7 +5,7 @@ import { Stack, Box, Tooltip, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import { useState, useEffect } from "react";
import PropTypes from "prop-types";
import { formatDateWithTz } from "../../../Utils/timeUtils";
import { formatDateWithTz } from "../../../../Utils/timeUtils.js";
import { useSelector } from "react-redux";
const PlaceholderCheck = ({ daysToShow }) => {
@@ -1,6 +1,6 @@
import { Stack, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import IconBox from "../../IconBox";
import IconBox from "../../IconBox/index.jsx";
import PropTypes from "prop-types";
const LegendBox = ({ children, icon, header, sx }) => {
@@ -12,11 +12,11 @@ import { Box, Stack, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import { useMemo, useState } from "react";
import { useSelector } from "react-redux";
import { formatDateWithTz } from "../../../Utils/timeUtils";
import { formatDateWithTz } from "../../../../Utils/timeUtils.js";
import {
tooltipDateFormatLookup,
tickDateFormatLookup,
} from "../Utils/chartUtilFunctions";
} from "../Utils/chartUtilFunctions.js";
import "./index.css";
const CustomToolTip = ({ active, payload, label, dateRange }) => {
@@ -1,6 +1,6 @@
import { useTheme } from "@emotion/react";
import { Box, Stack, Tooltip, Typography } from "@mui/material";
import { formatDateWithTz } from "../../../Utils/timeUtils";
import { formatDateWithTz } from "../../../../Utils/timeUtils.js";
import { useEffect, useState, forwardRef } from "react";
import { useSelector } from "react-redux";
import PropTypes from "prop-types";
@@ -2,9 +2,9 @@ import PropTypes from "prop-types";
import { useSelector } from "react-redux";
import { useTheme } from "@mui/material";
import { Text } from "recharts";
import { formatDateWithTz } from "../../../Utils/timeUtils";
import { formatDateWithTz } from "../../../../Utils/timeUtils.js";
import { Box, Stack, Typography } from "@mui/material";
import { tickDateFormatLookup, tooltipDateFormatLookup } from "./chartUtilFunctions";
import { tickDateFormatLookup, tooltipDateFormatLookup } from "./chartUtilFunctions.js";
/**
* Custom tick component for rendering time with timezone.
*
@@ -1,7 +1,7 @@
import "./check.css";
import PropTypes from "prop-types";
import CheckGrey from "../../assets/icons/check.svg?react";
import CheckOutlined from "../../assets/icons/check-outlined.svg?react";
import CheckGrey from "../../../assets/icons/check.svg?react";
import CheckOutlined from "../../../assets/icons/check-outlined.svg?react";
import { Box, Stack, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
@@ -10,7 +10,7 @@ import MenuItem from "@mui/material/MenuItem";
import Drawer from "@mui/material/Drawer";
import MenuIcon from "@mui/icons-material/Menu";
import CloseRoundedIcon from "@mui/icons-material/CloseRounded";
import ThemeSwitch from "../ThemeSwitch";
import ThemeSwitch from "../ThemeSwitch/index.jsx";
import { useTheme } from "@mui/material/styles";
import { useSelector } from "react-redux";
import { useLocation, useNavigate } from "react-router-dom";
@@ -1,7 +1,7 @@
import { Box, Stack, Typography } from "@mui/material";
import PropTypes from "prop-types";
import { useTheme } from "@emotion/react";
import ConfigBox from "../ConfigBox";
import ConfigBox from "../ConfigBox/index.jsx";
/**
* ConfigRow is a styled container used to layout content in a row format with specific padding, border, and spacing.
@@ -1,6 +1,6 @@
import PropTypes from "prop-types";
import { Button, Stack } from "@mui/material";
import { GenericDialog } from "./genericDialog";
import { GenericDialog } from "./genericDialog.jsx";
import { useTheme } from "@emotion/react";
import { useTranslation } from "react-i18next";
File renamed without changes.
@@ -1,8 +1,8 @@
import { useTheme } from "@emotion/react";
import Box from "@mui/material/Box";
import Background from "../../assets/Images/background-grid.svg?react";
import OutputAnimation from "../../assets/Animations/output.gif";
import DarkmodeOutput from "../../assets/Animations/darkmodeOutput.gif";
import Background from "../../../assets/Images/background-grid.svg?react";
import OutputAnimation from "../../../assets/Animations/output.gif";
import DarkmodeOutput from "../../../assets/Animations/darkmodeOutput.gif";
import { useSelector } from "react-redux";
const FallbackBackground = () => {
const theme = useTheme();
@@ -2,7 +2,7 @@ import PropTypes from "prop-types";
import { useTheme } from "@mui/material/styles";
import Box from "@mui/material/Box";
import Stack from "@mui/material/Stack";
import Check from "../Check/Check";
import Check from "../Check/Check.jsx";
const FallbackCheckList = ({ checks, type }) => {
const theme = useTheme();
return (
@@ -3,7 +3,7 @@ import { useTheme } from "@mui/material/styles";
import Link from "@mui/material/Link";
import { Link as RouterLink } from "react-router-dom";
import { useTranslation } from "react-i18next";
import Alert from "../Alert";
import Alert from "../Alert/index.jsx";
import PropTypes from "prop-types";
const renderWarningMessage = (t) => {
@@ -2,11 +2,11 @@ import PropTypes from "prop-types";
import { useTheme } from "@emotion/react";
import { Box, Stack } from "@mui/material";
import "./index.css";
import FallbackTitle from "./FallbackTitle";
import FallbackCheckList from "./FallbackCheckList";
import FallbackActionButtons from "./FallBackActionButtons";
import FallbackBackground from "./FallbackBackground";
import FallbackContainer from "./FallbackContainer";
import FallbackTitle from "./FallbackTitle.jsx";
import FallbackCheckList from "./FallbackCheckList.jsx";
import FallbackActionButtons from "./FallBackActionButtons.jsx";
import FallbackBackground from "./FallbackBackground.jsx";
import FallbackContainer from "./FallbackContainer.jsx";
/**
* Fallback component to display a fallback UI with a title, a list of checks, and a navigation button.
*
@@ -1,8 +1,8 @@
import { useTheme } from "@emotion/react";
import { Box, Stack } from "@mui/material";
import OutputAnimation from "../../assets/Animations/output.gif";
import DarkmodeOutput from "../../assets/Animations/darkmodeOutput.gif";
import Background from "../../assets/Images/background-grid.svg?react";
import OutputAnimation from "../../../assets/Animations/output.gif";
import DarkmodeOutput from "../../../assets/Animations/darkmodeOutput.gif";
import Background from "../../../assets/Images/background-grid.svg?react";
import { useSelector } from "react-redux";
/**
@@ -1,8 +1,8 @@
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { logger } from "../../Utils/Logger";
import { networkService } from "../../main";
import { logger } from "../../../Utils/Logger.js";
import { networkService } from "../../../main.jsx";
const withAdminCheck = (WrappedComponent) => {
const WithAdminCheck = (props) => {
@@ -1,7 +1,8 @@
import { Stack, Typography } from "@mui/material";
import PropTypes from "prop-types";
import { useTheme } from "@emotion/react";
import Dot from "../Dot";
import Dot from "../Dot/index.jsx";
import { StatusLabel } from "@/Components/v1/Label/index.jsx";
/**
* Host component.
* This subcomponent receives a params object and displays the host details.
@@ -14,7 +15,7 @@ import Dot from "../Dot";
* @param {number} params.percentage - The percentage to display.
* @returns {React.ElementType} Returns a div element with the host details.
*/
const Host = ({ url, title, percentageColor, percentage, showURL }) => {
const Host = ({ url, title, percentageColor, percentage, showURL, status }) => {
const theme = useTheme();
return (
<Stack>
@@ -22,21 +23,36 @@ const Host = ({ url, title, percentageColor, percentage, showURL }) => {
direction="row"
position="relative"
alignItems="center"
gap={theme.spacing(4)}
gap={theme.spacing(5)}
>
{title}
<Typography
variant="h6"
sx={{
fontWeight: 600,
}}
>
{title}
</Typography>
{percentageColor && percentage && (
<>
<Dot />
<Typography
component="span"
variant="h6"
sx={{
fontWeight: 600,
color: percentageColor,
fontWeight: 500,
}}
>
{percentage}%
</Typography>
{status && (
<StatusLabel
status={status}
text={status}
customStyles={{ textTransform: "capitalize" }}
/>
)}
</>
)}
</Stack>
@@ -51,6 +67,7 @@ Host.propTypes = {
percentage: PropTypes.string,
url: PropTypes.string,
showURL: PropTypes.bool,
status: PropTypes.string,
};
export default Host;
@@ -1,6 +1,6 @@
import PropTypes from "prop-types";
import { useTheme } from "@mui/material";
import { BaseLabel } from "../Label";
import { BaseLabel } from "../Label/index.jsx";
/**
* @component
@@ -1,4 +1,4 @@
import i18n from "../../Utils/i18n";
import i18n from "../../../Utils/i18n.js";
import { useSelector } from "react-redux";
import { useEffect } from "react";
const I18nLoader = () => {
@@ -1,6 +1,6 @@
import { RowContainer } from "../StandardContainer";
import { RowContainer } from "../StandardContainer/index.jsx";
import { Stack, Typography } from "@mui/material";
import Image from "../Image";
import Image from "../Image/index.jsx";
import { useTheme } from "@mui/material/styles";
@@ -1,9 +1,8 @@
import PropTypes from "prop-types";
import { FormControlLabel, Checkbox as MuiCheckbox } from "@mui/material";
import { useTheme } from "@emotion/react";
import CheckboxOutline from "../../../assets/icons/checkbox-outline.svg?react";
import CheckboxFilled from "../../../assets/icons/checkbox-filled.svg?react";
import "./index.css";
import CheckboxOutline from "../../../../assets/icons/checkbox-outline.svg?react";
import CheckboxFilled from "../../../../assets/icons/checkbox-filled.svg?react";
/**
* Checkbox Component
@@ -1,10 +1,10 @@
// Components
import { Box, Stack, Typography } from "@mui/material";
import CloudUploadIcon from "@mui/icons-material/CloudUpload";
import Image from "../../../Components/Image";
import Image from "../../Image/index.jsx";
import TextField from "@mui/material/TextField";
import IconButton from "@mui/material/IconButton";
import ProgressUpload from "../../ProgressBars";
import ProgressUpload from "../../ProgressBars/index.jsx";
import ImageIcon from "@mui/icons-material/Image";
// Utils
@@ -1,7 +1,7 @@
import PropTypes from "prop-types";
import { FormControlLabel, Radio as MUIRadio, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import RadioChecked from "../../../assets/icons/radio-checked.svg?react";
import RadioChecked from "../../../../assets/icons/radio-checked.svg?react";
import "./index.css";
/**
@@ -8,10 +8,10 @@ import {
Checkbox,
} from "@mui/material";
import { useTheme } from "@emotion/react";
import SearchIcon from "../../../assets/icons/search.svg?react";
import SearchIcon from "../../../../assets/icons/search.svg?react";
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import FieldWrapper from "../FieldWrapper";
import FieldWrapper from "../FieldWrapper/index.jsx";
/**
* Search component using Material UI's Autocomplete.
@@ -2,7 +2,7 @@ import PropTypes from "prop-types";
import { useTheme } from "@emotion/react";
import { MenuItem, Select as MuiSelect, Stack, Typography } from "@mui/material";
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
import FieldWrapper from "../FieldWrapper";
import FieldWrapper from "../FieldWrapper/index.jsx";
import "./index.css";
@@ -4,7 +4,7 @@ import PropTypes from "prop-types";
import VisibilityOff from "@mui/icons-material/VisibilityOff";
import Visibility from "@mui/icons-material/Visibility";
import ReorderRoundedIcon from "@mui/icons-material/ReorderRounded";
import DeleteIcon from "../../../../assets/icons/trash-bin.svg?react";
import DeleteIcon from "../../../../../assets/icons/trash-bin.svg?react";
export const HttpAdornment = ({ https }) => {
const theme = useTheme();
@@ -2,7 +2,7 @@ import { Stack, TextField, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import { forwardRef, useState, cloneElement } from "react";
import PropTypes from "prop-types";
import FieldWrapper from "../FieldWrapper";
import FieldWrapper from "../FieldWrapper/index.jsx";
const getSx = (theme, type, maxWidth) => {
const sx = {
@@ -147,11 +147,9 @@ const StatusLabel = ({ status, text, customStyles }) => {
}}
>
<Box
width={7}
height={7}
bgcolor={theme.palette[themeColor].lowContrast}
borderRadius="50%"
marginRight="5px"
borderRadius="0%"
marginRight="1px"
/>
</BaseLabel>
);
@@ -1,7 +1,7 @@
import Box from "@mui/material/Box";
import PropTypes from "prop-types";
import { useTheme } from "@emotion/react";
import BackgroundSVG from "../../../assets/Images/background.svg";
import BackgroundSVG from "../../../../assets/Images/background.svg";
import { useSelector } from "react-redux";
const AppLayout = ({ children }) => {
@@ -1,4 +1,4 @@
import Sidebar from "../../Sidebar";
import Sidebar from "../../Sidebar/index.jsx";
import { Outlet } from "react-router";
import { Stack } from "@mui/material";
Loaded 100 of 613 files, more files were not shown because too many files have changed in this diff. Show more