From e090d3cfd3e78ebac3a6cc61bb58595330650b63 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 12 Jan 2026 19:32:23 +0000 Subject: [PATCH 1/9] -> timeseries --- server/package-lock.json | 97 ++++ server/package.json | 1 + server/src/app.js | 1 - server/src/config/controllers.js | 47 -- server/src/config/controllers.ts | 35 ++ server/src/config/{routes.js => routes.ts} | 6 +- server/src/config/services.js | 84 +-- server/src/controllers/authController.ts | 233 +++++++++ .../controllers/{v1 => }/checkController.ts | 0 .../controllers/{v1 => }/controllerUtils.ts | 0 .../{v1 => }/diagnosticController.ts | 0 .../{v1 => }/incidentController.ts | 0 .../controllers/{v1 => }/inviteController.ts | 0 .../src/controllers/{v1 => }/logController.ts | 0 .../{v1 => }/maintenanceWindowController.ts | 0 .../controllers/{v1 => }/monitorController.ts | 2 +- .../{v1 => }/notificationController.ts | 0 .../controllers/{v1 => }/queueController.ts | 0 .../{v1 => }/settingsController.ts | 0 .../{v1 => }/statusPageController.ts | 0 .../controllers/v1/announcementsController.js | 77 --- server/src/controllers/v1/authController.js | 478 ------------------ server/src/controllers/v1/baseController.js | 83 --- server/src/db/{v1 => }/MongoDB.js | 0 .../0001_migrateStatusWindowThreshold.ts | 10 + .../0002_convertChecksToTimeSeries.ts | 93 ++++ server/src/db/migration/index.ts | 51 ++ server/src/db/{v1 => }/models/AppSettings.js | 0 server/src/db/models/Check.ts | 214 ++++++++ server/src/db/{v1 => }/models/Incident.js | 0 server/src/db/{v1 => }/models/InviteToken.js | 0 .../db/{v1 => }/models/MaintenanceWindow.js | 0 server/src/db/models/Migration.ts | 13 + server/src/db/{v1 => }/models/Monitor.js | 0 server/src/db/{v1 => }/models/MonitorStats.js | 0 server/src/db/{v1 => }/models/Notification.js | 0 .../src/db/{v1 => }/models/RecoveryToken.js | 0 server/src/db/{v1 => }/models/StatusPage.js | 0 server/src/db/{v1 => }/models/Team.js | 0 server/src/db/{v1 => }/models/User.js | 0 server/src/db/{v1 => }/modules/checkModule.js | 0 .../db/{v1 => }/modules/checkModuleQueries.js | 0 .../src/db/{v1 => }/modules/incidentModule.js | 0 .../src/db/{v1 => }/modules/inviteModule.js | 0 .../modules/maintenanceWindowModule.js | 0 .../src/db/{v1 => }/modules/monitorModule.js | 0 .../{v1 => }/modules/monitorModuleQueries.js | 0 .../db/{v1 => }/modules/notificationModule.js | 0 .../src/db/{v1 => }/modules/recoveryModule.js | 0 .../src/db/{v1 => }/modules/settingsModule.js | 0 .../db/{v1 => }/modules/statusPageModule.js | 0 server/src/db/{v1 => }/modules/userModule.js | 0 server/src/db/{v1 => }/utils/seedDb.js | 0 .../0001_migrateStatusWindowThreshold.ts | 18 - server/src/db/v1/migration/index.ts | 7 - server/src/db/v1/models/Check.js | 178 ------- server/src/index.js | 7 +- server/src/middleware/v1/handleErrors.js | 4 +- server/src/middleware/v1/isAllowed.js | 6 +- server/src/middleware/v1/verifyJWT.js | 6 +- server/src/middleware/v1/verifyOwnership.js | 4 +- .../repositories/checks/IChecksRepository.ts | 0 .../checks/MongoChecksRepistory.ts | 0 .../monitors/IMonitorsRepository.ts | 9 + .../monitors/MongoMonitorsRepository.ts | 5 + server/src/routes/v1/announcementsRoute.js | 33 -- server/src/routes/v1/monitorRoute.js | 2 +- .../service/{v1 => }/business/checkService.js | 0 .../{v1 => }/business/diagnosticService.js | 0 .../{v1 => }/business/incidentService.js | 0 .../{v1 => }/business/inviteService.js | 0 .../business/maintenanceWindowService.js | 0 .../{v1 => }/business/monitorService.js | 2 +- .../service/{v1 => }/business/userService.js | 0 .../SuperSimpleQueue/SuperSimpleQueue.js | 0 .../SuperSimpleQueueHelper.js | 0 .../{v1 => }/infrastructure/bufferService.js | 0 .../{v1 => }/infrastructure/emailService.js | 0 .../{v1 => }/infrastructure/errorService.js | 0 .../{v1 => }/infrastructure/networkService.js | 0 .../notificationProviders/matrix.js | 0 .../infrastructure/notificationService.js | 0 .../infrastructure/notificationUtils.js | 0 .../{v1 => }/infrastructure/statusService.js | 12 +- .../{v1 => }/system/serviceRegistry.js | 0 .../{v1 => }/system/settingsService.js | 0 .../service/{v1 => }/system/stringService.js | 0 .../{v1 => }/system/translationService.js | 0 server/src/types/check.ts | 79 +++ server/src/types/index.ts | 2 + server/src/types/monitor.ts | 29 ++ 91 files changed, 941 insertions(+), 987 deletions(-) delete mode 100644 server/src/config/controllers.js create mode 100644 server/src/config/controllers.ts rename server/src/config/{routes.js => routes.ts} (92%) create mode 100755 server/src/controllers/authController.ts rename server/src/controllers/{v1 => }/checkController.ts (100%) rename server/src/controllers/{v1 => }/controllerUtils.ts (100%) rename server/src/controllers/{v1 => }/diagnosticController.ts (100%) rename server/src/controllers/{v1 => }/incidentController.ts (100%) rename server/src/controllers/{v1 => }/inviteController.ts (100%) rename server/src/controllers/{v1 => }/logController.ts (100%) rename server/src/controllers/{v1 => }/maintenanceWindowController.ts (100%) rename server/src/controllers/{v1 => }/monitorController.ts (99%) rename server/src/controllers/{v1 => }/notificationController.ts (100%) rename server/src/controllers/{v1 => }/queueController.ts (100%) rename server/src/controllers/{v1 => }/settingsController.ts (100%) rename server/src/controllers/{v1 => }/statusPageController.ts (100%) delete mode 100755 server/src/controllers/v1/announcementsController.js delete mode 100755 server/src/controllers/v1/authController.js delete mode 100644 server/src/controllers/v1/baseController.js rename server/src/db/{v1 => }/MongoDB.js (100%) create mode 100644 server/src/db/migration/0001_migrateStatusWindowThreshold.ts create mode 100644 server/src/db/migration/0002_convertChecksToTimeSeries.ts create mode 100644 server/src/db/migration/index.ts rename server/src/db/{v1 => }/models/AppSettings.js (100%) create mode 100755 server/src/db/models/Check.ts rename server/src/db/{v1 => }/models/Incident.js (100%) rename server/src/db/{v1 => }/models/InviteToken.js (100%) rename server/src/db/{v1 => }/models/MaintenanceWindow.js (100%) create mode 100644 server/src/db/models/Migration.ts rename server/src/db/{v1 => }/models/Monitor.js (100%) rename server/src/db/{v1 => }/models/MonitorStats.js (100%) rename server/src/db/{v1 => }/models/Notification.js (100%) rename server/src/db/{v1 => }/models/RecoveryToken.js (100%) rename server/src/db/{v1 => }/models/StatusPage.js (100%) rename server/src/db/{v1 => }/models/Team.js (100%) rename server/src/db/{v1 => }/models/User.js (100%) rename server/src/db/{v1 => }/modules/checkModule.js (100%) rename server/src/db/{v1 => }/modules/checkModuleQueries.js (100%) rename server/src/db/{v1 => }/modules/incidentModule.js (100%) rename server/src/db/{v1 => }/modules/inviteModule.js (100%) rename server/src/db/{v1 => }/modules/maintenanceWindowModule.js (100%) rename server/src/db/{v1 => }/modules/monitorModule.js (100%) rename server/src/db/{v1 => }/modules/monitorModuleQueries.js (100%) rename server/src/db/{v1 => }/modules/notificationModule.js (100%) rename server/src/db/{v1 => }/modules/recoveryModule.js (100%) rename server/src/db/{v1 => }/modules/settingsModule.js (100%) rename server/src/db/{v1 => }/modules/statusPageModule.js (100%) rename server/src/db/{v1 => }/modules/userModule.js (100%) rename server/src/db/{v1 => }/utils/seedDb.js (100%) delete mode 100644 server/src/db/v1/migration/0001_migrateStatusWindowThreshold.ts delete mode 100644 server/src/db/v1/migration/index.ts delete mode 100755 server/src/db/v1/models/Check.js create mode 100644 server/src/repositories/checks/IChecksRepository.ts create mode 100644 server/src/repositories/checks/MongoChecksRepistory.ts create mode 100644 server/src/repositories/monitors/IMonitorsRepository.ts create mode 100644 server/src/repositories/monitors/MongoMonitorsRepository.ts delete mode 100755 server/src/routes/v1/announcementsRoute.js rename server/src/service/{v1 => }/business/checkService.js (100%) rename server/src/service/{v1 => }/business/diagnosticService.js (100%) rename server/src/service/{v1 => }/business/incidentService.js (100%) rename server/src/service/{v1 => }/business/inviteService.js (100%) rename server/src/service/{v1 => }/business/maintenanceWindowService.js (100%) rename server/src/service/{v1 => }/business/monitorService.js (99%) rename server/src/service/{v1 => }/business/userService.js (100%) rename server/src/service/{v1 => }/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js (100%) rename server/src/service/{v1 => }/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js (100%) rename server/src/service/{v1 => }/infrastructure/bufferService.js (100%) rename server/src/service/{v1 => }/infrastructure/emailService.js (100%) rename server/src/service/{v1 => }/infrastructure/errorService.js (100%) rename server/src/service/{v1 => }/infrastructure/networkService.js (100%) rename server/src/service/{v1 => }/infrastructure/notificationProviders/matrix.js (100%) rename server/src/service/{v1 => }/infrastructure/notificationService.js (100%) rename server/src/service/{v1 => }/infrastructure/notificationUtils.js (100%) rename server/src/service/{v1 => }/infrastructure/statusService.js (98%) rename server/src/service/{v1 => }/system/serviceRegistry.js (100%) rename server/src/service/{v1 => }/system/settingsService.js (100%) rename server/src/service/{v1 => }/system/stringService.js (100%) rename server/src/service/{v1 => }/system/translationService.js (100%) create mode 100644 server/src/types/check.ts create mode 100644 server/src/types/index.ts create mode 100644 server/src/types/monitor.ts diff --git a/server/package-lock.json b/server/package-lock.json index e08248989..eaf771a61 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -57,6 +57,7 @@ "esm": "3.2.25", "globals": "^15.14.0", "mocha": "11.1.0", + "nodemon": "^3.1.11", "prettier": "^3.3.3", "sinon": "19.0.2", "tsc-alias": "1.8.16", @@ -6732,6 +6733,13 @@ "node": ">= 4" } }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true, + "license": "ISC" + }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -8745,6 +8753,58 @@ "node": ">=6.0.0" } }, + "node_modules/nodemon": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.11.tgz", + "integrity": "sha512-is96t8F/1//UHAjNPHpbsNY46ELPpftGUoSVNXwUfMk/qdjSylYrWSu1XavVTBOn526kFiOR733ATgNBCQyH0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -9797,6 +9857,13 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, + "license": "MIT" + }, "node_modules/pump": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", @@ -10424,6 +10491,19 @@ "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", "license": "MIT" }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/sinon": { "version": "19.0.2", "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.2.tgz", @@ -11046,6 +11126,16 @@ "node": ">=0.6" } }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "license": "ISC", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, "node_modules/tough-cookie": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", @@ -11225,6 +11315,13 @@ "node": ">=0.8.0" } }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true, + "license": "MIT" + }, "node_modules/undici": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/undici/-/undici-6.22.0.tgz", diff --git a/server/package.json b/server/package.json index 050dd8e66..5610d32a9 100755 --- a/server/package.json +++ b/server/package.json @@ -69,6 +69,7 @@ "esm": "3.2.25", "globals": "^15.14.0", "mocha": "11.1.0", + "nodemon": "^3.1.11", "prettier": "^3.3.3", "sinon": "19.0.2", "tsc-alias": "1.8.16", diff --git a/server/src/app.js b/server/src/app.js index 4578de896..d782d07eb 100644 --- a/server/src/app.js +++ b/server/src/app.js @@ -14,7 +14,6 @@ import { sanitizeBody, sanitizeQuery } from "./middleware/v1/sanitization.js"; export const createApp = ({ services, controllers, envSettings, frontendPath, openApiSpec }) => { const allowedOrigin = envSettings.clientHost; - const app = express(); app.use(generalApiLimiter); // Static files diff --git a/server/src/config/controllers.js b/server/src/config/controllers.js deleted file mode 100644 index afd558930..000000000 --- a/server/src/config/controllers.js +++ /dev/null @@ -1,47 +0,0 @@ -import { createCommonDependencies } from "../controllers/v1/baseController.js"; - -// Services - -// V1 Controllers -import MonitorController from "../controllers/v1/monitorController.js"; -import AuthController from "../controllers/v1/authController.js"; -import SettingsController from "../controllers/v1/settingsController.js"; -import CheckController from "../controllers/v1/checkController.js"; -import InviteController from "../controllers/v1/inviteController.js"; -import MaintenanceWindowController from "../controllers/v1/maintenanceWindowController.js"; -import QueueController from "../controllers/v1/queueController.js"; -import LogController from "../controllers/v1/logController.js"; -import StatusPageController from "../controllers/v1/statusPageController.js"; -import NotificationController from "../controllers/v1/notificationController.js"; -import DiagnosticController from "../controllers/v1/diagnosticController.js"; -import IncidentController from "../controllers/v1/incidentController.js"; - -export const initializeControllers = (services) => { - const controllers = {}; - const commonDependencies = createCommonDependencies(services.db, services.errorService, services.logger, services.stringService); - - // V1 - controllers.authController = new AuthController(commonDependencies, { - settingsService: services.settingsService, - emailService: services.emailService, - jobQueue: services.jobQueue, - userService: services.userService, - }); - - controllers.monitorController = new MonitorController(services.monitorService); - - controllers.settingsController = new SettingsController(services.settingsService, services.emailService, services.db); - controllers.checkController = new CheckController(services.checkService); - controllers.inviteController = new InviteController(services.inviteService); - - controllers.maintenanceWindowController = new MaintenanceWindowController(services.maintenanceWindowService); - controllers.queueController = new QueueController(services.jobQueue); - controllers.logController = new LogController(services.logger); - controllers.statusPageController = new StatusPageController(services.db); - controllers.notificationController = new NotificationController(services.notificationService, services.db); - controllers.diagnosticController = new DiagnosticController(services.diagnosticService); - - controllers.incidentController = new IncidentController(services.incidentService); - - return controllers; -}; diff --git a/server/src/config/controllers.ts b/server/src/config/controllers.ts new file mode 100644 index 000000000..9fe834348 --- /dev/null +++ b/server/src/config/controllers.ts @@ -0,0 +1,35 @@ +import MonitorController from "../controllers/monitorController.js"; +import AuthController from "../controllers/authController.js"; +import SettingsController from "../controllers/settingsController.js"; +import CheckController from "../controllers/checkController.js"; +import InviteController from "../controllers/inviteController.js"; +import MaintenanceWindowController from "../controllers/maintenanceWindowController.js"; +import QueueController from "../controllers/queueController.js"; +import LogController from "../controllers/logController.js"; +import StatusPageController from "../controllers/statusPageController.js"; +import NotificationController from "../controllers/notificationController.js"; +import DiagnosticController from "../controllers/diagnosticController.js"; +import IncidentController from "../controllers/incidentController.js"; + +export const initializeControllers = (services: any) => { + const controllers: Record = {}; + + controllers.authController = new AuthController(services.userService); + + controllers.monitorController = new MonitorController(services.monitorService); + + controllers.settingsController = new SettingsController(services.settingsService, services.emailService, services.db); + controllers.checkController = new CheckController(services.checkService); + controllers.inviteController = new InviteController(services.inviteService); + + controllers.maintenanceWindowController = new MaintenanceWindowController(services.maintenanceWindowService); + controllers.queueController = new QueueController(services.jobQueue); + controllers.logController = new LogController(services.logger); + controllers.statusPageController = new StatusPageController(services.db); + controllers.notificationController = new NotificationController(services.notificationService, services.db); + controllers.diagnosticController = new DiagnosticController(services.diagnosticService); + + controllers.incidentController = new IncidentController(services.incidentService); + + return controllers; +}; diff --git a/server/src/config/routes.js b/server/src/config/routes.ts similarity index 92% rename from server/src/config/routes.js rename to server/src/config/routes.ts index 97b2d6a1d..303dd4eb7 100644 --- a/server/src/config/routes.js +++ b/server/src/config/routes.ts @@ -2,7 +2,7 @@ import { verifyJWT } from "../middleware/v1/verifyJWT.js"; import { authApiLimiter } from "../middleware/v1/rateLimiter.js"; import AuthRoutes from "../routes/v1/authRoute.js"; -import InviteRoutes from "../routes/v1//inviteRoute.js"; +import InviteRoutes from "../routes/v1/inviteRoute.js"; import MonitorRoutes from "../routes/v1/monitorRoute.js"; import CheckRoutes from "../routes/v1/checkRoute.js"; import SettingsRoutes from "../routes/v1/settingsRoute.js"; @@ -10,12 +10,12 @@ import MaintenanceWindowRoutes from "../routes/v1/maintenanceWindowRoute.js"; import StatusPageRoutes from "../routes/v1/statusPageRoute.js"; import QueueRoutes from "../routes/v1/queueRoute.js"; import LogRoutes from "../routes/v1/logRoutes.js"; -import DiagnosticRoutes from "../routes/v1//diagnosticRoute.js"; +import DiagnosticRoutes from "../routes/v1/diagnosticRoute.js"; import NotificationRoutes from "../routes/v1/notificationRoute.js"; import IncidentRoutes from "../routes/v1/incidentRoute.js"; -export const setupRoutes = (app, controllers) => { +export const setupRoutes = (app: any, controllers: Record) => { // V1 const authRoutes = new AuthRoutes(controllers.authController); const monitorRoutes = new MonitorRoutes(controllers.monitorController); diff --git a/server/src/config/services.js b/server/src/config/services.js index 9744c647d..28b7c9a86 100644 --- a/server/src/config/services.js +++ b/server/src/config/services.js @@ -1,23 +1,23 @@ -import ServiceRegistry from "../service/v1/system/serviceRegistry.js"; -import TranslationService from "../service/v1/system/translationService.js"; -import StringService from "../service/v1/system/stringService.js"; -import MongoDB from "../db/v1/MongoDB.js"; -import NetworkService from "../service/v1/infrastructure/networkService.js"; -import EmailService from "../service/v1/infrastructure/emailService.js"; -import BufferService from "../service/v1/infrastructure/bufferService.js"; -import StatusService from "../service/v1/infrastructure/statusService.js"; -import NotificationUtils from "../service/v1/infrastructure/notificationUtils.js"; -import NotificationService from "../service/v1/infrastructure/notificationService.js"; -import ErrorService from "../service/v1/infrastructure/errorService.js"; -import SuperSimpleQueueHelper from "../service/v1/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js"; -import SuperSimpleQueue from "../service/v1/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js"; -import UserService from "../service/v1/business/userService.js"; -import CheckService from "../service/v1/business/checkService.js"; -import DiagnosticService from "../service/v1/business/diagnosticService.js"; -import InviteService from "../service/v1/business/inviteService.js"; -import MaintenanceWindowService from "../service/v1/business/maintenanceWindowService.js"; -import MonitorService from "../service/v1/business/monitorService.js"; -import IncidentService from "../service/v1/business/incidentService.js"; +import ServiceRegistry from "../service/system/serviceRegistry.js"; +import TranslationService from "../service/system/translationService.js"; +import StringService from "../service/system/stringService.js"; +import MongoDB from "../db/MongoDB.js"; +import NetworkService from "../service/infrastructure/networkService.js"; +import EmailService from "../service/infrastructure/emailService.js"; +import BufferService from "../service/infrastructure/bufferService.js"; +import StatusService from "../service/infrastructure/statusService.js"; +import NotificationUtils from "../service/infrastructure/notificationUtils.js"; +import NotificationService from "../service/infrastructure/notificationService.js"; +import ErrorService from "../service/infrastructure/errorService.js"; +import SuperSimpleQueueHelper from "../service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js"; +import SuperSimpleQueue from "../service/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js"; +import UserService from "../service/business/userService.js"; +import CheckService from "../service/business/checkService.js"; +import DiagnosticService from "../service/business/diagnosticService.js"; +import InviteService from "../service/business/inviteService.js"; +import MaintenanceWindowService from "../service/business/maintenanceWindowService.js"; +import MonitorService from "../service/business/monitorService.js"; +import IncidentService from "../service/business/incidentService.js"; import papaparse from "papaparse"; import axios from "axios"; import got from "got"; @@ -47,29 +47,29 @@ import { GenerateAvatarImage } from "../utils/imageProcessing.js"; import { ParseBoolean } from "../utils/utils.js"; // Models -import Check from "../db/v1/models/Check.js"; -import Monitor from "../db/v1/models/Monitor.js"; -import User from "../db/v1/models/User.js"; -import InviteToken from "../db/v1/models/InviteToken.js"; -import StatusPage from "../db/v1/models/StatusPage.js"; -import Team from "../db/v1/models/Team.js"; -import MaintenanceWindow from "../db/v1/models/MaintenanceWindow.js"; -import MonitorStats from "../db/v1/models/MonitorStats.js"; -import Notification from "../db/v1/models/Notification.js"; -import RecoveryToken from "../db/v1/models/RecoveryToken.js"; -import AppSettings from "../db/v1/models/AppSettings.js"; -import Incident from "../db/v1/models/Incident.js"; +import Check from "../db/models/Check.js"; +import Monitor from "../db/models/Monitor.js"; +import User from "../db/models/User.js"; +import InviteToken from "../db/models/InviteToken.js"; +import StatusPage from "../db/models/StatusPage.js"; +import Team from "../db/models/Team.js"; +import MaintenanceWindow from "../db/models/MaintenanceWindow.js"; +import MonitorStats from "../db/models/MonitorStats.js"; +import Notification from "../db/models/Notification.js"; +import RecoveryToken from "../db/models/RecoveryToken.js"; +import AppSettings from "../db/models/AppSettings.js"; +import Incident from "../db/models/Incident.js"; -import InviteModule from "../db/v1/modules/inviteModule.js"; -import CheckModule from "../db/v1/modules/checkModule.js"; -import StatusPageModule from "../db/v1/modules/statusPageModule.js"; -import UserModule from "../db/v1/modules/userModule.js"; -import MaintenanceWindowModule from "../db/v1/modules/maintenanceWindowModule.js"; -import MonitorModule from "../db/v1/modules/monitorModule.js"; -import NotificationModule from "../db/v1/modules/notificationModule.js"; -import RecoveryModule from "../db/v1/modules/recoveryModule.js"; -import SettingsModule from "../db/v1/modules/settingsModule.js"; -import IncidentModule from "../db/v1/modules/incidentModule.js"; +import InviteModule from "../db/modules/inviteModule.js"; +import CheckModule from "../db/modules/checkModule.js"; +import StatusPageModule from "../db/modules/statusPageModule.js"; +import UserModule from "../db/modules/userModule.js"; +import MaintenanceWindowModule from "../db/modules/maintenanceWindowModule.js"; +import MonitorModule from "../db/modules/monitorModule.js"; +import NotificationModule from "../db/modules/notificationModule.js"; +import RecoveryModule from "../db/modules/recoveryModule.js"; +import SettingsModule from "../db/modules/settingsModule.js"; +import IncidentModule from "../db/modules/incidentModule.js"; export const initializeServices = async ({ logger, envSettings, settingsService }) => { const serviceRegistry = new ServiceRegistry({ logger }); diff --git a/server/src/controllers/authController.ts b/server/src/controllers/authController.ts new file mode 100755 index 000000000..d033aa39d --- /dev/null +++ b/server/src/controllers/authController.ts @@ -0,0 +1,233 @@ +import { Request, Response, NextFunction } from "express"; +import { AppError } from "@/utils/AppError.js"; + +import { + registrationBodyValidation, + loginValidation, + editUserBodyValidation, + recoveryValidation, + recoveryTokenBodyValidation, + newPasswordValidation, + getUserByIdParamValidation, + editUserByIdParamValidation, + editUserByIdBodyValidation, + editSuperadminUserByIdBodyValidation, + editUserPasswordByIdBodyValidation, +} from "@/validation/joi.js"; + +const SERVICE_NAME = "authController"; + +class AuthController { + static SERVICE_NAME = SERVICE_NAME; + + private userService: any; + + constructor(userService: any) { + this.userService = userService; + } + + get serviceName() { + return AuthController.SERVICE_NAME; + } + + registerUser = async (req: Request, res: Response, next: NextFunction) => { + try { + if (req.body?.email) { + req.body.email = req.body.email?.toLowerCase(); + } + await registrationBodyValidation.validateAsync(req.body); + const { user, token } = await this.userService.registerUser(req.body, req.file); + res.status(200).json({ + success: true, + msg: "User registered successfully", + data: { user, token }, + }); + } catch (error) { + next(error); + } + }; + + loginUser = async (req: Request, res: Response, next: NextFunction) => { + try { + if (req.body?.email) { + req.body.email = req.body.email?.toLowerCase(); + } + await loginValidation.validateAsync(req.body); + const { user, token } = await this.userService.loginUser(req.body.email, req.body.password); + + return res.status(200).json({ + success: true, + msg: "User logged in successfully", + data: { + user, + token, + }, + }); + } catch (error) { + next(error); + } + }; + + editUser = async (req: Request, res: Response, next: NextFunction) => { + try { + await editUserBodyValidation.validateAsync(req.body); + + const updatedUser = await this.userService.editUser(req.body, req.file, req.user); + + res.status(200).json({ + success: true, + msg: "User updated successfully", + data: updatedUser, + }); + } catch (error) { + next(error); + } + }; + + checkSuperadminExists = async (req: Request, res: Response, next: NextFunction) => { + try { + const superAdminExists = await this.userService.checkSuperadminExists(); + return res.status(200).json({ + success: true, + msg: "Superadmin existence checked successfully", + data: superAdminExists, + }); + } catch (error) { + next(error); + } + }; + + requestRecovery = async (req: Request, res: Response, next: NextFunction) => { + try { + await recoveryValidation.validateAsync(req.body); + const email = req?.body?.email; + const msgId = await this.userService.requestRecovery(email); + return res.status(200).json({ + success: true, + msg: "Password recovery email sent successfully", + data: msgId, + }); + } catch (error) { + next(error); + } + }; + + validateRecovery = async (req: Request, res: Response, next: NextFunction) => { + try { + await recoveryTokenBodyValidation.validateAsync(req.body); + await this.userService.validateRecovery(req.body.recoveryToken); + return res.status(200).json({ + success: true, + msg: "Recovery token is valid", + }); + } catch (error) { + next(error); + } + }; + + resetPassword = async (req: Request, res: Response, next: NextFunction) => { + try { + await newPasswordValidation.validateAsync(req.body); + const { user, token } = await this.userService.resetPassword(req.body.password, req.body.recoveryToken); + return res.status(200).json({ + success: true, + msg: "Password has been reset successfully", + data: { user, token }, + }); + } catch (error) { + next(error); + } + }; + + deleteUser = async (req: Request, res: Response, next: NextFunction) => { + try { + await this.userService.deleteUser(req.user); + return res.status(200).json({ + success: true, + msg: "User deleted successfully", + }); + } catch (error) { + next(error); + } + }; + + getAllUsers = async (req: Request, res: Response, next: NextFunction) => { + try { + const allUsers = await this.userService.getAllUsers(); + return res.status(200).json({ + success: true, + msg: "Users retrieved successfully", + data: allUsers, + }); + } catch (error) { + next(error); + } + }; + + getUserById = async (req: Request, res: Response, next: NextFunction) => { + try { + await getUserByIdParamValidation.validateAsync(req.params); + const userId = req?.params?.userId; + const roles = req?.user?.role; + + if (!userId) { + throw new Error("No user ID in request"); + } + + if (!roles || roles.length === 0) { + throw new Error("No roles in request"); + } + + const user = await this.userService.getUserById(roles, userId); + + return res.status(200).json({ success: true, msg: "ok", data: user }); + } catch (error) { + next(error); + } + }; + + editUserById = async (req: Request, res: Response, next: NextFunction) => { + try { + const roles = req?.user?.role; + if (!roles.includes("superadmin")) { + throw new AppError({ message: "Unauthorized", status: 403 }); + } + + const userId = req.params.userId; + const user = { ...req.body }; + + await editUserByIdParamValidation.validateAsync(req.params); + // If this is superadmin self edit, allow "superadmin" role + if (userId === req.user._id) { + await editSuperadminUserByIdBodyValidation.validateAsync(req.body); + } else { + await editUserByIdBodyValidation.validateAsync(req.body); + } + + await this.userService.editUserById(userId, user); + return res.status(200).json({ success: true, msg: "ok" }); + } catch (error) { + next(error); + } + }; + + editUserPasswordById = async (req: Request, res: Response, next: NextFunction) => { + try { + const roles = req?.user?.role; + if (!roles.includes("superadmin")) { + throw new AppError({ message: "Unauthorized", status: 403 }); + } + + const userId = req.params.userId; + await editUserByIdParamValidation.validateAsync(req.params); + await editUserPasswordByIdBodyValidation.validateAsync(req.body); + const updatedPassword = req.body.password; + await this.userService.setPasswordByUserId(userId, updatedPassword); + return res.status(200).json({ success: true, msg: "Password reset successfully" }); + } catch (error) { + next(error); + } + }; +} + +export default AuthController; diff --git a/server/src/controllers/v1/checkController.ts b/server/src/controllers/checkController.ts similarity index 100% rename from server/src/controllers/v1/checkController.ts rename to server/src/controllers/checkController.ts diff --git a/server/src/controllers/v1/controllerUtils.ts b/server/src/controllers/controllerUtils.ts similarity index 100% rename from server/src/controllers/v1/controllerUtils.ts rename to server/src/controllers/controllerUtils.ts diff --git a/server/src/controllers/v1/diagnosticController.ts b/server/src/controllers/diagnosticController.ts similarity index 100% rename from server/src/controllers/v1/diagnosticController.ts rename to server/src/controllers/diagnosticController.ts diff --git a/server/src/controllers/v1/incidentController.ts b/server/src/controllers/incidentController.ts similarity index 100% rename from server/src/controllers/v1/incidentController.ts rename to server/src/controllers/incidentController.ts diff --git a/server/src/controllers/v1/inviteController.ts b/server/src/controllers/inviteController.ts similarity index 100% rename from server/src/controllers/v1/inviteController.ts rename to server/src/controllers/inviteController.ts diff --git a/server/src/controllers/v1/logController.ts b/server/src/controllers/logController.ts similarity index 100% rename from server/src/controllers/v1/logController.ts rename to server/src/controllers/logController.ts diff --git a/server/src/controllers/v1/maintenanceWindowController.ts b/server/src/controllers/maintenanceWindowController.ts similarity index 100% rename from server/src/controllers/v1/maintenanceWindowController.ts rename to server/src/controllers/maintenanceWindowController.ts diff --git a/server/src/controllers/v1/monitorController.ts b/server/src/controllers/monitorController.ts similarity index 99% rename from server/src/controllers/v1/monitorController.ts rename to server/src/controllers/monitorController.ts index aac59cd27..425979062 100644 --- a/server/src/controllers/v1/monitorController.ts +++ b/server/src/controllers/monitorController.ts @@ -13,7 +13,7 @@ import { getCertificateParamValidation, getHardwareDetailsByIdParamValidation, getHardwareDetailsByIdQueryValidation, -} from "../../validation/joi.js"; +} from "@/validation/joi.js"; import sslChecker from "ssl-checker"; import { fetchMonitorCertificate } from "./controllerUtils.js"; import { AppError } from "@/utils/AppError.js"; diff --git a/server/src/controllers/v1/notificationController.ts b/server/src/controllers/notificationController.ts similarity index 100% rename from server/src/controllers/v1/notificationController.ts rename to server/src/controllers/notificationController.ts diff --git a/server/src/controllers/v1/queueController.ts b/server/src/controllers/queueController.ts similarity index 100% rename from server/src/controllers/v1/queueController.ts rename to server/src/controllers/queueController.ts diff --git a/server/src/controllers/v1/settingsController.ts b/server/src/controllers/settingsController.ts similarity index 100% rename from server/src/controllers/v1/settingsController.ts rename to server/src/controllers/settingsController.ts diff --git a/server/src/controllers/v1/statusPageController.ts b/server/src/controllers/statusPageController.ts similarity index 100% rename from server/src/controllers/v1/statusPageController.ts rename to server/src/controllers/statusPageController.ts diff --git a/server/src/controllers/v1/announcementsController.js b/server/src/controllers/v1/announcementsController.js deleted file mode 100755 index 0425b44aa..000000000 --- a/server/src/controllers/v1/announcementsController.js +++ /dev/null @@ -1,77 +0,0 @@ -import { createAnnouncementValidation } from "../../validation/joi.js"; -import BaseController from "./baseController.js"; - -const SERVICE_NAME = "announcementController"; - -/** - * Controller for managing announcements in the system. - * This class handles the creation of new announcements. - * - * @class AnnouncementController - */ - -class AnnouncementController extends BaseController { - static SERVICE_NAME = SERVICE_NAME; - constructor(commonDependencies) { - super(commonDependencies); - this.createAnnouncement = this.createAnnouncement.bind(this); - this.getAnnouncement = this.getAnnouncement.bind(this); - } - - get serviceName() { - return AnnouncementController.SERVICE_NAME; - } - - /** - * Handles the creation of a new announcement. - * - * @async - * @param {Object} req - The request object, containing the announcement data in the body. - * @param {Object} res - The response object used to send the result back to the client. - * @param {Function} next - The next middleware function in the stack for error handling. - * - * @returns {Promise} A promise that resolves once the response is sent. - */ - createAnnouncement = asyncHandler( - async (req, res, next) => { - await createAnnouncementValidation.validateAsync(req.body); - const { title, message } = req.body; - const announcementData = { - title: title.trim(), - message: message.trim(), - userId: req.user._id, - }; - - const newAnnouncement = await this.db.createAnnouncement(announcementData); - return res.success({ - msg: this.stringService.createAnnouncement, - data: newAnnouncement, - }); - }, - SERVICE_NAME, - "createAnnouncement" - ); - - /** - * Handles retrieving announcements with pagination. - * - * @async - * @param {Object} res - The response object used to send the result back to the client. - * - `data`: The list of announcements to be sent back to the client. - * - `msg`: A message about the success of the request. - * @param {Function} next - The next middleware function in the stack for error handling. - */ - getAnnouncement = asyncHandler( - async (req, res, next) => { - const allAnnouncements = await this.db.getAnnouncements(); - return res.success({ - msg: this.stringService.getAnnouncement, - data: allAnnouncements, - }); - }, - SERVICE_NAME, - "getAnnouncement" - ); -} - -export default AnnouncementController; diff --git a/server/src/controllers/v1/authController.js b/server/src/controllers/v1/authController.js deleted file mode 100755 index e52de3849..000000000 --- a/server/src/controllers/v1/authController.js +++ /dev/null @@ -1,478 +0,0 @@ -import BaseController from "./baseController.js"; -import { - registrationBodyValidation, - loginValidation, - editUserBodyValidation, - recoveryValidation, - recoveryTokenBodyValidation, - newPasswordValidation, - getUserByIdParamValidation, - editUserByIdParamValidation, - editUserByIdBodyValidation, - editSuperadminUserByIdBodyValidation, - editUserPasswordByIdBodyValidation, -} from "../../validation/joi.js"; - -const SERVICE_NAME = "authController"; -/** - * Authentication Controller - * - * Handles all authentication-related HTTP requests including user registration, - * login, password recovery, and user management operations. - * - * @class AuthController - * @description Manages user authentication and authorization operations - */ -class AuthController extends BaseController { - static SERVICE_NAME = SERVICE_NAME; - /** - * Creates an instance of AuthController. - * - * @param {Object} commonDependencies - Common dependencies injected into the controller - * @param {Object} dependencies - The dependencies required by the controller - * @param {Object} dependencies.settingsService - Service for application settings - * @param {Object} dependencies.emailService - Service for email operations - * @param {Object} dependencies.jobQueue - Service for job queue operations - * @param {Object} dependencies.userService - User business logic service - */ - constructor(commonDependencies, { settingsService, emailService, jobQueue, userService }) { - super(commonDependencies); - this.settingsService = settingsService; - this.emailService = emailService; - this.jobQueue = jobQueue; - this.userService = userService; - } - - get serviceName() { - return AuthController.SERVICE_NAME; - } - - /** - * Registers a new user in the system. - * - * @async - * @function registerUser - * @param {Object} req - Express request object - * @param {Object} req.body - Request body containing user registration data - * @param {string} req.body.firstName - User's first name - * @param {string} req.body.lastName - User's last name - * @param {string} req.body.email - User's email address (will be converted to lowercase) - * @param {string} req.body.password - User's password - * @param {string} [req.body.inviteToken] - Invite token for registration (required if superadmin exists) - * @param {string} [req.body.teamId] - Team ID (auto-assigned if superadmin) - * @param {Array} [req.body.role] - User roles (auto-assigned if superadmin) - * @param {Object} [req.file] - Profile image file uploaded via multer - * @param {Object} res - Express response object - * @returns {Promise} Success response with user data and JWT token - * @throws {Error} 422 - Validation error if request body is invalid - * @throws {Error} 409 - Conflict if user already exists - * @example - * // Register first user (becomes superadmin) - * POST /auth/register - * { - * "firstName": "John", - * "lastName": "Doe", - * "email": "john@example.com", - * "password": "SecurePass123!" - * } - * - * // Register subsequent user (requires invite token) - * POST /auth/register - * { - * "firstName": "Jane", - * "lastName": "Smith", - * "email": "jane@example.com", - * "password": "SecurePass123!", - * "inviteToken": "abc123..." - * } - */ - registerUser = this.asyncHandler( - async (req, res) => { - if (req.body?.email) { - req.body.email = req.body.email?.toLowerCase(); - } - await registrationBodyValidation.validateAsync(req.body); - const { user, token } = await this.userService.registerUser(req.body, req.file); - res.success({ - msg: this.stringService.authCreateUser, - data: { user, token }, - }); - }, - SERVICE_NAME, - "registerUser" - ); - - /** - * Authenticates a user and returns a JWT token. - * - * @async - * @function loginUser - * @param {Object} req - Express request object - * @param {Object} req.body - Request body containing login credentials - * @param {string} req.body.email - User's email address (will be converted to lowercase) - * @param {string} req.body.password - User's password - * @param {Object} res - Express response object - * @returns {Promise} Success response with user data and JWT token - * @throws {Error} 422 - Validation error if request body is invalid - * @throws {Error} 401 - Unauthorized if credentials are incorrect - * @example - * POST /auth/login - * { - * "email": "john@example.com", - * "password": "SecurePass123!" - * } - */ - loginUser = this.asyncHandler( - async (req, res) => { - if (req.body?.email) { - req.body.email = req.body.email?.toLowerCase(); - } - await loginValidation.validateAsync(req.body); - const { user, token } = await this.userService.loginUser(req.body.email, req.body.password); - - return res.success({ - msg: this.stringService.authLoginUser, - data: { - user, - token, - }, - }); - }, - SERVICE_NAME, - "loginUser" - ); - - /** - * Updates the current user's profile information. - * - * @async - * @function editUser - * @param {Object} req - Express request object - * @param {Object} req.body - Request body containing user update data - * @param {string} [req.body.firstName] - Updated first name - * @param {string} [req.body.lastName] - Updated last name - * @param {string} [req.body.password] - Current password (required for password change) - * @param {string} [req.body.newPassword] - New password (required for password change) - * @param {boolean} [req.body.deleteProfileImage] - Flag to delete profile image - * @param {Object} [req.file] - New profile image file - * @param {Object} req.user - Current authenticated user (from JWT) - * @param {Object} res - Express response object - * @returns {Promise} Success response with updated user data - * @throws {Error} 422 - Validation error if request body is invalid - * @throws {Error} 403 - Forbidden if current password is incorrect - * @example - * PUT /auth/user - * { - * "firstName": "John Updated", - * "lastName": "Doe Updated" - * } - * - * // Change password - * PUT /auth/user - * { - * "password": "OldPass123!", - * "newPassword": "NewPass123!" - * } - */ - editUser = this.asyncHandler( - async (req, res) => { - await editUserBodyValidation.validateAsync(req.body); - - const updatedUser = await this.userService.editUser(req.body, req.file, req.user); - - res.success({ - msg: this.stringService.authUpdateUser, - data: updatedUser, - }); - }, - SERVICE_NAME, - "editUser" - ); - - /** - * Checks if a superadmin account exists in the system. - * - * @async - * @function checkSuperadminExists - * @param {Object} req - Express request object - * @param {Object} res - Express response object - * @returns {Promise} Success response with boolean indicating superadmin existence - * @example - * GET /auth/users/superadmin - * // Response: { "data": true } or { "data": false } - */ - checkSuperadminExists = this.asyncHandler( - async (req, res) => { - const superAdminExists = await this.userService.checkSuperadminExists(); - return res.success({ - msg: this.stringService.authAdminExists, - data: superAdminExists, - }); - }, - SERVICE_NAME, - "checkSuperadminExists" - ); - - /** - * Initiates password recovery process by sending a recovery email. - * - * @async - * @function requestRecovery - * @param {Object} req - Express request object - * @param {Object} req.body - Request body containing email - * @param {string} req.body.email - Email address for password recovery - * @param {Object} res - Express response object - * @returns {Promise} Success response with message ID - * @throws {Error} 422 - Validation error if email is invalid - * @throws {Error} 404 - Not found if user doesn't exist - * @example - * POST /auth/recovery/request - * { - * "email": "john@example.com" - * } - */ - requestRecovery = this.asyncHandler( - async (req, res) => { - await recoveryValidation.validateAsync(req.body); - const email = req?.body?.email; - const msgId = await this.userService.requestRecovery(email); - return res.success({ - msg: this.stringService.authCreateRecoveryToken, - data: msgId, - }); - }, - SERVICE_NAME, - "requestRecovery" - ); - - /** - * Validates a password recovery token. - * - * @async - * @function validateRecovery - * @param {Object} req - Express request object - * @param {Object} req.body - Request body containing recovery token - * @param {string} req.body.recoveryToken - Recovery token to validate - * @param {Object} res - Express response object - * @returns {Promise} Success response if token is valid - * @throws {Error} 422 - Validation error if token format is invalid - * @throws {Error} 400 - Bad request if token is invalid or expired - * @example - * POST /auth/recovery/validate - * { - * "recoveryToken": "abc123..." - * } - */ - validateRecovery = this.asyncHandler( - async (req, res) => { - await recoveryTokenBodyValidation.validateAsync(req.body); - await this.userService.validateRecovery(req.body.recoveryToken); - return res.success({ - msg: this.stringService.authVerifyRecoveryToken, - }); - }, - SERVICE_NAME, - "validateRecovery" - ); - - /** - * Resets user password using a valid recovery token. - * - * @async - * @function resetPassword - * @param {Object} req - Express request object - * @param {Object} req.body - Request body containing new password and recovery token - * @param {string} req.body.password - New password - * @param {string} req.body.recoveryToken - Valid recovery token - * @param {Object} res - Express response object - * @returns {Promise} Success response with user data and JWT token - * @throws {Error} 422 - Validation error if password format is invalid - * @throws {Error} 400 - Bad request if token is invalid or expired - * @example - * POST /auth/recovery/reset - * { - * "password": "NewSecurePass123!", - * "recoveryToken": "abc123..." - * } - */ - resetPassword = this.asyncHandler( - async (req, res) => { - await newPasswordValidation.validateAsync(req.body); - const { user, token } = await this.userService.resetPassword(req.body.password, req.body.recoveryToken); - return res.success({ - msg: this.stringService.authResetPassword, - data: { user, token }, - }); - }, - SERVICE_NAME, - "resetPassword" - ); - - /** - * Deletes the current user's account and associated data. - * - * @async - * @function deleteUser - * @param {Object} req - Express request object - * @param {Object} req.user - Current authenticated user (from JWT) - * @param {string} req.user._id - User ID - * @param {string} req.user.email - User email - * @param {string} req.user.teamId - User's team ID - * @param {Array} req.user.role - User roles - * @param {Object} res - Express response object - * @returns {Promise} Success response confirming user deletion - * @throws {Error} 400 - Bad request if user is demo user - * @throws {Error} 404 - Not found if user doesn't exist - * @example - * DELETE /auth/user - * // Requires JWT authentication - */ - deleteUser = this.asyncHandler( - async (req, res) => { - await this.userService.deleteUser(req.user); - return res.success({ - msg: this.stringService.authDeleteUser, - }); - }, - SERVICE_NAME, - "deleteUser" - ); - - /** - * Retrieves all users in the system (admin/superadmin only). - * - * @async - * @function getAllUsers - * @param {Object} req - Express request object - * @param {Object} res - Express response object - * @returns {Promise} Success response with array of users - * @throws {Error} 403 - Forbidden if user doesn't have admin/superadmin role - * @example - * GET /auth/users - * // Requires JWT authentication with admin/superadmin role - */ - getAllUsers = this.asyncHandler( - async (req, res) => { - const allUsers = await this.userService.getAllUsers(); - return res.success({ - msg: this.stringService.authGetAllUsers, - data: allUsers, - }); - }, - SERVICE_NAME, - "getAllUsers" - ); - - /** - * Retrieves a specific user by ID (superadmin only). - * - * @async - * @function getUserById - * @param {Object} req - Express request object - * @param {Object} req.params - URL parameters - * @param {string} req.params.userId - ID of the user to retrieve - * @param {Object} req.user - Current authenticated user (from JWT) - * @param {Array} req.user.role - Current user's roles - * @param {Object} res - Express response object - * @returns {Promise} Success response with user data - * @throws {Error} 422 - Validation error if userId is invalid - * @throws {Error} 403 - Forbidden if user doesn't have superadmin role - * @throws {Error} 404 - Not found if user doesn't exist - * @example - * GET /auth/users/507f1f77bcf86cd799439011 - * // Requires JWT authentication with superadmin role - */ - getUserById = this.asyncHandler( - async (req, res) => { - await getUserByIdParamValidation.validateAsync(req.params); - const userId = req?.params?.userId; - const roles = req?.user?.role; - - if (!userId) { - throw new Error("No user ID in request"); - } - - if (!roles || roles.length === 0) { - throw new Error("No roles in request"); - } - - const user = await this.userService.getUserById(roles, userId); - - return res.success({ msg: "ok", data: user }); - }, - SERVICE_NAME, - "getUserById" - ); - - /** - * Updates a specific user by ID (superadmin only). - * - * @async - * @function editUserById - * @param {Object} req - Express request object - * @param {Object} req.params - URL parameters - * @param {string} req.params.userId - ID of the user to update - * @param {Object} req.body - Request body containing user update data - * @param {string} [req.body.firstName] - Updated first name - * @param {string} [req.body.lastName] - Updated last name - * @param {Array} [req.body.role] - Updated user roles - * @param {Object} req.user - Current authenticated user (from JWT) - * @param {string} req.user._id - Current user's ID - * @param {Array} req.user.role - Current user's roles - * @param {Object} res - Express response object - * @returns {Promise} Success response confirming user update - * @throws {Error} 422 - Validation error if parameters or body are invalid - * @throws {Error} 403 - Forbidden if user doesn't have superadmin role - * @throws {Error} 404 - Not found if user doesn't exist - * @example - * PUT /auth/users/507f1f77bcf86cd799439011 - * { - * "firstName": "Updated Name", - * "role": ["admin"] - * } - * // Requires JWT authentication with superadmin role - */ - editUserById = this.asyncHandler( - async (req, res) => { - const roles = req?.user?.role; - if (!roles.includes("superadmin")) { - throw this.errorService.createError("Unauthorized", 403); - } - - const userId = req.params.userId; - const user = { ...req.body }; - - await editUserByIdParamValidation.validateAsync(req.params); - // If this is superadmin self edit, allow "superadmin" role - if (userId === req.user._id) { - await editSuperadminUserByIdBodyValidation.validateAsync(req.body); - } else { - await editUserByIdBodyValidation.validateAsync(req.body); - } - - await this.userService.editUserById(userId, user); - return res.success({ msg: "ok" }); - }, - SERVICE_NAME, - "editUserById" - ); - editUserPasswordById = this.asyncHandler( - async (req, res) => { - const roles = req?.user?.role; - if (!roles.includes("superadmin")) { - throw this.errorService.createError("Unauthorized", 403); - } - - const userId = req.params.userId; - await editUserByIdParamValidation.validateAsync(req.params); - await editUserPasswordByIdBodyValidation.validateAsync(req.body); - const updatedPassword = req.body.password; - await this.userService.setPasswordByUserId(userId, updatedPassword); - return res.success({ msg: "Password reset successfully" }); - }, - SERVICE_NAME, - "editUserPasswordById" - ); -} - -export default AuthController; diff --git a/server/src/controllers/v1/baseController.js b/server/src/controllers/v1/baseController.js deleted file mode 100644 index e8612cec5..000000000 --- a/server/src/controllers/v1/baseController.js +++ /dev/null @@ -1,83 +0,0 @@ -import { AppError } from "../../service/v1/infrastructure/errorService.js"; - -export const createCommonDependencies = (db, errorService, logger, stringService) => { - return { - db, - errorService, - logger, - stringService, - }; -}; - -class BaseController { - constructor({ db, logger, errorService, ...additionalDependencies }) { - this.db = db; - this.logger = logger; - this.errorService = errorService; - Object.assign(this, additionalDependencies); - - this.asyncHandler = (fn, serviceName, methodName) => { - return async (req, res, next) => { - try { - await fn(req, res, next); - } catch (error) { - // Handle validation errors - if (error.isJoi) { - const validationError = this.errorService.createValidationError(error.message, error.details, serviceName, methodName); - return next(validationError); - } - - if (error.name === "ValidationError") { - const validationError = this.errorService.createValidationError("Database validation failed", error.errors, serviceName, methodName); - return next(validationError); - } - - if (error.name === "CastError") { - const notFoundError = this.errorService.createNotFoundError( - "Invalid resource identifier", - { field: error.path, value: error.value }, - serviceName, - methodName - ); - return next(notFoundError); - } - - if (error.code === "11000") { - const conflictError = this.errorService.createConflictError("Resource already exists", { - originalError: error.message, - code: error.code, - }); - conflictError.service = serviceName; - conflictError.method = methodName; - return next(conflictError); - } - - if (error instanceof AppError) { - error.service = error.service || serviceName; - error.method = error.method || methodName; - return next(error); - } - - if (error.status) { - const appError = this.errorService.createError(error.message, error.status, serviceName, methodName, { - originalError: error.message, - stack: error.stack, - }); - return next(appError); - } - - // For unknown errors, create a server error - const appError = this.errorService.createServerError(error.message || "An unexpected error occurred", { - originalError: error.message, - stack: error.stack, - }); - appError.service = serviceName; - appError.method = methodName; - appError.stack = error.stack; // Preserve original stack - return next(appError); - } - }; - }; - } -} -export default BaseController; diff --git a/server/src/db/v1/MongoDB.js b/server/src/db/MongoDB.js similarity index 100% rename from server/src/db/v1/MongoDB.js rename to server/src/db/MongoDB.js diff --git a/server/src/db/migration/0001_migrateStatusWindowThreshold.ts b/server/src/db/migration/0001_migrateStatusWindowThreshold.ts new file mode 100644 index 000000000..d9dd12aa1 --- /dev/null +++ b/server/src/db/migration/0001_migrateStatusWindowThreshold.ts @@ -0,0 +1,10 @@ +import Monitor from "@/db/models/Monitor.js"; +async function migrateStatusWindowThreshold() { + const monitors = await Monitor.find({ statusWindowThreshold: { $lt: 1 } }); + for (const monitor of monitors) { + monitor.statusWindowThreshold = monitor.statusWindowThreshold * 100; + await monitor.save(); + } +} + +export { migrateStatusWindowThreshold }; diff --git a/server/src/db/migration/0002_convertChecksToTimeSeries.ts b/server/src/db/migration/0002_convertChecksToTimeSeries.ts new file mode 100644 index 000000000..46e6fbc97 --- /dev/null +++ b/server/src/db/migration/0002_convertChecksToTimeSeries.ts @@ -0,0 +1,93 @@ +import mongoose from "mongoose"; + +const CHECKS_COLLECTION = "checks"; +const BACKUP_COLLECTION = "checks_backup"; +const BATCH_SIZE = 1000; + +const getDb = () => { + const db = mongoose.connection.db; + if (!db) { + throw new Error("Database connection is not initialized"); + } + return db; +}; + +const backupAndDropExistingCollection = async () => { + const db = getDb(); + const collections = await db.listCollections({ name: CHECKS_COLLECTION }).toArray(); + if (collections.length === 0) { + return false; + } + + await db.collection(CHECKS_COLLECTION).aggregate([ + { $match: {} }, + { $out: BACKUP_COLLECTION }, + ]).toArray(); + await db.collection(CHECKS_COLLECTION).drop(); + return true; +}; + +const createTimeSeriesCollection = async () => { + const db = getDb(); + const existing = await db.listCollections({ name: CHECKS_COLLECTION }).toArray(); + if (existing.length === 0) { + await db.createCollection(CHECKS_COLLECTION, { + timeseries: { + timeField: "createdAt", + metaField: "metadata", + granularity: "seconds", + }, + }); + } + + await db.collection(CHECKS_COLLECTION).createIndexes([ + { key: { updatedAt: 1 } }, + { key: { "metadata.monitorId": 1, updatedAt: 1 } }, + { key: { "metadata.monitorId": 1, updatedAt: -1 } }, + { key: { "metadata.teamId": 1, updatedAt: -1 } }, + ]); +}; + +const migrateBackupData = async () => { + const db = getDb(); + const backupExists = await db.listCollections({ name: BACKUP_COLLECTION }).toArray(); + if (backupExists.length === 0) { + return; + } + + const source = db.collection(BACKUP_COLLECTION); + const target = db.collection(CHECKS_COLLECTION); + const cursor = source.find(); + const operations: any[] = []; + + while (await cursor.hasNext()) { + const doc = await cursor.next(); + if (!doc) { + continue; + } + const metadata = { + monitorId: doc.monitorId, + teamId: doc.teamId, + type: doc.type, + }; + + operations.push({ insertOne: { document: { ...doc, metadata } } }); + + if (operations.length >= BATCH_SIZE) { + await target.bulkWrite(operations); + operations.length = 0; + } + } + + if (operations.length) { + await target.bulkWrite(operations); + } +}; + +export const convertChecksToTimeSeries = async () => { + const backedUp = await backupAndDropExistingCollection(); + await createTimeSeriesCollection(); + if (backedUp) { + await migrateBackupData(); + } +}; diff --git a/server/src/db/migration/index.ts b/server/src/db/migration/index.ts new file mode 100644 index 000000000..de2a1dee7 --- /dev/null +++ b/server/src/db/migration/index.ts @@ -0,0 +1,51 @@ +import { migrateStatusWindowThreshold } from "./0001_migrateStatusWindowThreshold.js"; +import { convertChecksToTimeSeries } from "./0002_convertChecksToTimeSeries.js"; +import MigrationModel from "../models/Migration.js"; + +type MigrationEntry = { + name: string; + execute: () => Promise; +}; + +const migrations: MigrationEntry[] = [ + { name: "0001_migrateStatusWindowThreshold", execute: migrateStatusWindowThreshold }, + { name: "0002_convertChecksToTimeSeries", execute: convertChecksToTimeSeries }, +]; + +const runMigrations = async (logger?: { info: Function; error: Function }) => { + try { + logger?.info({ message: "Running migrations", service: "Migrations" }); + for (const migration of migrations) { + const exists = await MigrationModel.findOne({ name: migration.name, status: "completed" }); + if (exists) { + logger?.info({ message: `Skipping ${migration.name}`, service: "Migrations" }); + continue; + } + + try { + await migration.execute(); + await MigrationModel.findOneAndUpdate( + { name: migration.name }, + { status: "completed", completedAt: new Date(), error: undefined }, + { upsert: true } + ); + logger?.info({ message: `Completed ${migration.name}`, service: "Migrations" }); + } catch (error) { + const err = error as Error; + await MigrationModel.findOneAndUpdate( + { name: migration.name }, + { status: "failed", error: err?.message }, + { upsert: true } + ); + throw error; + } + } + logger?.info({ message: "Migrations completed", service: "Migrations" }); + } catch (error) { + const err = error as Error; + logger?.error({ message: "Migration failed", service: "Migrations", details: err?.message, stack: err?.stack }); + throw error; + } +}; + +export { runMigrations }; diff --git a/server/src/db/v1/models/AppSettings.js b/server/src/db/models/AppSettings.js similarity index 100% rename from server/src/db/v1/models/AppSettings.js rename to server/src/db/models/AppSettings.js diff --git a/server/src/db/models/Check.ts b/server/src/db/models/Check.ts new file mode 100755 index 000000000..b13aa9a16 --- /dev/null +++ b/server/src/db/models/Check.ts @@ -0,0 +1,214 @@ +import mongoose from "mongoose"; +import { MonitorTypes } from "@/types/monitor.js"; + +const cpuSchema = new mongoose.Schema( + { + physical_core: { type: Number, default: 0 }, + logical_core: { type: Number, default: 0 }, + frequency: { type: Number, default: 0 }, + temperature: { type: [Number], default: [] }, + free_percent: { type: Number, default: 0 }, + usage_percent: { type: Number, default: 0 }, + }, + { _id: false } +); + +const memorySchema = new mongoose.Schema( + { + total_bytes: { type: Number, default: 0 }, + available_bytes: { type: Number, default: 0 }, + used_bytes: { type: Number, default: 0 }, + usage_percent: { type: Number, default: 0 }, + }, + { _id: false } +); + +const diskSchema = new mongoose.Schema( + { + device: { type: String, default: "" }, + mountpoint: { type: String, default: "" }, + read_speed_bytes: { type: Number, default: 0 }, + write_speed_bytes: { type: Number, default: 0 }, + total_bytes: { type: Number, default: 0 }, + free_bytes: { type: Number, default: 0 }, + usage_percent: { type: Number, default: 0 }, + }, + { _id: false } +); + +const hostSchema = new mongoose.Schema( + { + os: { type: String, default: "" }, + platform: { type: String, default: "" }, + kernel_version: { type: String, default: "" }, + }, + { _id: false } +); + +const errorSchema = new mongoose.Schema( + { + metric: { type: [String], default: [] }, + err: { type: String, default: "" }, + }, + { _id: false } +); + +const captureSchema = new mongoose.Schema( + { + version: { type: String, default: "" }, + mode: { type: String, default: "" }, + }, + { _id: false } +); + +const networkInterfaceSchema = new mongoose.Schema( + { + name: { type: String }, + bytes_sent: { type: Number, default: 0 }, + bytes_recv: { type: Number, default: 0 }, + packets_sent: { type: Number, default: 0 }, + packets_recv: { type: Number, default: 0 }, + err_in: { type: Number, default: 0 }, + err_out: { type: Number, default: 0 }, + drop_in: { type: Number, default: 0 }, + drop_out: { type: Number, default: 0 }, + fifo_in: { type: Number, default: 0 }, + fifo_out: { type: Number, default: 0 }, + }, + { _id: false } +); + +const metadataSchema = new mongoose.Schema( + { + monitorId: { + type: mongoose.Schema.Types.ObjectId, + ref: "Monitor", + immutable: true, + index: true, + }, + teamId: { + type: mongoose.Schema.Types.ObjectId, + ref: "Team", + immutable: true, + index: true, + }, + type: { + type: String, + enum: MonitorTypes, + required: true, + index: true, + }, + }, + { _id: false } +); + +const CheckSchema = new mongoose.Schema( + { + metadata: { + type: metadataSchema, + required: true, + }, + status: { + type: Boolean, + index: true, + }, + + responseTime: { + type: Number, + }, + + timings: { + type: Object, + default: {}, + }, + + statusCode: { + type: Number, + index: true, + }, + + message: { + type: String, + }, + + expiry: { + type: Date, + default: Date.now, + }, + + ack: { + type: Boolean, + default: false, + }, + + ackAt: { + type: Date, + }, + + // Hardware fields + cpu: { + type: cpuSchema, + default: () => ({}), + }, + memory: { + type: memorySchema, + default: () => ({}), + }, + disk: { + type: [diskSchema], + default: () => [], + }, + host: { + type: hostSchema, + default: () => ({}), + }, + + errors: { + type: [errorSchema], + default: () => [], + }, + + capture: { + type: captureSchema, + default: () => ({}), + }, + + net: { + type: [networkInterfaceSchema], + default: () => [], + }, + + // PageSpeed fields + accessibility: { + type: Number, + }, + bestPractices: { + type: Number, + }, + seo: { + type: Number, + }, + performance: { + type: Number, + }, + audits: { + type: Object, + }, + }, + { + timestamps: true, + strict: false, + timeseries: { + timeField: "createdAt", + metaField: "metadata", + granularity: "seconds", + }, + } +); + +CheckSchema.index({ updatedAt: 1 }); +CheckSchema.index({ "metadata.monitorId": 1, updatedAt: 1 }); +CheckSchema.index({ "metadata.monitorId": 1, updatedAt: -1 }); +CheckSchema.index({ "metadata.teamId": 1, updatedAt: -1 }); + +export default mongoose.model("Check", CheckSchema); diff --git a/server/src/db/v1/models/Incident.js b/server/src/db/models/Incident.js similarity index 100% rename from server/src/db/v1/models/Incident.js rename to server/src/db/models/Incident.js diff --git a/server/src/db/v1/models/InviteToken.js b/server/src/db/models/InviteToken.js similarity index 100% rename from server/src/db/v1/models/InviteToken.js rename to server/src/db/models/InviteToken.js diff --git a/server/src/db/v1/models/MaintenanceWindow.js b/server/src/db/models/MaintenanceWindow.js similarity index 100% rename from server/src/db/v1/models/MaintenanceWindow.js rename to server/src/db/models/MaintenanceWindow.js diff --git a/server/src/db/models/Migration.ts b/server/src/db/models/Migration.ts new file mode 100644 index 000000000..ba928d910 --- /dev/null +++ b/server/src/db/models/Migration.ts @@ -0,0 +1,13 @@ +import mongoose from "mongoose"; + +const MigrationSchema = new mongoose.Schema( + { + name: { type: String, required: true, unique: true }, + status: { type: String, enum: ["completed", "failed"], default: "completed" }, + completedAt: { type: Date }, + error: { type: String }, + }, + { timestamps: true } +); + +export default mongoose.model("Migration", MigrationSchema); diff --git a/server/src/db/v1/models/Monitor.js b/server/src/db/models/Monitor.js similarity index 100% rename from server/src/db/v1/models/Monitor.js rename to server/src/db/models/Monitor.js diff --git a/server/src/db/v1/models/MonitorStats.js b/server/src/db/models/MonitorStats.js similarity index 100% rename from server/src/db/v1/models/MonitorStats.js rename to server/src/db/models/MonitorStats.js diff --git a/server/src/db/v1/models/Notification.js b/server/src/db/models/Notification.js similarity index 100% rename from server/src/db/v1/models/Notification.js rename to server/src/db/models/Notification.js diff --git a/server/src/db/v1/models/RecoveryToken.js b/server/src/db/models/RecoveryToken.js similarity index 100% rename from server/src/db/v1/models/RecoveryToken.js rename to server/src/db/models/RecoveryToken.js diff --git a/server/src/db/v1/models/StatusPage.js b/server/src/db/models/StatusPage.js similarity index 100% rename from server/src/db/v1/models/StatusPage.js rename to server/src/db/models/StatusPage.js diff --git a/server/src/db/v1/models/Team.js b/server/src/db/models/Team.js similarity index 100% rename from server/src/db/v1/models/Team.js rename to server/src/db/models/Team.js diff --git a/server/src/db/v1/models/User.js b/server/src/db/models/User.js similarity index 100% rename from server/src/db/v1/models/User.js rename to server/src/db/models/User.js diff --git a/server/src/db/v1/modules/checkModule.js b/server/src/db/modules/checkModule.js similarity index 100% rename from server/src/db/v1/modules/checkModule.js rename to server/src/db/modules/checkModule.js diff --git a/server/src/db/v1/modules/checkModuleQueries.js b/server/src/db/modules/checkModuleQueries.js similarity index 100% rename from server/src/db/v1/modules/checkModuleQueries.js rename to server/src/db/modules/checkModuleQueries.js diff --git a/server/src/db/v1/modules/incidentModule.js b/server/src/db/modules/incidentModule.js similarity index 100% rename from server/src/db/v1/modules/incidentModule.js rename to server/src/db/modules/incidentModule.js diff --git a/server/src/db/v1/modules/inviteModule.js b/server/src/db/modules/inviteModule.js similarity index 100% rename from server/src/db/v1/modules/inviteModule.js rename to server/src/db/modules/inviteModule.js diff --git a/server/src/db/v1/modules/maintenanceWindowModule.js b/server/src/db/modules/maintenanceWindowModule.js similarity index 100% rename from server/src/db/v1/modules/maintenanceWindowModule.js rename to server/src/db/modules/maintenanceWindowModule.js diff --git a/server/src/db/v1/modules/monitorModule.js b/server/src/db/modules/monitorModule.js similarity index 100% rename from server/src/db/v1/modules/monitorModule.js rename to server/src/db/modules/monitorModule.js diff --git a/server/src/db/v1/modules/monitorModuleQueries.js b/server/src/db/modules/monitorModuleQueries.js similarity index 100% rename from server/src/db/v1/modules/monitorModuleQueries.js rename to server/src/db/modules/monitorModuleQueries.js diff --git a/server/src/db/v1/modules/notificationModule.js b/server/src/db/modules/notificationModule.js similarity index 100% rename from server/src/db/v1/modules/notificationModule.js rename to server/src/db/modules/notificationModule.js diff --git a/server/src/db/v1/modules/recoveryModule.js b/server/src/db/modules/recoveryModule.js similarity index 100% rename from server/src/db/v1/modules/recoveryModule.js rename to server/src/db/modules/recoveryModule.js diff --git a/server/src/db/v1/modules/settingsModule.js b/server/src/db/modules/settingsModule.js similarity index 100% rename from server/src/db/v1/modules/settingsModule.js rename to server/src/db/modules/settingsModule.js diff --git a/server/src/db/v1/modules/statusPageModule.js b/server/src/db/modules/statusPageModule.js similarity index 100% rename from server/src/db/v1/modules/statusPageModule.js rename to server/src/db/modules/statusPageModule.js diff --git a/server/src/db/v1/modules/userModule.js b/server/src/db/modules/userModule.js similarity index 100% rename from server/src/db/v1/modules/userModule.js rename to server/src/db/modules/userModule.js diff --git a/server/src/db/v1/utils/seedDb.js b/server/src/db/utils/seedDb.js similarity index 100% rename from server/src/db/v1/utils/seedDb.js rename to server/src/db/utils/seedDb.js diff --git a/server/src/db/v1/migration/0001_migrateStatusWindowThreshold.ts b/server/src/db/v1/migration/0001_migrateStatusWindowThreshold.ts deleted file mode 100644 index 55d26cc27..000000000 --- a/server/src/db/v1/migration/0001_migrateStatusWindowThreshold.ts +++ /dev/null @@ -1,18 +0,0 @@ -// import Monitor from "@/db/v1/models/Monitor.js"; -async function migrateStatusWindowThreshold() { - try { - // const monitors = await Monitor.find({ statusWindowThreshold: { $lt: 1 } }); - // for (const monitor of monitors) { - // monitor.statusWindowThreshold = monitor.statusWindowThreshold * 100; - // await monitor.save(); - // console.log(`Migrated monitor ${monitor._id}: statusWindowThreshold set to ${monitor.statusWindowThreshold}`); - // } - // console.log("StatusWindowThreshold migration complete."); - return true; - } catch (err) { - console.error("Migration error:", err); - return false; - } -} - -export { migrateStatusWindowThreshold }; diff --git a/server/src/db/v1/migration/index.ts b/server/src/db/v1/migration/index.ts deleted file mode 100644 index 4bf56895a..000000000 --- a/server/src/db/v1/migration/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { migrateStatusWindowThreshold } from "./0001_migrateStatusWindowThreshold.js"; - -const runMigrations = async () => { - await migrateStatusWindowThreshold(); -}; - -export { runMigrations }; diff --git a/server/src/db/v1/models/Check.js b/server/src/db/v1/models/Check.js deleted file mode 100755 index 7a5117979..000000000 --- a/server/src/db/v1/models/Check.js +++ /dev/null @@ -1,178 +0,0 @@ -import mongoose from "mongoose"; - -const cpuSchema = mongoose.Schema({ - physical_core: { type: Number, default: 0 }, - logical_core: { type: Number, default: 0 }, - frequency: { type: Number, default: 0 }, - temperature: { type: [Number], default: [] }, - free_percent: { type: Number, default: 0 }, - usage_percent: { type: Number, default: 0 }, -}); - -const memorySchema = mongoose.Schema({ - total_bytes: { type: Number, default: 0 }, - available_bytes: { type: Number, default: 0 }, - used_bytes: { type: Number, default: 0 }, - usage_percent: { type: Number, default: 0 }, -}); - -const diskSchema = mongoose.Schema({ - device: { type: String, default: "" }, - mountpoint: { type: String, default: "" }, - read_speed_bytes: { type: Number, default: 0 }, - write_speed_bytes: { type: Number, default: 0 }, - total_bytes: { type: Number, default: 0 }, - free_bytes: { type: Number, default: 0 }, - usage_percent: { type: Number, default: 0 }, -}); - -const hostSchema = mongoose.Schema({ - os: { type: String, default: "" }, - platform: { type: String, default: "" }, - kernel_version: { type: String, default: "" }, -}); - -const errorSchema = mongoose.Schema({ - metric: { type: [String], default: [] }, - err: { type: String, default: "" }, -}); - -const captureSchema = mongoose.Schema({ - version: { type: String, default: "" }, - mode: { type: String, default: "" }, -}); - -const networkInterfaceSchema = mongoose.Schema({ - name: { type: String }, - bytes_sent: { type: Number, default: 0 }, - bytes_recv: { type: Number, default: 0 }, - packets_sent: { type: Number, default: 0 }, - packets_recv: { type: Number, default: 0 }, - err_in: { type: Number, default: 0 }, - err_out: { type: Number, default: 0 }, - drop_in: { type: Number, default: 0 }, - drop_out: { type: Number, default: 0 }, - fifo_in: { type: Number, default: 0 }, - fifo_out: { type: Number, default: 0 }, -}); - -const CheckSchema = new mongoose.Schema( - { - // Common fields - monitorId: { - type: mongoose.Schema.Types.ObjectId, - ref: "Monitor", - immutable: true, - index: true, - }, - - teamId: { - type: mongoose.Schema.Types.ObjectId, - ref: "Team", - immutable: true, - index: true, - }, - type: { - type: String, - enum: ["http", "ping", "pagespeed", "hardware", "docker", "port", "game"], - required: true, - index: true, - }, - - status: { - type: Boolean, - index: true, - }, - - responseTime: { - type: Number, - }, - - timings: { - type: Object, - default: {}, - }, - - statusCode: { - type: Number, - index: true, - }, - - message: { - type: String, - }, - - expiry: { - type: Date, - default: Date.now, - expires: 60 * 60 * 24 * 30, // 30 days - }, - - ack: { - type: Boolean, - default: false, - }, - - ackAt: { - type: Date, - }, - - // Hardware fields - cpu: { - type: cpuSchema, - default: () => ({}), - }, - memory: { - type: memorySchema, - default: () => ({}), - }, - disk: { - type: [diskSchema], - default: () => [], - }, - host: { - type: hostSchema, - default: () => ({}), - }, - - errors: { - type: [errorSchema], - default: () => [], - }, - - capture: { - type: captureSchema, - default: () => ({}), - }, - - net: { - type: [networkInterfaceSchema], - default: () => [], - }, - - // PageSpeed fields - accessibility: { - type: Number, - }, - bestPractices: { - type: Number, - }, - seo: { - type: Number, - }, - performance: { - type: Number, - }, - audits: { - type: Object, - }, - }, - { timestamps: true } -); - -CheckSchema.index({ updatedAt: 1 }); -CheckSchema.index({ monitorId: 1, updatedAt: 1 }); -CheckSchema.index({ monitorId: 1, updatedAt: -1 }); -CheckSchema.index({ teamId: 1, updatedAt: -1 }); - -export default mongoose.model("Check", CheckSchema); diff --git a/server/src/index.js b/server/src/index.js index e8b756d0e..28dc5e8fd 100755 --- a/server/src/index.js +++ b/server/src/index.js @@ -5,10 +5,11 @@ import { initShutdownListener } from "./shutdown.js"; import { fileURLToPath } from "url"; import path from "path"; import fs from "fs"; +import { runMigrations } from "./db/migration/index.js"; import Logger from "./utils/logger.js"; -import SettingsService from "./service/v1/system/settingsService.js"; -import AppSettings from "./db/v1/models/AppSettings.js"; +import SettingsService from "./service/system/settingsService.js"; +import AppSettings from "./db/models/AppSettings.js"; const SERVICE_NAME = "Server"; let logger; @@ -30,6 +31,8 @@ const startApp = async () => { // Initialize services const services = await initializeServices({ logger, envSettings, settingsService }); + await runMigrations(logger); + // Initialize controllers const controllers = initializeControllers(services); diff --git a/server/src/middleware/v1/handleErrors.js b/server/src/middleware/v1/handleErrors.js index 43671fbe2..0a30b0420 100755 --- a/server/src/middleware/v1/handleErrors.js +++ b/server/src/middleware/v1/handleErrors.js @@ -1,6 +1,6 @@ import { logger } from "../../utils/logger.js"; -import ServiceRegistry from "../../service/v1/system/serviceRegistry.js"; -import StringService from "../../service/v1/system/stringService.js"; +import ServiceRegistry from "../../service/system/serviceRegistry.js"; +import StringService from "../../service/system/stringService.js"; const handleErrors = (error, req, res, next) => { const status = error.status || 500; diff --git a/server/src/middleware/v1/isAllowed.js b/server/src/middleware/v1/isAllowed.js index cc240f531..1d0de42b4 100755 --- a/server/src/middleware/v1/isAllowed.js +++ b/server/src/middleware/v1/isAllowed.js @@ -1,9 +1,9 @@ import jwt from "jsonwebtoken"; const TOKEN_PREFIX = "Bearer "; const SERVICE_NAME = "allowedRoles"; -import ServiceRegistry from "../../service/v1/system/serviceRegistry.js"; -import StringService from "../../service/v1/system/stringService.js"; -import SettingsService from "../../service/v1/system/settingsService.js"; +import ServiceRegistry from "../../service/system/serviceRegistry.js"; +import StringService from "../../service/system/stringService.js"; +import SettingsService from "../../service/system/settingsService.js"; const isAllowed = (allowedRoles) => { return (req, res, next) => { diff --git a/server/src/middleware/v1/verifyJWT.js b/server/src/middleware/v1/verifyJWT.js index b57391dfd..cf983a6c8 100755 --- a/server/src/middleware/v1/verifyJWT.js +++ b/server/src/middleware/v1/verifyJWT.js @@ -1,7 +1,7 @@ import jwt from "jsonwebtoken"; -import ServiceRegistry from "../../service/v1/system/serviceRegistry.js"; -import SettingsService from "../../service/v1/system/settingsService.js"; -import StringService from "../../service/v1/system/stringService.js"; +import ServiceRegistry from "../../service/system/serviceRegistry.js"; +import SettingsService from "../../service/system/settingsService.js"; +import StringService from "../../service/system/stringService.js"; const SERVICE_NAME = "verifyJWT"; const TOKEN_PREFIX = "Bearer "; diff --git a/server/src/middleware/v1/verifyOwnership.js b/server/src/middleware/v1/verifyOwnership.js index 741fb6436..6fcc84f60 100755 --- a/server/src/middleware/v1/verifyOwnership.js +++ b/server/src/middleware/v1/verifyOwnership.js @@ -1,6 +1,6 @@ import { logger } from "../../utils/logger.js"; -import ServiceRegistry from "../../service/v1/system/serviceRegistry.js"; -import StringService from "../../service/v1/system/stringService.js"; +import ServiceRegistry from "../../service/system/serviceRegistry.js"; +import StringService from "../../service/system/stringService.js"; import { ObjectId } from "mongodb"; const SERVICE_NAME = "verifyOwnership"; diff --git a/server/src/repositories/checks/IChecksRepository.ts b/server/src/repositories/checks/IChecksRepository.ts new file mode 100644 index 000000000..e69de29bb diff --git a/server/src/repositories/checks/MongoChecksRepistory.ts b/server/src/repositories/checks/MongoChecksRepistory.ts new file mode 100644 index 000000000..e69de29bb diff --git a/server/src/repositories/monitors/IMonitorsRepository.ts b/server/src/repositories/monitors/IMonitorsRepository.ts new file mode 100644 index 000000000..458ee5bad --- /dev/null +++ b/server/src/repositories/monitors/IMonitorsRepository.ts @@ -0,0 +1,9 @@ +import type { Monitor } from "@/types/index.js"; +export interface IMonitorsRepository { + // create + // single fetch + // collection fetch + findAll(): Promise; + // update + // delete +} diff --git a/server/src/repositories/monitors/MongoMonitorsRepository.ts b/server/src/repositories/monitors/MongoMonitorsRepository.ts new file mode 100644 index 000000000..b4bae06c8 --- /dev/null +++ b/server/src/repositories/monitors/MongoMonitorsRepository.ts @@ -0,0 +1,5 @@ +class MongoMonitorsRepository implements IMonitorsRepository { + findAll = async () => { + return null; + }; +} diff --git a/server/src/routes/v1/announcementsRoute.js b/server/src/routes/v1/announcementsRoute.js deleted file mode 100755 index 011dfac4a..000000000 --- a/server/src/routes/v1/announcementsRoute.js +++ /dev/null @@ -1,33 +0,0 @@ -import { Router } from "express"; -import { verifyJWT } from "../middleware/verifyJWT.js"; -import { isAllowed } from "../middleware/isAllowed.js"; - -class AnnouncementRoutes { - constructor(controller) { - this.router = Router(); - this.announcementController = controller; - this.initRoutes(); - } - - initRoutes() { - /** - * @route POST / - * @desc Create a new announcement - * @access Private (Requires JWT verification) - */ - this.router.post("/", verifyJWT, isAllowed(["admin", "superadmin"]), this.announcementController.createAnnouncement); - - /** - * @route GET / - * @desc Get announcements - * @access Public - */ - this.router.get("/", this.announcementController.getAnnouncement); - } - - getRouter() { - return this.router; - } -} - -export default AnnouncementRoutes; diff --git a/server/src/routes/v1/monitorRoute.js b/server/src/routes/v1/monitorRoute.js index fe430d46f..86463b6bb 100755 --- a/server/src/routes/v1/monitorRoute.js +++ b/server/src/routes/v1/monitorRoute.js @@ -1,7 +1,7 @@ import { Router } from "express"; import { isAllowed } from "../../middleware/v1/isAllowed.js"; import multer from "multer"; -import { fetchMonitorCertificate } from "../../controllers/v1/controllerUtils.js"; +import { fetchMonitorCertificate } from "../../controllers/controllerUtils.js"; const upload = multer({ storage: multer.memoryStorage(), // Store file in memory as Buffer }); diff --git a/server/src/service/v1/business/checkService.js b/server/src/service/business/checkService.js similarity index 100% rename from server/src/service/v1/business/checkService.js rename to server/src/service/business/checkService.js diff --git a/server/src/service/v1/business/diagnosticService.js b/server/src/service/business/diagnosticService.js similarity index 100% rename from server/src/service/v1/business/diagnosticService.js rename to server/src/service/business/diagnosticService.js diff --git a/server/src/service/v1/business/incidentService.js b/server/src/service/business/incidentService.js similarity index 100% rename from server/src/service/v1/business/incidentService.js rename to server/src/service/business/incidentService.js diff --git a/server/src/service/v1/business/inviteService.js b/server/src/service/business/inviteService.js similarity index 100% rename from server/src/service/v1/business/inviteService.js rename to server/src/service/business/inviteService.js diff --git a/server/src/service/v1/business/maintenanceWindowService.js b/server/src/service/business/maintenanceWindowService.js similarity index 100% rename from server/src/service/v1/business/maintenanceWindowService.js rename to server/src/service/business/maintenanceWindowService.js diff --git a/server/src/service/v1/business/monitorService.js b/server/src/service/business/monitorService.js similarity index 99% rename from server/src/service/v1/business/monitorService.js rename to server/src/service/business/monitorService.js index 2118e6281..4eae0176f 100644 --- a/server/src/service/v1/business/monitorService.js +++ b/server/src/service/business/monitorService.js @@ -1,4 +1,4 @@ -import { createMonitorsBodyValidation } from "../../../validation/joi.js"; +import { createMonitorsBodyValidation } from "@/validation/joi.js"; const SERVICE_NAME = "MonitorService"; class MonitorService { diff --git a/server/src/service/v1/business/userService.js b/server/src/service/business/userService.js similarity index 100% rename from server/src/service/v1/business/userService.js rename to server/src/service/business/userService.js diff --git a/server/src/service/v1/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js b/server/src/service/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js similarity index 100% rename from server/src/service/v1/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js rename to server/src/service/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js diff --git a/server/src/service/v1/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js b/server/src/service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js similarity index 100% rename from server/src/service/v1/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js rename to server/src/service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js diff --git a/server/src/service/v1/infrastructure/bufferService.js b/server/src/service/infrastructure/bufferService.js similarity index 100% rename from server/src/service/v1/infrastructure/bufferService.js rename to server/src/service/infrastructure/bufferService.js diff --git a/server/src/service/v1/infrastructure/emailService.js b/server/src/service/infrastructure/emailService.js similarity index 100% rename from server/src/service/v1/infrastructure/emailService.js rename to server/src/service/infrastructure/emailService.js diff --git a/server/src/service/v1/infrastructure/errorService.js b/server/src/service/infrastructure/errorService.js similarity index 100% rename from server/src/service/v1/infrastructure/errorService.js rename to server/src/service/infrastructure/errorService.js diff --git a/server/src/service/v1/infrastructure/networkService.js b/server/src/service/infrastructure/networkService.js similarity index 100% rename from server/src/service/v1/infrastructure/networkService.js rename to server/src/service/infrastructure/networkService.js diff --git a/server/src/service/v1/infrastructure/notificationProviders/matrix.js b/server/src/service/infrastructure/notificationProviders/matrix.js similarity index 100% rename from server/src/service/v1/infrastructure/notificationProviders/matrix.js rename to server/src/service/infrastructure/notificationProviders/matrix.js diff --git a/server/src/service/v1/infrastructure/notificationService.js b/server/src/service/infrastructure/notificationService.js similarity index 100% rename from server/src/service/v1/infrastructure/notificationService.js rename to server/src/service/infrastructure/notificationService.js diff --git a/server/src/service/v1/infrastructure/notificationUtils.js b/server/src/service/infrastructure/notificationUtils.js similarity index 100% rename from server/src/service/v1/infrastructure/notificationUtils.js rename to server/src/service/infrastructure/notificationUtils.js diff --git a/server/src/service/v1/infrastructure/statusService.js b/server/src/service/infrastructure/statusService.js similarity index 98% rename from server/src/service/v1/infrastructure/statusService.js rename to server/src/service/infrastructure/statusService.js index 829b6d850..3c1682818 100755 --- a/server/src/service/v1/infrastructure/statusService.js +++ b/server/src/service/infrastructure/statusService.js @@ -1,5 +1,5 @@ -import MonitorStats from "../../../db/v1/models/MonitorStats.js"; -import Check from "../../../db/v1/models/Check.js"; +import MonitorStats from "../../db/models/MonitorStats.js"; +import Check from "../../db/models/Check.js"; const SERVICE_NAME = "StatusService"; class StatusService { @@ -337,9 +337,11 @@ class StatusService { } = networkResponse; const check = { - monitorId, - teamId, - type, + metadata: { + monitorId, + teamId, + type, + }, status, statusCode: code, responseTime, diff --git a/server/src/service/v1/system/serviceRegistry.js b/server/src/service/system/serviceRegistry.js similarity index 100% rename from server/src/service/v1/system/serviceRegistry.js rename to server/src/service/system/serviceRegistry.js diff --git a/server/src/service/v1/system/settingsService.js b/server/src/service/system/settingsService.js similarity index 100% rename from server/src/service/v1/system/settingsService.js rename to server/src/service/system/settingsService.js diff --git a/server/src/service/v1/system/stringService.js b/server/src/service/system/stringService.js similarity index 100% rename from server/src/service/v1/system/stringService.js rename to server/src/service/system/stringService.js diff --git a/server/src/service/v1/system/translationService.js b/server/src/service/system/translationService.js similarity index 100% rename from server/src/service/v1/system/translationService.js rename to server/src/service/system/translationService.js diff --git a/server/src/types/check.ts b/server/src/types/check.ts new file mode 100644 index 000000000..f2ccc0b77 --- /dev/null +++ b/server/src/types/check.ts @@ -0,0 +1,79 @@ +import type { MonitorType } from "@/types/index.js"; + +export interface CheckTimingPhases { + wait: number; + dns: number; + tcp: number; + tls: number; + request: number; + firstByte: number; + download: number; + total: number; +} + +export interface CheckTimings { + start: number; + socket: number; + lookup: number; + connect: number; + secureConnect: number; + upload: number; + response: number; + end: number; + phases: CheckTimingPhases; +} + +export interface CheckCpuInfo { + physical_core: number; + logical_core: number; + frequency: number; + temperature: number[]; + free_percent: number; + usage_percent: number; +} + +export interface CheckMemoryInfo { + total_bytes: number; + available_bytes: number; + used_bytes: number; + usage_percent: number; +} + +export interface CheckHostInfo { + os: string; + platform: string; + kernel_version: string; +} + +export interface CheckCaptureInfo { + version: string; + mode: string; +} + +export interface CheckDiskInfo {} + +export interface CheckNetInfo {} + +export interface Check { + id: string; + monitorId: string; + teamId: string; + type: MonitorType; + status: boolean; + responseTime: number; + timings: CheckTimings; + statusCode: number; + message: string; + ack: boolean; + expiry: string; + cpu: CheckCpuInfo; + memory: CheckMemoryInfo; + disk: CheckDiskInfo[]; + host: CheckHostInfo; + errors: string[]; + capture: CheckCaptureInfo; + net: CheckNetInfo[]; + __v: number; + createdAt: string; + updatedAt: string; +} diff --git a/server/src/types/index.ts b/server/src/types/index.ts new file mode 100644 index 000000000..92bcb69b0 --- /dev/null +++ b/server/src/types/index.ts @@ -0,0 +1,2 @@ +export * from "@/types/check.js"; +export * from "@/types/monitor.js"; diff --git a/server/src/types/monitor.ts b/server/src/types/monitor.ts new file mode 100644 index 000000000..6a386c2e4 --- /dev/null +++ b/server/src/types/monitor.ts @@ -0,0 +1,29 @@ +export const MonitorTypes = ["http", "ping", "pagespeed", "hardware", "docker", "port", "game"] as const; +export type MonitorType = (typeof MonitorTypes)[number]; + +export interface Monitor { + id: string; + userId: string; + teamId: string; + name: string; + description: string; + statusWindow: boolean[]; + statusWindowSize: number; + statusWindowThreshold: number; + type: MonitorType; + ignoreTlsErrors: boolean; + url: string; + isActive: boolean; + interval: number; + notifications: string[]; + alertThreshold: number; + selectedDisks: string[]; + group: string | null; + cpuAlertThreshold: number; + memoryAlertThreshold: number; + diskAlertThreshold: number; + tempAlertThreshold: number; + createdAt: string; + updatedAt: string; + status: boolean; +} From 7a6b0d5da421ea29acf6c0a2c93d5b78193eee5d Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 12 Jan 2026 22:58:46 +0000 Subject: [PATCH 2/9] refactoring --- server/package-lock.json | 11 + server/package.json | 1 + server/src/config/services.js | 14 +- server/src/db/models/Check.ts | 140 +++++++++--- .../src/db/models/{Monitor.js => Monitor.ts} | 72 ++++--- server/src/db/models/index.ts | 5 + server/src/db/modules/checkModule.js | 43 ++-- server/src/db/modules/monitorModule.js | 23 +- server/src/db/modules/monitorModuleQueries.js | 21 +- .../repositories/checks/IChecksRepository.ts | 10 + .../checks/MongoChecksRepistory.ts | 203 ++++++++++++++++++ server/src/repositories/index.ts | 5 + .../monitors/IMonitorsRepository.ts | 17 +- .../monitors/MongoMonitorsRepository.ts | 124 ++++++++++- .../v1/{monitorRoute.js => monitorRoute.ts} | 4 +- server/src/service/business/monitorService.js | 36 +++- .../service/infrastructure/statusService.js | 4 +- server/src/types/check.ts | 57 ++++- server/src/types/monitor.ts | 25 ++- 19 files changed, 699 insertions(+), 116 deletions(-) mode change 100755 => 100644 server/src/db/models/Check.ts rename server/src/db/models/{Monitor.js => Monitor.ts} (70%) mode change 100755 => 100644 create mode 100644 server/src/db/models/index.ts create mode 100644 server/src/repositories/index.ts rename server/src/routes/v1/{monitorRoute.js => monitorRoute.ts} (96%) diff --git a/server/package-lock.json b/server/package-lock.json index eaf771a61..d254da407 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -48,6 +48,7 @@ "@eslint/js": "^9.17.0", "@types/express": "5.0.3", "@types/jsonwebtoken": "9.0.10", + "@types/multer": "^2.0.0", "@types/nodemailer": "7.0.1", "@types/ping": "0.4.4", "c8": "10.1.3", @@ -3301,6 +3302,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/multer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz", + "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, "node_modules/@types/node": { "version": "24.9.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.1.tgz", diff --git a/server/package.json b/server/package.json index 5610d32a9..3547810ce 100755 --- a/server/package.json +++ b/server/package.json @@ -60,6 +60,7 @@ "@eslint/js": "^9.17.0", "@types/express": "5.0.3", "@types/jsonwebtoken": "9.0.10", + "@types/multer": "^2.0.0", "@types/nodemailer": "7.0.1", "@types/ping": "0.4.4", "c8": "10.1.3", diff --git a/server/src/config/services.js b/server/src/config/services.js index 28b7c9a86..0916752ab 100644 --- a/server/src/config/services.js +++ b/server/src/config/services.js @@ -47,7 +47,7 @@ import { GenerateAvatarImage } from "../utils/imageProcessing.js"; import { ParseBoolean } from "../utils/utils.js"; // Models -import Check from "../db/models/Check.js"; +import { CheckModel } from "@/db/models/index.js"; import Monitor from "../db/models/Monitor.js"; import User from "../db/models/User.js"; import InviteToken from "../db/models/InviteToken.js"; @@ -71,6 +71,9 @@ import RecoveryModule from "../db/modules/recoveryModule.js"; import SettingsModule from "../db/modules/settingsModule.js"; import IncidentModule from "../db/modules/incidentModule.js"; +// repositories +import { MongoMonitorsRepository, MongoChecksRepository } from "@/repositories/index.js"; + export const initializeServices = async ({ logger, envSettings, settingsService }) => { const serviceRegistry = new ServiceRegistry({ logger }); ServiceRegistry.instance = serviceRegistry; @@ -81,7 +84,7 @@ export const initializeServices = async ({ logger, envSettings, settingsService const stringService = new StringService(translationService); // Create DB - const checkModule = new CheckModule({ logger, Check, Monitor, User }); + const checkModule = new CheckModule({ logger, CheckModel, Monitor, User }); const inviteModule = new InviteModule({ InviteToken, crypto, stringService }); const statusPageModule = new StatusPageModule({ StatusPage, NormalizeData, stringService }); const userModule = new UserModule({ User, Team, GenerateAvatarImage, ParseBoolean, stringService }); @@ -89,7 +92,6 @@ export const initializeServices = async ({ logger, envSettings, settingsService const monitorModule = new MonitorModule({ Monitor, MonitorStats, - Check, stringService, fs, path, @@ -120,6 +122,10 @@ export const initializeServices = async ({ logger, envSettings, settingsService await db.connect(); + // Repositories + const monitorsRepository = new MongoMonitorsRepository(); + const checksRepository = new MongoChecksRepository(); + const networkService = new NetworkService({ axios, got, @@ -220,6 +226,8 @@ export const initializeServices = async ({ logger, envSettings, settingsService logger, errorService, games, + monitorsRepository, + checksRepository, }); const services = { diff --git a/server/src/db/models/Check.ts b/server/src/db/models/Check.ts old mode 100755 new mode 100644 index b13aa9a16..b4a31f8f7 --- a/server/src/db/models/Check.ts +++ b/server/src/db/models/Check.ts @@ -1,7 +1,78 @@ -import mongoose from "mongoose"; -import { MonitorTypes } from "@/types/monitor.js"; +import { Schema, model, Types } from "mongoose"; +import { + MonitorTypes, + type MonitorType, +} from "@/types/monitor.js"; +import type { + Check, + CheckAudits, + CheckCaptureInfo, + CheckCpuInfo, + CheckDiskInfo, + CheckErrorInfo, + CheckHostInfo, + CheckMemoryInfo, + CheckMetadata, + CheckNetworkInterfaceInfo, + CheckTimings, + CheckTimingPhases, +} from "@/types/check.js"; -const cpuSchema = new mongoose.Schema( +type CheckMetadataDocument = Omit & { + monitorId: Types.ObjectId; + teamId: Types.ObjectId; + type: MonitorType; +}; + +type CheckDocumentBase = Omit< + Check, + "id" | "metadata" | "expiry" | "ackAt" | "createdAt" | "updatedAt" +> & { + metadata: CheckMetadataDocument; + expiry: Date; + ackAt?: Date | null; + createdAt: Date; + updatedAt: Date; + __v: number; +}; + +interface CheckDocument extends CheckDocumentBase { + _id: Types.ObjectId; +} + +const timingPhasesSchema = new Schema( + { + wait: { type: Number, default: 0 }, + dns: { type: Number, default: 0 }, + tcp: { type: Number, default: 0 }, + tls: { type: Number, default: 0 }, + request: { type: Number, default: 0 }, + firstByte: { type: Number, default: 0 }, + download: { type: Number, default: 0 }, + total: { type: Number, default: 0 }, + }, + { _id: false } +); + +const timingsSchema = new Schema( + { + start: { type: Number, default: 0 }, + socket: { type: Number, default: 0 }, + lookup: { type: Number, default: 0 }, + connect: { type: Number, default: 0 }, + secureConnect: { type: Number, default: 0 }, + upload: { type: Number, default: 0 }, + response: { type: Number, default: 0 }, + end: { type: Number, default: 0 }, + phases: { + type: timingPhasesSchema, + default: () => ({}), + }, + }, + { _id: false } +); + +const cpuSchema = new Schema( { physical_core: { type: Number, default: 0 }, logical_core: { type: Number, default: 0 }, @@ -13,7 +84,7 @@ const cpuSchema = new mongoose.Schema( { _id: false } ); -const memorySchema = new mongoose.Schema( +const memorySchema = new Schema( { total_bytes: { type: Number, default: 0 }, available_bytes: { type: Number, default: 0 }, @@ -23,7 +94,7 @@ const memorySchema = new mongoose.Schema( { _id: false } ); -const diskSchema = new mongoose.Schema( +const diskSchema = new Schema( { device: { type: String, default: "" }, mountpoint: { type: String, default: "" }, @@ -36,7 +107,7 @@ const diskSchema = new mongoose.Schema( { _id: false } ); -const hostSchema = new mongoose.Schema( +const hostSchema = new Schema( { os: { type: String, default: "" }, platform: { type: String, default: "" }, @@ -45,7 +116,7 @@ const hostSchema = new mongoose.Schema( { _id: false } ); -const errorSchema = new mongoose.Schema( +const errorSchema = new Schema( { metric: { type: [String], default: [] }, err: { type: String, default: "" }, @@ -53,7 +124,7 @@ const errorSchema = new mongoose.Schema( { _id: false } ); -const captureSchema = new mongoose.Schema( +const captureSchema = new Schema( { version: { type: String, default: "" }, mode: { type: String, default: "" }, @@ -61,9 +132,9 @@ const captureSchema = new mongoose.Schema( { _id: false } ); -const networkInterfaceSchema = new mongoose.Schema( +const networkInterfaceSchema = new Schema( { - name: { type: String }, + name: { type: String, default: "" }, bytes_sent: { type: Number, default: 0 }, bytes_recv: { type: Number, default: 0 }, packets_sent: { type: Number, default: 0 }, @@ -78,17 +149,30 @@ const networkInterfaceSchema = new mongoose.Schema( { _id: false } ); -const metadataSchema = new mongoose.Schema( +const auditsSchema = new Schema( + { + cls: { type: Number, default: 0 }, + si: { type: Number, default: 0 }, + fcp: { type: Number, default: 0 }, + lcp: { type: Number, default: 0 }, + tbt: { type: Number, default: 0 }, + }, + { _id: false } +); + +const metadataSchema = new Schema( { monitorId: { - type: mongoose.Schema.Types.ObjectId, + type: Schema.Types.ObjectId, ref: "Monitor", + required: true, immutable: true, index: true, }, teamId: { - type: mongoose.Schema.Types.ObjectId, + type: Schema.Types.ObjectId, ref: "Team", + required: true, immutable: true, index: true, }, @@ -102,7 +186,7 @@ const metadataSchema = new mongoose.Schema( { _id: false } ); -const CheckSchema = new mongoose.Schema( +const CheckSchema = new Schema( { metadata: { type: metadataSchema, @@ -112,40 +196,32 @@ const CheckSchema = new mongoose.Schema( type: Boolean, index: true, }, - responseTime: { type: Number, }, - timings: { - type: Object, - default: {}, + type: timingsSchema, + default: undefined, }, - statusCode: { type: Number, index: true, }, - message: { type: String, }, - expiry: { type: Date, default: Date.now, }, - ack: { type: Boolean, default: false, }, - ackAt: { type: Date, + default: undefined, }, - - // Hardware fields cpu: { type: cpuSchema, default: () => ({}), @@ -162,23 +238,18 @@ const CheckSchema = new mongoose.Schema( type: hostSchema, default: () => ({}), }, - errors: { type: [errorSchema], default: () => [], }, - capture: { type: captureSchema, default: () => ({}), }, - net: { type: [networkInterfaceSchema], default: () => [], }, - - // PageSpeed fields accessibility: { type: Number, }, @@ -192,7 +263,8 @@ const CheckSchema = new mongoose.Schema( type: Number, }, audits: { - type: Object, + type: auditsSchema, + default: undefined, }, }, { @@ -211,4 +283,8 @@ CheckSchema.index({ "metadata.monitorId": 1, updatedAt: 1 }); CheckSchema.index({ "metadata.monitorId": 1, updatedAt: -1 }); CheckSchema.index({ "metadata.teamId": 1, updatedAt: -1 }); -export default mongoose.model("Check", CheckSchema); +const CheckModel = model("Check", CheckSchema); + +export type { CheckDocument, CheckMetadataDocument }; +export { CheckModel }; +export default CheckModel; diff --git a/server/src/db/models/Monitor.js b/server/src/db/models/Monitor.ts old mode 100755 new mode 100644 similarity index 70% rename from server/src/db/models/Monitor.js rename to server/src/db/models/Monitor.ts index 901dc39d1..f6f9d4371 --- a/server/src/db/models/Monitor.js +++ b/server/src/db/models/Monitor.ts @@ -1,18 +1,49 @@ -import mongoose from "mongoose"; +import { Schema, model, Types, type UpdateQuery } from "mongoose"; +import type { Monitor, MonitorMatchMethod, MonitorThresholds } from "@/types/monitor.js"; +import { MonitorTypes } from "@/types/monitor.js"; import Check from "./Check.js"; import MonitorStats from "./MonitorStats.js"; import StatusPage from "./StatusPage.js"; -const MonitorSchema = mongoose.Schema( +type MonitorDocumentBase = Omit< + Monitor, + "id" | "userId" | "teamId" | "notifications" | "selectedDisks" | "statusWindow" | "createdAt" | "updatedAt" +> & { + statusWindow: boolean[]; + notifications: Types.ObjectId[]; + selectedDisks: string[]; + matchMethod?: MonitorMatchMethod; + thresholds?: MonitorThresholds; +}; + +interface MonitorDocument extends MonitorDocumentBase { + _id: Types.ObjectId; + userId: Types.ObjectId; + teamId: Types.ObjectId; + createdAt: Date; + updatedAt: Date; +} + +const thresholdsSchema = new Schema( + { + usage_cpu: { type: Number }, + usage_memory: { type: Number }, + usage_disk: { type: Number }, + usage_temperature: { type: Number }, + }, + { _id: false } +); + +const MonitorSchema = new Schema( { userId: { - type: mongoose.Schema.Types.ObjectId, + type: Schema.Types.ObjectId, ref: "User", immutable: true, required: true, }, teamId: { - type: mongoose.Schema.Types.ObjectId, + type: Schema.Types.ObjectId, ref: "Team", immutable: true, required: true, @@ -43,7 +74,7 @@ const MonitorSchema = mongoose.Schema( type: { type: String, required: true, - enum: ["http", "ping", "pagespeed", "hardware", "docker", "port", "game"], + enum: MonitorTypes, }, ignoreTlsErrors: { type: Boolean, @@ -71,7 +102,6 @@ const MonitorSchema = mongoose.Schema( default: true, }, interval: { - // in milliseconds type: Number, default: 60000, }, @@ -81,7 +111,7 @@ const MonitorSchema = mongoose.Schema( }, notifications: [ { - type: mongoose.Schema.Types.ObjectId, + type: Schema.Types.ObjectId, ref: "Notification", }, ], @@ -89,13 +119,7 @@ const MonitorSchema = mongoose.Schema( type: String, }, thresholds: { - type: { - usage_cpu: { type: Number }, - usage_memory: { type: Number }, - usage_disk: { type: Number }, - usage_temperature: { type: Number }, - }, - _id: false, + type: thresholdsSchema, }, alertThreshold: { type: Number, @@ -137,7 +161,7 @@ const MonitorSchema = mongoose.Schema( trim: true, maxLength: 50, default: null, - set: function (value) { + set(value: string | null) { return value && value.trim() ? value.trim() : null; }, }, @@ -148,7 +172,6 @@ const MonitorSchema = mongoose.Schema( ); MonitorSchema.pre("findOneAndDelete", async function (next) { - // Delete checks and stats try { const doc = await this.model.findOne(this.getFilter()); @@ -157,20 +180,17 @@ MonitorSchema.pre("findOneAndDelete", async function (next) { } await Check.deleteMany({ monitorId: doc._id }); - - // Deal with status pages await StatusPage.updateMany({ monitors: doc?._id }, { $pull: { monitors: doc?._id } }); - await MonitorStats.deleteMany({ monitorId: doc?._id.toString() }); next(); } catch (error) { - next(error); + next(error as Error); } }); MonitorSchema.pre("deleteMany", async function (next) { const filter = this.getFilter(); - const monitors = await this.model.find(filter).select(["_id", "type"]).lean(); + const monitors = (await this.model.find(filter).select(["_id", "type"]).lean()) as { _id: Types.ObjectId }[]; for (const monitor of monitors) { await Check.deleteMany({ monitorId: monitor._id }); @@ -197,8 +217,8 @@ MonitorSchema.pre("save", function (next) { }); MonitorSchema.pre("findOneAndUpdate", function (next) { - const update = this.getUpdate(); - if (update.alertThreshold) { + const update = this.getUpdate() as UpdateQuery | null; + if (update && !Array.isArray(update) && update.alertThreshold !== undefined) { update.cpuAlertThreshold = update.alertThreshold; update.memoryAlertThreshold = update.alertThreshold; update.diskAlertThreshold = update.alertThreshold; @@ -209,4 +229,8 @@ MonitorSchema.pre("findOneAndUpdate", function (next) { MonitorSchema.index({ teamId: 1, type: 1 }); -export default mongoose.model("Monitor", MonitorSchema); +const MonitorModel = model("Monitor", MonitorSchema); + +export type { MonitorDocument }; +export { MonitorModel }; +export default MonitorModel; diff --git a/server/src/db/models/index.ts b/server/src/db/models/index.ts new file mode 100644 index 000000000..473940874 --- /dev/null +++ b/server/src/db/models/index.ts @@ -0,0 +1,5 @@ +export * from "@/db/models/Monitor.js"; +export { default as MonitorModel } from "@/db/models/Monitor.js"; + +export * from "@/db/models/Check.js"; +export { default as CheckModel } from "@/db/models/Check.js"; diff --git a/server/src/db/modules/checkModule.js b/server/src/db/modules/checkModule.js index dfca02bed..871761290 100755 --- a/server/src/db/modules/checkModule.js +++ b/server/src/db/modules/checkModule.js @@ -1,4 +1,6 @@ import { ObjectId } from "mongodb"; +import mongoose from "mongoose"; +import { CheckModel } from "@/db/models/index.js"; import { buildChecksSummaryByTeamIdPipeline } from "./checkModuleQueries.js"; const SERVICE_NAME = "checkModule"; @@ -12,18 +14,15 @@ const dateRangeLookup = { }; class CheckModule { - constructor({ logger, Check, HardwareCheck, PageSpeedCheck, Monitor, User }) { + constructor({ logger, Monitor, User }) { this.logger = logger; - this.Check = Check; - this.HardwareCheck = HardwareCheck; - this.PageSpeedCheck = PageSpeedCheck; this.Monitor = Monitor; this.User = User; } createChecks = async (checks) => { try { - await this.Check.insertMany(checks, { ordered: false }); + await CheckModel.insertMany(checks, { ordered: false }); } catch (error) { error.service = SERVICE_NAME; error.method = "createCheck"; @@ -41,7 +40,7 @@ class CheckModule { // Match const matchStage = { - monitorId: new ObjectId(monitorId), + "metadata.monitorId": new ObjectId(monitorId), ...(typeof status !== "undefined" && { status }), ...(typeof ack !== "undefined" && ackStage), ...(dateRangeLookup[dateRange] && { @@ -79,7 +78,7 @@ class CheckModule { skip = page * rowsPerPage; } - const checks = await this.Check.aggregate([ + const checks = await CheckModel.aggregate([ { $match: matchStage }, { $sort: { createdAt: sortOrder } }, { @@ -115,7 +114,7 @@ class CheckModule { const ackStage = ack === "true" ? { ack: true } : { $or: [{ ack: false }, { ack: { $exists: false } }] }; const matchStage = { - teamId: new ObjectId(teamId), + "metadata.teamId": new ObjectId(teamId), status: false, ...(typeof ack !== "undefined" && ackStage), ...(dateRangeLookup[dateRange] && { @@ -170,7 +169,7 @@ class CheckModule { }, ]; - const checks = await this.Check.aggregate(aggregatePipeline); + const checks = await CheckModel.aggregate(aggregatePipeline); return checks[0]; } catch (error) { error.service = SERVICE_NAME; @@ -181,7 +180,11 @@ class CheckModule { ackCheck = async (checkId, teamId, ack) => { try { - const updatedCheck = await this.Check.findOneAndUpdate({ _id: checkId, teamId: teamId }, { $set: { ack, ackAt: new Date() } }, { new: true }); + const updatedCheck = await CheckModel.findOneAndUpdate( + { _id: checkId, "metadata.teamId": teamId }, + { $set: { ack, ackAt: new Date() } }, + { new: true } + ); if (!updatedCheck) { throw new Error("Check not found"); @@ -197,7 +200,11 @@ class CheckModule { ackAllChecks = async (monitorId, teamId, ack, path) => { try { - const updatedChecks = await this.Check.updateMany(path === "monitor" ? { monitorId } : { teamId }, { $set: { ack, ackAt: new Date() } }); + const filter = + path === "monitor" + ? { "metadata.monitorId": new mongoose.Types.ObjectId(monitorId) } + : { "metadata.teamId": new mongoose.Types.ObjectId(teamId) }; + const updatedChecks = await CheckModel.updateMany(filter, { $set: { ack, ackAt: new Date() } }); return updatedChecks.modifiedCount; } catch (error) { error.service = SERVICE_NAME; @@ -209,9 +216,9 @@ class CheckModule { getChecksSummaryByTeamId = async ({ teamId }) => { try { const matchStage = { - teamId: new ObjectId(teamId), + "metadata.teamId": new ObjectId(teamId), }; - const checks = await this.Check.aggregate(buildChecksSummaryByTeamIdPipeline({ matchStage })); + const checks = await CheckModel.aggregate(buildChecksSummaryByTeamIdPipeline({ matchStage })); return checks[0].summary; } catch (error) { error.service = SERVICE_NAME; @@ -221,7 +228,7 @@ class CheckModule { }; deleteChecks = async (monitorId) => { try { - const result = await this.Check.deleteMany({ monitorId }); + const result = await CheckModel.deleteMany({ "metadata.monitorId": monitorId }); return result.deletedCount; } catch (error) { error.service = SERVICE_NAME; @@ -237,7 +244,7 @@ class CheckModule { const monitorIds = teamMonitors.map((monitor) => monitor._id); // Delete all checks for these monitors in one operation - const deleteResult = await this.Check.deleteMany({ monitorId: { $in: monitorIds } }); + const deleteResult = await CheckModel.deleteMany({ "metadata.monitorId": { $in: monitorIds } }); return deleteResult.deletedCount; } catch (error) { @@ -249,7 +256,7 @@ class CheckModule { updateChecksTTL = async (teamId, ttl) => { try { - await this.Check.collection.dropIndex("expiry_1"); + await CheckModel.collection.dropIndex("expiry_1"); } catch (error) { this.logger.error({ message: error.message, @@ -260,9 +267,9 @@ class CheckModule { } try { - await this.Check.collection.createIndex( + await CheckModel.collection.createIndex( { expiry: 1 }, - { expireAfterSeconds: ttl } // TTL in seconds, adjust as necessary + { expireAfterSeconds: ttl, partialFilterExpression: { "metadata.mode": { $exists: true } } } ); } catch (error) { error.service = SERVICE_NAME; diff --git a/server/src/db/modules/monitorModule.js b/server/src/db/modules/monitorModule.js index 39168f0b2..316caa2ea 100755 --- a/server/src/db/modules/monitorModule.js +++ b/server/src/db/modules/monitorModule.js @@ -8,13 +8,14 @@ import { buildFilteredMonitorsByTeamIdPipeline, } from "./monitorModuleQueries.js"; +import { CheckModel } from "@/db/models/index.js"; + const SERVICE_NAME = "monitorModule"; class MonitorModule { - constructor({ Monitor, MonitorStats, Check, stringService, fs, path, fileURLToPath, ObjectId, NormalizeData, NormalizeDataUptimeDetails }) { + constructor({ Monitor, MonitorStats, stringService, fs, path, fileURLToPath, ObjectId, NormalizeData, NormalizeDataUptimeDetails }) { this.Monitor = Monitor; this.MonitorStats = MonitorStats; - this.Check = Check; this.stringService = stringService; this.fs = fs; this.path = path; @@ -123,15 +124,18 @@ class MonitorModule { //Helper getMonitorChecks = async (monitorId, dateRange, sortOrder) => { + const objectId = new this.ObjectId(monitorId); const indexSpec = { - monitorId: 1, - updatedAt: sortOrder, // This will be 1 or -1 + "metadata.monitorId": 1, + updatedAt: sortOrder, }; + const matchBase = { "metadata.monitorId": objectId }; + const [checksAll, checksForDateRange] = await Promise.all([ - this.Check.find({ monitorId }).sort({ createdAt: sortOrder }).hint(indexSpec).lean(), - this.Check.find({ - monitorId, + CheckModel.find(matchBase).sort({ createdAt: sortOrder }).hint(indexSpec).lean(), + CheckModel.find({ + ...matchBase, createdAt: { $gte: dateRange.start, $lte: dateRange.end }, }) .hint(indexSpec) @@ -238,7 +242,8 @@ class MonitorModule { const dateString = formatLookup[dateRange]; - const results = await this.Check.aggregate(buildUptimeDetailsPipeline(monitorId, dates, dateString)); + console.log("WTTTTFFF"); + const results = await CheckModel.aggregate(buildUptimeDetailsPipeline(monitorId, dates, dateString)); const monitorData = results[0]; @@ -313,7 +318,7 @@ class MonitorModule { }; const dateString = formatLookup[dateRange]; - const hardwareStats = await this.Check.aggregate(buildHardwareDetailsPipeline(monitor, dates, dateString)); + const hardwareStats = await CheckModel.aggregate(buildHardwareDetailsPipeline(monitor, dates, dateString)); const stats = hardwareStats[0]; diff --git a/server/src/db/modules/monitorModuleQueries.js b/server/src/db/modules/monitorModuleQueries.js index 32aed1529..e6c6b4ec6 100755 --- a/server/src/db/modules/monitorModuleQueries.js +++ b/server/src/db/modules/monitorModuleQueries.js @@ -4,7 +4,7 @@ const buildUptimeDetailsPipeline = (monitorId, dates, dateString) => { return [ { $match: { - monitorId: new ObjectId(monitorId), + "metadata.monitorId": new ObjectId(monitorId), updatedAt: { $gte: dates.start, $lte: dates.end }, }, }, @@ -172,8 +172,8 @@ const buildHardwareDetailsPipeline = (monitor, dates, dateString) => { return [ { $match: { - monitorId: monitor._id, - type: "hardware", + "metadata.monitorId": monitor._id, + "metadata.type": "hardware", createdAt: { $gte: dates.start, $lte: dates.end }, }, }, @@ -233,11 +233,16 @@ const buildHardwareDetailsPipeline = (monitor, dates, dateString) => { }, pipeline: [ { - $match: { - $expr: { - $and: [{ $eq: ["$monitorId", monitor._id] }, { $gte: ["$createdAt", dates.start] }, { $lte: ["$createdAt", dates.end] }], - }, - }, + $match: { + $expr: { + $and: [ + { $eq: ["$metadata.monitorId", monitor._id] }, + { $eq: ["$metadata.type", "hardware"] }, + { $gte: ["$createdAt", dates.start] }, + { $lte: ["$createdAt", dates.end] }, + ], + }, + }, }, { $group: { diff --git a/server/src/repositories/checks/IChecksRepository.ts b/server/src/repositories/checks/IChecksRepository.ts index e69de29bb..df69cf18a 100644 --- a/server/src/repositories/checks/IChecksRepository.ts +++ b/server/src/repositories/checks/IChecksRepository.ts @@ -0,0 +1,10 @@ +import type { LatestChecksMap } from "@/repositories/checks/MongoChecksRepistory.js"; + +export interface IChecksRepository { + // create + // single fetch + // collection fetch + findLatestChecksByMonitorIds(monitorIds: string[]): Promise; + // update + // delete +} diff --git a/server/src/repositories/checks/MongoChecksRepistory.ts b/server/src/repositories/checks/MongoChecksRepistory.ts index e69de29bb..d04118da0 100644 --- a/server/src/repositories/checks/MongoChecksRepistory.ts +++ b/server/src/repositories/checks/MongoChecksRepistory.ts @@ -0,0 +1,203 @@ +import { IChecksRepository } from "@/repositories/index.js"; +import type { + Check, + CheckAudits, + CheckCaptureInfo, + CheckCpuInfo, + CheckDiskInfo, + CheckErrorInfo, + CheckHostInfo, + CheckMemoryInfo, + CheckMetadata, + CheckNetworkInterfaceInfo, + CheckTimings, +} from "@/types/index.js"; +import { CheckModel, type CheckDocument } from "@/db/models/index.js"; +import mongoose from "mongoose"; + +export type LatestChecksMap = Record; + +class MongoChecksRepistory implements IChecksRepository { + private toEntity = (doc: CheckDocument): Check => { + const toStringId = (value: mongoose.Types.ObjectId | string | undefined | null): string => { + if (!value) { + return ""; + } + return value instanceof mongoose.Types.ObjectId ? value.toString() : String(value); + }; + + const toDateString = (value?: Date | string | null): string => { + if (!value) { + return new Date(0).toISOString(); + } + return value instanceof Date ? value.toISOString() : new Date(value).toISOString(); + }; + + const toOptionalDateString = (value?: Date | string | null): string | undefined => { + if (!value) { + return undefined; + } + return toDateString(value); + }; + + const mapTimings = (timings?: CheckTimings): CheckTimings => { + const phases = timings?.phases ?? { + wait: 0, + dns: 0, + tcp: 0, + tls: 0, + request: 0, + firstByte: 0, + download: 0, + total: 0, + }; + + return { + start: timings?.start ?? 0, + socket: timings?.socket ?? 0, + lookup: timings?.lookup ?? 0, + connect: timings?.connect ?? 0, + secureConnect: timings?.secureConnect ?? 0, + upload: timings?.upload ?? 0, + response: timings?.response ?? 0, + end: timings?.end ?? 0, + phases, + }; + }; + + const mapCpu = (cpu?: CheckCpuInfo): CheckCpuInfo => ({ + physical_core: cpu?.physical_core ?? 0, + logical_core: cpu?.logical_core ?? 0, + frequency: cpu?.frequency ?? 0, + temperature: cpu?.temperature ?? [], + free_percent: cpu?.free_percent ?? 0, + usage_percent: cpu?.usage_percent ?? 0, + }); + + const mapMemory = (memory?: CheckMemoryInfo): CheckMemoryInfo => ({ + total_bytes: memory?.total_bytes ?? 0, + available_bytes: memory?.available_bytes ?? 0, + used_bytes: memory?.used_bytes ?? 0, + usage_percent: memory?.usage_percent ?? 0, + }); + + const mapHost = (host?: CheckHostInfo): CheckHostInfo => ({ + os: host?.os ?? "", + platform: host?.platform ?? "", + kernel_version: host?.kernel_version ?? "", + }); + + const mapCapture = (capture?: CheckCaptureInfo): CheckCaptureInfo => ({ + version: capture?.version ?? "", + mode: capture?.mode ?? "", + }); + + const mapDisks = (disks?: CheckDiskInfo[]): CheckDiskInfo[] => + (disks ?? []).map((disk) => ({ + device: disk?.device ?? "", + mountpoint: disk?.mountpoint ?? "", + read_speed_bytes: disk?.read_speed_bytes ?? 0, + write_speed_bytes: disk?.write_speed_bytes ?? 0, + total_bytes: disk?.total_bytes ?? 0, + free_bytes: disk?.free_bytes ?? 0, + usage_percent: disk?.usage_percent ?? 0, + })); + + const mapErrors = (errors?: CheckErrorInfo[]): CheckErrorInfo[] => + (errors ?? []).map((error) => ({ + metric: error?.metric ?? [], + err: error?.err ?? "", + })); + + const mapNet = (net?: CheckNetworkInterfaceInfo[]): CheckNetworkInterfaceInfo[] => + (net ?? []).map((iface) => ({ + name: iface?.name ?? "", + bytes_sent: iface?.bytes_sent ?? 0, + bytes_recv: iface?.bytes_recv ?? 0, + packets_sent: iface?.packets_sent ?? 0, + packets_recv: iface?.packets_recv ?? 0, + err_in: iface?.err_in ?? 0, + err_out: iface?.err_out ?? 0, + drop_in: iface?.drop_in ?? 0, + drop_out: iface?.drop_out ?? 0, + fifo_in: iface?.fifo_in ?? 0, + fifo_out: iface?.fifo_out ?? 0, + })); + + const mapAudits = (audits?: CheckAudits): CheckAudits | undefined => { + if (!audits) { + return undefined; + } + return { + cls: audits.cls ?? 0, + si: audits.si ?? 0, + fcp: audits.fcp ?? 0, + lcp: audits.lcp ?? 0, + tbt: audits.tbt ?? 0, + }; + }; + + const mapMetadata = (metadata: CheckDocument["metadata"]): CheckMetadata => ({ + monitorId: toStringId(metadata.monitorId), + teamId: toStringId(metadata.teamId), + type: metadata.type, + }); + + return { + id: toStringId(doc._id), + metadata: mapMetadata(doc.metadata), + status: doc.status ?? false, + responseTime: doc.responseTime ?? 0, + timings: mapTimings(doc.timings), + statusCode: doc.statusCode ?? 0, + message: doc.message ?? "", + ack: doc.ack ?? false, + ackAt: toOptionalDateString(doc.ackAt), + expiry: toDateString(doc.expiry), + cpu: mapCpu(doc.cpu), + memory: mapMemory(doc.memory), + disk: mapDisks(doc.disk), + host: mapHost(doc.host), + errors: mapErrors(doc.errors), + capture: mapCapture(doc.capture), + net: mapNet(doc.net), + accessibility: doc.accessibility, + bestPractices: doc.bestPractices, + seo: doc.seo, + performance: doc.performance, + audits: mapAudits(doc.audits), + __v: doc.__v ?? 0, + createdAt: toDateString(doc.createdAt), + updatedAt: toDateString(doc.updatedAt), + }; + }; + + findLatestChecksByMonitorIds = async (monitorIds: string[]): Promise => { + const mongoIds = monitorIds.map((id) => new mongoose.Types.ObjectId(id)); + const checkMap = await CheckModel.aggregate([ + { + $match: { + "metadata.monitorId": { $in: mongoIds }, + }, + }, + { $sort: { createdAt: -1 } }, + { + $group: { + _id: "$metadata.monitorId", + latestChecks: { $push: "$$ROOT" }, + }, + }, + { + $project: { + latestChecks: { $slice: [{ $ifNull: ["$latestChecks", []] }, 25] }, + }, + }, + ]); + return checkMap.reduce((acc, cm) => { + acc[cm._id.toString()] = cm.latestChecks.map((c: CheckDocument) => this.toEntity(c)); + return acc; + }, {}); + }; +} + +export default MongoChecksRepistory; diff --git a/server/src/repositories/index.ts b/server/src/repositories/index.ts new file mode 100644 index 000000000..c2bae6939 --- /dev/null +++ b/server/src/repositories/index.ts @@ -0,0 +1,5 @@ +export * from "@/repositories/monitors/IMonitorsRepository.js"; +export { default as MongoMonitorsRepository } from "@/repositories/monitors/MongoMonitorsRepository.js"; + +export * from "@/repositories/checks/IChecksRepository.js"; +export { default as MongoChecksRepository } from "@/repositories/checks/MongoChecksRepistory.js"; diff --git a/server/src/repositories/monitors/IMonitorsRepository.ts b/server/src/repositories/monitors/IMonitorsRepository.ts index 458ee5bad..865d7f8e4 100644 --- a/server/src/repositories/monitors/IMonitorsRepository.ts +++ b/server/src/repositories/monitors/IMonitorsRepository.ts @@ -1,9 +1,24 @@ -import type { Monitor } from "@/types/index.js"; +import { type MonitorType, type Monitor } from "@/types/index.js"; + +export interface TeamQueryConfig { + limit?: number; + type?: MonitorType | MonitorType[]; + page?: number; + rowsPerPage?: number; + filter?: string; + field?: string; + order?: "asc" | "desc"; +} + export interface IMonitorsRepository { // create // single fetch // collection fetch findAll(): Promise; + findByTeamId(teamId: string, config: TeamQueryConfig): Promise; // update // delete + + // counts + findMonitorCountByTeamIdAndType(teamId: string, config: TeamQueryConfig): Promise; } diff --git a/server/src/repositories/monitors/MongoMonitorsRepository.ts b/server/src/repositories/monitors/MongoMonitorsRepository.ts index b4bae06c8..dd85f9a3d 100644 --- a/server/src/repositories/monitors/MongoMonitorsRepository.ts +++ b/server/src/repositories/monitors/MongoMonitorsRepository.ts @@ -1,5 +1,125 @@ +import { MonitorModel } from "@/db/models/index.js"; +import type { MonitorDocument } from "@/db/models/Monitor.js"; +import type { Monitor, MonitorType } from "@/types/monitor.js"; +import mongoose, { type FilterQuery } from "mongoose"; +import type { IMonitorsRepository, TeamQueryConfig } from "./IMonitorsRepository.js"; + class MongoMonitorsRepository implements IMonitorsRepository { - findAll = async () => { - return null; + findAll = async (): Promise => { + const documents = await MonitorModel.find().exec(); + return this.mapDocuments(documents); + }; + + findByTeamId = async (teamId: string, config: TeamQueryConfig): Promise => { + const { page = 0, rowsPerPage = 25, filter, field = "createdAt", order = "desc", type, limit } = config ?? {}; + + const query: Record = { + teamId: new mongoose.Types.ObjectId(teamId), + }; + + if (type !== undefined) { + query.type = Array.isArray(type) ? { $in: type } : type; + } + + if (filter !== undefined) { + switch (field) { + case "name": + query.$or = [{ name: { $regex: filter, $options: "i" } }, { url: { $regex: filter, $options: "i" } }]; + break; + case "isActive": + query.isActive = filter === "true"; + break; + case "status": + query.status = filter === "true"; + break; + case "type": + query.type = filter; + break; + default: + break; + } + } + + const sort = { [field]: order === "asc" ? 1 : -1 } as const; + const skip = Math.max(page, 0) * rowsPerPage; + const limitValue = limit ?? rowsPerPage; + + const documents = await MonitorModel.find(query).sort(sort).skip(skip).limit(limitValue).exec(); + + return this.mapDocuments(documents); + }; + + findMonitorCountByTeamIdAndType = async (teamId: string, config?: TeamQueryConfig): Promise => { + const { type } = config ?? {}; + + const query: FilterQuery = { + teamId: new mongoose.Types.ObjectId(teamId), + }; + + if (type !== undefined) { + query.type = Array.isArray(type) ? { $in: type } : type; + } + + const count = await MonitorModel.countDocuments(query); + return count; + }; + + private mapDocuments = (documents: MonitorDocument[]): Monitor[] | null => { + if (!documents?.length) { + return null; + } + return documents.map((doc) => this.toEntity(doc)); + }; + + private toEntity = (doc: MonitorDocument): Monitor => { + const toStringId = (value: unknown): string => { + if (value instanceof mongoose.Types.ObjectId) { + return value.toString(); + } + return value?.toString() ?? ""; + }; + + const toDateString = (value: Date | string): string => { + return value instanceof Date ? value.toISOString() : value; + }; + + const notificationIds = (doc.notifications ?? []).map((notification) => toStringId(notification)); + + return { + id: toStringId(doc._id), + userId: toStringId(doc.userId), + teamId: toStringId(doc.teamId), + name: doc.name, + description: doc.description ?? undefined, + status: doc.status ?? undefined, + statusWindow: doc.statusWindow ?? [], + statusWindowSize: doc.statusWindowSize, + statusWindowThreshold: doc.statusWindowThreshold, + type: doc.type, + ignoreTlsErrors: doc.ignoreTlsErrors, + jsonPath: doc.jsonPath ?? undefined, + expectedValue: doc.expectedValue ?? undefined, + matchMethod: doc.matchMethod ?? undefined, + url: doc.url, + port: doc.port ?? undefined, + isActive: doc.isActive, + interval: doc.interval, + uptimePercentage: doc.uptimePercentage ?? undefined, + notifications: notificationIds, + secret: doc.secret ?? undefined, + thresholds: doc.thresholds ?? undefined, + alertThreshold: doc.alertThreshold, + cpuAlertThreshold: doc.cpuAlertThreshold, + memoryAlertThreshold: doc.memoryAlertThreshold, + diskAlertThreshold: doc.diskAlertThreshold, + tempAlertThreshold: doc.tempAlertThreshold, + selectedDisks: doc.selectedDisks ?? [], + gameId: doc.gameId ?? undefined, + group: doc.group ?? null, + createdAt: toDateString(doc.createdAt), + updatedAt: toDateString(doc.updatedAt), + }; }; } + +export default MongoMonitorsRepository; diff --git a/server/src/routes/v1/monitorRoute.js b/server/src/routes/v1/monitorRoute.ts similarity index 96% rename from server/src/routes/v1/monitorRoute.js rename to server/src/routes/v1/monitorRoute.ts index 86463b6bb..e68e0019f 100755 --- a/server/src/routes/v1/monitorRoute.js +++ b/server/src/routes/v1/monitorRoute.ts @@ -7,7 +7,9 @@ const upload = multer({ }); class MonitorRoutes { - constructor(monitorController) { + private router: Router; + private monitorController: any; + constructor(monitorController: any) { this.router = Router(); this.monitorController = monitorController; this.initRoutes(); diff --git a/server/src/service/business/monitorService.js b/server/src/service/business/monitorService.js index 4eae0176f..f457e5c7a 100644 --- a/server/src/service/business/monitorService.js +++ b/server/src/service/business/monitorService.js @@ -1,10 +1,23 @@ import { createMonitorsBodyValidation } from "@/validation/joi.js"; +import { NormalizeData } from "@/utils/dataUtils.js"; const SERVICE_NAME = "MonitorService"; class MonitorService { static SERVICE_NAME = SERVICE_NAME; - constructor({ db, settingsService, jobQueue, stringService, emailService, papaparse, logger, errorService, games }) { + constructor({ + db, + settingsService, + jobQueue, + stringService, + emailService, + papaparse, + logger, + errorService, + games, + monitorsRepository, + checksRepository, + }) { this.db = db; this.settingsService = settingsService; this.jobQueue = jobQueue; @@ -14,6 +27,8 @@ class MonitorService { this.logger = logger; this.errorService = errorService; this.games = games; + this.monitorsRepository = monitorsRepository; + this.checksRepository = checksRepository; } get serviceName() { @@ -205,6 +220,7 @@ class MonitorService { }; getMonitorsByTeamId = async ({ teamId, limit, type, page, rowsPerPage, filter, field, order }) => { + console.log("que"); const monitors = await this.db.monitorModule.getMonitorsByTeamId({ limit, type, @@ -228,7 +244,8 @@ class MonitorService { }; getMonitorsWithChecksByTeamId = async ({ teamId, limit, type, page, rowsPerPage, filter, field, order, explain }) => { - const result = await this.db.monitorModule.getMonitorsWithChecksByTeamId({ + const count = await this.monitorsRepository.findMonitorCountByTeamIdAndType(teamId, { type, filter }); + const monitors = await this.monitorsRepository.findByTeamId(teamId, { limit, type, page, @@ -236,10 +253,19 @@ class MonitorService { filter, field, order, - teamId, - explain, }); - return result; + + const monitorIds = monitors?.map((m) => m.id) ?? []; + const checksMap = await this.checksRepository.findLatestChecksByMonitorIds(monitorIds); + const monitorsWithChecks = (monitors ?? []).map((monitor) => { + const checks = NormalizeData(checksMap[monitor.id] ?? [], 10, 100); + return { + ...monitor, + checks, + }; + }); + + return { count, monitors: monitorsWithChecks }; }; exportMonitorsToCSV = async ({ teamId }) => { diff --git a/server/src/service/infrastructure/statusService.js b/server/src/service/infrastructure/statusService.js index 3c1682818..843c356ed 100755 --- a/server/src/service/infrastructure/statusService.js +++ b/server/src/service/infrastructure/statusService.js @@ -1,5 +1,5 @@ import MonitorStats from "../../db/models/MonitorStats.js"; -import Check from "../../db/models/Check.js"; +import { CheckModel } from "@/db/models/index.js"; const SERVICE_NAME = "StatusService"; class StatusService { @@ -115,7 +115,7 @@ class StatusService { if (!check._id) { try { - const checkModel = new Check(check); + const checkModel = new CheckModel(check); savedCheck = await checkModel.save(); this.buffer.removeCheckFromBuffer(check); diff --git a/server/src/types/check.ts b/server/src/types/check.ts index f2ccc0b77..2120d5de1 100644 --- a/server/src/types/check.ts +++ b/server/src/types/check.ts @@ -1,5 +1,11 @@ import type { MonitorType } from "@/types/index.js"; +export interface CheckMetadata { + monitorId: string; + teamId: string; + type: MonitorType; +} + export interface CheckTimingPhases { wait: number; dns: number; @@ -50,29 +56,66 @@ export interface CheckCaptureInfo { mode: string; } -export interface CheckDiskInfo {} +export interface CheckDiskInfo { + device: string; + mountpoint: string; + read_speed_bytes: number; + write_speed_bytes: number; + total_bytes: number; + free_bytes: number; + usage_percent: number; +} -export interface CheckNetInfo {} +export interface CheckErrorInfo { + metric: string[]; + err: string; +} + +export interface CheckNetworkInterfaceInfo { + name: string; + bytes_sent: number; + bytes_recv: number; + packets_sent: number; + packets_recv: number; + err_in: number; + err_out: number; + drop_in: number; + drop_out: number; + fifo_in: number; + fifo_out: number; +} + +export interface CheckAudits { + cls: number; + si: number; + fcp: number; + lcp: number; + tbt: number; +} export interface Check { id: string; - monitorId: string; - teamId: string; - type: MonitorType; + metadata: CheckMetadata; status: boolean; responseTime: number; timings: CheckTimings; statusCode: number; message: string; ack: boolean; + ackAt?: string | null; expiry: string; cpu: CheckCpuInfo; memory: CheckMemoryInfo; disk: CheckDiskInfo[]; host: CheckHostInfo; - errors: string[]; + errors: CheckErrorInfo[]; capture: CheckCaptureInfo; - net: CheckNetInfo[]; + net: CheckNetworkInterfaceInfo[]; + accessibility?: number; + bestPractices?: number; + seo?: number; + performance?: number; + audits?: CheckAudits; __v: number; createdAt: string; updatedAt: string; diff --git a/server/src/types/monitor.ts b/server/src/types/monitor.ts index 6a386c2e4..4c8dc7528 100644 --- a/server/src/types/monitor.ts +++ b/server/src/types/monitor.ts @@ -1,29 +1,46 @@ export const MonitorTypes = ["http", "ping", "pagespeed", "hardware", "docker", "port", "game"] as const; export type MonitorType = (typeof MonitorTypes)[number]; +export interface MonitorThresholds { + usage_cpu?: number; + usage_memory?: number; + usage_disk?: number; + usage_temperature?: number; +} + +export type MonitorMatchMethod = "equal" | "include" | "regex" | ""; + export interface Monitor { id: string; userId: string; teamId: string; name: string; - description: string; + description?: string; + status?: boolean; statusWindow: boolean[]; statusWindowSize: number; statusWindowThreshold: number; type: MonitorType; ignoreTlsErrors: boolean; + jsonPath?: string; + expectedValue?: string; + matchMethod?: MonitorMatchMethod; url: string; + port?: number; isActive: boolean; interval: number; + uptimePercentage?: number; notifications: string[]; + secret?: string; + thresholds?: MonitorThresholds; alertThreshold: number; - selectedDisks: string[]; - group: string | null; cpuAlertThreshold: number; memoryAlertThreshold: number; diskAlertThreshold: number; tempAlertThreshold: number; + selectedDisks: string[]; + gameId?: string; + group: string | null; createdAt: string; updatedAt: string; - status: boolean; } From 25d1039376bdadb05854af79f70fbb16cca87362 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 12 Jan 2026 23:57:39 +0000 Subject: [PATCH 3/9] update pagespeed --- client/package-lock.json | 605 ++++++++++++++++++ .../src/Components/v1/ActionsMenu/index.jsx | 12 +- .../Components/v1/Charts/BarChart/index.jsx | 4 +- .../Components/v1/MonitorActions/index.jsx | 2 +- .../v1/MonitorDetailsControlHeader/index.jsx | 6 +- .../v1/MonitorDetailsControlHeader/status.jsx | 2 +- .../Components/v1/PageStateWrapper/index.jsx | 2 +- client/src/Components/v1/StatBox/index.jsx | 2 +- client/src/Hooks/{v1 => }/checkHooks.js | 4 +- client/src/Hooks/{v1 => }/inviteHooks.js | 2 +- client/src/Hooks/{v1 => }/logHooks.js | 4 +- client/src/Hooks/{v1 => }/monitorHooks.js | 10 +- client/src/Hooks/{v1 => }/settingsHooks.js | 14 +- client/src/Hooks/{v1 => }/useIsAdmin.js | 0 client/src/Hooks/{v1 => }/useMonitorUtils.js | 0 client/src/Hooks/{v1 => }/useNotifications.js | 6 +- client/src/Hooks/{v1 => }/useSendTestEmail.js | 4 +- client/src/Hooks/{v1 => }/userHooks.js | 4 +- client/src/Pages/{v1 => }/About/index.jsx | 0 .../Account/EditUser/hooks/editUser.js | 6 +- .../Pages/{v1 => }/Account/EditUser/index.jsx | 4 +- .../components/AddMemberMenu/index.jsx | 0 .../AddTeamMember/hooks/useAddTeamMember.jsx | 2 +- .../components/AddTeamMember/index.jsx | 4 +- .../components/ChangePasswordModal/index.jsx | 4 +- .../Account/components/PasswordPanel.jsx | 8 +- .../Account/components/ProfilePanel.jsx | 12 +- .../Account/components/RoleTable/index.jsx | 2 +- .../{v1 => }/Account/components/TeamPanel.jsx | 10 +- client/src/Pages/{v1 => }/Account/index.jsx | 0 client/src/Pages/{v1 => }/Auth/CheckEmail.jsx | 10 +- .../Pages/{v1 => }/Auth/ForgotPassword.jsx | 12 +- .../Auth/Login/hooks/useLoadingSubmit.jsx | 0 .../Auth/Login/hooks/useLoginForm.jsx | 0 .../Auth/Login/hooks/useLoginSubmit.jsx | 4 +- .../Auth/Login/hooks/useValidateLoginForm.jsx | 2 +- .../src/Pages/{v1 => }/Auth/Login/index.jsx | 0 .../{v1 => }/Auth/NewPasswordConfirmed.jsx | 8 +- .../Pages/{v1 => }/Auth/Register/index.jsx | 8 +- .../Pages/{v1 => }/Auth/SetNewPassword.jsx | 12 +- .../{v1 => }/Auth/components/AuthHeader.jsx | 4 +- .../Auth/components/AuthPageWrapper.jsx | 4 +- .../Auth/components/PasswordTooltip.jsx | 0 .../Auth/hooks/usePasswordFeedback.jsx | 2 +- .../Auth/hooks/useValidatePassword.jsx | 2 +- client/src/Pages/{v1 => }/Auth/index.css | 0 .../Components/IncidentTable/index.jsx | 6 +- .../Components/OptionsHeader/index.jsx | 0 .../Components/OptionsHeader/skeleton.jsx | 0 .../Components/StatusBoxes/StatusBox.jsx | 10 +- .../Components/StatusBoxes/index.jsx | 0 .../Components/StatusBoxes/skeleton.jsx | 0 client/src/Pages/{v1 => }/Incidents/index.jsx | 5 +- .../Components/ActiveIncidentsPanel/index.jsx | 0 .../Components/IncidentTable/index.jsx | 2 +- .../IncidentsSummaryPanel/index.jsx | 0 .../IncidentsSummaryPanel/skeleton.jsx | 0 .../LatestIncidentsPanel/IncidentItem.jsx | 0 .../Components/LatestIncidentsPanel/index.jsx | 0 .../Components/OptionsHeader/index.jsx | 0 .../Components/StatisticsPanel/index.jsx | 0 .../Components/SummaryCard/index.jsx | 0 .../Incidents2/hooks/useFetchIncidents.js | 4 +- .../src/Pages/{v1 => }/Incidents2/index.jsx | 2 +- .../Create/Components/CustomAlertsSection.jsx | 2 +- .../Components/CustomThreshold/index.jsx | 0 .../Create/Components/DiskSelection.jsx | 0 .../Components/MonitorActionButtons.jsx | 0 .../Create/Components/MonitorStatusHeader.jsx | 2 +- .../hooks/useInfrastructureMonitorForm.jsx | 0 .../Create/hooks/useInfrastructureSubmit.jsx | 5 +- .../hooks/useValidateInfrastructureForm.jsx | 4 +- .../{v1 => }/Infrastructure/Create/index.jsx | 9 +- .../AreaChartBoxes/InfraAreaChart.jsx | 0 .../Components/AreaChartBoxes/index.jsx | 0 .../Components/AreaChartBoxes/skeleton.jsx | 0 .../Components/BaseContainer/index.jsx | 0 .../Details/Components/GaugeBoxes/Gauge.jsx | 0 .../Details/Components/GaugeBoxes/index.jsx | 0 .../Components/GaugeBoxes/skeleton.jsx | 0 .../Components/NetworkStats/NetworkCharts.jsx | 0 .../NetworkStats/NetworkStatBoxes.jsx | 0 .../Details/Components/NetworkStats/index.jsx | 0 .../Components/NetworkStats/skeleton.jsx | 0 .../Details/Components/StatusBoxes/index.jsx | 2 +- .../Details/Hooks/useHardwareUtils.jsx | 0 .../{v1 => }/Infrastructure/Details/index.jsx | 4 +- .../Monitors/Components/Filters/index.jsx | 0 .../Components/MonitorsTable/index.jsx | 4 +- .../Components/MonitorsTableMenu/index.jsx | 8 +- .../Infrastructure/Monitors/index.jsx | 6 +- .../src/Pages/{v1 => }/Integrations/index.css | 0 .../src/Pages/{v1 => }/Integrations/index.jsx | 0 .../Diagnostics/components/gauges/index.jsx | 0 .../Diagnostics/components/stats/index.jsx | 2 +- .../Pages/{v1 => }/Logs/Diagnostics/index.jsx | 12 +- .../{v1 => }/Logs/Diagnostics/utils/utils.js | 0 client/src/Pages/{v1 => }/Logs/Logs/index.jsx | 3 +- .../Queue/components/FailedJobTable/index.jsx | 2 +- .../Logs/Queue/components/JobTable/index.jsx | 2 +- .../Logs/Queue/components/Metrics/index.jsx | 0 .../Queue/components/MetricsTable/index.jsx | 0 .../src/Pages/{v1 => }/Logs/Queue/index.jsx | 2 +- client/src/Pages/{v1 => }/Logs/index.jsx | 0 .../Components/ConfigSelect/index.jsx | 0 .../Components/MonitorList/index.jsx | 0 .../Components/MonitorsConfig/index.jsx | 0 .../hooks/useMaintenanceActions.jsx | 4 +- .../hooks/useMaintenanceData.jsx | 4 +- .../Maintenance/CreateMaintenance/index.css | 0 .../Maintenance/CreateMaintenance/index.jsx | 10 +- .../MaintenanceTable/ActionsMenu/index.jsx | 8 +- .../Maintenance/MaintenanceTable/index.jsx | 4 +- .../src/Pages/{v1 => }/Maintenance/index.css | 0 .../src/Pages/{v1 => }/Maintenance/index.jsx | 2 +- client/src/Pages/{v1 => }/NotFound/index.jsx | 2 +- .../Notifications/components/ActionMenu.jsx | 0 .../{v1 => }/Notifications/create/index.jsx | 6 +- .../Pages/{v1 => }/Notifications/index.jsx | 2 +- .../src/Pages/{v1 => }/Notifications/utils.js | 0 .../Pages/{v1 => }/PageSpeed/Create/index.css | 0 .../Pages/{v1 => }/PageSpeed/Create/index.jsx | 15 +- .../{v1 => }/PageSpeed/Create/skeleton.jsx | 0 .../Details/Components/Charts/AreaChart.jsx | 2 +- .../Components/Charts/AreaChartLegend.jsx | 2 +- .../Details/Components/Charts/PieChart.jsx | 0 .../Components/Charts/PieChartLegend.jsx | 2 +- .../Components/PageSpeedAreaChart/index.jsx | 2 +- .../PageSpeedAreaChart/skeleton.jsx | 0 .../Components/PageSpeedStatusBoxes/index.jsx | 2 +- .../Components/PerformanceReport/index.jsx | 2 +- .../Components/PerformanceReport/skeleton.jsx | 0 .../{v1 => }/PageSpeed/Details/index.jsx | 4 +- .../Monitors/Components/Card/index.jsx | 11 +- .../Monitors/Components/MonitorGrid/index.jsx | 0 .../{v1 => }/PageSpeed/Monitors/index.jsx | 45 +- .../src/Pages/{v1 => }/ServerUnreachable.jsx | 10 +- .../Pages/{v1 => }/Settings/SettingsAbout.jsx | 0 .../Settings/SettingsDemoMonitors.jsx | 0 .../Pages/{v1 => }/Settings/SettingsEmail.jsx | 4 +- .../{v1 => }/Settings/SettingsExport.jsx | 0 .../Settings/SettingsGlobalThresholds.jsx | 0 .../{v1 => }/Settings/SettingsPagespeed.jsx | 0 .../Pages/{v1 => }/Settings/SettingsStats.jsx | 10 - .../{v1 => }/Settings/SettingsTimeZone.jsx | 2 +- .../Pages/{v1 => }/Settings/SettingsUI.jsx | 0 .../Pages/{v1 => }/Settings/SettingsURL.jsx | 0 client/src/Pages/{v1 => }/Settings/index.jsx | 15 +- .../Create/Components/MonitorList/index.jsx | 0 .../Create/Components/Progress/index.jsx | 2 +- .../Create/Components/Skeleton/index.jsx | 0 .../Create/Components/Tabs/ConfigStack.jsx | 0 .../Create/Components/Tabs/Content.jsx | 0 .../Create/Components/Tabs/Settings.jsx | 2 +- .../Create/Components/Tabs/index.jsx | 0 .../Create/Hooks/useCreateStatusPage.jsx | 4 +- .../Create/Hooks/useMonitorsFetch.jsx | 4 +- .../{v1 => }/StatusPage/Create/index.jsx | 6 +- .../Status/Components/AdminLink/index.jsx | 0 .../Components/ControlsHeader/index.jsx | 2 +- .../Status/Components/MonitorsList/index.jsx | 2 +- .../Status/Components/Skeleton/index.jsx | 0 .../Status/Components/StatusBar/index.jsx | 0 .../Status/Hooks/useStatusPageDelete.jsx | 4 +- .../Status/Hooks/useStatusPageFetch.jsx | 6 +- .../{v1 => }/StatusPage/Status/index.jsx | 2 +- .../Components/StatusPagesTable/index.jsx | 0 .../StatusPages/Hooks/useStatusPagesFetch.jsx | 4 +- .../{v1 => }/StatusPage/StatusPages/index.jsx | 2 +- .../{v1 => }/Uptime/BulkImport/Upload.jsx | 0 .../{v1 => }/Uptime/BulkImport/index.jsx | 4 +- .../Pages/{v1 => }/Uptime/Create/index.css | 0 .../Pages/{v1 => }/Uptime/Create/index.jsx | 13 +- .../Pages/{v1 => }/Uptime/Create/skeleton.jsx | 0 .../Details/Components/ChartBoxes/index.jsx | 8 +- .../Components/ChartBoxes/skeleton.jsx | 0 .../Components/Charts/CustomLabels.jsx | 2 +- .../Components/Charts/DownBarChart.jsx | 0 .../Components/Charts/ResponseGaugeChart.jsx | 0 .../Components/Charts/ResponseTimeChart.jsx | 2 +- .../Charts/ResponseTimeChartSkeleton.jsx | 0 .../Details/Components/Charts/UpBarChart.jsx | 0 .../Components/ResponseTable/index.jsx | 4 +- .../Components/ResponseTable/skeleton.jsx | 0 .../Components/UptimeStatusBoxes/index.jsx | 4 +- .../Details/Hooks/useCertificateFetch.jsx | 6 +- .../Pages/{v1 => }/Uptime/Details/index.jsx | 6 +- .../Monitors/Components/Filter/index.jsx | 0 .../Components/LoadingSpinner/index.jsx | 0 .../Components/SearchComponent/index.jsx | 0 .../Monitors/Components/Skeleton/index.jsx | 0 .../Monitors/Components/StatusBoxes/index.jsx | 0 .../Components/StatusBoxes/skeleton.jsx | 0 .../Components/StatusBoxes/statusBox.jsx | 6 +- .../Components/UptimeDataTable/index.jsx | 10 +- .../Uptime/Monitors/Hooks/useDebounce.jsx | 0 .../Pages/{v1 => }/Uptime/Monitors/index.jsx | 8 +- client/src/Routes/index.jsx | 62 +- server/src/db/models/Check.ts | 23 +- server/src/db/modules/checkModule.js | 2 +- server/src/db/modules/monitorModule.js | 1 - server/src/service/business/monitorService.js | 1 - .../service/infrastructure/statusService.js | 28 +- server/src/types/check.ts | 19 +- 204 files changed, 977 insertions(+), 343 deletions(-) rename client/src/Hooks/{v1 => }/checkHooks.js (97%) rename client/src/Hooks/{v1 => }/inviteHooks.js (97%) rename client/src/Hooks/{v1 => }/logHooks.js (96%) rename client/src/Hooks/{v1 => }/monitorHooks.js (98%) rename client/src/Hooks/{v1 => }/settingsHooks.js (89%) rename client/src/Hooks/{v1 => }/useIsAdmin.js (100%) rename client/src/Hooks/{v1 => }/useMonitorUtils.js (100%) rename client/src/Hooks/{v1 => }/useNotifications.js (96%) rename client/src/Hooks/{v1 => }/useSendTestEmail.js (93%) rename client/src/Hooks/{v1 => }/userHooks.js (94%) rename client/src/Pages/{v1 => }/About/index.jsx (100%) rename client/src/Pages/{v1 => }/Account/EditUser/hooks/editUser.js (91%) rename client/src/Pages/{v1 => }/Account/EditUser/index.jsx (96%) rename client/src/Pages/{v1 => }/Account/components/AddMemberMenu/index.jsx (100%) rename client/src/Pages/{v1 => }/Account/components/AddTeamMember/hooks/useAddTeamMember.jsx (93%) rename client/src/Pages/{v1 => }/Account/components/AddTeamMember/index.jsx (97%) rename client/src/Pages/{v1 => }/Account/components/PasswordPanel.jsx (95%) rename client/src/Pages/{v1 => }/Account/components/ProfilePanel.jsx (97%) rename client/src/Pages/{v1 => }/Account/components/RoleTable/index.jsx (93%) rename client/src/Pages/{v1 => }/Account/components/TeamPanel.jsx (96%) rename client/src/Pages/{v1 => }/Account/index.jsx (100%) rename client/src/Pages/{v1 => }/Auth/CheckEmail.jsx (94%) rename client/src/Pages/{v1 => }/Auth/ForgotPassword.jsx (93%) rename client/src/Pages/{v1 => }/Auth/Login/hooks/useLoadingSubmit.jsx (100%) rename client/src/Pages/{v1 => }/Auth/Login/hooks/useLoginForm.jsx (100%) rename client/src/Pages/{v1 => }/Auth/Login/hooks/useLoginSubmit.jsx (87%) rename client/src/Pages/{v1 => }/Auth/Login/hooks/useValidateLoginForm.jsx (90%) rename client/src/Pages/{v1 => }/Auth/Login/index.jsx (100%) rename client/src/Pages/{v1 => }/Auth/NewPasswordConfirmed.jsx (92%) rename client/src/Pages/{v1 => }/Auth/Register/index.jsx (97%) rename client/src/Pages/{v1 => }/Auth/SetNewPassword.jsx (95%) rename client/src/Pages/{v1 => }/Auth/components/AuthHeader.jsx (87%) rename client/src/Pages/{v1 => }/Auth/components/AuthPageWrapper.jsx (93%) rename client/src/Pages/{v1 => }/Auth/components/PasswordTooltip.jsx (100%) rename client/src/Pages/{v1 => }/Auth/hooks/usePasswordFeedback.jsx (96%) rename client/src/Pages/{v1 => }/Auth/hooks/useValidatePassword.jsx (96%) rename client/src/Pages/{v1 => }/Auth/index.css (100%) rename client/src/Pages/{v1 => }/Incidents/Components/IncidentTable/index.jsx (95%) rename client/src/Pages/{v1 => }/Incidents/Components/OptionsHeader/index.jsx (100%) rename client/src/Pages/{v1 => }/Incidents/Components/OptionsHeader/skeleton.jsx (100%) rename client/src/Pages/{v1 => }/Incidents/Components/StatusBoxes/StatusBox.jsx (87%) rename client/src/Pages/{v1 => }/Incidents/Components/StatusBoxes/index.jsx (100%) rename client/src/Pages/{v1 => }/Incidents/Components/StatusBoxes/skeleton.jsx (100%) rename client/src/Pages/{v1 => }/Incidents/index.jsx (93%) rename client/src/Pages/{v1 => }/Incidents2/Components/ActiveIncidentsPanel/index.jsx (100%) rename client/src/Pages/{v1 => }/Incidents2/Components/IncidentTable/index.jsx (98%) rename client/src/Pages/{v1 => }/Incidents2/Components/IncidentsSummaryPanel/index.jsx (100%) rename client/src/Pages/{v1 => }/Incidents2/Components/IncidentsSummaryPanel/skeleton.jsx (100%) rename client/src/Pages/{v1 => }/Incidents2/Components/LatestIncidentsPanel/IncidentItem.jsx (100%) rename client/src/Pages/{v1 => }/Incidents2/Components/LatestIncidentsPanel/index.jsx (100%) rename client/src/Pages/{v1 => }/Incidents2/Components/OptionsHeader/index.jsx (100%) rename client/src/Pages/{v1 => }/Incidents2/Components/StatisticsPanel/index.jsx (100%) rename client/src/Pages/{v1 => }/Incidents2/Components/SummaryCard/index.jsx (100%) rename client/src/Pages/{v1 => }/Incidents2/hooks/useFetchIncidents.js (97%) rename client/src/Pages/{v1 => }/Incidents2/index.jsx (97%) rename client/src/Pages/{v1 => }/Infrastructure/Create/Components/CustomAlertsSection.jsx (96%) rename client/src/Pages/{v1 => }/Infrastructure/Create/Components/CustomThreshold/index.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Create/Components/DiskSelection.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Create/Components/MonitorActionButtons.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Create/Components/MonitorStatusHeader.jsx (95%) rename client/src/Pages/{v1 => }/Infrastructure/Create/hooks/useInfrastructureMonitorForm.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Create/hooks/useInfrastructureSubmit.jsx (96%) rename client/src/Pages/{v1 => }/Infrastructure/Create/hooks/useValidateInfrastructureForm.jsx (85%) rename client/src/Pages/{v1 => }/Infrastructure/Create/index.jsx (97%) rename client/src/Pages/{v1 => }/Infrastructure/Details/Components/AreaChartBoxes/InfraAreaChart.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Details/Components/AreaChartBoxes/index.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Details/Components/AreaChartBoxes/skeleton.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Details/Components/BaseContainer/index.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Details/Components/GaugeBoxes/Gauge.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Details/Components/GaugeBoxes/index.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Details/Components/GaugeBoxes/skeleton.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Details/Components/NetworkStats/NetworkCharts.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Details/Components/NetworkStats/NetworkStatBoxes.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Details/Components/NetworkStats/index.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Details/Components/NetworkStats/skeleton.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Details/Components/StatusBoxes/index.jsx (97%) rename client/src/Pages/{v1 => }/Infrastructure/Details/Hooks/useHardwareUtils.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Details/index.jsx (96%) rename client/src/Pages/{v1 => }/Infrastructure/Monitors/Components/Filters/index.jsx (100%) rename client/src/Pages/{v1 => }/Infrastructure/Monitors/Components/MonitorsTable/index.jsx (95%) rename client/src/Pages/{v1 => }/Infrastructure/Monitors/Components/MonitorsTableMenu/index.jsx (94%) rename client/src/Pages/{v1 => }/Infrastructure/Monitors/index.jsx (94%) rename client/src/Pages/{v1 => }/Integrations/index.css (100%) rename client/src/Pages/{v1 => }/Integrations/index.jsx (100%) rename client/src/Pages/{v1 => }/Logs/Diagnostics/components/gauges/index.jsx (100%) rename client/src/Pages/{v1 => }/Logs/Diagnostics/components/stats/index.jsx (96%) rename client/src/Pages/{v1 => }/Logs/Diagnostics/index.jsx (88%) rename client/src/Pages/{v1 => }/Logs/Diagnostics/utils/utils.js (100%) rename client/src/Pages/{v1 => }/Logs/Logs/index.jsx (97%) rename client/src/Pages/{v1 => }/Logs/Queue/components/FailedJobTable/index.jsx (96%) rename client/src/Pages/{v1 => }/Logs/Queue/components/JobTable/index.jsx (97%) rename client/src/Pages/{v1 => }/Logs/Queue/components/Metrics/index.jsx (100%) rename client/src/Pages/{v1 => }/Logs/Queue/components/MetricsTable/index.jsx (100%) rename client/src/Pages/{v1 => }/Logs/Queue/index.jsx (95%) rename client/src/Pages/{v1 => }/Logs/index.jsx (100%) rename client/src/Pages/{v1 => }/Maintenance/CreateMaintenance/Components/ConfigSelect/index.jsx (100%) rename client/src/Pages/{v1 => }/Maintenance/CreateMaintenance/Components/MonitorList/index.jsx (100%) rename client/src/Pages/{v1 => }/Maintenance/CreateMaintenance/Components/MonitorsConfig/index.jsx (100%) rename client/src/Pages/{v1 => }/Maintenance/CreateMaintenance/hooks/useMaintenanceActions.jsx (93%) rename client/src/Pages/{v1 => }/Maintenance/CreateMaintenance/hooks/useMaintenanceData.jsx (95%) rename client/src/Pages/{v1 => }/Maintenance/CreateMaintenance/index.css (100%) rename client/src/Pages/{v1 => }/Maintenance/CreateMaintenance/index.jsx (97%) rename client/src/Pages/{v1 => }/Maintenance/MaintenanceTable/ActionsMenu/index.jsx (93%) rename client/src/Pages/{v1 => }/Maintenance/MaintenanceTable/index.jsx (97%) rename client/src/Pages/{v1 => }/Maintenance/index.css (100%) rename client/src/Pages/{v1 => }/Maintenance/index.jsx (98%) rename client/src/Pages/{v1 => }/NotFound/index.jsx (96%) rename client/src/Pages/{v1 => }/Notifications/components/ActionMenu.jsx (100%) rename client/src/Pages/{v1 => }/Notifications/create/index.jsx (97%) rename client/src/Pages/{v1 => }/Notifications/index.jsx (98%) rename client/src/Pages/{v1 => }/Notifications/utils.js (100%) rename client/src/Pages/{v1 => }/PageSpeed/Create/index.css (100%) rename client/src/Pages/{v1 => }/PageSpeed/Create/index.jsx (96%) rename client/src/Pages/{v1 => }/PageSpeed/Create/skeleton.jsx (100%) rename client/src/Pages/{v1 => }/PageSpeed/Details/Components/Charts/AreaChart.jsx (99%) rename client/src/Pages/{v1 => }/PageSpeed/Details/Components/Charts/AreaChartLegend.jsx (94%) rename client/src/Pages/{v1 => }/PageSpeed/Details/Components/Charts/PieChart.jsx (100%) rename client/src/Pages/{v1 => }/PageSpeed/Details/Components/Charts/PieChartLegend.jsx (96%) rename client/src/Pages/{v1 => }/PageSpeed/Details/Components/PageSpeedAreaChart/index.jsx (93%) rename client/src/Pages/{v1 => }/PageSpeed/Details/Components/PageSpeedAreaChart/skeleton.jsx (100%) rename client/src/Pages/{v1 => }/PageSpeed/Details/Components/PageSpeedStatusBoxes/index.jsx (91%) rename client/src/Pages/{v1 => }/PageSpeed/Details/Components/PerformanceReport/index.jsx (93%) rename client/src/Pages/{v1 => }/PageSpeed/Details/Components/PerformanceReport/skeleton.jsx (100%) rename client/src/Pages/{v1 => }/PageSpeed/Details/index.jsx (95%) rename client/src/Pages/{v1 => }/PageSpeed/Monitors/Components/Card/index.jsx (96%) rename client/src/Pages/{v1 => }/PageSpeed/Monitors/Components/MonitorGrid/index.jsx (100%) rename client/src/Pages/{v1 => }/PageSpeed/Monitors/index.jsx (64%) rename client/src/Pages/{v1 => }/ServerUnreachable.jsx (92%) rename client/src/Pages/{v1 => }/Settings/SettingsAbout.jsx (100%) rename client/src/Pages/{v1 => }/Settings/SettingsDemoMonitors.jsx (100%) rename client/src/Pages/{v1 => }/Settings/SettingsEmail.jsx (98%) rename client/src/Pages/{v1 => }/Settings/SettingsExport.jsx (100%) rename client/src/Pages/{v1 => }/Settings/SettingsGlobalThresholds.jsx (100%) rename client/src/Pages/{v1 => }/Settings/SettingsPagespeed.jsx (100%) rename client/src/Pages/{v1 => }/Settings/SettingsStats.jsx (86%) rename client/src/Pages/{v1 => }/Settings/SettingsTimeZone.jsx (97%) rename client/src/Pages/{v1 => }/Settings/SettingsUI.jsx (100%) rename client/src/Pages/{v1 => }/Settings/SettingsURL.jsx (100%) rename client/src/Pages/{v1 => }/Settings/index.jsx (95%) rename client/src/Pages/{v1 => }/StatusPage/Create/Components/MonitorList/index.jsx (100%) rename client/src/Pages/{v1 => }/StatusPage/Create/Components/Progress/index.jsx (92%) rename client/src/Pages/{v1 => }/StatusPage/Create/Components/Skeleton/index.jsx (100%) rename client/src/Pages/{v1 => }/StatusPage/Create/Components/Tabs/ConfigStack.jsx (100%) rename client/src/Pages/{v1 => }/StatusPage/Create/Components/Tabs/Content.jsx (100%) rename client/src/Pages/{v1 => }/StatusPage/Create/Components/Tabs/Settings.jsx (98%) rename client/src/Pages/{v1 => }/StatusPage/Create/Components/Tabs/index.jsx (100%) rename client/src/Pages/{v1 => }/StatusPage/Create/Hooks/useCreateStatusPage.jsx (83%) rename client/src/Pages/{v1 => }/StatusPage/Create/Hooks/useMonitorsFetch.jsx (88%) rename client/src/Pages/{v1 => }/StatusPage/Create/index.jsx (97%) rename client/src/Pages/{v1 => }/StatusPage/Status/Components/AdminLink/index.jsx (100%) rename client/src/Pages/{v1 => }/StatusPage/Status/Components/ControlsHeader/index.jsx (97%) rename client/src/Pages/{v1 => }/StatusPage/Status/Components/MonitorsList/index.jsx (95%) rename client/src/Pages/{v1 => }/StatusPage/Status/Components/Skeleton/index.jsx (100%) rename client/src/Pages/{v1 => }/StatusPage/Status/Components/StatusBar/index.jsx (100%) rename client/src/Pages/{v1 => }/StatusPage/Status/Hooks/useStatusPageDelete.jsx (89%) rename client/src/Pages/{v1 => }/StatusPage/Status/Hooks/useStatusPageFetch.jsx (87%) rename client/src/Pages/{v1 => }/StatusPage/Status/index.jsx (98%) rename client/src/Pages/{v1 => }/StatusPage/StatusPages/Components/StatusPagesTable/index.jsx (100%) rename client/src/Pages/{v1 => }/StatusPage/StatusPages/Hooks/useStatusPagesFetch.jsx (86%) rename client/src/Pages/{v1 => }/StatusPage/StatusPages/index.jsx (95%) rename client/src/Pages/{v1 => }/Uptime/BulkImport/Upload.jsx (100%) rename client/src/Pages/{v1 => }/Uptime/BulkImport/index.jsx (95%) rename client/src/Pages/{v1 => }/Uptime/Create/index.css (100%) rename client/src/Pages/{v1 => }/Uptime/Create/index.jsx (98%) rename client/src/Pages/{v1 => }/Uptime/Create/skeleton.jsx (100%) rename client/src/Pages/{v1 => }/Uptime/Details/Components/ChartBoxes/index.jsx (92%) rename client/src/Pages/{v1 => }/Uptime/Details/Components/ChartBoxes/skeleton.jsx (100%) rename client/src/Pages/{v1 => }/Uptime/Details/Components/Charts/CustomLabels.jsx (93%) rename client/src/Pages/{v1 => }/Uptime/Details/Components/Charts/DownBarChart.jsx (100%) rename client/src/Pages/{v1 => }/Uptime/Details/Components/Charts/ResponseGaugeChart.jsx (100%) rename client/src/Pages/{v1 => }/Uptime/Details/Components/Charts/ResponseTimeChart.jsx (89%) rename client/src/Pages/{v1 => }/Uptime/Details/Components/Charts/ResponseTimeChartSkeleton.jsx (100%) rename client/src/Pages/{v1 => }/Uptime/Details/Components/Charts/UpBarChart.jsx (100%) rename client/src/Pages/{v1 => }/Uptime/Details/Components/ResponseTable/index.jsx (97%) rename client/src/Pages/{v1 => }/Uptime/Details/Components/ResponseTable/skeleton.jsx (100%) rename client/src/Pages/{v1 => }/Uptime/Details/Components/UptimeStatusBoxes/index.jsx (92%) rename client/src/Pages/{v1 => }/Uptime/Details/Hooks/useCertificateFetch.jsx (84%) rename client/src/Pages/{v1 => }/Uptime/Details/index.jsx (95%) rename client/src/Pages/{v1 => }/Uptime/Monitors/Components/Filter/index.jsx (100%) rename client/src/Pages/{v1 => }/Uptime/Monitors/Components/LoadingSpinner/index.jsx (100%) rename client/src/Pages/{v1 => }/Uptime/Monitors/Components/SearchComponent/index.jsx (100%) rename client/src/Pages/{v1 => }/Uptime/Monitors/Components/Skeleton/index.jsx (100%) rename client/src/Pages/{v1 => }/Uptime/Monitors/Components/StatusBoxes/index.jsx (100%) rename client/src/Pages/{v1 => }/Uptime/Monitors/Components/StatusBoxes/skeleton.jsx (100%) rename client/src/Pages/{v1 => }/Uptime/Monitors/Components/StatusBoxes/statusBox.jsx (90%) rename client/src/Pages/{v1 => }/Uptime/Monitors/Components/UptimeDataTable/index.jsx (97%) rename client/src/Pages/{v1 => }/Uptime/Monitors/Hooks/useDebounce.jsx (100%) rename client/src/Pages/{v1 => }/Uptime/Monitors/index.jsx (96%) diff --git a/client/package-lock.json b/client/package-lock.json index 75dbe43da..e917619ae 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -499,6 +499,262 @@ "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", "license": "MIT" }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/linux-x64": { "version": "0.25.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", @@ -515,6 +771,134 @@ "node": ">=18" } }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", @@ -1696,6 +2080,123 @@ } } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.0.tgz", + "integrity": "sha512-KxN+zCjOYHGwCl4UCtSfZ6jrq/qi88JDUtiEFk8LELEHq2Egfc/FgW+jItZiOLRuQfb/3xJSgFuNPC9jzggX+A==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.0.tgz", + "integrity": "sha512-yDvqx3lWlcugozax3DItKJI5j05B0d4Kvnjx+5mwiUpWramVvmAByYigMplaoAQ3pvdprGCTCE03eduqE/8mPQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.0.tgz", + "integrity": "sha512-2KOU574vD3gzcPSjxO0eyR5iWlnxxtmW1F5CkNOHmMlueKNCQkxR6+ekgWyVnz6zaZihpUNkGxjsYrkTJKhkaw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.0.tgz", + "integrity": "sha512-gE5ACNSxHcEZyP2BA9TuTakfZvULEW4YAOtxl/A/YDbIir/wPKukde0BNPlnBiP88ecaN4BJI2TtAd+HKuZPQQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.0.tgz", + "integrity": "sha512-GSxU6r5HnWij7FoSo7cZg3l5GPg4HFLkzsFFh0N/b16q5buW1NAWuCJ+HMtIdUEi6XF0qH+hN0TEd78laRp7Dg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.0.tgz", + "integrity": "sha512-KGiGKGDg8qLRyOWmk6IeiHJzsN/OYxO6nSbT0Vj4MwjS2XQy/5emsmtoqLAabqrohbgLWJ5GV3s/ljdrIr8Qjg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.0.tgz", + "integrity": "sha512-46OzWeqEVQyX3N2/QdiU/CMXYDH/lSHpgfBkuhl3igpZiaB3ZIfSjKuOnybFVBQzjsLwkus2mjaESy8H41SzvA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.0.tgz", + "integrity": "sha512-lfgW3KtQP4YauqdPpcUZHPcqQXmTmH4nYU0cplNeW583CMkAGjtImw4PKli09NFi2iQgChk4e9erkwlfYem6Lg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.0.tgz", + "integrity": "sha512-nn8mEyzMbdEJzT7cwxgObuwviMx6kPRxzYiOl6o/o+ChQq23gfdlZcUNnt89lPhhz3BYsZ72rp0rxNqBSfqlqw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-arm64-musl": { "version": "4.41.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.0.tgz", @@ -1709,6 +2210,71 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.0.tgz", + "integrity": "sha512-WbnJaxPv1gPIm6S8O/Wg+wfE/OzGSXlBMbOe4ie+zMyykMOeqmgD1BhPxZQuDqwUN+0T/xOFtL2RUWBspnZj3w==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.0.tgz", + "integrity": "sha512-eRDWR5t67/b2g8Q/S8XPi0YdbKcCs4WQ8vklNnUYLaSWF+Cbv2axZsp4jni6/j7eKvMLYCYdcsv8dcU+a6QNFg==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.0.tgz", + "integrity": "sha512-TWrZb6GF5jsEKG7T1IHwlLMDRy2f3DPqYldmIhnA2DVqvvhY2Ai184vZGgahRrg8k9UBWoSlHv+suRfTN7Ua4A==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.0.tgz", + "integrity": "sha512-ieQljaZKuJpmWvd8gW87ZmSFwid6AxMDk5bhONJ57U8zT77zpZ/TPKkU9HpnnFrM4zsgr4kiGuzbIbZTGi7u9A==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.0.tgz", + "integrity": "sha512-/L3pW48SxrWAlVsKCN0dGLB2bi8Nv8pr5S5ocSM+S0XCn5RCVCXqi8GVtHFsOBBCSeR+u9brV2zno5+mg3S4Aw==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.41.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.0.tgz", @@ -1735,6 +2301,45 @@ "linux" ] }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.0.tgz", + "integrity": "sha512-4yodtcOrFHpbomJGVEqZ8fzD4kfBeCbpsUy5Pqk4RluXOdsWdjLnjhiKy2w3qzcASWd04fp52Xz7JKarVJ5BTg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.0.tgz", + "integrity": "sha512-tmazCrAsKzdkXssEc65zIE1oC6xPHwfy9d5Ta25SRCDOZS+I6RypVVShWALNuU9bxIfGA0aqrmzlzoM5wO5SPQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.0.tgz", + "integrity": "sha512-h1J+Yzjo/X+0EAvR2kIXJDuTuyT7drc+t2ALY0nIcGPbTatNOf0VWdhEA2Z4AAjv6X1NJV7SYo5oCTYRJhSlVA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", diff --git a/client/src/Components/v1/ActionsMenu/index.jsx b/client/src/Components/v1/ActionsMenu/index.jsx index 229c7c875..5cd0dfa5b 100644 --- a/client/src/Components/v1/ActionsMenu/index.jsx +++ b/client/src/Components/v1/ActionsMenu/index.jsx @@ -12,7 +12,7 @@ import { useNavigate } from "react-router-dom"; import { createToast } from "../../../Utils/toastUtils.jsx"; import PropTypes from "prop-types"; -import { usePauseMonitor, useDeleteMonitor } from "../../../Hooks/v1/monitorHooks.js"; +import { usePauseMonitor, useDeleteMonitor } from "../../../Hooks/monitorHooks.js"; const ActionsMenu = ({ monitor, @@ -31,7 +31,8 @@ const ActionsMenu = ({ const handleRemove = async (event) => { event.preventDefault(); event.stopPropagation(); - let monitor = { _id: actions.id }; + let monitor = { id: actions.id }; + console.log(monitor); await deleteMonitor({ monitor }); updateRowCallback(); }; @@ -39,7 +40,7 @@ const ActionsMenu = ({ const handlePause = async () => { try { setIsLoading(true); - await pauseMonitor({ monitorId: monitor._id }); + await pauseMonitor({ monitorId: monitor.id }); pauseCallback(); } catch (error) { createToast({ body: "Failed to pause monitor." }); @@ -72,7 +73,7 @@ const ActionsMenu = ({ aria-label="monitor actions" onClick={(event) => { event.stopPropagation(); - openMenu(event, monitor._id, monitor.type === "ping" ? null : monitor.url); + openMenu(event, monitor.id, monitor.type === "ping" ? null : monitor.url); }} sx={{ "&:focus": { @@ -197,6 +198,7 @@ const ActionsMenu = ({ confirmationButtonLabel="Delete" /* Do we need stop propagation? */ onConfirm={(e) => { + console.log(e); e.stopPropagation(); handleRemove(e); }} @@ -210,7 +212,7 @@ const ActionsMenu = ({ ActionsMenu.propTypes = { monitor: PropTypes.shape({ - _id: PropTypes.string, + id: PropTypes.string, url: PropTypes.string, type: PropTypes.string, isActive: PropTypes.bool, diff --git a/client/src/Components/v1/Charts/BarChart/index.jsx b/client/src/Components/v1/Charts/BarChart/index.jsx index 2bf8e1798..9f0ed8aa6 100644 --- a/client/src/Components/v1/Charts/BarChart/index.jsx +++ b/client/src/Components/v1/Charts/BarChart/index.jsx @@ -103,7 +103,7 @@ const BarChart = ({ checks = [] }) => { } placement="top" - key={`check-${check?._id}`} + key={`check-${check?.id}`} slotProps={{ popper: { className: "bar-tooltip", @@ -145,7 +145,7 @@ const BarChart = ({ checks = [] }) => { position="relative" width="9px" height="100%" - backgroundColor={theme.palette.primary.lowContrast} // CAIO_REVIEW + backgroundColor={theme.palette.primary.lowContrast} sx={{ borderRadius: theme.spacing(1.5), /* diff --git a/client/src/Components/v1/MonitorActions/index.jsx b/client/src/Components/v1/MonitorActions/index.jsx index 23cebc972..624d34b9a 100644 --- a/client/src/Components/v1/MonitorActions/index.jsx +++ b/client/src/Components/v1/MonitorActions/index.jsx @@ -11,7 +11,7 @@ import MenuList from "@mui/material/MenuList"; import { useNavigate } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { createToast } from "../../../Utils/toastUtils.jsx"; -import { useExportMonitors } from "../../../Hooks/v1/monitorHooks.js"; +import { useExportMonitors } from "../../../Hooks/monitorHooks.js"; const MonitorActions = ({ isLoading }) => { const [open, setOpen] = React.useState(false); diff --git a/client/src/Components/v1/MonitorDetailsControlHeader/index.jsx b/client/src/Components/v1/MonitorDetailsControlHeader/index.jsx index ae565f3bb..bb4399b85 100644 --- a/client/src/Components/v1/MonitorDetailsControlHeader/index.jsx +++ b/client/src/Components/v1/MonitorDetailsControlHeader/index.jsx @@ -12,10 +12,10 @@ import EmailIcon from "@mui/icons-material/Email"; import PropTypes from "prop-types"; import { useNavigate } from "react-router-dom"; import { useTheme } from "@mui/material/styles"; -import { usePauseMonitor } from "../../../Hooks/v1/monitorHooks.js"; -import { useSendTestEmail } from "../../../Hooks/v1/useSendTestEmail.js"; +import { usePauseMonitor } from "../../../Hooks/monitorHooks.js"; +import { useSendTestEmail } from "../../../Hooks/useSendTestEmail.js"; import { useTranslation } from "react-i18next"; -import { useTestAllNotifications } from "../../../Hooks/v1/useNotifications.js"; +import { useTestAllNotifications } from "../../../Hooks/useNotifications.js"; /** * MonitorDetailsControlHeader component displays the control header for monitor details. * It includes status display, pause/resume button, and a configure button for admins. diff --git a/client/src/Components/v1/MonitorDetailsControlHeader/status.jsx b/client/src/Components/v1/MonitorDetailsControlHeader/status.jsx index d9b7afc40..febf449d4 100644 --- a/client/src/Components/v1/MonitorDetailsControlHeader/status.jsx +++ b/client/src/Components/v1/MonitorDetailsControlHeader/status.jsx @@ -7,7 +7,7 @@ import Dot from "../Dot/index.jsx"; import { formatDurationRounded } from "../../../Utils/timeUtils.js"; import PropTypes from "prop-types"; import { useTheme } from "@emotion/react"; -import { useMonitorUtils } from "../../../Hooks/v1/useMonitorUtils.js"; +import { useMonitorUtils } from "../../../Hooks/useMonitorUtils.js"; import { formatMonitorUrl } from "../../../Utils/utils.js"; /** * Status component displays the status information of a monitor. diff --git a/client/src/Components/v1/PageStateWrapper/index.jsx b/client/src/Components/v1/PageStateWrapper/index.jsx index ac97704df..08adbe514 100644 --- a/client/src/Components/v1/PageStateWrapper/index.jsx +++ b/client/src/Components/v1/PageStateWrapper/index.jsx @@ -3,7 +3,7 @@ import Fallback from "../Fallback/index.jsx"; import { Typography } from "@mui/material"; import { useTheme } from "@emotion/react"; import { useTranslation } from "react-i18next"; -import { useIsAdmin } from "../../../Hooks/v1/useIsAdmin.js"; +import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; import PropTypes from "prop-types"; const PageStateWrapper = ({ networkError, diff --git a/client/src/Components/v1/StatBox/index.jsx b/client/src/Components/v1/StatBox/index.jsx index 1b5f1cf6f..e72f947b3 100644 --- a/client/src/Components/v1/StatBox/index.jsx +++ b/client/src/Components/v1/StatBox/index.jsx @@ -2,7 +2,7 @@ import { Stack, Typography } from "@mui/material"; import Image from "../Image/index.jsx"; import { useTheme } from "@mui/material/styles"; import PropTypes from "prop-types"; -import { useMonitorUtils } from "../../../Hooks/v1/useMonitorUtils.js"; +import { useMonitorUtils } from "../../../Hooks/useMonitorUtils.js"; /** * StatBox Component diff --git a/client/src/Hooks/v1/checkHooks.js b/client/src/Hooks/checkHooks.js similarity index 97% rename from client/src/Hooks/v1/checkHooks.js rename to client/src/Hooks/checkHooks.js index 96fd1fe1c..b8af32073 100644 --- a/client/src/Hooks/v1/checkHooks.js +++ b/client/src/Hooks/checkHooks.js @@ -1,6 +1,6 @@ import { useState, useEffect } from "react"; -import { networkService } from "../../main.jsx"; -import { createToast } from "../../Utils/toastUtils.jsx"; +import { networkService } from "../main.jsx"; +import { createToast } from "../Utils/toastUtils.jsx"; import { useTranslation } from "react-i18next"; const useFetchChecksTeam = ({ diff --git a/client/src/Hooks/v1/inviteHooks.js b/client/src/Hooks/inviteHooks.js similarity index 97% rename from client/src/Hooks/v1/inviteHooks.js rename to client/src/Hooks/inviteHooks.js index b6a0851af..c862eec31 100644 --- a/client/src/Hooks/v1/inviteHooks.js +++ b/client/src/Hooks/inviteHooks.js @@ -1,5 +1,5 @@ import { useState } from "react"; -import { networkService } from "../../main.jsx"; +import { networkService } from "../main.jsx"; import { useTranslation } from "react-i18next"; const CLIENT_HOST = import.meta.env.VITE_APP_CLIENT_HOST; diff --git a/client/src/Hooks/v1/logHooks.js b/client/src/Hooks/logHooks.js similarity index 96% rename from client/src/Hooks/v1/logHooks.js rename to client/src/Hooks/logHooks.js index ff4d13872..d5162de5a 100644 --- a/client/src/Hooks/v1/logHooks.js +++ b/client/src/Hooks/logHooks.js @@ -1,6 +1,6 @@ import { useState, useEffect } from "react"; -import { networkService } from "../../main.jsx"; -import { createToast } from "../../Utils/toastUtils.jsx"; +import { networkService } from "../main.jsx"; +import { createToast } from "../Utils/toastUtils.jsx"; import { useTranslation } from "react-i18next"; const useFetchLogs = () => { diff --git a/client/src/Hooks/v1/monitorHooks.js b/client/src/Hooks/monitorHooks.js similarity index 98% rename from client/src/Hooks/v1/monitorHooks.js rename to client/src/Hooks/monitorHooks.js index 8acbea608..ffc356320 100644 --- a/client/src/Hooks/v1/monitorHooks.js +++ b/client/src/Hooks/monitorHooks.js @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; -import { networkService } from "../../main.jsx"; -import { createToast } from "../../Utils/toastUtils.jsx"; +import { networkService } from "../main.jsx"; +import { createToast } from "../Utils/toastUtils.jsx"; import { useTheme } from "@emotion/react"; import { useMonitorUtils } from "./useMonitorUtils.js"; import { useNavigate } from "react-router-dom"; @@ -67,12 +67,13 @@ const useFetchMonitorsWithChecks = ({ field, order, }); + const { count, monitors } = res?.data?.data ?? {}; const mappedMonitors = monitors.map((monitor) => getMonitorWithPercentage(monitor, theme) ); setMonitors(mappedMonitors); - setCount(count?.monitorsCount ?? 0); + setCount(count || 0); } catch (error) { console.error(error); setNetworkError(true); @@ -347,7 +348,8 @@ const useDeleteMonitor = () => { const deleteMonitor = async ({ monitor, redirect }) => { try { setIsLoading(true); - await networkService.deleteMonitorById({ monitorId: monitor._id }); + console.log(monitor); + await networkService.deleteMonitorById({ monitorId: monitor.id }); createToast({ body: "Monitor deleted successfully!" }); if (redirect) { navigate(redirect); diff --git a/client/src/Hooks/v1/settingsHooks.js b/client/src/Hooks/settingsHooks.js similarity index 89% rename from client/src/Hooks/v1/settingsHooks.js rename to client/src/Hooks/settingsHooks.js index 787e46ff9..8c4bef385 100644 --- a/client/src/Hooks/v1/settingsHooks.js +++ b/client/src/Hooks/settingsHooks.js @@ -1,6 +1,6 @@ import { useState, useEffect } from "react"; -import { networkService } from "../../main.jsx"; -import { createToast } from "../../Utils/toastUtils.jsx"; +import { networkService } from "../main.jsx"; +import { createToast } from "../Utils/toastUtils.jsx"; import { useTranslation } from "react-i18next"; const useFetchSettings = ({ setSettingsData, setIsApiKeySet, setIsEmailPasswordSet }) => { @@ -42,11 +42,11 @@ const useSaveSettings = ({ setIsLoading(true); try { const settingsResponse = await networkService.updateAppSettings({ settings }); - if (settings.checkTTL) { - await networkService.updateChecksTTL({ - ttl: settings.checkTTL, - }); - } + // if (settings.checkTTL) { + // await networkService.updateChecksTTL({ + // ttl: settings.checkTTL, + // }); + // } setIsApiKeySet(settingsResponse.data.data.pagespeedKeySet); setIsEmailPasswordSet(settingsResponse.data.data.emailPasswordSet); if (settingsResponse.data.data.pagespeedKeySet === true) { diff --git a/client/src/Hooks/v1/useIsAdmin.js b/client/src/Hooks/useIsAdmin.js similarity index 100% rename from client/src/Hooks/v1/useIsAdmin.js rename to client/src/Hooks/useIsAdmin.js diff --git a/client/src/Hooks/v1/useMonitorUtils.js b/client/src/Hooks/useMonitorUtils.js similarity index 100% rename from client/src/Hooks/v1/useMonitorUtils.js rename to client/src/Hooks/useMonitorUtils.js diff --git a/client/src/Hooks/v1/useNotifications.js b/client/src/Hooks/useNotifications.js similarity index 96% rename from client/src/Hooks/v1/useNotifications.js rename to client/src/Hooks/useNotifications.js index d1b4a6652..5f2058b6a 100644 --- a/client/src/Hooks/v1/useNotifications.js +++ b/client/src/Hooks/useNotifications.js @@ -1,9 +1,9 @@ import { useState, useEffect, useCallback } from "react"; -import { createToast } from "../../Utils/toastUtils.jsx"; -import { networkService } from "../../main.jsx"; +import { createToast } from "../Utils/toastUtils.jsx"; +import { networkService } from "../main.jsx"; import { useNavigate } from "react-router-dom"; import { useTranslation } from "react-i18next"; -import { NOTIFICATION_TYPES } from "../../Pages/v1/Notifications/utils.js"; +import { NOTIFICATION_TYPES } from "../Pages/Notifications/utils.js"; const useCreateNotification = () => { const navigate = useNavigate(); diff --git a/client/src/Hooks/v1/useSendTestEmail.js b/client/src/Hooks/useSendTestEmail.js similarity index 93% rename from client/src/Hooks/v1/useSendTestEmail.js rename to client/src/Hooks/useSendTestEmail.js index 0be77954a..7223a489a 100644 --- a/client/src/Hooks/v1/useSendTestEmail.js +++ b/client/src/Hooks/useSendTestEmail.js @@ -1,7 +1,7 @@ import { useState } from "react"; -import { networkService } from "../../main.jsx"; +import { networkService } from "../main.jsx"; import { useSelector } from "react-redux"; -import { createToast } from "../../Utils/toastUtils.jsx"; +import { createToast } from "../Utils/toastUtils.jsx"; import { useTranslation } from "react-i18next"; const useSendTestEmail = () => { diff --git a/client/src/Hooks/v1/userHooks.js b/client/src/Hooks/userHooks.js similarity index 94% rename from client/src/Hooks/v1/userHooks.js rename to client/src/Hooks/userHooks.js index f9c454450..3d822f979 100644 --- a/client/src/Hooks/v1/userHooks.js +++ b/client/src/Hooks/userHooks.js @@ -1,6 +1,6 @@ import { useEffect, useState, useCallback } from "react"; -import { networkService } from "../../main.jsx"; -import { createToast } from "../../Utils/toastUtils.jsx"; +import { networkService } from "../main.jsx"; +import { createToast } from "../Utils/toastUtils.jsx"; import { useTranslation } from "react-i18next"; export const useGetUser = (userId) => { diff --git a/client/src/Pages/v1/About/index.jsx b/client/src/Pages/About/index.jsx similarity index 100% rename from client/src/Pages/v1/About/index.jsx rename to client/src/Pages/About/index.jsx diff --git a/client/src/Pages/v1/Account/EditUser/hooks/editUser.js b/client/src/Pages/Account/EditUser/hooks/editUser.js similarity index 91% rename from client/src/Pages/v1/Account/EditUser/hooks/editUser.js rename to client/src/Pages/Account/EditUser/hooks/editUser.js index 00660aead..aeb50ffff 100644 --- a/client/src/Pages/v1/Account/EditUser/hooks/editUser.js +++ b/client/src/Pages/Account/EditUser/hooks/editUser.js @@ -1,8 +1,8 @@ import { useState, useEffect } from "react"; -import { ROLES } from "../../../../../Utils/roleUtils.js"; -import { editUserValidation } from "../../../../../Validation/validation.js"; +import { ROLES } from "../../../../Utils/roleUtils.js"; +import { editUserValidation } from "../../../../Validation/validation.js"; import Joi from "joi"; -import { createToast } from "../../../../../Utils/toastUtils.jsx"; +import { createToast } from "../../../../Utils/toastUtils.jsx"; import { useTranslation } from "react-i18next"; export const useEditUserForm = (user) => { const [searchInput, setSearchInput] = useState(""); diff --git a/client/src/Pages/v1/Account/EditUser/index.jsx b/client/src/Pages/Account/EditUser/index.jsx similarity index 96% rename from client/src/Pages/v1/Account/EditUser/index.jsx rename to client/src/Pages/Account/EditUser/index.jsx index 674a522b8..2b2ac5128 100644 --- a/client/src/Pages/v1/Account/EditUser/index.jsx +++ b/client/src/Pages/Account/EditUser/index.jsx @@ -11,8 +11,8 @@ import ChangePasswordModal from "@/Pages/Account/components/ChangePasswordModal/ import { useParams } from "react-router-dom"; import { useTheme } from "@emotion/react"; import { useTranslation } from "react-i18next"; -import { useGetUser, useEditUser } from "../../../../Hooks/v1/userHooks.js"; -import { EDITABLE_ROLES, ROLES } from "../../../../Utils/roleUtils.js"; +import { useGetUser, useEditUser } from "../../../Hooks/userHooks.js"; +import { EDITABLE_ROLES, ROLES } from "../../../Utils/roleUtils.js"; import { useEditUserForm, useValidateEditUserForm } from "./hooks/editUser.js"; import { useSelector } from "react-redux"; diff --git a/client/src/Pages/v1/Account/components/AddMemberMenu/index.jsx b/client/src/Pages/Account/components/AddMemberMenu/index.jsx similarity index 100% rename from client/src/Pages/v1/Account/components/AddMemberMenu/index.jsx rename to client/src/Pages/Account/components/AddMemberMenu/index.jsx diff --git a/client/src/Pages/v1/Account/components/AddTeamMember/hooks/useAddTeamMember.jsx b/client/src/Pages/Account/components/AddTeamMember/hooks/useAddTeamMember.jsx similarity index 93% rename from client/src/Pages/v1/Account/components/AddTeamMember/hooks/useAddTeamMember.jsx rename to client/src/Pages/Account/components/AddTeamMember/hooks/useAddTeamMember.jsx index 58db019a3..1237777ff 100644 --- a/client/src/Pages/v1/Account/components/AddTeamMember/hooks/useAddTeamMember.jsx +++ b/client/src/Pages/Account/components/AddTeamMember/hooks/useAddTeamMember.jsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { newOrChangedCredentials } from "../../../../../../Validation/validation.js"; +import { newOrChangedCredentials } from "../../../../../Validation/validation.js"; import { useTranslation } from "react-i18next"; const useAddTeamMember = () => { const { t } = useTranslation(); diff --git a/client/src/Pages/v1/Account/components/AddTeamMember/index.jsx b/client/src/Pages/Account/components/AddTeamMember/index.jsx similarity index 97% rename from client/src/Pages/v1/Account/components/AddTeamMember/index.jsx rename to client/src/Pages/Account/components/AddTeamMember/index.jsx index 219658b63..e5280af16 100644 --- a/client/src/Pages/v1/Account/components/AddTeamMember/index.jsx +++ b/client/src/Pages/Account/components/AddTeamMember/index.jsx @@ -2,10 +2,10 @@ import { Button, Stack } from "@mui/material"; import { GenericDialog } from "@/Components/v1/Dialog/genericDialog.jsx"; import TextInput from "@/Components/v1/Inputs/TextInput/index.jsx"; import Select from "@/Components/v1/Inputs/Select/index.jsx"; -import { useGetInviteToken } from "../../../../../Hooks/v1/inviteHooks.js"; +import { useGetInviteToken } from "../../../../Hooks/inviteHooks.js"; import { useTheme } from "@emotion/react"; import { useTranslation } from "react-i18next"; -import { createToast } from "../../../../../Utils/toastUtils.jsx"; +import { createToast } from "../../../../Utils/toastUtils.jsx"; import { useState } from "react"; import PasswordTooltip from "../../../Auth/components/PasswordTooltip.jsx"; import useAddTeamMember from "./hooks/useAddTeamMember.jsx"; diff --git a/client/src/Pages/Account/components/ChangePasswordModal/index.jsx b/client/src/Pages/Account/components/ChangePasswordModal/index.jsx index cc284a675..725a9b00e 100644 --- a/client/src/Pages/Account/components/ChangePasswordModal/index.jsx +++ b/client/src/Pages/Account/components/ChangePasswordModal/index.jsx @@ -2,12 +2,12 @@ import { useState } from "react"; import { Button, Stack } from "@mui/material"; import { GenericDialog } from "@/Components/v1/Dialog/genericDialog"; import TextInput from "@/Components/v1/Inputs/TextInput"; -import PasswordTooltip from "@/Pages/v1/Auth/components/PasswordTooltip"; +import PasswordTooltip from "@/Pages/Auth/components/PasswordTooltip"; import { useTheme } from "@emotion/react"; import { useTranslation } from "react-i18next"; import { createToast } from "../../../../Utils/toastUtils"; import { PasswordEndAdornment } from "@/Components/v1/Inputs/TextInput/Adornments"; -import usePasswordFeedback from "@/Pages/v1/Auth/hooks/usePasswordFeedback"; +import usePasswordFeedback from "@/Pages/Auth/hooks/usePasswordFeedback"; import PropTypes from "prop-types"; const ChangePasswordModal = ({ isSaving, isLoading, changePassword }) => { diff --git a/client/src/Pages/v1/Account/components/PasswordPanel.jsx b/client/src/Pages/Account/components/PasswordPanel.jsx similarity index 95% rename from client/src/Pages/v1/Account/components/PasswordPanel.jsx rename to client/src/Pages/Account/components/PasswordPanel.jsx index ca2af9205..f54c61a16 100644 --- a/client/src/Pages/v1/Account/components/PasswordPanel.jsx +++ b/client/src/Pages/Account/components/PasswordPanel.jsx @@ -4,12 +4,12 @@ import { useTheme } from "@emotion/react"; import { Box, Stack, Typography, Button } from "@mui/material"; import { PasswordEndAdornment } from "@/Components/v1/Inputs/TextInput/Adornments/index.jsx"; import TextInput from "@/Components/v1/Inputs/TextInput/index.jsx"; -import { newOrChangedCredentials } from "../../../../Validation/validation.js"; +import { newOrChangedCredentials } from "../../../Validation/validation.js"; import Alert from "@/Components/v1/Alert/index.jsx"; -import { update } from "../../../../Features/Auth/authSlice.js"; +import { update } from "../../../Features/Auth/authSlice.js"; import { useDispatch, useSelector } from "react-redux"; -import { createToast } from "../../../../Utils/toastUtils.jsx"; -import { getTouchedFieldErrors } from "../../../../Validation/error.js"; +import { createToast } from "../../../Utils/toastUtils.jsx"; +import { getTouchedFieldErrors } from "../../../Validation/error.js"; import { useTranslation } from "react-i18next"; const defaultPasswordsState = { diff --git a/client/src/Pages/v1/Account/components/ProfilePanel.jsx b/client/src/Pages/Account/components/ProfilePanel.jsx similarity index 97% rename from client/src/Pages/v1/Account/components/ProfilePanel.jsx rename to client/src/Pages/Account/components/ProfilePanel.jsx index 2035861a2..d59923ae4 100644 --- a/client/src/Pages/v1/Account/components/ProfilePanel.jsx +++ b/client/src/Pages/Account/components/ProfilePanel.jsx @@ -5,15 +5,11 @@ import { Box, Button, Divider, Stack, Typography } from "@mui/material"; import Avatar from "@/Components/v1/Avatar/index.jsx"; import TextInput from "@/Components/v1/Inputs/TextInput/index.jsx"; import ImageUpload from "@/Components/v1/Inputs/ImageUpload/index.jsx"; -import { newOrChangedCredentials } from "../../../../Validation/validation.js"; +import { newOrChangedCredentials } from "../../../Validation/validation.js"; import { useDispatch, useSelector } from "react-redux"; -import { - clearAuthState, - deleteUser, - update, -} from "../../../../Features/Auth/authSlice.js"; -import { createToast } from "../../../../Utils/toastUtils.jsx"; -import { logger } from "../../../../Utils/Logger.js"; +import { clearAuthState, deleteUser, update } from "../../../Features/Auth/authSlice.js"; +import { createToast } from "../../../Utils/toastUtils.jsx"; +import { logger } from "../../../Utils/Logger.js"; import { GenericDialog } from "@/Components/v1/Dialog/genericDialog.jsx"; import Dialog from "@/Components/v1/Dialog/index.jsx"; import { useTranslation } from "react-i18next"; diff --git a/client/src/Pages/v1/Account/components/RoleTable/index.jsx b/client/src/Pages/Account/components/RoleTable/index.jsx similarity index 93% rename from client/src/Pages/v1/Account/components/RoleTable/index.jsx rename to client/src/Pages/Account/components/RoleTable/index.jsx index 02dcaaf0d..5eea33685 100644 --- a/client/src/Pages/v1/Account/components/RoleTable/index.jsx +++ b/client/src/Pages/Account/components/RoleTable/index.jsx @@ -3,7 +3,7 @@ import DataTable from "@/Components/v1/Table/index.jsx"; import DeleteOutlineRoundedIcon from "@mui/icons-material/DeleteOutlineRounded"; import { useTranslation } from "react-i18next"; -import { ROLES } from "../../../../../Utils/roleUtils.js"; +import { ROLES } from "../../../../Utils/roleUtils.js"; const RoleTable = ({ roles, handleDeleteRole }) => { const { t } = useTranslation(); diff --git a/client/src/Pages/v1/Account/components/TeamPanel.jsx b/client/src/Pages/Account/components/TeamPanel.jsx similarity index 96% rename from client/src/Pages/v1/Account/components/TeamPanel.jsx rename to client/src/Pages/Account/components/TeamPanel.jsx index 02918eb30..03a6145a5 100644 --- a/client/src/Pages/v1/Account/components/TeamPanel.jsx +++ b/client/src/Pages/Account/components/TeamPanel.jsx @@ -4,16 +4,16 @@ import { Button, ButtonGroup, Stack, Typography } from "@mui/material"; import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import TextInput from "@/Components/v1/Inputs/TextInput/index.jsx"; -import { newOrChangedCredentials } from "../../../../Validation/validation.js"; -import { networkService } from "../../../../main.jsx"; -import { createToast } from "../../../../Utils/toastUtils.jsx"; +import { newOrChangedCredentials } from "../../../Validation/validation.js"; +import { networkService } from "../../../main.jsx"; +import { createToast } from "../../../Utils/toastUtils.jsx"; import Select from "@/Components/v1/Inputs/Select/index.jsx"; import { GenericDialog } from "@/Components/v1/Dialog/genericDialog.jsx"; import AddTeamMember from "./AddTeamMember/index.jsx"; import DataTable from "@/Components/v1/Table/index.jsx"; -import { useGetInviteToken } from "../../../../Hooks/v1/inviteHooks.js"; +import { useGetInviteToken } from "../../../Hooks/inviteHooks.js"; import { useNavigate } from "react-router-dom"; -import { useIsSuperAdmin } from "../../../../Hooks/v1/useIsAdmin.js"; +import { useIsSuperAdmin } from "@/Hooks/useIsAdmin.js"; import AddMemberMenu from "./AddMemberMenu/index.jsx"; /** * TeamPanel component manages the organization and team members, diff --git a/client/src/Pages/v1/Account/index.jsx b/client/src/Pages/Account/index.jsx similarity index 100% rename from client/src/Pages/v1/Account/index.jsx rename to client/src/Pages/Account/index.jsx diff --git a/client/src/Pages/v1/Auth/CheckEmail.jsx b/client/src/Pages/Auth/CheckEmail.jsx similarity index 94% rename from client/src/Pages/v1/Auth/CheckEmail.jsx rename to client/src/Pages/Auth/CheckEmail.jsx index c12a84804..6aee7a470 100644 --- a/client/src/Pages/v1/Auth/CheckEmail.jsx +++ b/client/src/Pages/Auth/CheckEmail.jsx @@ -3,12 +3,12 @@ import { useEffect, useState } from "react"; import { useTheme } from "@emotion/react"; import { useDispatch } from "react-redux"; import { useNavigate } from "react-router-dom"; -import { createToast } from "../../../Utils/toastUtils.jsx"; -import { forgotPassword } from "../../../Features/Auth/authSlice.js"; +import { createToast } from "../../Utils/toastUtils.jsx"; +import { forgotPassword } from "../../Features/Auth/authSlice.js"; import { Trans, useTranslation } from "react-i18next"; -import Background from "../../../assets/Images/background-grid.svg?react"; -import EmailIcon from "../../../assets/icons/email.svg?react"; -import Logo from "../../../assets/icons/checkmate-icon.svg?react"; +import Background from "@/assets/Images/background-grid.svg?react"; +import EmailIcon from "@/assets/icons/email.svg?react"; +import Logo from "@/assets/icons/checkmate-icon.svg?react"; import IconBox from "@/Components/v1/IconBox/index.jsx"; import "./index.css"; diff --git a/client/src/Pages/v1/Auth/ForgotPassword.jsx b/client/src/Pages/Auth/ForgotPassword.jsx similarity index 93% rename from client/src/Pages/v1/Auth/ForgotPassword.jsx rename to client/src/Pages/Auth/ForgotPassword.jsx index 8cbd85d8a..0a89b2987 100644 --- a/client/src/Pages/v1/Auth/ForgotPassword.jsx +++ b/client/src/Pages/Auth/ForgotPassword.jsx @@ -1,15 +1,15 @@ import { Box, Stack, Typography, Button } from "@mui/material"; import { useTheme } from "@emotion/react"; -import { createToast } from "../../../Utils/toastUtils.jsx"; +import { createToast } from "../../Utils/toastUtils.jsx"; import { useDispatch, useSelector } from "react-redux"; -import { forgotPassword } from "../../../Features/Auth/authSlice.js"; +import { forgotPassword } from "../../Features/Auth/authSlice.js"; import { useEffect, useState } from "react"; -import { newOrChangedCredentials } from "../../../Validation/validation.js"; +import { newOrChangedCredentials } from "../../Validation/validation.js"; import { useNavigate } from "react-router-dom"; import TextInput from "@/Components/v1/Inputs/TextInput/index.jsx"; -import Logo from "../../../assets/icons/checkmate-icon.svg?react"; -import Key from "../../../assets/icons/key.svg?react"; -import Background from "../../../assets/Images/background-grid.svg?react"; +import Logo from "@/assets/icons/checkmate-icon.svg?react"; +import Key from "@/assets/icons/key.svg?react"; +import Background from "@/assets/Images/background-grid.svg?react"; import IconBox from "@/Components/v1/IconBox/index.jsx"; import { Trans, useTranslation } from "react-i18next"; import "./index.css"; diff --git a/client/src/Pages/v1/Auth/Login/hooks/useLoadingSubmit.jsx b/client/src/Pages/Auth/Login/hooks/useLoadingSubmit.jsx similarity index 100% rename from client/src/Pages/v1/Auth/Login/hooks/useLoadingSubmit.jsx rename to client/src/Pages/Auth/Login/hooks/useLoadingSubmit.jsx diff --git a/client/src/Pages/v1/Auth/Login/hooks/useLoginForm.jsx b/client/src/Pages/Auth/Login/hooks/useLoginForm.jsx similarity index 100% rename from client/src/Pages/v1/Auth/Login/hooks/useLoginForm.jsx rename to client/src/Pages/Auth/Login/hooks/useLoginForm.jsx diff --git a/client/src/Pages/v1/Auth/Login/hooks/useLoginSubmit.jsx b/client/src/Pages/Auth/Login/hooks/useLoginSubmit.jsx similarity index 87% rename from client/src/Pages/v1/Auth/Login/hooks/useLoginSubmit.jsx rename to client/src/Pages/Auth/Login/hooks/useLoginSubmit.jsx index 0eed9bd07..b009793d5 100644 --- a/client/src/Pages/v1/Auth/Login/hooks/useLoginSubmit.jsx +++ b/client/src/Pages/Auth/Login/hooks/useLoginSubmit.jsx @@ -1,7 +1,7 @@ import { useDispatch } from "react-redux"; -import { login } from "../../../../../Features/Auth/authSlice.js"; +import { login } from "../../../../Features/Auth/authSlice.js"; import { useNavigate } from "react-router-dom"; -import { createToast } from "../../../../../Utils/toastUtils.jsx"; +import { createToast } from "../../../../Utils/toastUtils.jsx"; import { useTranslation } from "react-i18next"; const useLoginSubmit = () => { diff --git a/client/src/Pages/v1/Auth/Login/hooks/useValidateLoginForm.jsx b/client/src/Pages/Auth/Login/hooks/useValidateLoginForm.jsx similarity index 90% rename from client/src/Pages/v1/Auth/Login/hooks/useValidateLoginForm.jsx rename to client/src/Pages/Auth/Login/hooks/useValidateLoginForm.jsx index ca9bef879..0872213ad 100644 --- a/client/src/Pages/v1/Auth/Login/hooks/useValidateLoginForm.jsx +++ b/client/src/Pages/Auth/Login/hooks/useValidateLoginForm.jsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { loginCredentials } from "../../../../../Validation/validation.js"; +import { loginCredentials } from "../../../../Validation/validation.js"; const useValidateLoginForm = () => { const [errors, setErrors] = useState({ diff --git a/client/src/Pages/v1/Auth/Login/index.jsx b/client/src/Pages/Auth/Login/index.jsx similarity index 100% rename from client/src/Pages/v1/Auth/Login/index.jsx rename to client/src/Pages/Auth/Login/index.jsx diff --git a/client/src/Pages/v1/Auth/NewPasswordConfirmed.jsx b/client/src/Pages/Auth/NewPasswordConfirmed.jsx similarity index 92% rename from client/src/Pages/v1/Auth/NewPasswordConfirmed.jsx rename to client/src/Pages/Auth/NewPasswordConfirmed.jsx index 629494098..53b352853 100644 --- a/client/src/Pages/v1/Auth/NewPasswordConfirmed.jsx +++ b/client/src/Pages/Auth/NewPasswordConfirmed.jsx @@ -2,10 +2,10 @@ import { Box, Button, Stack, Typography } from "@mui/material"; import { useTheme } from "@emotion/react"; import { useNavigate } from "react-router-dom"; import { useDispatch } from "react-redux"; -import { clearAuthState } from "../../../Features/Auth/authSlice.js"; -import Background from "../../../assets/Images/background-grid.svg?react"; -import ConfirmIcon from "../../../assets/icons/check-outlined.svg?react"; -import Logo from "../../../assets/icons/checkmate-icon.svg?react"; +import { clearAuthState } from "../../Features/Auth/authSlice.js"; +import Background from "@/assets/Images/background-grid.svg?react"; +import ConfirmIcon from "@/assets/icons/check-outlined.svg?react"; +import Logo from "@/assets/icons/checkmate-icon.svg?react"; import IconBox from "@/Components/v1/IconBox/index.jsx"; import { Trans, useTranslation } from "react-i18next"; import "./index.css"; diff --git a/client/src/Pages/v1/Auth/Register/index.jsx b/client/src/Pages/Auth/Register/index.jsx similarity index 97% rename from client/src/Pages/v1/Auth/Register/index.jsx rename to client/src/Pages/Auth/Register/index.jsx index d6515b85c..3345d8aa0 100644 --- a/client/src/Pages/v1/Auth/Register/index.jsx +++ b/client/src/Pages/Auth/Register/index.jsx @@ -13,11 +13,11 @@ import { useState, useEffect } from "react"; import { useNavigate } from "react-router-dom"; import { useDispatch, useSelector } from "react-redux"; import { useParams } from "react-router-dom"; -import { networkService } from "../../../../main.jsx"; -import { newOrChangedCredentials } from "../../../../Validation/validation.js"; -import { register } from "../../../../Features/Auth/authSlice.js"; +import { networkService } from "../../../main.jsx"; +import { newOrChangedCredentials } from "../../../Validation/validation.js"; +import { register } from "../../../Features/Auth/authSlice.js"; import AuthPageWrapper from "../components/AuthPageWrapper.jsx"; -import { createToast } from "../../../../Utils/toastUtils.jsx"; +import { createToast } from "../../../Utils/toastUtils.jsx"; import PropTypes from "prop-types"; const getFeedbackStatus = (form, errors, field, criteria) => { diff --git a/client/src/Pages/v1/Auth/SetNewPassword.jsx b/client/src/Pages/Auth/SetNewPassword.jsx similarity index 95% rename from client/src/Pages/v1/Auth/SetNewPassword.jsx rename to client/src/Pages/Auth/SetNewPassword.jsx index 45f3351f3..6525c3f27 100644 --- a/client/src/Pages/v1/Auth/SetNewPassword.jsx +++ b/client/src/Pages/Auth/SetNewPassword.jsx @@ -4,16 +4,16 @@ import { useNavigate } from "react-router-dom"; import { useParams } from "react-router-dom"; import { useTheme } from "@emotion/react"; import { Box, Stack, Typography, Button } from "@mui/material"; -import { setNewPassword } from "../../../Features/Auth/authSlice.js"; -import { createToast } from "../../../Utils/toastUtils.jsx"; -import { newOrChangedCredentials } from "../../../Validation/validation.js"; +import { setNewPassword } from "../../Features/Auth/authSlice.js"; +import { createToast } from "../../Utils/toastUtils.jsx"; +import { newOrChangedCredentials } from "../../Validation/validation.js"; import Check from "@/Components/v1/Check/Check.jsx"; import TextInput from "@/Components/v1/Inputs/TextInput/index.jsx"; import { PasswordEndAdornment } from "@/Components/v1/Inputs/TextInput/Adornments/index.jsx"; import IconBox from "@/Components/v1/IconBox/index.jsx"; -import LockIcon from "../../../assets/icons/lock.svg?react"; -import Logo from "../../../assets/icons/checkmate-icon.svg?react"; -import Background from "../../../assets/Images/background-grid.svg?react"; +import LockIcon from "@/assets/icons/lock.svg?react"; +import Logo from "@/assets/icons/checkmate-icon.svg?react"; +import Background from "@/assets/Images/background-grid.svg?react"; import "./index.css"; import { useValidatePassword } from "./hooks/useValidatePassword.jsx"; import { Trans, useTranslation } from "react-i18next"; diff --git a/client/src/Pages/v1/Auth/components/AuthHeader.jsx b/client/src/Pages/Auth/components/AuthHeader.jsx similarity index 87% rename from client/src/Pages/v1/Auth/components/AuthHeader.jsx rename to client/src/Pages/Auth/components/AuthHeader.jsx index a34e83d6a..56b69ef14 100644 --- a/client/src/Pages/v1/Auth/components/AuthHeader.jsx +++ b/client/src/Pages/Auth/components/AuthHeader.jsx @@ -1,8 +1,8 @@ // Components import Stack from "@mui/material/Stack"; import Typography from "@mui/material/Typography"; -import Logo from "../../../../assets/icons/checkmate-icon.svg?react"; -import LanguageSelector from "../../../../Components/LanguageSelector.jsx"; +import Logo from "@/assets/icons/checkmate-icon.svg?react"; +import LanguageSelector from "@/Components/LanguageSelector.jsx"; import ThemeSwitch from "@/Components/v1/ThemeSwitch/index.jsx"; // Utils diff --git a/client/src/Pages/v1/Auth/components/AuthPageWrapper.jsx b/client/src/Pages/Auth/components/AuthPageWrapper.jsx similarity index 93% rename from client/src/Pages/v1/Auth/components/AuthPageWrapper.jsx rename to client/src/Pages/Auth/components/AuthPageWrapper.jsx index 7e358e6ab..a5fbe311b 100644 --- a/client/src/Pages/v1/Auth/components/AuthPageWrapper.jsx +++ b/client/src/Pages/Auth/components/AuthPageWrapper.jsx @@ -1,10 +1,10 @@ -import Background from "../../../../assets/Images/background-grid.svg?react"; +import Background from "@/assets/Images/background-grid.svg?react"; import Stack from "@mui/material/Stack"; import Box from "@mui/material/Box"; import Typography from "@mui/material/Typography"; import AuthHeader from "./AuthHeader.jsx"; import { useTheme } from "@mui/material/styles"; -import Logo from "../../../../assets/icons/checkmate-icon.svg?react"; +import Logo from "@/assets/icons/checkmate-icon.svg?react"; import PropTypes from "prop-types"; const AuthPageWrapper = ({ children, heading, welcome }) => { diff --git a/client/src/Pages/v1/Auth/components/PasswordTooltip.jsx b/client/src/Pages/Auth/components/PasswordTooltip.jsx similarity index 100% rename from client/src/Pages/v1/Auth/components/PasswordTooltip.jsx rename to client/src/Pages/Auth/components/PasswordTooltip.jsx diff --git a/client/src/Pages/v1/Auth/hooks/usePasswordFeedback.jsx b/client/src/Pages/Auth/hooks/usePasswordFeedback.jsx similarity index 96% rename from client/src/Pages/v1/Auth/hooks/usePasswordFeedback.jsx rename to client/src/Pages/Auth/hooks/usePasswordFeedback.jsx index 3c199e25f..73e8fb738 100644 --- a/client/src/Pages/v1/Auth/hooks/usePasswordFeedback.jsx +++ b/client/src/Pages/Auth/hooks/usePasswordFeedback.jsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { newOrChangedCredentials } from "../../../../Validation/validation.js"; +import { newOrChangedCredentials } from "../../../Validation/validation.js"; const usePasswordFeedback = () => { const [feedback, setFeedback] = useState({}); diff --git a/client/src/Pages/v1/Auth/hooks/useValidatePassword.jsx b/client/src/Pages/Auth/hooks/useValidatePassword.jsx similarity index 96% rename from client/src/Pages/v1/Auth/hooks/useValidatePassword.jsx rename to client/src/Pages/Auth/hooks/useValidatePassword.jsx index 231b8eeb8..014804d35 100644 --- a/client/src/Pages/v1/Auth/hooks/useValidatePassword.jsx +++ b/client/src/Pages/Auth/hooks/useValidatePassword.jsx @@ -1,5 +1,5 @@ import { useMemo, useState } from "react"; -import { newOrChangedCredentials } from "../../../../Validation/validation.js"; +import { newOrChangedCredentials } from "../../../Validation/validation.js"; const getFeedbackStatus = (form, errors, field, criteria) => { const fieldErrors = errors[field]; diff --git a/client/src/Pages/v1/Auth/index.css b/client/src/Pages/Auth/index.css similarity index 100% rename from client/src/Pages/v1/Auth/index.css rename to client/src/Pages/Auth/index.css diff --git a/client/src/Pages/v1/Incidents/Components/IncidentTable/index.jsx b/client/src/Pages/Incidents/Components/IncidentTable/index.jsx similarity index 95% rename from client/src/Pages/v1/Incidents/Components/IncidentTable/index.jsx rename to client/src/Pages/Incidents/Components/IncidentTable/index.jsx index df457c0e2..78d6d26be 100644 --- a/client/src/Pages/v1/Incidents/Components/IncidentTable/index.jsx +++ b/client/src/Pages/Incidents/Components/IncidentTable/index.jsx @@ -13,14 +13,12 @@ import GenericFallback from "@/Components/v1/GenericFallback/index.jsx"; import NetworkError from "@/Components/v1/GenericFallback/NetworkError.jsx"; //Utils -import { formatDateWithTz } from "../../../../../Utils/timeUtils.js"; +import { formatDateWithTz } from "@/Utils/timeUtils.js"; import { useSelector } from "react-redux"; import { useState } from "react"; import PropTypes from "prop-types"; import { useTranslation } from "react-i18next"; -import { useFetchChecksTeam } from "../../../../../Hooks/v1/checkHooks.js"; -import { useFetchChecksByMonitor } from "../../../../../Hooks/v1/checkHooks.js"; -import { useResolveIncident } from "../../../../../Hooks/v1/checkHooks.js"; +import { useFetchChecksTeam, useFetchChecksByMonitor, useResolveIncident } from "@/Hooks/checkHooks.js"; import { Button, Typography, useTheme } from "@mui/material"; import { lighten } from "@mui/material/styles"; diff --git a/client/src/Pages/v1/Incidents/Components/OptionsHeader/index.jsx b/client/src/Pages/Incidents/Components/OptionsHeader/index.jsx similarity index 100% rename from client/src/Pages/v1/Incidents/Components/OptionsHeader/index.jsx rename to client/src/Pages/Incidents/Components/OptionsHeader/index.jsx diff --git a/client/src/Pages/v1/Incidents/Components/OptionsHeader/skeleton.jsx b/client/src/Pages/Incidents/Components/OptionsHeader/skeleton.jsx similarity index 100% rename from client/src/Pages/v1/Incidents/Components/OptionsHeader/skeleton.jsx rename to client/src/Pages/Incidents/Components/OptionsHeader/skeleton.jsx diff --git a/client/src/Pages/v1/Incidents/Components/StatusBoxes/StatusBox.jsx b/client/src/Pages/Incidents/Components/StatusBoxes/StatusBox.jsx similarity index 87% rename from client/src/Pages/v1/Incidents/Components/StatusBoxes/StatusBox.jsx rename to client/src/Pages/Incidents/Components/StatusBoxes/StatusBox.jsx index cd7078e6c..c27c5948c 100644 --- a/client/src/Pages/v1/Incidents/Components/StatusBoxes/StatusBox.jsx +++ b/client/src/Pages/Incidents/Components/StatusBoxes/StatusBox.jsx @@ -1,11 +1,11 @@ import PropTypes from "prop-types"; import { useTheme } from "@emotion/react"; import { Box, Stack, Typography } from "@mui/material"; -import Background from "../../../../../assets/Images/background-grid.svg?react"; -import AlertIcon from "../../../../../assets/icons/alert-icon.svg?react"; -import CheckIcon from "../../../../../assets/icons/check-icon.svg?react"; -import CloseIcon from "../../../../../assets/icons/close-icon.svg?react"; -import WarningIcon from "../../../../../assets/icons/warning-icon.svg?react"; +import Background from "@/assets/Images/background-grid.svg?react"; +import AlertIcon from "@/assets/icons/alert-icon.svg?react"; +import CheckIcon from "@/assets/icons/check-icon.svg?react"; +import CloseIcon from "@/assets/icons/close-icon.svg?react"; +import WarningIcon from "@/assets/icons/warning-icon.svg?react"; const StatusBox = ({ title, value, status }) => { const theme = useTheme(); diff --git a/client/src/Pages/v1/Incidents/Components/StatusBoxes/index.jsx b/client/src/Pages/Incidents/Components/StatusBoxes/index.jsx similarity index 100% rename from client/src/Pages/v1/Incidents/Components/StatusBoxes/index.jsx rename to client/src/Pages/Incidents/Components/StatusBoxes/index.jsx diff --git a/client/src/Pages/v1/Incidents/Components/StatusBoxes/skeleton.jsx b/client/src/Pages/Incidents/Components/StatusBoxes/skeleton.jsx similarity index 100% rename from client/src/Pages/v1/Incidents/Components/StatusBoxes/skeleton.jsx rename to client/src/Pages/Incidents/Components/StatusBoxes/skeleton.jsx diff --git a/client/src/Pages/v1/Incidents/index.jsx b/client/src/Pages/Incidents/index.jsx similarity index 93% rename from client/src/Pages/v1/Incidents/index.jsx rename to client/src/Pages/Incidents/index.jsx index 91cab2a40..c8462f649 100644 --- a/client/src/Pages/v1/Incidents/index.jsx +++ b/client/src/Pages/Incidents/index.jsx @@ -9,9 +9,8 @@ import { Box, Button } from "@mui/material"; //Utils import { useTheme } from "@emotion/react"; -import { useFetchMonitorsByTeamId } from "../../../Hooks/v1/monitorHooks.js"; -import { useFetchChecksSummaryByTeamId } from "../../../Hooks/v1/checkHooks.js"; -import { useAcknowledgeChecks } from "../../../Hooks/v1/checkHooks.js"; +import { useFetchMonitorsByTeamId } from "@/Hooks/monitorHooks.js"; +import { useFetchChecksSummaryByTeamId, useAcknowledgeChecks } from "@/Hooks/checkHooks.js"; import { useState, useEffect } from "react"; import NetworkError from "@/Components/v1/GenericFallback/NetworkError.jsx"; import { useTranslation } from "react-i18next"; diff --git a/client/src/Pages/v1/Incidents2/Components/ActiveIncidentsPanel/index.jsx b/client/src/Pages/Incidents2/Components/ActiveIncidentsPanel/index.jsx similarity index 100% rename from client/src/Pages/v1/Incidents2/Components/ActiveIncidentsPanel/index.jsx rename to client/src/Pages/Incidents2/Components/ActiveIncidentsPanel/index.jsx diff --git a/client/src/Pages/v1/Incidents2/Components/IncidentTable/index.jsx b/client/src/Pages/Incidents2/Components/IncidentTable/index.jsx similarity index 98% rename from client/src/Pages/v1/Incidents2/Components/IncidentTable/index.jsx rename to client/src/Pages/Incidents2/Components/IncidentTable/index.jsx index 8cac4e07b..d613e15c7 100644 --- a/client/src/Pages/v1/Incidents2/Components/IncidentTable/index.jsx +++ b/client/src/Pages/Incidents2/Components/IncidentTable/index.jsx @@ -8,7 +8,7 @@ import GenericFallback from "@/Components/v1/GenericFallback/index.jsx"; import NetworkError from "@/Components/v1/GenericFallback/NetworkError.jsx"; //Utils -import { formatDateWithTz } from "../../../../../Utils/timeUtils.js"; +import { formatDateWithTz } from "../../../../Utils/timeUtils.js"; import { useSelector } from "react-redux"; import PropTypes from "prop-types"; import { useTranslation } from "react-i18next"; diff --git a/client/src/Pages/v1/Incidents2/Components/IncidentsSummaryPanel/index.jsx b/client/src/Pages/Incidents2/Components/IncidentsSummaryPanel/index.jsx similarity index 100% rename from client/src/Pages/v1/Incidents2/Components/IncidentsSummaryPanel/index.jsx rename to client/src/Pages/Incidents2/Components/IncidentsSummaryPanel/index.jsx diff --git a/client/src/Pages/v1/Incidents2/Components/IncidentsSummaryPanel/skeleton.jsx b/client/src/Pages/Incidents2/Components/IncidentsSummaryPanel/skeleton.jsx similarity index 100% rename from client/src/Pages/v1/Incidents2/Components/IncidentsSummaryPanel/skeleton.jsx rename to client/src/Pages/Incidents2/Components/IncidentsSummaryPanel/skeleton.jsx diff --git a/client/src/Pages/v1/Incidents2/Components/LatestIncidentsPanel/IncidentItem.jsx b/client/src/Pages/Incidents2/Components/LatestIncidentsPanel/IncidentItem.jsx similarity index 100% rename from client/src/Pages/v1/Incidents2/Components/LatestIncidentsPanel/IncidentItem.jsx rename to client/src/Pages/Incidents2/Components/LatestIncidentsPanel/IncidentItem.jsx diff --git a/client/src/Pages/v1/Incidents2/Components/LatestIncidentsPanel/index.jsx b/client/src/Pages/Incidents2/Components/LatestIncidentsPanel/index.jsx similarity index 100% rename from client/src/Pages/v1/Incidents2/Components/LatestIncidentsPanel/index.jsx rename to client/src/Pages/Incidents2/Components/LatestIncidentsPanel/index.jsx diff --git a/client/src/Pages/v1/Incidents2/Components/OptionsHeader/index.jsx b/client/src/Pages/Incidents2/Components/OptionsHeader/index.jsx similarity index 100% rename from client/src/Pages/v1/Incidents2/Components/OptionsHeader/index.jsx rename to client/src/Pages/Incidents2/Components/OptionsHeader/index.jsx diff --git a/client/src/Pages/v1/Incidents2/Components/StatisticsPanel/index.jsx b/client/src/Pages/Incidents2/Components/StatisticsPanel/index.jsx similarity index 100% rename from client/src/Pages/v1/Incidents2/Components/StatisticsPanel/index.jsx rename to client/src/Pages/Incidents2/Components/StatisticsPanel/index.jsx diff --git a/client/src/Pages/v1/Incidents2/Components/SummaryCard/index.jsx b/client/src/Pages/Incidents2/Components/SummaryCard/index.jsx similarity index 100% rename from client/src/Pages/v1/Incidents2/Components/SummaryCard/index.jsx rename to client/src/Pages/Incidents2/Components/SummaryCard/index.jsx diff --git a/client/src/Pages/v1/Incidents2/hooks/useFetchIncidents.js b/client/src/Pages/Incidents2/hooks/useFetchIncidents.js similarity index 97% rename from client/src/Pages/v1/Incidents2/hooks/useFetchIncidents.js rename to client/src/Pages/Incidents2/hooks/useFetchIncidents.js index a67f6b7ee..ab22c42e0 100644 --- a/client/src/Pages/v1/Incidents2/hooks/useFetchIncidents.js +++ b/client/src/Pages/Incidents2/hooks/useFetchIncidents.js @@ -1,6 +1,6 @@ import { useState, useCallback } from "react"; -import { networkService } from "../../../../main.jsx"; -import { createToast } from "../../../../Utils/toastUtils.jsx"; +import { networkService } from "../../../main.jsx"; +import { createToast } from "../../../Utils/toastUtils.jsx"; import { useTranslation } from "react-i18next"; /** * Hook to fetch and manage incidents diff --git a/client/src/Pages/v1/Incidents2/index.jsx b/client/src/Pages/Incidents2/index.jsx similarity index 97% rename from client/src/Pages/v1/Incidents2/index.jsx rename to client/src/Pages/Incidents2/index.jsx index 2983a38e8..eda68d976 100644 --- a/client/src/Pages/v1/Incidents2/index.jsx +++ b/client/src/Pages/Incidents2/index.jsx @@ -14,7 +14,7 @@ import { useTranslation } from "react-i18next"; // Hooks import useFetchIncidents from "./hooks/useFetchIncidents.js"; -import { useFetchMonitorsByTeamId } from "../../../Hooks/v1/monitorHooks.js"; +import { useFetchMonitorsByTeamId } from "../../Hooks/monitorHooks.js"; const Incidents2 = () => { const { t } = useTranslation(); diff --git a/client/src/Pages/v1/Infrastructure/Create/Components/CustomAlertsSection.jsx b/client/src/Pages/Infrastructure/Create/Components/CustomAlertsSection.jsx similarity index 96% rename from client/src/Pages/v1/Infrastructure/Create/Components/CustomAlertsSection.jsx rename to client/src/Pages/Infrastructure/Create/Components/CustomAlertsSection.jsx index 5fe1d8984..64f82cec2 100644 --- a/client/src/Pages/v1/Infrastructure/Create/Components/CustomAlertsSection.jsx +++ b/client/src/Pages/Infrastructure/Create/Components/CustomAlertsSection.jsx @@ -1,7 +1,7 @@ import ConfigBox from "@/Components/v1/ConfigBox/index.jsx"; import { Box, Stack, Typography } from "@mui/material"; import { CustomThreshold } from "./CustomThreshold/index.jsx"; -import { capitalizeFirstLetter } from "../../../../../Utils/stringUtils.js"; +import { capitalizeFirstLetter } from "../../../../Utils/stringUtils.js"; import { useTheme } from "@emotion/react"; import { useTranslation } from "react-i18next"; import PropTypes from "prop-types"; diff --git a/client/src/Pages/v1/Infrastructure/Create/Components/CustomThreshold/index.jsx b/client/src/Pages/Infrastructure/Create/Components/CustomThreshold/index.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Create/Components/CustomThreshold/index.jsx rename to client/src/Pages/Infrastructure/Create/Components/CustomThreshold/index.jsx diff --git a/client/src/Pages/v1/Infrastructure/Create/Components/DiskSelection.jsx b/client/src/Pages/Infrastructure/Create/Components/DiskSelection.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Create/Components/DiskSelection.jsx rename to client/src/Pages/Infrastructure/Create/Components/DiskSelection.jsx diff --git a/client/src/Pages/v1/Infrastructure/Create/Components/MonitorActionButtons.jsx b/client/src/Pages/Infrastructure/Create/Components/MonitorActionButtons.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Create/Components/MonitorActionButtons.jsx rename to client/src/Pages/Infrastructure/Create/Components/MonitorActionButtons.jsx diff --git a/client/src/Pages/v1/Infrastructure/Create/Components/MonitorStatusHeader.jsx b/client/src/Pages/Infrastructure/Create/Components/MonitorStatusHeader.jsx similarity index 95% rename from client/src/Pages/v1/Infrastructure/Create/Components/MonitorStatusHeader.jsx rename to client/src/Pages/Infrastructure/Create/Components/MonitorStatusHeader.jsx index 570f38a7e..8fa6f4ff1 100644 --- a/client/src/Pages/v1/Infrastructure/Create/Components/MonitorStatusHeader.jsx +++ b/client/src/Pages/Infrastructure/Create/Components/MonitorStatusHeader.jsx @@ -1,5 +1,5 @@ import { Box, Stack, Tooltip, Typography } from "@mui/material"; -import { useMonitorUtils } from "../../../../../Hooks/v1/useMonitorUtils.js"; +import { useMonitorUtils } from "../../../../Hooks/useMonitorUtils.js"; import { useTheme } from "@emotion/react"; import { useTranslation } from "react-i18next"; import PulseDot from "@/Components/v1/Animated/PulseDot.jsx"; diff --git a/client/src/Pages/v1/Infrastructure/Create/hooks/useInfrastructureMonitorForm.jsx b/client/src/Pages/Infrastructure/Create/hooks/useInfrastructureMonitorForm.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Create/hooks/useInfrastructureMonitorForm.jsx rename to client/src/Pages/Infrastructure/Create/hooks/useInfrastructureMonitorForm.jsx diff --git a/client/src/Pages/v1/Infrastructure/Create/hooks/useInfrastructureSubmit.jsx b/client/src/Pages/Infrastructure/Create/hooks/useInfrastructureSubmit.jsx similarity index 96% rename from client/src/Pages/v1/Infrastructure/Create/hooks/useInfrastructureSubmit.jsx rename to client/src/Pages/Infrastructure/Create/hooks/useInfrastructureSubmit.jsx index 15a5f3c5d..c5c7aacf2 100644 --- a/client/src/Pages/v1/Infrastructure/Create/hooks/useInfrastructureSubmit.jsx +++ b/client/src/Pages/Infrastructure/Create/hooks/useInfrastructureSubmit.jsx @@ -1,7 +1,4 @@ -import { - useCreateMonitor, - useUpdateMonitor, -} from "../../../../../Hooks/v1/monitorHooks.js"; +import { useCreateMonitor, useUpdateMonitor } from "../../../../Hooks/monitorHooks.js"; const useInfrastructureSubmit = () => { const [createMonitor, isCreating] = useCreateMonitor(); const [updateMonitor, isUpdating] = useUpdateMonitor(); diff --git a/client/src/Pages/v1/Infrastructure/Create/hooks/useValidateInfrastructureForm.jsx b/client/src/Pages/Infrastructure/Create/hooks/useValidateInfrastructureForm.jsx similarity index 85% rename from client/src/Pages/v1/Infrastructure/Create/hooks/useValidateInfrastructureForm.jsx rename to client/src/Pages/Infrastructure/Create/hooks/useValidateInfrastructureForm.jsx index 73097d0d8..f7665e65f 100644 --- a/client/src/Pages/v1/Infrastructure/Create/hooks/useValidateInfrastructureForm.jsx +++ b/client/src/Pages/Infrastructure/Create/hooks/useValidateInfrastructureForm.jsx @@ -1,6 +1,6 @@ import { useState } from "react"; -import { infrastructureMonitorValidation } from "../../../../../Validation/validation.js"; -import { createToast } from "../../../../../Utils/toastUtils.jsx"; +import { infrastructureMonitorValidation } from "../../../../Validation/validation.js"; +import { createToast } from "../../../../Utils/toastUtils.jsx"; const useValidateInfrastructureForm = () => { const [errors, setErrors] = useState({}); diff --git a/client/src/Pages/v1/Infrastructure/Create/index.jsx b/client/src/Pages/Infrastructure/Create/index.jsx similarity index 97% rename from client/src/Pages/v1/Infrastructure/Create/index.jsx rename to client/src/Pages/Infrastructure/Create/index.jsx index c74d49816..b27c11cd4 100644 --- a/client/src/Pages/v1/Infrastructure/Create/index.jsx +++ b/client/src/Pages/Infrastructure/Create/index.jsx @@ -13,8 +13,8 @@ import CustomAlertsSection from "./Components/CustomAlertsSection.jsx"; import DiskSelection from "./Components/DiskSelection.jsx"; // Utils import NotificationsConfig from "@/Components/v1/NotificationConfig/index.jsx"; -import { useGetNotificationsByTeamId } from "../../../../Hooks/v1/useNotifications.js"; -import { networkService } from "../../../../Utils/NetworkService"; +import { useGetNotificationsByTeamId } from "../../../Hooks/useNotifications.js"; +import { networkService } from "../../../Utils/NetworkService.js"; import { useParams } from "react-router-dom"; import { useState, useEffect } from "react"; import { useTheme } from "@emotion/react"; @@ -24,7 +24,7 @@ import { useFetchGlobalSettings, useFetchHardwareMonitorById, usePauseMonitor, -} from "../../../../Hooks/v1/monitorHooks.js"; +} from "../../../Hooks/monitorHooks.js"; import useInfrastructureMonitorForm from "./hooks/useInfrastructureMonitorForm.jsx"; import useValidateInfrastructureForm from "./hooks/useValidateInfrastructureForm.jsx"; import useInfrastructureSubmit from "./hooks/useInfrastructureSubmit.jsx"; @@ -150,7 +150,8 @@ const CreateInfrastructureMonitor = () => { const handleRemove = async (event) => { event.preventDefault(); - await deleteMonitor({ monitor, redirect: "/infrastructure" }); + const TEMP_MONITOR = { id: monitor._id }; + await deleteMonitor({ monitor: TEMP_MONITOR, redirect: "/infrastructure" }); }; const isBusy = diff --git a/client/src/Pages/v1/Infrastructure/Details/Components/AreaChartBoxes/InfraAreaChart.jsx b/client/src/Pages/Infrastructure/Details/Components/AreaChartBoxes/InfraAreaChart.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Details/Components/AreaChartBoxes/InfraAreaChart.jsx rename to client/src/Pages/Infrastructure/Details/Components/AreaChartBoxes/InfraAreaChart.jsx diff --git a/client/src/Pages/v1/Infrastructure/Details/Components/AreaChartBoxes/index.jsx b/client/src/Pages/Infrastructure/Details/Components/AreaChartBoxes/index.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Details/Components/AreaChartBoxes/index.jsx rename to client/src/Pages/Infrastructure/Details/Components/AreaChartBoxes/index.jsx diff --git a/client/src/Pages/v1/Infrastructure/Details/Components/AreaChartBoxes/skeleton.jsx b/client/src/Pages/Infrastructure/Details/Components/AreaChartBoxes/skeleton.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Details/Components/AreaChartBoxes/skeleton.jsx rename to client/src/Pages/Infrastructure/Details/Components/AreaChartBoxes/skeleton.jsx diff --git a/client/src/Pages/v1/Infrastructure/Details/Components/BaseContainer/index.jsx b/client/src/Pages/Infrastructure/Details/Components/BaseContainer/index.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Details/Components/BaseContainer/index.jsx rename to client/src/Pages/Infrastructure/Details/Components/BaseContainer/index.jsx diff --git a/client/src/Pages/v1/Infrastructure/Details/Components/GaugeBoxes/Gauge.jsx b/client/src/Pages/Infrastructure/Details/Components/GaugeBoxes/Gauge.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Details/Components/GaugeBoxes/Gauge.jsx rename to client/src/Pages/Infrastructure/Details/Components/GaugeBoxes/Gauge.jsx diff --git a/client/src/Pages/v1/Infrastructure/Details/Components/GaugeBoxes/index.jsx b/client/src/Pages/Infrastructure/Details/Components/GaugeBoxes/index.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Details/Components/GaugeBoxes/index.jsx rename to client/src/Pages/Infrastructure/Details/Components/GaugeBoxes/index.jsx diff --git a/client/src/Pages/v1/Infrastructure/Details/Components/GaugeBoxes/skeleton.jsx b/client/src/Pages/Infrastructure/Details/Components/GaugeBoxes/skeleton.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Details/Components/GaugeBoxes/skeleton.jsx rename to client/src/Pages/Infrastructure/Details/Components/GaugeBoxes/skeleton.jsx diff --git a/client/src/Pages/v1/Infrastructure/Details/Components/NetworkStats/NetworkCharts.jsx b/client/src/Pages/Infrastructure/Details/Components/NetworkStats/NetworkCharts.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Details/Components/NetworkStats/NetworkCharts.jsx rename to client/src/Pages/Infrastructure/Details/Components/NetworkStats/NetworkCharts.jsx diff --git a/client/src/Pages/v1/Infrastructure/Details/Components/NetworkStats/NetworkStatBoxes.jsx b/client/src/Pages/Infrastructure/Details/Components/NetworkStats/NetworkStatBoxes.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Details/Components/NetworkStats/NetworkStatBoxes.jsx rename to client/src/Pages/Infrastructure/Details/Components/NetworkStats/NetworkStatBoxes.jsx diff --git a/client/src/Pages/v1/Infrastructure/Details/Components/NetworkStats/index.jsx b/client/src/Pages/Infrastructure/Details/Components/NetworkStats/index.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Details/Components/NetworkStats/index.jsx rename to client/src/Pages/Infrastructure/Details/Components/NetworkStats/index.jsx diff --git a/client/src/Pages/v1/Infrastructure/Details/Components/NetworkStats/skeleton.jsx b/client/src/Pages/Infrastructure/Details/Components/NetworkStats/skeleton.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Details/Components/NetworkStats/skeleton.jsx rename to client/src/Pages/Infrastructure/Details/Components/NetworkStats/skeleton.jsx diff --git a/client/src/Pages/v1/Infrastructure/Details/Components/StatusBoxes/index.jsx b/client/src/Pages/Infrastructure/Details/Components/StatusBoxes/index.jsx similarity index 97% rename from client/src/Pages/v1/Infrastructure/Details/Components/StatusBoxes/index.jsx rename to client/src/Pages/Infrastructure/Details/Components/StatusBoxes/index.jsx index 7f09e82d5..ef91709cf 100644 --- a/client/src/Pages/v1/Infrastructure/Details/Components/StatusBoxes/index.jsx +++ b/client/src/Pages/Infrastructure/Details/Components/StatusBoxes/index.jsx @@ -4,7 +4,7 @@ import StatusBoxes from "@/Components/v1/StatusBoxes/index.jsx"; import StatBox from "@/Components/v1/StatBox/index.jsx"; //Utils -import { useMonitorUtils } from "../../../../../../Hooks/v1/useMonitorUtils.js"; +import { useMonitorUtils } from "../../../../../Hooks/useMonitorUtils.js"; import { useHardwareUtils } from "../../Hooks/useHardwareUtils.jsx"; import { useTranslation } from "react-i18next"; diff --git a/client/src/Pages/v1/Infrastructure/Details/Hooks/useHardwareUtils.jsx b/client/src/Pages/Infrastructure/Details/Hooks/useHardwareUtils.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Details/Hooks/useHardwareUtils.jsx rename to client/src/Pages/Infrastructure/Details/Hooks/useHardwareUtils.jsx diff --git a/client/src/Pages/v1/Infrastructure/Details/index.jsx b/client/src/Pages/Infrastructure/Details/index.jsx similarity index 96% rename from client/src/Pages/v1/Infrastructure/Details/index.jsx rename to client/src/Pages/Infrastructure/Details/index.jsx index f9c51c27d..62a5c2642 100644 --- a/client/src/Pages/v1/Infrastructure/Details/index.jsx +++ b/client/src/Pages/Infrastructure/Details/index.jsx @@ -13,8 +13,8 @@ import TabContext from "@mui/lab/TabContext"; // Utils import { useTheme } from "@emotion/react"; -import { useIsAdmin } from "../../../../Hooks/v1/useIsAdmin.js"; -import { useFetchHardwareMonitorById } from "../../../../Hooks/v1/monitorHooks.js"; +import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; +import { useFetchHardwareMonitorById } from "../../../Hooks/monitorHooks.js"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { useParams } from "react-router-dom"; diff --git a/client/src/Pages/v1/Infrastructure/Monitors/Components/Filters/index.jsx b/client/src/Pages/Infrastructure/Monitors/Components/Filters/index.jsx similarity index 100% rename from client/src/Pages/v1/Infrastructure/Monitors/Components/Filters/index.jsx rename to client/src/Pages/Infrastructure/Monitors/Components/Filters/index.jsx diff --git a/client/src/Pages/v1/Infrastructure/Monitors/Components/MonitorsTable/index.jsx b/client/src/Pages/Infrastructure/Monitors/Components/MonitorsTable/index.jsx similarity index 95% rename from client/src/Pages/v1/Infrastructure/Monitors/Components/MonitorsTable/index.jsx rename to client/src/Pages/Infrastructure/Monitors/Components/MonitorsTable/index.jsx index cc2cd5f98..510115d8a 100644 --- a/client/src/Pages/v1/Infrastructure/Monitors/Components/MonitorsTable/index.jsx +++ b/client/src/Pages/Infrastructure/Monitors/Components/MonitorsTable/index.jsx @@ -7,12 +7,12 @@ import { Stack } from "@mui/material"; import { InfrastructureMenu } from "../MonitorsTableMenu/index.jsx"; import LoadingSpinner from "../../../../Uptime/Monitors/Components/LoadingSpinner/index.jsx"; // Assets -import CPUChipIcon from "../../../../../../assets/icons/cpu-chip.svg?react"; +import CPUChipIcon from "@/assets/icons/cpu-chip.svg?react"; import CustomGauge from "@/Components/v1/Charts/CustomGauge/index.jsx"; // Utils import { useTheme } from "@emotion/react"; -import { useMonitorUtils } from "../../../../../../Hooks/v1/useMonitorUtils.js"; +import { useMonitorUtils } from "../../../../../Hooks/useMonitorUtils.js"; import { useNavigate } from "react-router-dom"; import PropTypes from "prop-types"; import { useTranslation } from "react-i18next"; diff --git a/client/src/Pages/v1/Infrastructure/Monitors/Components/MonitorsTableMenu/index.jsx b/client/src/Pages/Infrastructure/Monitors/Components/MonitorsTableMenu/index.jsx similarity index 94% rename from client/src/Pages/v1/Infrastructure/Monitors/Components/MonitorsTableMenu/index.jsx rename to client/src/Pages/Infrastructure/Monitors/Components/MonitorsTableMenu/index.jsx index d3af34d00..39aa84e90 100644 --- a/client/src/Pages/v1/Infrastructure/Monitors/Components/MonitorsTableMenu/index.jsx +++ b/client/src/Pages/Infrastructure/Monitors/Components/MonitorsTableMenu/index.jsx @@ -3,13 +3,13 @@ import { useRef, useState } from "react"; import { useTheme } from "@emotion/react"; import { useNavigate } from "react-router-dom"; -import { createToast } from "../../../../../../Utils/toastUtils.jsx"; +import { createToast } from "@/Utils/toastUtils.jsx"; import { IconButton, Menu, MenuItem } from "@mui/material"; -import Settings from "../../../../../../assets/icons/settings-bold.svg?react"; +import Settings from "@/assets/icons/settings-bold.svg?react"; import PropTypes from "prop-types"; import Dialog from "@/Components/v1/Dialog/index.jsx"; -import { networkService } from "../../../../../../Utils/NetworkService.js"; -import { usePauseMonitor } from "../../../../../../Hooks/v1/monitorHooks.js"; +import { networkService } from "@/Utils/NetworkService.js"; +import { usePauseMonitor } from "@/Hooks/monitorHooks.js"; import { useTranslation } from "react-i18next"; /** diff --git a/client/src/Pages/v1/Infrastructure/Monitors/index.jsx b/client/src/Pages/Infrastructure/Monitors/index.jsx similarity index 94% rename from client/src/Pages/v1/Infrastructure/Monitors/index.jsx rename to client/src/Pages/Infrastructure/Monitors/index.jsx index 6c3a657ab..90817f116 100644 --- a/client/src/Pages/v1/Infrastructure/Monitors/index.jsx +++ b/client/src/Pages/Infrastructure/Monitors/index.jsx @@ -11,11 +11,11 @@ import SearchComponent from "../../Uptime/Monitors/Components/SearchComponent/in // Utils import { useTheme } from "@emotion/react"; import { useEffect, useState } from "react"; -import { useIsAdmin } from "../../../../Hooks/v1/useIsAdmin.js"; +import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; import { useTranslation } from "react-i18next"; -import { useFetchMonitorsByTeamId } from "../../../../Hooks/v1/monitorHooks.js"; +import { useFetchMonitorsByTeamId } from "../../../Hooks/monitorHooks.js"; import { useDispatch, useSelector } from "react-redux"; -import { setRowsPerPage } from "../../../../Features/UI/uiSlice.js"; +import { setRowsPerPage } from "../../../Features/UI/uiSlice.js"; // Constants const TYPES = ["hardware"]; const BREADCRUMBS = [{ name: `infrastructure`, path: "/infrastructure" }]; diff --git a/client/src/Pages/v1/Integrations/index.css b/client/src/Pages/Integrations/index.css similarity index 100% rename from client/src/Pages/v1/Integrations/index.css rename to client/src/Pages/Integrations/index.css diff --git a/client/src/Pages/v1/Integrations/index.jsx b/client/src/Pages/Integrations/index.jsx similarity index 100% rename from client/src/Pages/v1/Integrations/index.jsx rename to client/src/Pages/Integrations/index.jsx diff --git a/client/src/Pages/v1/Logs/Diagnostics/components/gauges/index.jsx b/client/src/Pages/Logs/Diagnostics/components/gauges/index.jsx similarity index 100% rename from client/src/Pages/v1/Logs/Diagnostics/components/gauges/index.jsx rename to client/src/Pages/Logs/Diagnostics/components/gauges/index.jsx diff --git a/client/src/Pages/v1/Logs/Diagnostics/components/stats/index.jsx b/client/src/Pages/Logs/Diagnostics/components/stats/index.jsx similarity index 96% rename from client/src/Pages/v1/Logs/Diagnostics/components/stats/index.jsx rename to client/src/Pages/Logs/Diagnostics/components/stats/index.jsx index b99f34506..b169a6a85 100644 --- a/client/src/Pages/v1/Logs/Diagnostics/components/stats/index.jsx +++ b/client/src/Pages/Logs/Diagnostics/components/stats/index.jsx @@ -7,7 +7,7 @@ import CircularProgress from "@mui/material/CircularProgress"; import { useTheme } from "@emotion/react"; import PropTypes from "prop-types"; -import { getHumanReadableDuration } from "../../../../../../Utils/timeUtils.js"; +import { getHumanReadableDuration } from "../../../../../Utils/timeUtils.js"; import { formatBytes } from "../../utils/utils.js"; import { useTranslation } from "react-i18next"; diff --git a/client/src/Pages/v1/Logs/Diagnostics/index.jsx b/client/src/Pages/Logs/Diagnostics/index.jsx similarity index 88% rename from client/src/Pages/v1/Logs/Diagnostics/index.jsx rename to client/src/Pages/Logs/Diagnostics/index.jsx index 54feee516..07b504c77 100644 --- a/client/src/Pages/v1/Logs/Diagnostics/index.jsx +++ b/client/src/Pages/Logs/Diagnostics/index.jsx @@ -6,8 +6,8 @@ import StatBox from "@/Components/v1/StatBox/index.jsx"; import StatusBoxes from "@/Components/v1/StatusBoxes/index.jsx"; import { useTheme } from "@emotion/react"; import { useTranslation } from "react-i18next"; -import { useFetchDiagnostics } from "../../../../Hooks/v1/logHooks.js"; -import { getHumanReadableDuration } from "../../../../Utils/timeUtils.js"; +import { useFetchDiagnostics } from "../../../Hooks/logHooks.js"; +import { getHumanReadableDuration } from "../../../Utils/timeUtils.js"; import { formatBytes, getPercentage } from "./utils/utils.js"; const Diagnostics = () => { @@ -26,12 +26,12 @@ const Diagnostics = () => { status="up" heading={t("status")} subHeading={ - error + error ? t("logsPage.logLevelSelect.values.error") - : isLoading + : isLoading ? t("commonSaving") - : diagnostics - ? t("diagnosticsPage.diagnosticDescription") + : diagnostics + ? t("diagnosticsPage.diagnosticDescription") : t("general.noOptionsFound", { unit: "data" }) } /> diff --git a/client/src/Pages/v1/Logs/Diagnostics/utils/utils.js b/client/src/Pages/Logs/Diagnostics/utils/utils.js similarity index 100% rename from client/src/Pages/v1/Logs/Diagnostics/utils/utils.js rename to client/src/Pages/Logs/Diagnostics/utils/utils.js diff --git a/client/src/Pages/v1/Logs/Logs/index.jsx b/client/src/Pages/Logs/Logs/index.jsx similarity index 97% rename from client/src/Pages/v1/Logs/Logs/index.jsx rename to client/src/Pages/Logs/Logs/index.jsx index 64c4cb97a..c44a83ed9 100644 --- a/client/src/Pages/v1/Logs/Logs/index.jsx +++ b/client/src/Pages/Logs/Logs/index.jsx @@ -4,7 +4,7 @@ import Select from "@/Components/v1/Inputs/Select/index.jsx"; import Typography from "@mui/material/Typography"; import Divider from "@mui/material/Divider"; -import { useFetchLogs } from "../../../../Hooks/v1/logHooks.js"; +import { useFetchLogs } from "../../../Hooks/logHooks.js"; import { useTheme } from "@emotion/react"; import { useState } from "react"; import { useTranslation } from "react-i18next"; @@ -51,7 +51,6 @@ const Logs = () => { ]; return ( - { const MS_LOOKUP = { diff --git a/client/src/Pages/v1/Maintenance/CreateMaintenance/hooks/useMaintenanceData.jsx b/client/src/Pages/Maintenance/CreateMaintenance/hooks/useMaintenanceData.jsx similarity index 95% rename from client/src/Pages/v1/Maintenance/CreateMaintenance/hooks/useMaintenanceData.jsx rename to client/src/Pages/Maintenance/CreateMaintenance/hooks/useMaintenanceData.jsx index d21906e41..c3be0091a 100644 --- a/client/src/Pages/v1/Maintenance/CreateMaintenance/hooks/useMaintenanceData.jsx +++ b/client/src/Pages/Maintenance/CreateMaintenance/hooks/useMaintenanceData.jsx @@ -1,4 +1,4 @@ -import { networkService } from "../../../../../main.jsx"; +import { networkService } from "../../../../main.jsx"; import dayjs from "dayjs"; import { MS_PER_SECOND, @@ -6,7 +6,7 @@ import { MS_PER_HOUR, MS_PER_DAY, MS_PER_WEEK, -} from "../../../../../Utils/timeUtils.js"; +} from "../../../../Utils/timeUtils.js"; const useMaintenanceData = () => { const REVERSE_REPEAT_LOOKUP = { 0: "none", diff --git a/client/src/Pages/v1/Maintenance/CreateMaintenance/index.css b/client/src/Pages/Maintenance/CreateMaintenance/index.css similarity index 100% rename from client/src/Pages/v1/Maintenance/CreateMaintenance/index.css rename to client/src/Pages/Maintenance/CreateMaintenance/index.css diff --git a/client/src/Pages/v1/Maintenance/CreateMaintenance/index.jsx b/client/src/Pages/Maintenance/CreateMaintenance/index.jsx similarity index 97% rename from client/src/Pages/v1/Maintenance/CreateMaintenance/index.jsx rename to client/src/Pages/Maintenance/CreateMaintenance/index.jsx index d0e7b03cd..384805f3a 100644 --- a/client/src/Pages/v1/Maintenance/CreateMaintenance/index.jsx +++ b/client/src/Pages/Maintenance/CreateMaintenance/index.jsx @@ -7,8 +7,8 @@ import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; import { LocalizationProvider } from "@mui/x-date-pickers"; import { DatePicker } from "@mui/x-date-pickers/DatePicker"; import { MobileTimePicker } from "@mui/x-date-pickers/MobileTimePicker"; -import { maintenanceWindowValidation } from "../../../../Validation/validation.js"; -import { createToast } from "../../../../Utils/toastUtils.jsx"; +import { maintenanceWindowValidation } from "@/Validation/validation.js"; +import { createToast } from "@/Utils/toastUtils.jsx"; import MonitorList from "./Components/MonitorList/index.jsx"; import ConfigSelect from "./Components/ConfigSelect/index.jsx"; import useMaintenanceData from "./hooks/useMaintenanceData.jsx"; @@ -16,13 +16,13 @@ import useMaintenanceActions from "./hooks/useMaintenanceActions.jsx"; import TextInput from "@/Components/v1/Inputs/TextInput/index.jsx"; import Breadcrumbs from "@/Components/v1/Breadcrumbs/index.jsx"; -import CalendarIcon from "../../../../assets/icons/calendar.svg?react"; +import CalendarIcon from "@/assets/icons/calendar.svg?react"; import "./index.css"; import Search from "@/Components/v1/Inputs/Search/index.jsx"; -import { logger } from "../../../../Utils/Logger.js"; +import { logger } from "@/Utils/Logger.js"; import { useNavigate, useParams } from "react-router-dom"; -import { buildErrors, hasValidationErrors } from "../../../../Validation/error.js"; +import { buildErrors, hasValidationErrors } from "@/Validation/error.js"; import { useTranslation } from "react-i18next"; import dayjs from "dayjs"; diff --git a/client/src/Pages/v1/Maintenance/MaintenanceTable/ActionsMenu/index.jsx b/client/src/Pages/Maintenance/MaintenanceTable/ActionsMenu/index.jsx similarity index 93% rename from client/src/Pages/v1/Maintenance/MaintenanceTable/ActionsMenu/index.jsx rename to client/src/Pages/Maintenance/MaintenanceTable/ActionsMenu/index.jsx index b2654da49..38a3d8e64 100644 --- a/client/src/Pages/v1/Maintenance/MaintenanceTable/ActionsMenu/index.jsx +++ b/client/src/Pages/Maintenance/MaintenanceTable/ActionsMenu/index.jsx @@ -3,11 +3,11 @@ import { useTheme } from "@emotion/react"; import { useNavigate } from "react-router-dom"; import { useSelector } from "react-redux"; import { IconButton, Menu, MenuItem } from "@mui/material"; -import { logger } from "../../../../../Utils/Logger.js"; -import Settings from "../../../../../assets/icons/settings-bold.svg?react"; +import { logger } from "@/Utils/Logger.js"; +import Settings from "@/assets/icons/settings-bold.svg?react"; import PropTypes from "prop-types"; -import { networkService } from "../../../../../main.jsx"; -import { createToast } from "../../../../../Utils/toastUtils.jsx"; +import { networkService } from "../../../../main.jsx"; +import { createToast } from "@/Utils/toastUtils.jsx"; import { useTranslation } from "react-i18next"; import Dialog from "@/Components/v1/Dialog/index.jsx"; diff --git a/client/src/Pages/v1/Maintenance/MaintenanceTable/index.jsx b/client/src/Pages/Maintenance/MaintenanceTable/index.jsx similarity index 97% rename from client/src/Pages/v1/Maintenance/MaintenanceTable/index.jsx rename to client/src/Pages/Maintenance/MaintenanceTable/index.jsx index f1d44f944..faeb2072c 100644 --- a/client/src/Pages/v1/Maintenance/MaintenanceTable/index.jsx +++ b/client/src/Pages/Maintenance/MaintenanceTable/index.jsx @@ -7,9 +7,9 @@ import ArrowUpwardRoundedIcon from "@mui/icons-material/ArrowUpwardRounded"; import ActionsMenu from "./ActionsMenu/index.jsx"; import { memo } from "react"; import { useDispatch, useSelector } from "react-redux"; -import { formatDurationRounded } from "../../../../Utils/timeUtils.js"; +import { formatDurationRounded } from "../../../Utils/timeUtils.js"; import { StatusLabel } from "@/Components/v1/Label/index.jsx"; -import { setRowsPerPage } from "../../../../Features/UI/uiSlice.js"; +import { setRowsPerPage } from "../../../Features/UI/uiSlice.js"; import { useTranslation } from "react-i18next"; import { useTheme } from "@emotion/react"; import { useNavigate } from "react-router-dom"; diff --git a/client/src/Pages/v1/Maintenance/index.css b/client/src/Pages/Maintenance/index.css similarity index 100% rename from client/src/Pages/v1/Maintenance/index.css rename to client/src/Pages/Maintenance/index.css diff --git a/client/src/Pages/v1/Maintenance/index.jsx b/client/src/Pages/Maintenance/index.jsx similarity index 98% rename from client/src/Pages/v1/Maintenance/index.jsx rename to client/src/Pages/Maintenance/index.jsx index cba0e9f18..b49cd9f6e 100644 --- a/client/src/Pages/v1/Maintenance/index.jsx +++ b/client/src/Pages/Maintenance/index.jsx @@ -4,7 +4,7 @@ import { useState, useEffect } from "react"; import "./index.css"; import MaintenanceTable from "./MaintenanceTable/index.jsx"; import { useSelector } from "react-redux"; -import { networkService } from "../../../main.jsx"; +import { networkService } from "../../main.jsx"; import Breadcrumbs from "@/Components/v1/Breadcrumbs/index.jsx"; import { useNavigate } from "react-router-dom"; import { useTranslation } from "react-i18next"; diff --git a/client/src/Pages/v1/NotFound/index.jsx b/client/src/Pages/NotFound/index.jsx similarity index 96% rename from client/src/Pages/v1/NotFound/index.jsx rename to client/src/Pages/NotFound/index.jsx index 48825c9f6..27e3173b0 100644 --- a/client/src/Pages/v1/NotFound/index.jsx +++ b/client/src/Pages/NotFound/index.jsx @@ -1,5 +1,5 @@ import PropTypes from "prop-types"; -import NotFoundSvg from "../../../assets/Images/sushi_404.svg"; +import NotFoundSvg from "@/assets/Images/sushi_404.svg"; import { Button, Stack, Typography } from "@mui/material"; import { useNavigate } from "react-router-dom"; import { useTheme } from "@emotion/react"; diff --git a/client/src/Pages/v1/Notifications/components/ActionMenu.jsx b/client/src/Pages/Notifications/components/ActionMenu.jsx similarity index 100% rename from client/src/Pages/v1/Notifications/components/ActionMenu.jsx rename to client/src/Pages/Notifications/components/ActionMenu.jsx diff --git a/client/src/Pages/v1/Notifications/create/index.jsx b/client/src/Pages/Notifications/create/index.jsx similarity index 97% rename from client/src/Pages/v1/Notifications/create/index.jsx rename to client/src/Pages/Notifications/create/index.jsx index b1c50493c..11bf2a95d 100644 --- a/client/src/Pages/v1/Notifications/create/index.jsx +++ b/client/src/Pages/Notifications/create/index.jsx @@ -18,9 +18,9 @@ import { useEditNotification, useTestNotification, useDeleteNotification, -} from "../../../../Hooks/v1/useNotifications.js"; -import { notificationValidation } from "../../../../Validation/validation.js"; -import { createToast } from "../../../../Utils/toastUtils.jsx"; +} from "../../../Hooks/useNotifications.js"; +import { notificationValidation } from "../../../Validation/validation.js"; +import { createToast } from "../../../Utils/toastUtils.jsx"; import { useTranslation } from "react-i18next"; import { useParams, useNavigate } from "react-router-dom"; import { diff --git a/client/src/Pages/v1/Notifications/index.jsx b/client/src/Pages/Notifications/index.jsx similarity index 98% rename from client/src/Pages/v1/Notifications/index.jsx rename to client/src/Pages/Notifications/index.jsx index 78ec6e9bb..8ebdb22ec 100644 --- a/client/src/Pages/v1/Notifications/index.jsx +++ b/client/src/Pages/Notifications/index.jsx @@ -14,7 +14,7 @@ import { useNavigate } from "react-router-dom"; import { useGetNotificationsByTeamId, useDeleteNotification, -} from "../../../Hooks/v1/useNotifications.js"; +} from "../../Hooks/useNotifications.js"; import { useTranslation } from "react-i18next"; const Notifications = () => { diff --git a/client/src/Pages/v1/Notifications/utils.js b/client/src/Pages/Notifications/utils.js similarity index 100% rename from client/src/Pages/v1/Notifications/utils.js rename to client/src/Pages/Notifications/utils.js diff --git a/client/src/Pages/v1/PageSpeed/Create/index.css b/client/src/Pages/PageSpeed/Create/index.css similarity index 100% rename from client/src/Pages/v1/PageSpeed/Create/index.css rename to client/src/Pages/PageSpeed/Create/index.css diff --git a/client/src/Pages/v1/PageSpeed/Create/index.jsx b/client/src/Pages/PageSpeed/Create/index.jsx similarity index 96% rename from client/src/Pages/v1/PageSpeed/Create/index.jsx rename to client/src/Pages/PageSpeed/Create/index.jsx index cb856bd37..2cce26159 100644 --- a/client/src/Pages/v1/PageSpeed/Create/index.jsx +++ b/client/src/Pages/PageSpeed/Create/index.jsx @@ -16,22 +16,22 @@ import Radio from "@/Components/v1/Inputs/Radio/index.jsx"; // Utils import { useState, useEffect } from "react"; import { useSelector } from "react-redux"; -import { monitorValidation } from "../../../../Validation/validation.js"; -import { parseDomainName } from "../../../../Utils/monitorUtils.js"; +import { monitorValidation } from "../../../Validation/validation.js"; +import { parseDomainName } from "../../../Utils/monitorUtils.js"; import { useTranslation } from "react-i18next"; -import { useGetNotificationsByTeamId } from "../../../../Hooks/v1/useNotifications.js"; +import { useGetNotificationsByTeamId } from "../../../Hooks/useNotifications.js"; import { useTheme } from "@emotion/react"; -import { createToast } from "../../../../Utils/toastUtils.jsx"; +import { createToast } from "../../../Utils/toastUtils.jsx"; import { useParams } from "react-router"; -import { useMonitorUtils } from "../../../../Hooks/v1/useMonitorUtils.js"; +import { useMonitorUtils } from "../../../Hooks/useMonitorUtils.js"; import { useCreateMonitor, useFetchMonitorById, useDeleteMonitor, useUpdateMonitor, usePauseMonitor, -} from "../../../../Hooks/v1/monitorHooks.js"; +} from "../../../Hooks/monitorHooks.js"; const PageSpeedSetup = () => { const { monitorId } = useParams(); @@ -178,7 +178,8 @@ const PageSpeedSetup = () => { const handleRemove = async (event) => { event.preventDefault(); - await deleteMonitor({ monitor, redirect: "/pagespeed" }); + const TEMP_MONITOR = { id: monitor._id }; + await deleteMonitor({ monitor: TEMP_MONITOR, redirect: "/pagespeed" }); }; const isBusy = isLoading || isCreating || isDeleting || isUpdating || isPausing; diff --git a/client/src/Pages/v1/PageSpeed/Create/skeleton.jsx b/client/src/Pages/PageSpeed/Create/skeleton.jsx similarity index 100% rename from client/src/Pages/v1/PageSpeed/Create/skeleton.jsx rename to client/src/Pages/PageSpeed/Create/skeleton.jsx diff --git a/client/src/Pages/v1/PageSpeed/Details/Components/Charts/AreaChart.jsx b/client/src/Pages/PageSpeed/Details/Components/Charts/AreaChart.jsx similarity index 99% rename from client/src/Pages/v1/PageSpeed/Details/Components/Charts/AreaChart.jsx rename to client/src/Pages/PageSpeed/Details/Components/Charts/AreaChart.jsx index 5c79cc06c..06b92c933 100644 --- a/client/src/Pages/v1/PageSpeed/Details/Components/Charts/AreaChart.jsx +++ b/client/src/Pages/PageSpeed/Details/Components/Charts/AreaChart.jsx @@ -11,7 +11,7 @@ import { import { useTheme } from "@emotion/react"; import { useMemo, useState } from "react"; import { Box, Stack, Typography } from "@mui/material"; -import { formatDateWithTz } from "../../../../../../Utils/timeUtils.js"; +import { formatDateWithTz } from "../../../../../Utils/timeUtils.js"; import { useSelector } from "react-redux"; const config = { diff --git a/client/src/Pages/v1/PageSpeed/Details/Components/Charts/AreaChartLegend.jsx b/client/src/Pages/PageSpeed/Details/Components/Charts/AreaChartLegend.jsx similarity index 94% rename from client/src/Pages/v1/PageSpeed/Details/Components/Charts/AreaChartLegend.jsx rename to client/src/Pages/PageSpeed/Details/Components/Charts/AreaChartLegend.jsx index c0da1600f..113e4d618 100644 --- a/client/src/Pages/v1/PageSpeed/Details/Components/Charts/AreaChartLegend.jsx +++ b/client/src/Pages/PageSpeed/Details/Components/Charts/AreaChartLegend.jsx @@ -1,6 +1,6 @@ import { Box, Typography, Divider } from "@mui/material"; import Checkbox from "@/Components/v1/Inputs/Checkbox/index.jsx"; -import MetricsIcon from "../../../../../../assets/icons/ruler-icon.svg?react"; +import MetricsIcon from "@/assets/icons/ruler-icon.svg?react"; import LegendBox from "@/Components/v1/Charts/LegendBox/index.jsx"; import { useTranslation } from "react-i18next"; import { useTheme } from "@emotion/react"; diff --git a/client/src/Pages/v1/PageSpeed/Details/Components/Charts/PieChart.jsx b/client/src/Pages/PageSpeed/Details/Components/Charts/PieChart.jsx similarity index 100% rename from client/src/Pages/v1/PageSpeed/Details/Components/Charts/PieChart.jsx rename to client/src/Pages/PageSpeed/Details/Components/Charts/PieChart.jsx diff --git a/client/src/Pages/v1/PageSpeed/Details/Components/Charts/PieChartLegend.jsx b/client/src/Pages/PageSpeed/Details/Components/Charts/PieChartLegend.jsx similarity index 96% rename from client/src/Pages/v1/PageSpeed/Details/Components/Charts/PieChartLegend.jsx rename to client/src/Pages/PageSpeed/Details/Components/Charts/PieChartLegend.jsx index 1297bd699..43e2371b4 100644 --- a/client/src/Pages/v1/PageSpeed/Details/Components/Charts/PieChartLegend.jsx +++ b/client/src/Pages/PageSpeed/Details/Components/Charts/PieChartLegend.jsx @@ -1,7 +1,7 @@ import { Stack, Box, Typography } from "@mui/material"; import { useTheme } from "@emotion/react"; import LegendBox from "@/Components/v1/Charts/LegendBox/index.jsx"; -import SpeedometerIcon from "../../../../../../assets/icons/speedometer-icon.svg?react"; +import SpeedometerIcon from "@/assets/icons/speedometer-icon.svg?react"; import PropTypes from "prop-types"; const PieChartLegend = ({ audits }) => { diff --git a/client/src/Pages/v1/PageSpeed/Details/Components/PageSpeedAreaChart/index.jsx b/client/src/Pages/PageSpeed/Details/Components/PageSpeedAreaChart/index.jsx similarity index 93% rename from client/src/Pages/v1/PageSpeed/Details/Components/PageSpeedAreaChart/index.jsx rename to client/src/Pages/PageSpeed/Details/Components/PageSpeedAreaChart/index.jsx index 1281a396e..aa88d57e5 100644 --- a/client/src/Pages/v1/PageSpeed/Details/Components/PageSpeedAreaChart/index.jsx +++ b/client/src/Pages/PageSpeed/Details/Components/PageSpeedAreaChart/index.jsx @@ -2,7 +2,7 @@ import ChartBox from "@/Components/v1/Charts/ChartBox/index.jsx"; import AreaChart from "../Charts/AreaChart.jsx"; import AreaChartLegend from "../Charts/AreaChartLegend.jsx"; import SkeletonLayout from "./skeleton.jsx"; -import ScoreIcon from "../../../../../../assets/icons/monitor-graph-line.svg?react"; +import ScoreIcon from "@/assets/icons/monitor-graph-line.svg?react"; import { Stack } from "@mui/material"; import PropTypes from "prop-types"; diff --git a/client/src/Pages/v1/PageSpeed/Details/Components/PageSpeedAreaChart/skeleton.jsx b/client/src/Pages/PageSpeed/Details/Components/PageSpeedAreaChart/skeleton.jsx similarity index 100% rename from client/src/Pages/v1/PageSpeed/Details/Components/PageSpeedAreaChart/skeleton.jsx rename to client/src/Pages/PageSpeed/Details/Components/PageSpeedAreaChart/skeleton.jsx diff --git a/client/src/Pages/v1/PageSpeed/Details/Components/PageSpeedStatusBoxes/index.jsx b/client/src/Pages/PageSpeed/Details/Components/PageSpeedStatusBoxes/index.jsx similarity index 91% rename from client/src/Pages/v1/PageSpeed/Details/Components/PageSpeedStatusBoxes/index.jsx rename to client/src/Pages/PageSpeed/Details/Components/PageSpeedStatusBoxes/index.jsx index ff265317c..493d1ece6 100644 --- a/client/src/Pages/v1/PageSpeed/Details/Components/PageSpeedStatusBoxes/index.jsx +++ b/client/src/Pages/PageSpeed/Details/Components/PageSpeedStatusBoxes/index.jsx @@ -1,7 +1,7 @@ import StatusBoxes from "@/Components/v1/StatusBoxes/index.jsx"; import StatBox from "@/Components/v1/StatBox/index.jsx"; import { Typography } from "@mui/material"; -import { getHumanReadableDuration } from "../../../../../../Utils/timeUtils.js"; +import { getHumanReadableDuration } from "../../../../../Utils/timeUtils.js"; import { useTranslation } from "react-i18next"; const PageSpeedStatusBoxes = ({ shouldRender, monitor }) => { diff --git a/client/src/Pages/v1/PageSpeed/Details/Components/PerformanceReport/index.jsx b/client/src/Pages/PageSpeed/Details/Components/PerformanceReport/index.jsx similarity index 93% rename from client/src/Pages/v1/PageSpeed/Details/Components/PerformanceReport/index.jsx rename to client/src/Pages/PageSpeed/Details/Components/PerformanceReport/index.jsx index 27f9e885b..c2eecaa6a 100644 --- a/client/src/Pages/v1/PageSpeed/Details/Components/PerformanceReport/index.jsx +++ b/client/src/Pages/PageSpeed/Details/Components/PerformanceReport/index.jsx @@ -1,5 +1,5 @@ import ChartBox from "@/Components/v1/Charts/ChartBox/index.jsx"; -import PerformanceIcon from "../../../../../../assets/icons/performance-report.svg?react"; +import PerformanceIcon from "@/assets/icons/performance-report.svg?react"; import PieChart from "../Charts/PieChart.jsx"; import { Typography } from "@mui/material"; import { useTheme } from "@emotion/react"; diff --git a/client/src/Pages/v1/PageSpeed/Details/Components/PerformanceReport/skeleton.jsx b/client/src/Pages/PageSpeed/Details/Components/PerformanceReport/skeleton.jsx similarity index 100% rename from client/src/Pages/v1/PageSpeed/Details/Components/PerformanceReport/skeleton.jsx rename to client/src/Pages/PageSpeed/Details/Components/PerformanceReport/skeleton.jsx diff --git a/client/src/Pages/v1/PageSpeed/Details/index.jsx b/client/src/Pages/PageSpeed/Details/index.jsx similarity index 95% rename from client/src/Pages/v1/PageSpeed/Details/index.jsx rename to client/src/Pages/PageSpeed/Details/index.jsx index 836f0ca37..8a87133df 100644 --- a/client/src/Pages/v1/PageSpeed/Details/index.jsx +++ b/client/src/Pages/PageSpeed/Details/index.jsx @@ -9,9 +9,9 @@ import PerformanceReport from "./Components/PerformanceReport/index.jsx"; import GenericFallback from "@/Components/v1/GenericFallback/index.jsx"; // Utils import { useTheme } from "@emotion/react"; -import { useIsAdmin } from "../../../../Hooks/v1/useIsAdmin.js"; +import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; import { useParams } from "react-router-dom"; -import { useFetchStatsByMonitorId } from "../../../../Hooks/v1/monitorHooks.js"; +import { useFetchStatsByMonitorId } from "../../../Hooks/monitorHooks.js"; import { useState } from "react"; import { useTranslation } from "react-i18next"; // Constants diff --git a/client/src/Pages/v1/PageSpeed/Monitors/Components/Card/index.jsx b/client/src/Pages/PageSpeed/Monitors/Components/Card/index.jsx similarity index 96% rename from client/src/Pages/v1/PageSpeed/Monitors/Components/Card/index.jsx rename to client/src/Pages/PageSpeed/Monitors/Components/Card/index.jsx index 4e551526b..8a6444d1b 100644 --- a/client/src/Pages/v1/PageSpeed/Monitors/Components/Card/index.jsx +++ b/client/src/Pages/PageSpeed/Monitors/Components/Card/index.jsx @@ -1,17 +1,14 @@ import PropTypes from "prop-types"; // import PageSpeedIcon from "../../../../assets/icons/page-speed.svg?react"; -import PageSpeedIcon from "../../../../../../assets/icons/page-speed.svg?react"; +import PageSpeedIcon from "@/assets/icons/page-speed.svg?react"; import { StatusLabel } from "@/Components/v1/Label/index.jsx"; import { Box, Grid, Stack, Typography } from "@mui/material"; import { useNavigate } from "react-router-dom"; import { useTheme } from "@emotion/react"; import { Area, AreaChart, CartesianGrid, ResponsiveContainer, Tooltip } from "recharts"; import { useSelector } from "react-redux"; -import { - formatDateWithTz, - formatDurationSplit, -} from "../../../../../../Utils/timeUtils.js"; -import { useMonitorUtils } from "../../../../../../Hooks/v1/useMonitorUtils.js"; +import { formatDateWithTz, formatDurationSplit } from "@/Utils/timeUtils.js"; +import { useMonitorUtils } from "@/Hooks/useMonitorUtils.js"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import IconBox from "@/Components/v1/IconBox/index.jsx"; @@ -224,7 +221,7 @@ const Card = ({ monitor }) => { navigate(`/pagespeed/${monitor._id}`)} + onClick={() => navigate(`/pagespeed/${monitor.id}`)} border={1} borderColor={theme.palette.primary.lowContrast} borderRadius={theme.shape.borderRadius} diff --git a/client/src/Pages/v1/PageSpeed/Monitors/Components/MonitorGrid/index.jsx b/client/src/Pages/PageSpeed/Monitors/Components/MonitorGrid/index.jsx similarity index 100% rename from client/src/Pages/v1/PageSpeed/Monitors/Components/MonitorGrid/index.jsx rename to client/src/Pages/PageSpeed/Monitors/Components/MonitorGrid/index.jsx diff --git a/client/src/Pages/v1/PageSpeed/Monitors/index.jsx b/client/src/Pages/PageSpeed/Monitors/index.jsx similarity index 64% rename from client/src/Pages/v1/PageSpeed/Monitors/index.jsx rename to client/src/Pages/PageSpeed/Monitors/index.jsx index 7485a72c9..548cd3491 100644 --- a/client/src/Pages/v1/PageSpeed/Monitors/index.jsx +++ b/client/src/Pages/PageSpeed/Monitors/index.jsx @@ -10,9 +10,12 @@ import FallbackPageSpeedWarning from "@/Components/v1/Fallback/FallbackPageSpeed // Utils import { useTheme } from "@emotion/react"; -import { useIsAdmin } from "../../../../Hooks/v1/useIsAdmin.js"; -import { useFetchMonitorsByTeamId } from "../../../../Hooks/v1/monitorHooks.js"; -import { useFetchSettings } from "../../../../Hooks/v1/settingsHooks.js"; +import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; +import { + useFetchMonitorsByTeamId, + useFetchMonitorsWithChecks, +} from "@/Hooks/monitorHooks.js"; +import { useFetchSettings } from "@/Hooks/settingsHooks.js"; // Constants const BREADCRUMBS = [{ name: `pagespeed`, path: "/pagespeed" }]; const TYPES = ["pagespeed"]; @@ -20,14 +23,30 @@ const PageSpeed = () => { const theme = useTheme(); const isAdmin = useIsAdmin(); - const [monitors, monitorsSummary, isLoading, networkError] = useFetchMonitorsByTeamId({ - limit: 10, + // const [monitors, monitorsSummary, isLoading, networkError] = useFetchMonitorsByTeamId({ + // limit: 10, + // types: TYPES, + // page: null, + // rowsPerPage: null, + // filter: null, + // field: null, + // order: null, + // }); + + const [ + monitorsWithChecks, + monitorsWithChecksCount, + monitorsWithChecksIsLoading, + monitorsWithChecksNetworkError, + ] = useFetchMonitorsWithChecks({ types: TYPES, + limit: 10, page: null, rowsPerPage: null, filter: null, field: null, order: null, + monitorUpdateTrigger: null, }); const [settingsData, setSettingsData] = useState(undefined); @@ -40,9 +59,9 @@ const PageSpeed = () => { return ( <> { diff --git a/client/src/Pages/v1/ServerUnreachable.jsx b/client/src/Pages/ServerUnreachable.jsx similarity index 92% rename from client/src/Pages/v1/ServerUnreachable.jsx rename to client/src/Pages/ServerUnreachable.jsx index 8230f473b..bfbbfa90a 100644 --- a/client/src/Pages/v1/ServerUnreachable.jsx +++ b/client/src/Pages/ServerUnreachable.jsx @@ -2,14 +2,14 @@ import React, { useState } from "react"; import { Box, Typography, Button, Stack } from "@mui/material"; import { useTheme } from "@emotion/react"; import { useNavigate } from "react-router-dom"; -import { networkService } from "../../Utils/NetworkService.js"; +import { networkService } from "@/Utils/NetworkService.js"; import Alert from "@/Components/v1/Alert/index.jsx"; -import { createToast } from "../../Utils/toastUtils.jsx"; +import { createToast } from "@/Utils/toastUtils.jsx"; import { useTranslation } from "react-i18next"; -import Background from "../../assets/Images/background-grid.svg?react"; -import Logo from "../../assets/icons/checkmate-icon.svg?react"; +import Background from "@/assets/Images/background-grid.svg?react"; +import Logo from "@/assets/icons/checkmate-icon.svg?react"; import ThemeSwitch from "@/Components/v1/ThemeSwitch/index.jsx"; -import LanguageSelector from "../../Components/LanguageSelector.jsx"; +import LanguageSelector from "@/Components/LanguageSelector.jsx"; const ServerUnreachable = () => { const theme = useTheme(); diff --git a/client/src/Pages/v1/Settings/SettingsAbout.jsx b/client/src/Pages/Settings/SettingsAbout.jsx similarity index 100% rename from client/src/Pages/v1/Settings/SettingsAbout.jsx rename to client/src/Pages/Settings/SettingsAbout.jsx diff --git a/client/src/Pages/v1/Settings/SettingsDemoMonitors.jsx b/client/src/Pages/Settings/SettingsDemoMonitors.jsx similarity index 100% rename from client/src/Pages/v1/Settings/SettingsDemoMonitors.jsx rename to client/src/Pages/Settings/SettingsDemoMonitors.jsx diff --git a/client/src/Pages/v1/Settings/SettingsEmail.jsx b/client/src/Pages/Settings/SettingsEmail.jsx similarity index 98% rename from client/src/Pages/v1/Settings/SettingsEmail.jsx rename to client/src/Pages/Settings/SettingsEmail.jsx index 7b5ad175e..6f0b02137 100644 --- a/client/src/Pages/v1/Settings/SettingsEmail.jsx +++ b/client/src/Pages/Settings/SettingsEmail.jsx @@ -12,8 +12,8 @@ import { PropTypes } from "prop-types"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { PasswordEndAdornment } from "@/Components/v1/Inputs/TextInput/Adornments/index.jsx"; -import { useSendTestEmail } from "../../../Hooks/v1/useSendTestEmail.js"; -import { createToast } from "../../../Utils/toastUtils.jsx"; +import { useSendTestEmail } from "@/Hooks/useSendTestEmail.js"; +import { createToast } from "@/Utils/toastUtils.jsx"; const SettingsEmail = ({ isAdmin, diff --git a/client/src/Pages/v1/Settings/SettingsExport.jsx b/client/src/Pages/Settings/SettingsExport.jsx similarity index 100% rename from client/src/Pages/v1/Settings/SettingsExport.jsx rename to client/src/Pages/Settings/SettingsExport.jsx diff --git a/client/src/Pages/v1/Settings/SettingsGlobalThresholds.jsx b/client/src/Pages/Settings/SettingsGlobalThresholds.jsx similarity index 100% rename from client/src/Pages/v1/Settings/SettingsGlobalThresholds.jsx rename to client/src/Pages/Settings/SettingsGlobalThresholds.jsx diff --git a/client/src/Pages/v1/Settings/SettingsPagespeed.jsx b/client/src/Pages/Settings/SettingsPagespeed.jsx similarity index 100% rename from client/src/Pages/v1/Settings/SettingsPagespeed.jsx rename to client/src/Pages/Settings/SettingsPagespeed.jsx diff --git a/client/src/Pages/v1/Settings/SettingsStats.jsx b/client/src/Pages/Settings/SettingsStats.jsx similarity index 86% rename from client/src/Pages/v1/Settings/SettingsStats.jsx rename to client/src/Pages/Settings/SettingsStats.jsx index b68006ab2..690b306be 100644 --- a/client/src/Pages/v1/Settings/SettingsStats.jsx +++ b/client/src/Pages/Settings/SettingsStats.jsx @@ -36,16 +36,6 @@ const SettingsStats = ({ isAdmin, HEADING_SX, handleChange, settingsData, errors - {t("settingsPage.statsSettings.clearAllStatsDescription")} diff --git a/client/src/Pages/v1/Settings/SettingsTimeZone.jsx b/client/src/Pages/Settings/SettingsTimeZone.jsx similarity index 97% rename from client/src/Pages/v1/Settings/SettingsTimeZone.jsx rename to client/src/Pages/Settings/SettingsTimeZone.jsx index f684c871d..8ed7e5b3b 100644 --- a/client/src/Pages/v1/Settings/SettingsTimeZone.jsx +++ b/client/src/Pages/Settings/SettingsTimeZone.jsx @@ -3,7 +3,7 @@ import Stack from "@mui/material/Stack"; import Typography from "@mui/material/Typography"; import ConfigBox from "@/Components/v1/ConfigBox/index.jsx"; import Search from "@/Components/v1/Inputs/Search/index.jsx"; -import timezones from "../../../Utils/timezones.json"; +import timezones from "@/Utils/timezones.json"; // Utils import { useTheme } from "@emotion/react"; diff --git a/client/src/Pages/v1/Settings/SettingsUI.jsx b/client/src/Pages/Settings/SettingsUI.jsx similarity index 100% rename from client/src/Pages/v1/Settings/SettingsUI.jsx rename to client/src/Pages/Settings/SettingsUI.jsx diff --git a/client/src/Pages/v1/Settings/SettingsURL.jsx b/client/src/Pages/Settings/SettingsURL.jsx similarity index 100% rename from client/src/Pages/v1/Settings/SettingsURL.jsx rename to client/src/Pages/Settings/SettingsURL.jsx diff --git a/client/src/Pages/v1/Settings/index.jsx b/client/src/Pages/Settings/index.jsx similarity index 95% rename from client/src/Pages/v1/Settings/index.jsx rename to client/src/Pages/Settings/index.jsx index b6137121b..27cc6bb21 100644 --- a/client/src/Pages/v1/Settings/index.jsx +++ b/client/src/Pages/Settings/index.jsx @@ -12,27 +12,22 @@ import SettingsGlobalThresholds from "./SettingsGlobalThresholds.jsx"; import SettingsExport from "./SettingsExport.jsx"; import Button from "@mui/material/Button"; // Utils -import { settingsValidation } from "../../../Validation/validation.js"; +import { settingsValidation } from "@/Validation/validation.js"; import { useState } from "react"; import { useTheme } from "@emotion/react"; import { useTranslation } from "react-i18next"; import { useSelector, useDispatch } from "react-redux"; -import { - setTimezone, - setMode, - setLanguage, - setShowURL, -} from "../../../Features/UI/uiSlice.js"; +import { setTimezone, setMode, setLanguage, setShowURL } from "@/Features/UI/uiSlice.js"; import SettingsStats from "./SettingsStats.jsx"; -import { useFetchSettings, useSaveSettings } from "../../../Hooks/v1/settingsHooks.js"; -import { useIsAdmin } from "../../../Hooks/v1/useIsAdmin.js"; +import { useFetchSettings, useSaveSettings } from "@/Hooks/settingsHooks.js"; +import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; import { useAddDemoMonitors, useDeleteAllMonitors, useDeleteMonitorStats, useFetchJson, -} from "../../../Hooks/v1/monitorHooks.js"; +} from "@/Hooks/monitorHooks.js"; // Constants const BREADCRUMBS = [{ name: `Settings`, path: "/settings" }]; diff --git a/client/src/Pages/v1/StatusPage/Create/Components/MonitorList/index.jsx b/client/src/Pages/StatusPage/Create/Components/MonitorList/index.jsx similarity index 100% rename from client/src/Pages/v1/StatusPage/Create/Components/MonitorList/index.jsx rename to client/src/Pages/StatusPage/Create/Components/MonitorList/index.jsx diff --git a/client/src/Pages/v1/StatusPage/Create/Components/Progress/index.jsx b/client/src/Pages/StatusPage/Create/Components/Progress/index.jsx similarity index 92% rename from client/src/Pages/v1/StatusPage/Create/Components/Progress/index.jsx rename to client/src/Pages/StatusPage/Create/Components/Progress/index.jsx index 232a12f1d..2d9731ea0 100644 --- a/client/src/Pages/v1/StatusPage/Create/Components/Progress/index.jsx +++ b/client/src/Pages/StatusPage/Create/Components/Progress/index.jsx @@ -2,7 +2,7 @@ import { Button, Box } from "@mui/material"; import ProgressUpload from "@/Components/v1/ProgressBars/index.jsx"; import ImageIcon from "@mui/icons-material/Image"; import { useTranslation } from "react-i18next"; -import { formatBytes } from "../../../../../../Utils/fileUtils.js"; +import { formatBytes } from "../../../../../Utils/fileUtils.js"; const Progress = ({ isLoading, progressValue, logo, logoType, removeLogo, errors }) => { const { t } = useTranslation(); if (isLoading) { diff --git a/client/src/Pages/v1/StatusPage/Create/Components/Skeleton/index.jsx b/client/src/Pages/StatusPage/Create/Components/Skeleton/index.jsx similarity index 100% rename from client/src/Pages/v1/StatusPage/Create/Components/Skeleton/index.jsx rename to client/src/Pages/StatusPage/Create/Components/Skeleton/index.jsx diff --git a/client/src/Pages/v1/StatusPage/Create/Components/Tabs/ConfigStack.jsx b/client/src/Pages/StatusPage/Create/Components/Tabs/ConfigStack.jsx similarity index 100% rename from client/src/Pages/v1/StatusPage/Create/Components/Tabs/ConfigStack.jsx rename to client/src/Pages/StatusPage/Create/Components/Tabs/ConfigStack.jsx diff --git a/client/src/Pages/v1/StatusPage/Create/Components/Tabs/Content.jsx b/client/src/Pages/StatusPage/Create/Components/Tabs/Content.jsx similarity index 100% rename from client/src/Pages/v1/StatusPage/Create/Components/Tabs/Content.jsx rename to client/src/Pages/StatusPage/Create/Components/Tabs/Content.jsx diff --git a/client/src/Pages/v1/StatusPage/Create/Components/Tabs/Settings.jsx b/client/src/Pages/StatusPage/Create/Components/Tabs/Settings.jsx similarity index 98% rename from client/src/Pages/v1/StatusPage/Create/Components/Tabs/Settings.jsx rename to client/src/Pages/StatusPage/Create/Components/Tabs/Settings.jsx index a668a9db8..d4c583d3a 100644 --- a/client/src/Pages/v1/StatusPage/Create/Components/Tabs/Settings.jsx +++ b/client/src/Pages/StatusPage/Create/Components/Tabs/Settings.jsx @@ -11,7 +11,7 @@ import Progress from "../Progress/index.jsx"; // Utils import { useTheme } from "@emotion/react"; -import timezones from "../../../../../../Utils/timezones.json"; +import timezones from "../../../../../Utils/timezones.json"; import PropTypes from "prop-types"; import { useTranslation } from "react-i18next"; import { useMemo, useState, useCallback } from "react"; diff --git a/client/src/Pages/v1/StatusPage/Create/Components/Tabs/index.jsx b/client/src/Pages/StatusPage/Create/Components/Tabs/index.jsx similarity index 100% rename from client/src/Pages/v1/StatusPage/Create/Components/Tabs/index.jsx rename to client/src/Pages/StatusPage/Create/Components/Tabs/index.jsx diff --git a/client/src/Pages/v1/StatusPage/Create/Hooks/useCreateStatusPage.jsx b/client/src/Pages/StatusPage/Create/Hooks/useCreateStatusPage.jsx similarity index 83% rename from client/src/Pages/v1/StatusPage/Create/Hooks/useCreateStatusPage.jsx rename to client/src/Pages/StatusPage/Create/Hooks/useCreateStatusPage.jsx index 808598052..dac5997f9 100644 --- a/client/src/Pages/v1/StatusPage/Create/Hooks/useCreateStatusPage.jsx +++ b/client/src/Pages/StatusPage/Create/Hooks/useCreateStatusPage.jsx @@ -1,6 +1,6 @@ import { useState } from "react"; -import { networkService } from "../../../../../main.jsx"; -import { createToast } from "../../../../../Utils/toastUtils.jsx"; +import { networkService } from "../../../../main.jsx"; +import { createToast } from "../../../../Utils/toastUtils.jsx"; const useCreateStatusPage = (isCreate, url) => { const [isLoading, setIsLoading] = useState(false); diff --git a/client/src/Pages/v1/StatusPage/Create/Hooks/useMonitorsFetch.jsx b/client/src/Pages/StatusPage/Create/Hooks/useMonitorsFetch.jsx similarity index 88% rename from client/src/Pages/v1/StatusPage/Create/Hooks/useMonitorsFetch.jsx rename to client/src/Pages/StatusPage/Create/Hooks/useMonitorsFetch.jsx index 81fefd65c..95ce2b8c0 100644 --- a/client/src/Pages/v1/StatusPage/Create/Hooks/useMonitorsFetch.jsx +++ b/client/src/Pages/StatusPage/Create/Hooks/useMonitorsFetch.jsx @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; -import { networkService } from "../../../../../main.jsx"; +import { networkService } from "../../../../main.jsx"; import { useSelector } from "react-redux"; -import { createToast } from "../../../../../Utils/toastUtils.jsx"; +import { createToast } from "../../../../Utils/toastUtils.jsx"; const useMonitorsFetch = () => { const { user } = useSelector((state) => state.auth); diff --git a/client/src/Pages/v1/StatusPage/Create/index.jsx b/client/src/Pages/StatusPage/Create/index.jsx similarity index 97% rename from client/src/Pages/v1/StatusPage/Create/index.jsx rename to client/src/Pages/StatusPage/Create/index.jsx index d9fafed70..7fbe6a8dc 100644 --- a/client/src/Pages/v1/StatusPage/Create/index.jsx +++ b/client/src/Pages/StatusPage/Create/index.jsx @@ -8,11 +8,11 @@ import Breadcrumbs from "@/Components/v1/Breadcrumbs/index.jsx"; //Utils import { useTheme } from "@emotion/react"; import { useState, useEffect, useRef, useCallback } from "react"; -import { statusPageValidation } from "../../../../Validation/validation.js"; -import { buildErrors } from "../../../../Validation/error.js"; +import { statusPageValidation } from "../../../Validation/validation.js"; +import { buildErrors } from "../../../Validation/error.js"; import { useMonitorsFetch } from "./Hooks/useMonitorsFetch.jsx"; import { useCreateStatusPage } from "./Hooks/useCreateStatusPage.jsx"; -import { createToast } from "../../../../Utils/toastUtils.jsx"; +import { createToast } from "../../../Utils/toastUtils.jsx"; import { useNavigate } from "react-router-dom"; import { useStatusPageFetch } from "../Status/Hooks/useStatusPageFetch.jsx"; import { useParams } from "react-router-dom"; diff --git a/client/src/Pages/v1/StatusPage/Status/Components/AdminLink/index.jsx b/client/src/Pages/StatusPage/Status/Components/AdminLink/index.jsx similarity index 100% rename from client/src/Pages/v1/StatusPage/Status/Components/AdminLink/index.jsx rename to client/src/Pages/StatusPage/Status/Components/AdminLink/index.jsx diff --git a/client/src/Pages/v1/StatusPage/Status/Components/ControlsHeader/index.jsx b/client/src/Pages/StatusPage/Status/Components/ControlsHeader/index.jsx similarity index 97% rename from client/src/Pages/v1/StatusPage/Status/Components/ControlsHeader/index.jsx rename to client/src/Pages/StatusPage/Status/Components/ControlsHeader/index.jsx index c56aa40cc..60a4882f5 100644 --- a/client/src/Pages/v1/StatusPage/Status/Components/ControlsHeader/index.jsx +++ b/client/src/Pages/StatusPage/Status/Components/ControlsHeader/index.jsx @@ -1,7 +1,7 @@ // Components import { Box, Stack, Typography, Button } from "@mui/material"; import Image from "@/Components/v1/Image/index.jsx"; -import SettingsIcon from "../../../../../../assets/icons/settings-bold.svg?react"; +import SettingsIcon from "@/assets/icons/settings-bold.svg?react"; import ThemeSwitch from "@/Components/v1/ThemeSwitch/index.jsx"; import ArrowOutwardIcon from "@mui/icons-material/ArrowOutward"; //Utils diff --git a/client/src/Pages/v1/StatusPage/Status/Components/MonitorsList/index.jsx b/client/src/Pages/StatusPage/Status/Components/MonitorsList/index.jsx similarity index 95% rename from client/src/Pages/v1/StatusPage/Status/Components/MonitorsList/index.jsx rename to client/src/Pages/StatusPage/Status/Components/MonitorsList/index.jsx index 1628b3d44..89e32e5d5 100644 --- a/client/src/Pages/v1/StatusPage/Status/Components/MonitorsList/index.jsx +++ b/client/src/Pages/StatusPage/Status/Components/MonitorsList/index.jsx @@ -6,7 +6,7 @@ import { StatusLabel } from "@/Components/v1/Label/index.jsx"; //Utils import { useTheme } from "@mui/material/styles"; -import { useMonitorUtils } from "../../../../../../Hooks/v1/useMonitorUtils.js"; +import { useMonitorUtils } from "../../../../../Hooks/useMonitorUtils.js"; import PropTypes from "prop-types"; import { useSelector } from "react-redux"; diff --git a/client/src/Pages/v1/StatusPage/Status/Components/Skeleton/index.jsx b/client/src/Pages/StatusPage/Status/Components/Skeleton/index.jsx similarity index 100% rename from client/src/Pages/v1/StatusPage/Status/Components/Skeleton/index.jsx rename to client/src/Pages/StatusPage/Status/Components/Skeleton/index.jsx diff --git a/client/src/Pages/v1/StatusPage/Status/Components/StatusBar/index.jsx b/client/src/Pages/StatusPage/Status/Components/StatusBar/index.jsx similarity index 100% rename from client/src/Pages/v1/StatusPage/Status/Components/StatusBar/index.jsx rename to client/src/Pages/StatusPage/Status/Components/StatusBar/index.jsx diff --git a/client/src/Pages/v1/StatusPage/Status/Hooks/useStatusPageDelete.jsx b/client/src/Pages/StatusPage/Status/Hooks/useStatusPageDelete.jsx similarity index 89% rename from client/src/Pages/v1/StatusPage/Status/Hooks/useStatusPageDelete.jsx rename to client/src/Pages/StatusPage/Status/Hooks/useStatusPageDelete.jsx index 038a771ba..73b9a8a5f 100644 --- a/client/src/Pages/v1/StatusPage/Status/Hooks/useStatusPageDelete.jsx +++ b/client/src/Pages/StatusPage/Status/Hooks/useStatusPageDelete.jsx @@ -1,6 +1,6 @@ import { useState } from "react"; -import { networkService } from "../../../../../Utils/NetworkService.js"; -import { createToast } from "../../../../../Utils/toastUtils.jsx"; +import { networkService } from "../../../../Utils/NetworkService.js"; +import { createToast } from "../../../../Utils/toastUtils.jsx"; import { useTranslation } from "react-i18next"; /** diff --git a/client/src/Pages/v1/StatusPage/Status/Hooks/useStatusPageFetch.jsx b/client/src/Pages/StatusPage/Status/Hooks/useStatusPageFetch.jsx similarity index 87% rename from client/src/Pages/v1/StatusPage/Status/Hooks/useStatusPageFetch.jsx rename to client/src/Pages/StatusPage/Status/Hooks/useStatusPageFetch.jsx index 506082887..7db6b6c5e 100644 --- a/client/src/Pages/v1/StatusPage/Status/Hooks/useStatusPageFetch.jsx +++ b/client/src/Pages/StatusPage/Status/Hooks/useStatusPageFetch.jsx @@ -1,9 +1,9 @@ import { useEffect, useState, useCallback } from "react"; -import { networkService } from "../../../../../main.jsx"; +import { networkService } from "../../../../main.jsx"; import { useSelector } from "react-redux"; -import { createToast } from "../../../../../Utils/toastUtils.jsx"; +import { createToast } from "../../../../Utils/toastUtils.jsx"; import { useTheme } from "@emotion/react"; -import { useMonitorUtils } from "../../../../../Hooks/v1/useMonitorUtils.js"; +import { useMonitorUtils } from "../../../../Hooks/useMonitorUtils.js"; const useStatusPageFetch = (isCreate = false, url) => { const [isLoading, setIsLoading] = useState(true); diff --git a/client/src/Pages/v1/StatusPage/Status/index.jsx b/client/src/Pages/StatusPage/Status/index.jsx similarity index 98% rename from client/src/Pages/v1/StatusPage/Status/index.jsx rename to client/src/Pages/StatusPage/Status/index.jsx index e700bbbd9..adcd9c2c7 100644 --- a/client/src/Pages/v1/StatusPage/Status/index.jsx +++ b/client/src/Pages/StatusPage/Status/index.jsx @@ -12,7 +12,7 @@ import TextLink from "@/Components/v1/TextLink/index.jsx"; // Utils import { useStatusPageFetch } from "./Hooks/useStatusPageFetch.jsx"; import { useTheme } from "@emotion/react"; -import { useIsAdmin } from "../../../../Hooks/v1/useIsAdmin.js"; +import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; import { useLocation } from "react-router-dom"; import { useParams } from "react-router-dom"; import { useTranslation } from "react-i18next"; diff --git a/client/src/Pages/v1/StatusPage/StatusPages/Components/StatusPagesTable/index.jsx b/client/src/Pages/StatusPage/StatusPages/Components/StatusPagesTable/index.jsx similarity index 100% rename from client/src/Pages/v1/StatusPage/StatusPages/Components/StatusPagesTable/index.jsx rename to client/src/Pages/StatusPage/StatusPages/Components/StatusPagesTable/index.jsx diff --git a/client/src/Pages/v1/StatusPage/StatusPages/Hooks/useStatusPagesFetch.jsx b/client/src/Pages/StatusPage/StatusPages/Hooks/useStatusPagesFetch.jsx similarity index 86% rename from client/src/Pages/v1/StatusPage/StatusPages/Hooks/useStatusPagesFetch.jsx rename to client/src/Pages/StatusPage/StatusPages/Hooks/useStatusPagesFetch.jsx index 89df1b84d..839ff4cdf 100644 --- a/client/src/Pages/v1/StatusPage/StatusPages/Hooks/useStatusPagesFetch.jsx +++ b/client/src/Pages/StatusPage/StatusPages/Hooks/useStatusPagesFetch.jsx @@ -1,7 +1,7 @@ import { useState, useEffect } from "react"; -import { networkService } from "../../../../../main.jsx"; +import { networkService } from "../../../../main.jsx"; import { useSelector } from "react-redux"; -import { createToast } from "../../../../../Utils/toastUtils.jsx"; +import { createToast } from "../../../../Utils/toastUtils.jsx"; const useStatusPagesFetch = () => { const { user } = useSelector((state) => state.auth); diff --git a/client/src/Pages/v1/StatusPage/StatusPages/index.jsx b/client/src/Pages/StatusPage/StatusPages/index.jsx similarity index 95% rename from client/src/Pages/v1/StatusPage/StatusPages/index.jsx rename to client/src/Pages/StatusPage/StatusPages/index.jsx index 3c60fe950..7137d01ad 100644 --- a/client/src/Pages/v1/StatusPage/StatusPages/index.jsx +++ b/client/src/Pages/StatusPage/StatusPages/index.jsx @@ -7,7 +7,7 @@ import PageStateWrapper from "@/Components/v1/PageStateWrapper/index.jsx"; // Utils import { useTheme } from "@emotion/react"; import { useStatusPagesFetch } from "./Hooks/useStatusPagesFetch.jsx"; -import { useIsAdmin } from "../../../../Hooks/v1/useIsAdmin.js"; +import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; const BREADCRUMBS = [{ name: `Status Pages`, path: "" }]; const StatusPages = () => { diff --git a/client/src/Pages/v1/Uptime/BulkImport/Upload.jsx b/client/src/Pages/Uptime/BulkImport/Upload.jsx similarity index 100% rename from client/src/Pages/v1/Uptime/BulkImport/Upload.jsx rename to client/src/Pages/Uptime/BulkImport/Upload.jsx diff --git a/client/src/Pages/v1/Uptime/BulkImport/index.jsx b/client/src/Pages/Uptime/BulkImport/index.jsx similarity index 95% rename from client/src/Pages/v1/Uptime/BulkImport/index.jsx rename to client/src/Pages/Uptime/BulkImport/index.jsx index 9f3efcd67..6f2f7bcb5 100644 --- a/client/src/Pages/v1/Uptime/BulkImport/index.jsx +++ b/client/src/Pages/Uptime/BulkImport/index.jsx @@ -5,14 +5,14 @@ import { useState } from "react"; import { Box, Stack, Typography, Button, Link } from "@mui/material"; //Components -import { createToast } from "../../../../Utils/toastUtils.jsx"; +import { createToast } from "../../../Utils/toastUtils.jsx"; import Breadcrumbs from "@/Components/v1/Breadcrumbs/index.jsx"; import ConfigBox from "@/Components/v1/ConfigBox/index.jsx"; import UploadFile from "./Upload.jsx"; import { useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; import { Trans, useTranslation } from "react-i18next"; -import { useCreateBulkMonitors } from "../../../../Hooks/v1/monitorHooks.js"; +import { useCreateBulkMonitors } from "../../../Hooks/monitorHooks.js"; const BulkImport = () => { const theme = useTheme(); diff --git a/client/src/Pages/v1/Uptime/Create/index.css b/client/src/Pages/Uptime/Create/index.css similarity index 100% rename from client/src/Pages/v1/Uptime/Create/index.css rename to client/src/Pages/Uptime/Create/index.css diff --git a/client/src/Pages/v1/Uptime/Create/index.jsx b/client/src/Pages/Uptime/Create/index.jsx similarity index 98% rename from client/src/Pages/v1/Uptime/Create/index.jsx rename to client/src/Pages/Uptime/Create/index.jsx index 202f64d85..c3421e875 100644 --- a/client/src/Pages/v1/Uptime/Create/index.jsx +++ b/client/src/Pages/Uptime/Create/index.jsx @@ -26,14 +26,14 @@ import PropTypes from "prop-types"; import { useTheme } from "@emotion/react"; import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import { monitorValidation } from "../../../../Validation/validation.js"; -import { createToast } from "../../../../Utils/toastUtils.jsx"; +import { monitorValidation } from "../../../Validation/validation.js"; +import { createToast } from "../../../Utils/toastUtils.jsx"; import { PauseOutlined as PauseOutlinedIcon, PlayArrowOutlined as PlayArrowOutlinedIcon, } from "@mui/icons-material"; -import { useMonitorUtils } from "../../../../Hooks/v1/useMonitorUtils.js"; -import { useGetNotificationsByTeamId } from "../../../../Hooks/v1/useNotifications.js"; +import { useMonitorUtils } from "../../../Hooks/useMonitorUtils.js"; +import { useGetNotificationsByTeamId } from "../../../Hooks/useNotifications.js"; import { useParams } from "react-router-dom"; import { useCreateMonitor, @@ -42,7 +42,7 @@ import { usePauseMonitor, useFetchMonitorById, useFetchMonitorGames, -} from "../../../../Hooks/v1/monitorHooks.js"; +} from "../../../Hooks/monitorHooks.js"; /** * Create page renders monitor creation or configuration views. @@ -287,7 +287,8 @@ const UptimeCreate = ({ isClone = false }) => { const handleRemove = async (event) => { event.preventDefault(); - await deleteMonitor({ monitor, redirect: "/uptime" }); + const TEMP_MONITOR = { id: monitor._id }; + await deleteMonitor({ monitor: TEMP_MONITOR, redirect: "/uptime" }); }; const isBusy = isLoading || isCreating || isDeleting || isUpdating || isPausing; diff --git a/client/src/Pages/v1/Uptime/Create/skeleton.jsx b/client/src/Pages/Uptime/Create/skeleton.jsx similarity index 100% rename from client/src/Pages/v1/Uptime/Create/skeleton.jsx rename to client/src/Pages/Uptime/Create/skeleton.jsx diff --git a/client/src/Pages/v1/Uptime/Details/Components/ChartBoxes/index.jsx b/client/src/Pages/Uptime/Details/Components/ChartBoxes/index.jsx similarity index 92% rename from client/src/Pages/v1/Uptime/Details/Components/ChartBoxes/index.jsx rename to client/src/Pages/Uptime/Details/Components/ChartBoxes/index.jsx index 45f35a42e..582c7891f 100644 --- a/client/src/Pages/v1/Uptime/Details/Components/ChartBoxes/index.jsx +++ b/client/src/Pages/Uptime/Details/Components/ChartBoxes/index.jsx @@ -1,15 +1,15 @@ // Components import { Stack, Typography, Box } from "@mui/material"; import ChartBox from "@/Components/v1/Charts/ChartBox/index.jsx"; -import UptimeIcon from "../../../../../../assets/icons/uptime-icon.svg?react"; -import IncidentsIcon from "../../../../../../assets/icons/incidents.svg?react"; -import AverageResponseIcon from "../../../../../../assets/icons/average-response-icon.svg?react"; +import UptimeIcon from "@/assets/icons/uptime-icon.svg?react"; +import IncidentsIcon from "@/assets/icons/incidents.svg?react"; +import AverageResponseIcon from "@/assets/icons/average-response-icon.svg?react"; import UpBarChart from "../Charts/UpBarChart.jsx"; import DownBarChart from "../Charts/DownBarChart.jsx"; import ResponseGaugeChart from "../Charts/ResponseGaugeChart.jsx"; import SkeletonLayout from "./skeleton.jsx"; // Utils -import { formatDateWithTz } from "../../../../../../Utils/timeUtils.js"; +import { formatDateWithTz } from "../../../../../Utils/timeUtils.js"; import PropTypes from "prop-types"; import { useTheme } from "@emotion/react"; import { useState } from "react"; diff --git a/client/src/Pages/v1/Uptime/Details/Components/ChartBoxes/skeleton.jsx b/client/src/Pages/Uptime/Details/Components/ChartBoxes/skeleton.jsx similarity index 100% rename from client/src/Pages/v1/Uptime/Details/Components/ChartBoxes/skeleton.jsx rename to client/src/Pages/Uptime/Details/Components/ChartBoxes/skeleton.jsx diff --git a/client/src/Pages/v1/Uptime/Details/Components/Charts/CustomLabels.jsx b/client/src/Pages/Uptime/Details/Components/Charts/CustomLabels.jsx similarity index 93% rename from client/src/Pages/v1/Uptime/Details/Components/Charts/CustomLabels.jsx rename to client/src/Pages/Uptime/Details/Components/Charts/CustomLabels.jsx index c9c1ff58d..472c8d058 100644 --- a/client/src/Pages/v1/Uptime/Details/Components/Charts/CustomLabels.jsx +++ b/client/src/Pages/Uptime/Details/Components/Charts/CustomLabels.jsx @@ -1,6 +1,6 @@ import PropTypes from "prop-types"; import { useSelector } from "react-redux"; -import { formatDateWithTz } from "../../../../../../Utils/timeUtils.js"; +import { formatDateWithTz } from "../../../../../Utils/timeUtils.js"; const CustomLabels = ({ x, width, height, firstDataPoint, lastDataPoint, type }) => { const uiTimezone = useSelector((state) => state.ui.timezone); diff --git a/client/src/Pages/v1/Uptime/Details/Components/Charts/DownBarChart.jsx b/client/src/Pages/Uptime/Details/Components/Charts/DownBarChart.jsx similarity index 100% rename from client/src/Pages/v1/Uptime/Details/Components/Charts/DownBarChart.jsx rename to client/src/Pages/Uptime/Details/Components/Charts/DownBarChart.jsx diff --git a/client/src/Pages/v1/Uptime/Details/Components/Charts/ResponseGaugeChart.jsx b/client/src/Pages/Uptime/Details/Components/Charts/ResponseGaugeChart.jsx similarity index 100% rename from client/src/Pages/v1/Uptime/Details/Components/Charts/ResponseGaugeChart.jsx rename to client/src/Pages/Uptime/Details/Components/Charts/ResponseGaugeChart.jsx diff --git a/client/src/Pages/v1/Uptime/Details/Components/Charts/ResponseTimeChart.jsx b/client/src/Pages/Uptime/Details/Components/Charts/ResponseTimeChart.jsx similarity index 89% rename from client/src/Pages/v1/Uptime/Details/Components/Charts/ResponseTimeChart.jsx rename to client/src/Pages/Uptime/Details/Components/Charts/ResponseTimeChart.jsx index daa7b4f53..861b600d4 100644 --- a/client/src/Pages/v1/Uptime/Details/Components/Charts/ResponseTimeChart.jsx +++ b/client/src/Pages/Uptime/Details/Components/Charts/ResponseTimeChart.jsx @@ -1,6 +1,6 @@ import ChartBox from "@/Components/v1/Charts/ChartBox/index.jsx"; import MonitorDetailsAreaChart from "@/Components/v1/Charts/MonitorDetailsAreaChart/index.jsx"; -import ResponseTimeIcon from "../../../../../../assets/icons/response-time-icon.svg?react"; +import ResponseTimeIcon from "@/assets/icons/response-time-icon.svg?react"; import SkeletonLayout from "./ResponseTimeChartSkeleton.jsx"; import PropTypes from "prop-types"; diff --git a/client/src/Pages/v1/Uptime/Details/Components/Charts/ResponseTimeChartSkeleton.jsx b/client/src/Pages/Uptime/Details/Components/Charts/ResponseTimeChartSkeleton.jsx similarity index 100% rename from client/src/Pages/v1/Uptime/Details/Components/Charts/ResponseTimeChartSkeleton.jsx rename to client/src/Pages/Uptime/Details/Components/Charts/ResponseTimeChartSkeleton.jsx diff --git a/client/src/Pages/v1/Uptime/Details/Components/Charts/UpBarChart.jsx b/client/src/Pages/Uptime/Details/Components/Charts/UpBarChart.jsx similarity index 100% rename from client/src/Pages/v1/Uptime/Details/Components/Charts/UpBarChart.jsx rename to client/src/Pages/Uptime/Details/Components/Charts/UpBarChart.jsx diff --git a/client/src/Pages/v1/Uptime/Details/Components/ResponseTable/index.jsx b/client/src/Pages/Uptime/Details/Components/ResponseTable/index.jsx similarity index 97% rename from client/src/Pages/v1/Uptime/Details/Components/ResponseTable/index.jsx rename to client/src/Pages/Uptime/Details/Components/ResponseTable/index.jsx index 0d0defc3b..0715561d4 100644 --- a/client/src/Pages/v1/Uptime/Details/Components/ResponseTable/index.jsx +++ b/client/src/Pages/Uptime/Details/Components/ResponseTable/index.jsx @@ -1,11 +1,11 @@ import ChartBox from "@/Components/v1/Charts/ChartBox/index.jsx"; import PropTypes from "prop-types"; -import HistoryIcon from "../../../../../../assets/icons/history-icon.svg?react"; +import HistoryIcon from "@/assets/icons/history-icon.svg?react"; import Table from "@/Components/v1/Table/index.jsx"; import TablePagination from "@/Components/v1/Table/TablePagination/index.jsx"; import { StatusLabel } from "@/Components/v1/Label/index.jsx"; import { useTranslation } from "react-i18next"; -import { formatDateWithTz } from "../../../../../../Utils/timeUtils.js"; +import { formatDateWithTz } from "../../../../../Utils/timeUtils.js"; import SkeletonLayout from "./skeleton.jsx"; import Tooltip from "@mui/material/Tooltip"; import Box from "@mui/material/Box"; diff --git a/client/src/Pages/v1/Uptime/Details/Components/ResponseTable/skeleton.jsx b/client/src/Pages/Uptime/Details/Components/ResponseTable/skeleton.jsx similarity index 100% rename from client/src/Pages/v1/Uptime/Details/Components/ResponseTable/skeleton.jsx rename to client/src/Pages/Uptime/Details/Components/ResponseTable/skeleton.jsx diff --git a/client/src/Pages/v1/Uptime/Details/Components/UptimeStatusBoxes/index.jsx b/client/src/Pages/Uptime/Details/Components/UptimeStatusBoxes/index.jsx similarity index 92% rename from client/src/Pages/v1/Uptime/Details/Components/UptimeStatusBoxes/index.jsx rename to client/src/Pages/Uptime/Details/Components/UptimeStatusBoxes/index.jsx index a7b971839..0bfdc1096 100644 --- a/client/src/Pages/v1/Uptime/Details/Components/UptimeStatusBoxes/index.jsx +++ b/client/src/Pages/Uptime/Details/Components/UptimeStatusBoxes/index.jsx @@ -2,10 +2,10 @@ import StatusBoxes from "@/Components/v1/StatusBoxes/index.jsx"; import StatBox from "@/Components/v1/StatBox/index.jsx"; import PropTypes from "prop-types"; -import { getHumanReadableDuration } from "../../../../../../Utils/timeUtils.js"; +import { getHumanReadableDuration } from "../../../../../Utils/timeUtils.js"; import { useTheme } from "@mui/material/styles"; import { Typography } from "@mui/material"; -import { useMonitorUtils } from "../../../../../../Hooks/v1/useMonitorUtils.js"; +import { useMonitorUtils } from "../../../../../Hooks/useMonitorUtils.js"; const UptimeStatusBoxes = ({ isLoading = false, diff --git a/client/src/Pages/v1/Uptime/Details/Hooks/useCertificateFetch.jsx b/client/src/Pages/Uptime/Details/Hooks/useCertificateFetch.jsx similarity index 84% rename from client/src/Pages/v1/Uptime/Details/Hooks/useCertificateFetch.jsx rename to client/src/Pages/Uptime/Details/Hooks/useCertificateFetch.jsx index f85111f97..e74a99d82 100644 --- a/client/src/Pages/v1/Uptime/Details/Hooks/useCertificateFetch.jsx +++ b/client/src/Pages/Uptime/Details/Hooks/useCertificateFetch.jsx @@ -1,7 +1,7 @@ -import { logger } from "../../../../../Utils/Logger.js"; +import { logger } from "../../../../Utils/Logger.js"; import { useEffect, useState } from "react"; -import { networkService } from "../../../../../main.jsx"; -import { formatDateWithTz } from "../../../../../Utils/timeUtils.js"; +import { networkService } from "../../../../main.jsx"; +import { formatDateWithTz } from "../../../../Utils/timeUtils.js"; const useCertificateFetch = ({ monitor, diff --git a/client/src/Pages/v1/Uptime/Details/index.jsx b/client/src/Pages/Uptime/Details/index.jsx similarity index 95% rename from client/src/Pages/v1/Uptime/Details/index.jsx rename to client/src/Pages/Uptime/Details/index.jsx index f5e283495..144ceb4dc 100644 --- a/client/src/Pages/v1/Uptime/Details/index.jsx +++ b/client/src/Pages/Uptime/Details/index.jsx @@ -15,10 +15,10 @@ import { useState } from "react"; import { useParams } from "react-router-dom"; import { useSelector } from "react-redux"; import { useTheme } from "@emotion/react"; -import { useIsAdmin } from "../../../../Hooks/v1/useIsAdmin.js"; -import { useFetchUptimeMonitorById } from "../../../../Hooks/v1/monitorHooks.js"; +import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; +import { useFetchUptimeMonitorById } from "../../../Hooks/monitorHooks.js"; import useCertificateFetch from "./Hooks/useCertificateFetch.jsx"; -import { useFetchChecksByMonitor } from "../../../../Hooks/v1/checkHooks.js"; +import { useFetchChecksByMonitor } from "../../../Hooks/checkHooks.js"; import { useTranslation } from "react-i18next"; // Constants diff --git a/client/src/Pages/v1/Uptime/Monitors/Components/Filter/index.jsx b/client/src/Pages/Uptime/Monitors/Components/Filter/index.jsx similarity index 100% rename from client/src/Pages/v1/Uptime/Monitors/Components/Filter/index.jsx rename to client/src/Pages/Uptime/Monitors/Components/Filter/index.jsx diff --git a/client/src/Pages/v1/Uptime/Monitors/Components/LoadingSpinner/index.jsx b/client/src/Pages/Uptime/Monitors/Components/LoadingSpinner/index.jsx similarity index 100% rename from client/src/Pages/v1/Uptime/Monitors/Components/LoadingSpinner/index.jsx rename to client/src/Pages/Uptime/Monitors/Components/LoadingSpinner/index.jsx diff --git a/client/src/Pages/v1/Uptime/Monitors/Components/SearchComponent/index.jsx b/client/src/Pages/Uptime/Monitors/Components/SearchComponent/index.jsx similarity index 100% rename from client/src/Pages/v1/Uptime/Monitors/Components/SearchComponent/index.jsx rename to client/src/Pages/Uptime/Monitors/Components/SearchComponent/index.jsx diff --git a/client/src/Pages/v1/Uptime/Monitors/Components/Skeleton/index.jsx b/client/src/Pages/Uptime/Monitors/Components/Skeleton/index.jsx similarity index 100% rename from client/src/Pages/v1/Uptime/Monitors/Components/Skeleton/index.jsx rename to client/src/Pages/Uptime/Monitors/Components/Skeleton/index.jsx diff --git a/client/src/Pages/v1/Uptime/Monitors/Components/StatusBoxes/index.jsx b/client/src/Pages/Uptime/Monitors/Components/StatusBoxes/index.jsx similarity index 100% rename from client/src/Pages/v1/Uptime/Monitors/Components/StatusBoxes/index.jsx rename to client/src/Pages/Uptime/Monitors/Components/StatusBoxes/index.jsx diff --git a/client/src/Pages/v1/Uptime/Monitors/Components/StatusBoxes/skeleton.jsx b/client/src/Pages/Uptime/Monitors/Components/StatusBoxes/skeleton.jsx similarity index 100% rename from client/src/Pages/v1/Uptime/Monitors/Components/StatusBoxes/skeleton.jsx rename to client/src/Pages/Uptime/Monitors/Components/StatusBoxes/skeleton.jsx diff --git a/client/src/Pages/v1/Uptime/Monitors/Components/StatusBoxes/statusBox.jsx b/client/src/Pages/Uptime/Monitors/Components/StatusBoxes/statusBox.jsx similarity index 90% rename from client/src/Pages/v1/Uptime/Monitors/Components/StatusBoxes/statusBox.jsx rename to client/src/Pages/Uptime/Monitors/Components/StatusBoxes/statusBox.jsx index c745e7935..c9015816a 100644 --- a/client/src/Pages/v1/Uptime/Monitors/Components/StatusBoxes/statusBox.jsx +++ b/client/src/Pages/Uptime/Monitors/Components/StatusBoxes/statusBox.jsx @@ -1,9 +1,9 @@ import PropTypes from "prop-types"; import { useTheme } from "@emotion/react"; import { Box, Stack, Typography } from "@mui/material"; -import Arrow from "../../../../../../assets/icons/top-right-arrow.svg?react"; -import Background from "../../../../../../assets/Images/background-grid.svg?react"; -import ClockSnooze from "../../../../../../assets/icons/clock-snooze.svg?react"; +import Arrow from "@/assets/icons/top-right-arrow.svg?react"; +import Background from "@/assets/Images/background-grid.svg?react"; +import ClockSnooze from "@/assets/icons/clock-snooze.svg?react"; const StatusBox = ({ title, value, status }) => { const theme = useTheme(); diff --git a/client/src/Pages/v1/Uptime/Monitors/Components/UptimeDataTable/index.jsx b/client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx similarity index 97% rename from client/src/Pages/v1/Uptime/Monitors/Components/UptimeDataTable/index.jsx rename to client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx index 9cf2d247d..fe220251d 100644 --- a/client/src/Pages/v1/Uptime/Monitors/Components/UptimeDataTable/index.jsx +++ b/client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx @@ -13,7 +13,7 @@ import TableSkeleton from "@/Components/v1/Table/skeleton.jsx"; // Utils import { useTheme } from "@emotion/react"; -import { useMonitorUtils } from "../../../../../../Hooks/v1/useMonitorUtils.js"; +import { useMonitorUtils } from "../../../../../Hooks/useMonitorUtils.js"; import { useNavigate } from "react-router-dom"; import PropTypes from "prop-types"; import { useTranslation } from "react-i18next"; @@ -24,13 +24,13 @@ import { useTranslation } from "react-i18next"; * @param {boolean} props.isAdmin - Whether the current user has admin privileges * @param {boolean} props.isLoading - Loading state of the table * @param {Array<{ - * _id: string, + * id: string, * url: string, * title: string, * percentage: number, * percentageColor: string, * monitor: { - * _id: string, + * id: string, * type: string, * checks: Array * } @@ -101,7 +101,7 @@ const UptimeDataTable = ({ ), render: (row) => ( { - navigate(`/uptime/${row._id}`); + navigate(`/uptime/${row.id}`); }, emptyView: "No monitors found", }} diff --git a/client/src/Pages/v1/Uptime/Monitors/Hooks/useDebounce.jsx b/client/src/Pages/Uptime/Monitors/Hooks/useDebounce.jsx similarity index 100% rename from client/src/Pages/v1/Uptime/Monitors/Hooks/useDebounce.jsx rename to client/src/Pages/Uptime/Monitors/Hooks/useDebounce.jsx diff --git a/client/src/Pages/v1/Uptime/Monitors/index.jsx b/client/src/Pages/Uptime/Monitors/index.jsx similarity index 96% rename from client/src/Pages/v1/Uptime/Monitors/index.jsx rename to client/src/Pages/Uptime/Monitors/index.jsx index cacfc23b4..9a73fae63 100644 --- a/client/src/Pages/v1/Uptime/Monitors/index.jsx +++ b/client/src/Pages/Uptime/Monitors/index.jsx @@ -5,7 +5,7 @@ // Components import Breadcrumbs from "@/Components/v1/Breadcrumbs/index.jsx"; -import Greeting from "../../../../Utils/greeting.jsx"; +import Greeting from "../../../Utils/greeting.jsx"; import StatusBoxes from "./Components/StatusBoxes/index.jsx"; import UptimeDataTable from "./Components/UptimeDataTable/index.jsx"; import Pagination from "@/Components/v1/Table/TablePagination/index.jsx"; @@ -20,16 +20,16 @@ import MonitorCountHeader from "@/Components/v1/MonitorCountHeader/index.jsx"; import { Stack, Box, Button } from "@mui/material"; // Utils import { useState, useCallback, useEffect } from "react"; -import { useIsAdmin } from "../../../../Hooks/v1/useIsAdmin.js"; +import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; import { useTheme } from "@emotion/react"; import { useNavigate } from "react-router-dom"; import { useSelector, useDispatch } from "react-redux"; -import { setRowsPerPage } from "../../../../Features/UI/uiSlice.js"; +import { setRowsPerPage } from "../../../Features/UI/uiSlice.js"; import PropTypes from "prop-types"; import { useFetchMonitorsWithSummary, useFetchMonitorsWithChecks, -} from "../../../../Hooks/v1/monitorHooks.js"; +} from "../../../Hooks/monitorHooks.js"; import { useTranslation } from "react-i18next"; const TYPES = ["http", "ping", "docker", "port", "game"]; diff --git a/client/src/Routes/index.jsx b/client/src/Routes/index.jsx index 255d913c1..d9f6d58cb 100644 --- a/client/src/Routes/index.jsx +++ b/client/src/Routes/index.jsx @@ -1,58 +1,58 @@ import { useSelector } from "react-redux"; import { Navigate, Route, Routes as LibRoutes } from "react-router"; import HomeLayout from "@/Components/v1/Layouts/HomeLayout"; -import NotFound from "../Pages/v1/NotFound"; +import NotFound from "../Pages/NotFound/index.jsx"; // Auth -import AuthLogin from "../Pages/v1/Auth/Login"; -import AuthRegister from "../Pages/v1/Auth/Register/"; -import AuthForgotPassword from "../Pages/v1/Auth/ForgotPassword"; -import AuthCheckEmail from "../Pages/v1/Auth/CheckEmail"; -import AuthSetNewPassword from "../Pages/v1/Auth/SetNewPassword"; -import AuthNewPasswordConfirmed from "../Pages/v1/Auth/NewPasswordConfirmed"; +import AuthLogin from "../Pages/Auth/Login/index.jsx"; +import AuthRegister from "../Pages/Auth/Register/index.jsx"; +import AuthForgotPassword from "../Pages/Auth/ForgotPassword.jsx"; +import AuthCheckEmail from "../Pages/Auth/CheckEmail.jsx"; +import AuthSetNewPassword from "../Pages/Auth/SetNewPassword.jsx"; +import AuthNewPasswordConfirmed from "../Pages/Auth/NewPasswordConfirmed.jsx"; // Uptime -import Uptime from "../Pages/v1/Uptime/Monitors"; -import UptimeDetails from "../Pages/v1/Uptime/Details"; -import UptimeCreate from "../Pages/v1/Uptime/Create"; +import Uptime from "../Pages/Uptime/Monitors/index.jsx"; +import UptimeDetails from "../Pages/Uptime/Details/index.jsx"; +import UptimeCreate from "../Pages/Uptime/Create/index.jsx"; // PageSpeed -import PageSpeed from "../Pages/v1/PageSpeed/Monitors"; -import PageSpeedDetails from "../Pages/v1/PageSpeed/Details"; -import PageSpeedCreate from "../Pages/v1/PageSpeed/Create"; +import PageSpeed from "../Pages/PageSpeed/Monitors/index.jsx"; +import PageSpeedDetails from "../Pages/PageSpeed/Details/index.jsx"; +import PageSpeedCreate from "../Pages/PageSpeed/Create/index.jsx"; // Infrastructure -import Infrastructure from "../Pages/v1/Infrastructure/Monitors"; -import InfrastructureCreate from "../Pages/v1/Infrastructure/Create"; -import InfrastructureDetails from "../Pages/v1/Infrastructure/Details"; +import Infrastructure from "../Pages/Infrastructure/Monitors/index.jsx"; +import InfrastructureCreate from "../Pages/Infrastructure/Create/index.jsx"; +import InfrastructureDetails from "../Pages/Infrastructure/Details/index.jsx"; // Server Status -import ServerUnreachable from "../Pages/v1/ServerUnreachable.jsx"; +import ServerUnreachable from "../Pages/ServerUnreachable.jsx"; // Incidents -import Checks from "../Pages/v1/Incidents"; -import Incidents2 from "../Pages/v1/Incidents2"; +import Checks from "../Pages/Incidents"; +import Incidents2 from "../Pages/Incidents2/index.jsx"; // Status pages -import CreateStatus from "../Pages/v1/StatusPage/Create"; -import StatusPages from "../Pages/v1/StatusPage/StatusPages"; -import Status from "../Pages/v1/StatusPage/Status"; +import CreateStatus from "../Pages/StatusPage/Create/index.jsx"; +import StatusPages from "../Pages/StatusPage/StatusPages/index.jsx"; +import Status from "../Pages/StatusPage/Status/index.jsx"; -import Notifications from "../Pages/v1/Notifications"; -import CreateNotifications from "../Pages/v1/Notifications/create"; +import Notifications from "../Pages/Notifications/index.jsx"; +import CreateNotifications from "../Pages/Notifications/create/index.jsx"; // Settings -import Account from "../Pages/v1/Account"; -import EditUser from "../Pages/v1/Account/EditUser"; -import Settings from "../Pages/v1/Settings"; +import Account from "../Pages/Account/index.jsx"; +import EditUser from "../Pages/Account/EditUser/index.jsx"; +import Settings from "../Pages/Settings"; -import Maintenance from "../Pages/v1/Maintenance"; +import Maintenance from "../Pages/Maintenance/index.jsx"; import ProtectedRoute from "../Components/v1/ProtectedRoute"; import RoleProtectedRoute from "../Components/v1/RoleProtectedRoute"; -import CreateNewMaintenanceWindow from "../Pages/v1/Maintenance/CreateMaintenance"; +import CreateNewMaintenanceWindow from "../Pages/Maintenance/CreateMaintenance/index.jsx"; import withAdminCheck from "@/Components/v1/HOC/withAdminCheck"; -import BulkImport from "../Pages/v1/Uptime/BulkImport"; -import Logs from "../Pages/v1/Logs"; +import BulkImport from "../Pages/Uptime/BulkImport/index.jsx"; +import Logs from "../Pages/Logs/index.jsx"; const Routes = () => { const mode = useSelector((state) => state.ui.mode); diff --git a/server/src/db/models/Check.ts b/server/src/db/models/Check.ts index b4a31f8f7..3ebacd3f6 100644 --- a/server/src/db/models/Check.ts +++ b/server/src/db/models/Check.ts @@ -16,6 +16,7 @@ import type { CheckNetworkInterfaceInfo, CheckTimings, CheckTimingPhases, + ILighthouseAudit, } from "@/types/check.js"; type CheckMetadataDocument = Omit & { @@ -149,13 +150,25 @@ const networkInterfaceSchema = new Schema( { _id: false } ); +const lighthouseAuditSchema = new Schema( + { + id: { type: String }, + title: { type: String }, + score: { type: Number }, + displayValue: { type: String }, + numericValue: { type: Number }, + numericUnit: { type: String }, + }, + { _id: false } +); + const auditsSchema = new Schema( { - cls: { type: Number, default: 0 }, - si: { type: Number, default: 0 }, - fcp: { type: Number, default: 0 }, - lcp: { type: Number, default: 0 }, - tbt: { type: Number, default: 0 }, + cls: { type: lighthouseAuditSchema, default: undefined }, + si: { type: lighthouseAuditSchema, default: undefined }, + fcp: { type: lighthouseAuditSchema, default: undefined }, + lcp: { type: lighthouseAuditSchema, default: undefined }, + tbt: { type: lighthouseAuditSchema, default: undefined }, }, { _id: false } ); diff --git a/server/src/db/modules/checkModule.js b/server/src/db/modules/checkModule.js index 871761290..e420d5ce7 100755 --- a/server/src/db/modules/checkModule.js +++ b/server/src/db/modules/checkModule.js @@ -22,7 +22,7 @@ class CheckModule { createChecks = async (checks) => { try { - await CheckModel.insertMany(checks, { ordered: false }); + await CheckModel.insertMany(checks, { ordered: false, runValidators: true }); } catch (error) { error.service = SERVICE_NAME; error.method = "createCheck"; diff --git a/server/src/db/modules/monitorModule.js b/server/src/db/modules/monitorModule.js index 316caa2ea..d1d4abc5a 100755 --- a/server/src/db/modules/monitorModule.js +++ b/server/src/db/modules/monitorModule.js @@ -242,7 +242,6 @@ class MonitorModule { const dateString = formatLookup[dateRange]; - console.log("WTTTTFFF"); const results = await CheckModel.aggregate(buildUptimeDetailsPipeline(monitorId, dates, dateString)); const monitorData = results[0]; diff --git a/server/src/service/business/monitorService.js b/server/src/service/business/monitorService.js index f457e5c7a..4bdc45eb4 100644 --- a/server/src/service/business/monitorService.js +++ b/server/src/service/business/monitorService.js @@ -220,7 +220,6 @@ class MonitorService { }; getMonitorsByTeamId = async ({ teamId, limit, type, page, rowsPerPage, filter, field, order }) => { - console.log("que"); const monitors = await this.db.monitorModule.getMonitorsByTeamId({ limit, type, diff --git a/server/src/service/infrastructure/statusService.js b/server/src/service/infrastructure/statusService.js index 843c356ed..5b64c7419 100755 --- a/server/src/service/infrastructure/statusService.js +++ b/server/src/service/infrastructure/statusService.js @@ -367,18 +367,30 @@ class StatusService { } const categories = payload?.lighthouseResult?.categories ?? {}; const audits = payload?.lighthouseResult?.audits ?? {}; - const { - "cumulative-layout-shift": cls = 0, - "speed-index": si = 0, - "first-contentful-paint": fcp = 0, - "largest-contentful-paint": lcp = 0, - "total-blocking-time": tbt = 0, - } = audits; + const mapAudit = (audit) => { + if (!audit || typeof audit !== "object") { + return undefined; + } + return { + id: audit.id, + title: audit.title, + score: typeof audit.score === "number" ? audit.score : audit.score ?? null, + displayValue: audit.displayValue, + numericValue: typeof audit.numericValue === "number" ? audit.numericValue : undefined, + numericUnit: audit.numericUnit, + }; + }; check.accessibility = (categories?.accessibility?.score || 0) * 100; check.bestPractices = (categories?.["best-practices"]?.score || 0) * 100; check.seo = (categories?.seo?.score || 0) * 100; check.performance = (categories?.performance?.score || 0) * 100; - check.audits = { cls, si, fcp, lcp, tbt }; + check.audits = { + cls: mapAudit(audits?.["cumulative-layout-shift"]), + si: mapAudit(audits?.["speed-index"]), + fcp: mapAudit(audits?.["first-contentful-paint"]), + lcp: mapAudit(audits?.["largest-contentful-paint"]), + tbt: mapAudit(audits?.["total-blocking-time"]), + }; } if (type === "hardware") { diff --git a/server/src/types/check.ts b/server/src/types/check.ts index 2120d5de1..28353497e 100644 --- a/server/src/types/check.ts +++ b/server/src/types/check.ts @@ -86,11 +86,20 @@ export interface CheckNetworkInterfaceInfo { } export interface CheckAudits { - cls: number; - si: number; - fcp: number; - lcp: number; - tbt: number; + cls: ILighthouseAudit; + si: ILighthouseAudit; + fcp: ILighthouseAudit; + lcp: ILighthouseAudit; + tbt: ILighthouseAudit; +} + +export interface ILighthouseAudit { + id?: string; + title?: string; + score?: number | null; + displayValue?: string; + numericValue?: number; + numericUnit?: string; } export interface Check { From 2b0a51520a40f28b54877b1658f4c44fbcdc6e35 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Tue, 13 Jan 2026 17:50:31 +0000 Subject: [PATCH 4/9] infra --- .../Pages/Infrastructure/Monitors/index.jsx | 20 +++++++++++-------- client/src/Pages/Uptime/Monitors/index.jsx | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/client/src/Pages/Infrastructure/Monitors/index.jsx b/client/src/Pages/Infrastructure/Monitors/index.jsx index 90817f116..4d739417c 100644 --- a/client/src/Pages/Infrastructure/Monitors/index.jsx +++ b/client/src/Pages/Infrastructure/Monitors/index.jsx @@ -13,7 +13,11 @@ import { useTheme } from "@emotion/react"; import { useEffect, useState } from "react"; import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; import { useTranslation } from "react-i18next"; -import { useFetchMonitorsByTeamId } from "../../../Hooks/monitorHooks.js"; +import { + useFetchMonitorsByTeamId, + useFetchMonitorsWithChecks, +} from "@/Hooks/monitorHooks.js"; + import { useDispatch, useSelector } from "react-redux"; import { setRowsPerPage } from "../../../Features/UI/uiSlice.js"; // Constants @@ -70,14 +74,14 @@ const InfrastructureMonitors = () => { const field = toFilterStatus !== undefined ? "status" : undefined; - const [monitors, summary, isLoading, networkError] = useFetchMonitorsByTeamId({ - limit: 1, + const [monitors, count, isLoading, networkError] = useFetchMonitorsWithChecks({ types: TYPES, - page, + limit: 1, + page: page, field: field, filter: toFilterStatus ?? search, - rowsPerPage, - updateTrigger, + rowsPerPage: rowsPerPage, + monitorUpdateTrigger: updateTrigger, }); return ( @@ -99,7 +103,7 @@ const InfrastructureMonitors = () => { { isSearching={isSearching} /> Date: Tue, 13 Jan 2026 18:37:22 +0000 Subject: [PATCH 5/9] _id -> id --- .../Infrastructure/Monitors/Components/MonitorsTable/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/Pages/Infrastructure/Monitors/Components/MonitorsTable/index.jsx b/client/src/Pages/Infrastructure/Monitors/Components/MonitorsTable/index.jsx index 510115d8a..5f0360312 100644 --- a/client/src/Pages/Infrastructure/Monitors/Components/MonitorsTable/index.jsx +++ b/client/src/Pages/Infrastructure/Monitors/Components/MonitorsTable/index.jsx @@ -115,7 +115,7 @@ const MonitorsTable = ({ : theme.palette.success.main; return { - id: monitor._id, + id: monitor.id, name: monitor.name, url: monitor.url, processor, From f8e88623a881fb5b55126de8b325a1bed3c225ac Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Tue, 13 Jan 2026 18:54:28 +0000 Subject: [PATCH 6/9] hardware details pipeline refactor --- server/src/db/modules/monitorModule.js | 16 +- server/src/db/modules/monitorModuleQueries.js | 829 ++++-------------- 2 files changed, 188 insertions(+), 657 deletions(-) diff --git a/server/src/db/modules/monitorModule.js b/server/src/db/modules/monitorModule.js index d1d4abc5a..9c8ca7e32 100755 --- a/server/src/db/modules/monitorModule.js +++ b/server/src/db/modules/monitorModule.js @@ -1,11 +1,13 @@ import { buildUptimeDetailsPipeline, - buildHardwareDetailsPipeline, buildMonitorSummaryByTeamIdPipeline, buildMonitorsByTeamIdPipeline, buildMonitorsAndSummaryByTeamIdPipeline, buildMonitorsWithChecksByTeamIdPipeline, buildFilteredMonitorsByTeamIdPipeline, + getHardwareStats, + getUpChecks, + getAggregateData, } from "./monitorModuleQueries.js"; import { CheckModel } from "@/db/models/index.js"; @@ -317,9 +319,17 @@ class MonitorModule { }; const dateString = formatLookup[dateRange]; - const hardwareStats = await CheckModel.aggregate(buildHardwareDetailsPipeline(monitor, dates, dateString)); + const [aggregateData, upChecksCount, metrics] = await Promise.all([ + getAggregateData(monitorId, dates), + getUpChecks(monitorId, dates), + getHardwareStats(monitorId, dates, dateString), + ]); - const stats = hardwareStats[0]; + const stats = { + aggregateData: aggregateData, + upChecks: upChecksCount, + checks: metrics, + }; return { ...monitor.toObject(), diff --git a/server/src/db/modules/monitorModuleQueries.js b/server/src/db/modules/monitorModuleQueries.js index e6c6b4ec6..596f11791 100755 --- a/server/src/db/modules/monitorModuleQueries.js +++ b/server/src/db/modules/monitorModuleQueries.js @@ -1,4 +1,5 @@ import { ObjectId } from "mongodb"; +import { CheckModel } from "@/db/models/index.js"; const buildUptimeDetailsPipeline = (monitorId, dates, dateString) => { return [ @@ -168,659 +169,6 @@ const buildUptimeDetailsPipeline = (monitorId, dates, dateString) => { ]; }; -const buildHardwareDetailsPipeline = (monitor, dates, dateString) => { - return [ - { - $match: { - "metadata.monitorId": monitor._id, - "metadata.type": "hardware", - createdAt: { $gte: dates.start, $lte: dates.end }, - }, - }, - { - $sort: { - createdAt: 1, - }, - }, - { - $facet: { - aggregateData: [ - { - $group: { - _id: null, - latestCheck: { - $last: "$$ROOT", - }, - totalChecks: { - $sum: 1, - }, - }, - }, - ], - upChecks: [ - { - $match: { - status: true, - }, - }, - { - $group: { - _id: null, - totalChecks: { - $sum: 1, - }, - }, - }, - ], - checks: [ - { - $limit: 1, - }, - { - $project: { - diskCount: { - $size: { $ifNull: ["$disk", []] }, - }, - netCount: { $size: { $ifNull: ["$net", []] } }, - }, - }, - { - $lookup: { - from: "checks", - let: { - diskCount: "$diskCount", - netCount: "$netCount", - }, - pipeline: [ - { - $match: { - $expr: { - $and: [ - { $eq: ["$metadata.monitorId", monitor._id] }, - { $eq: ["$metadata.type", "hardware"] }, - { $gte: ["$createdAt", dates.start] }, - { $lte: ["$createdAt", dates.end] }, - ], - }, - }, - }, - { - $group: { - _id: { - $dateToString: { - format: dateString, - date: "$createdAt", - }, - }, - avgCpuUsage: { - $avg: "$cpu.usage_percent", - }, - avgMemoryUsage: { - $avg: "$memory.usage_percent", - }, - avgTemperatures: { - $push: { - $ifNull: ["$cpu.temperature", [0]], - }, - }, - disks: { - $push: "$disk", - }, - net: { - $push: "$net", - }, - updatedAts: { - $push: "$updatedAt", - }, - }, - }, - { - $project: { - _id: 1, - avgCpuUsage: 1, - avgMemoryUsage: 1, - avgTemperature: { - $map: { - input: { - $range: [ - 0, - { - $size: { - // Handle null temperatures array - $ifNull: [ - { $arrayElemAt: ["$avgTemperatures", 0] }, - [0], // Default to single-element array if null - ], - }, - }, - ], - }, - as: "index", - in: { - $avg: { - $map: { - input: "$avgTemperatures", - as: "tempArray", - in: { - $ifNull: [ - { $arrayElemAt: ["$$tempArray", "$$index"] }, - 0, // Default to 0 if element is null - ], - }, - }, - }, - }, - }, - }, - disks: { - $map: { - input: { - $range: [0, "$$diskCount"], - }, - as: "diskIndex", - in: { - name: { - $concat: [ - "disk", - { - $toString: "$$diskIndex", - }, - ], - }, - readSpeed: { - $avg: { - $map: { - input: "$disks", - as: "diskArray", - in: { - $arrayElemAt: ["$$diskArray.read_speed_bytes", "$$diskIndex"], - }, - }, - }, - }, - writeSpeed: { - $avg: { - $map: { - input: "$disks", - as: "diskArray", - in: { - $arrayElemAt: ["$$diskArray.write_speed_bytes", "$$diskIndex"], - }, - }, - }, - }, - totalBytes: { - $avg: { - $map: { - input: "$disks", - as: "diskArray", - in: { - $arrayElemAt: ["$$diskArray.total_bytes", "$$diskIndex"], - }, - }, - }, - }, - freeBytes: { - $avg: { - $map: { - input: "$disks", - as: "diskArray", - in: { - $arrayElemAt: ["$$diskArray.free_bytes", "$$diskIndex"], - }, - }, - }, - }, - usagePercent: { - $avg: { - $map: { - input: "$disks", - as: "diskArray", - in: { - $arrayElemAt: ["$$diskArray.usage_percent", "$$diskIndex"], - }, - }, - }, - }, - }, - }, - }, - net: { - $map: { - input: { $range: [0, { $size: { $ifNull: [{ $arrayElemAt: ["$net", 0] }, []] } }] }, - as: "netIndex", - in: { - name: { - $arrayElemAt: [ - { - $map: { - input: { $arrayElemAt: ["$net", 0] }, - as: "iface", - in: "$$iface.name", - }, - }, - "$$netIndex", - ], - }, - bytesSentPerSecond: { - $let: { - vars: { - first: { - $arrayElemAt: [ - { $map: { input: { $arrayElemAt: ["$net", 0] }, as: "iface", in: "$$iface.bytes_sent" } }, - "$$netIndex", - ], - }, - last: { - $arrayElemAt: [ - { - $map: { - input: { - $arrayElemAt: [{ $ifNull: ["$net", []] }, { $subtract: [{ $size: { $ifNull: ["$net", []] } }, 1] }], - }, - as: "iface", - in: "$$iface.bytes_sent", - }, - }, - "$$netIndex", - ], - }, - tFirst: { $arrayElemAt: ["$updatedAts", 0] }, - tLast: { - $arrayElemAt: [{ $ifNull: ["$updatedAts", []] }, { $subtract: [{ $size: { $ifNull: ["$updatedAts", []] } }, 1] }], - }, - }, - in: { - $cond: [ - { $gt: [{ $subtract: ["$$tLast", "$$tFirst"] }, 0] }, - { - $divide: [{ $subtract: ["$$last", "$$first"] }, { $divide: [{ $subtract: ["$$tLast", "$$tFirst"] }, 1000] }], - }, - 0, - ], - }, - }, - }, - deltaBytesRecv: { - $let: { - vars: { - first: { - $arrayElemAt: [ - { $map: { input: { $arrayElemAt: ["$net", 0] }, as: "iface", in: "$$iface.bytes_recv" } }, - "$$netIndex", - ], - }, - last: { - $arrayElemAt: [ - { - $map: { - input: { - $arrayElemAt: [{ $ifNull: ["$net", []] }, { $subtract: [{ $size: { $ifNull: ["$net", []] } }, 1] }], - }, - as: "iface", - in: "$$iface.bytes_recv", - }, - }, - "$$netIndex", - ], - }, - tFirst: { $arrayElemAt: ["$updatedAts", 0] }, - tLast: { - $arrayElemAt: [{ $ifNull: ["$updatedAts", []] }, { $subtract: [{ $size: { $ifNull: ["$updatedAts", []] } }, 1] }], - }, - }, - in: { - $cond: [ - { $gt: [{ $subtract: ["$$tLast", "$$tFirst"] }, 0] }, - { - $divide: [{ $subtract: ["$$last", "$$first"] }, { $divide: [{ $subtract: ["$$tLast", "$$tFirst"] }, 1000] }], - }, - 0, - ], - }, - }, - }, - deltaPacketsSent: { - $let: { - vars: { - first: { - $arrayElemAt: [ - { $map: { input: { $arrayElemAt: ["$net", 0] }, as: "iface", in: "$$iface.packets_sent" } }, - "$$netIndex", - ], - }, - last: { - $arrayElemAt: [ - { - $map: { - input: { - $arrayElemAt: [{ $ifNull: ["$net", []] }, { $subtract: [{ $size: { $ifNull: ["$net", []] } }, 1] }], - }, - as: "iface", - in: "$$iface.packets_sent", - }, - }, - "$$netIndex", - ], - }, - tFirst: { $arrayElemAt: ["$updatedAts", 0] }, - tLast: { - $arrayElemAt: [{ $ifNull: ["$updatedAts", []] }, { $subtract: [{ $size: { $ifNull: ["$updatedAts", []] } }, 1] }], - }, - }, - in: { - $cond: [ - { $gt: [{ $subtract: ["$$tLast", "$$tFirst"] }, 0] }, - { - $divide: [{ $subtract: ["$$last", "$$first"] }, { $divide: [{ $subtract: ["$$tLast", "$$tFirst"] }, 1000] }], - }, - 0, - ], - }, - }, - }, - deltaPacketsRecv: { - $let: { - vars: { - first: { - $arrayElemAt: [ - { - $map: { - input: { $arrayElemAt: ["$net", 0] }, - as: "iface", - in: "$$iface.packets_recv", - }, - }, - "$$netIndex", - ], - }, - last: { - $arrayElemAt: [ - { - $map: { - input: { - $arrayElemAt: [ - { $ifNull: ["$net", []] }, - { - $subtract: [{ $size: { $ifNull: ["$net", []] } }, 1], - }, - ], - }, - as: "iface", - in: "$$iface.packets_recv", - }, - }, - "$$netIndex", - ], - }, - tFirst: { $arrayElemAt: ["$updatedAts", 0] }, - tLast: { - $arrayElemAt: [ - { $ifNull: ["$updatedAts", []] }, - { - $subtract: [{ $size: { $ifNull: ["$updatedAts", []] } }, 1], - }, - ], - }, - }, - in: { - $cond: [ - { $gt: [{ $subtract: ["$$tLast", "$$tFirst"] }, 0] }, - { - $divide: [{ $subtract: ["$$last", "$$first"] }, { $divide: [{ $subtract: ["$$tLast", "$$tFirst"] }, 1000] }], - }, - 0, - ], - }, - }, - }, - deltaErrIn: { - $let: { - vars: { - first: { - $arrayElemAt: [{ $map: { input: { $arrayElemAt: ["$net", 0] }, as: "iface", in: "$$iface.err_in" } }, "$$netIndex"], - }, - last: { - $arrayElemAt: [ - { - $map: { - input: { - $arrayElemAt: [{ $ifNull: ["$net", []] }, { $subtract: [{ $size: { $ifNull: ["$net", []] } }, 1] }], - }, - as: "iface", - in: "$$iface.err_in", - }, - }, - "$$netIndex", - ], - }, - tFirst: { $arrayElemAt: ["$updatedAts", 0] }, - tLast: { - $arrayElemAt: [{ $ifNull: ["$updatedAts", []] }, { $subtract: [{ $size: { $ifNull: ["$updatedAts", []] } }, 1] }], - }, - }, - in: { - $cond: [ - { $gt: [{ $subtract: ["$$tLast", "$$tFirst"] }, 0] }, - { - $divide: [{ $subtract: ["$$last", "$$first"] }, { $divide: [{ $subtract: ["$$tLast", "$$tFirst"] }, 1000] }], - }, - 0, - ], - }, - }, - }, - deltaErrOut: { - $let: { - vars: { - first: { - $arrayElemAt: [ - { - $map: { - input: { $arrayElemAt: ["$net", 0] }, - as: "iface", - in: "$$iface.err_out", - }, - }, - "$$netIndex", - ], - }, - last: { - $arrayElemAt: [ - { - $map: { - input: { - $arrayElemAt: [ - { $ifNull: ["$net", []] }, - { - $subtract: [{ $size: { $ifNull: ["$net", []] } }, 1], - }, - ], - }, - as: "iface", - in: "$$iface.err_out", - }, - }, - "$$netIndex", - ], - }, - tFirst: { $arrayElemAt: ["$updatedAts", 0] }, - tLast: { - $arrayElemAt: [ - { $ifNull: ["$updatedAts", []] }, - { - $subtract: [{ $size: { $ifNull: ["$updatedAts", []] } }, 1], - }, - ], - }, - }, - in: { - $cond: [ - { $gt: [{ $subtract: ["$$tLast", "$$tFirst"] }, 0] }, - { - $divide: [{ $subtract: ["$$last", "$$first"] }, { $divide: [{ $subtract: ["$$tLast", "$$tFirst"] }, 1000] }], - }, - 0, - ], - }, - }, - }, - deltaDropIn: { - $let: { - vars: { - first: { - $arrayElemAt: [ - { - $map: { - input: { $arrayElemAt: ["$net", 0] }, - as: "iface", - in: "$$iface.drop_in", - }, - }, - "$$netIndex", - ], - }, - last: { - $arrayElemAt: [ - { - $map: { - input: { - $arrayElemAt: [ - { $ifNull: ["$net", []] }, - { - $subtract: [{ $size: { $ifNull: ["$net", []] } }, 1], - }, - ], - }, - as: "iface", - in: "$$iface.drop_in", - }, - }, - "$$netIndex", - ], - }, - tFirst: { $arrayElemAt: ["$updatedAts", 0] }, - tLast: { - $arrayElemAt: [ - { $ifNull: ["$updatedAts", []] }, - { - $subtract: [{ $size: { $ifNull: ["$updatedAts", []] } }, 1], - }, - ], - }, - }, - in: { - $cond: [ - { $gt: [{ $subtract: ["$$tLast", "$$tFirst"] }, 0] }, - { - $divide: [{ $subtract: ["$$last", "$$first"] }, { $divide: [{ $subtract: ["$$tLast", "$$tFirst"] }, 1000] }], - }, - 0, - ], - }, - }, - }, - deltaDropOut: { - $let: { - vars: { - first: { - $arrayElemAt: [ - { - $map: { - input: { $arrayElemAt: ["$net", 0] }, - as: "iface", - in: "$$iface.drop_out", - }, - }, - "$$netIndex", - ], - }, - last: { - $arrayElemAt: [ - { - $map: { - input: { - $arrayElemAt: [ - { $ifNull: ["$net", []] }, - { - $subtract: [{ $size: { $ifNull: ["$net", []] } }, 1], - }, - ], - }, - as: "iface", - in: "$$iface.drop_out", - }, - }, - "$$netIndex", - ], - }, - tFirst: { $arrayElemAt: ["$updatedAts", 0] }, - tLast: { - $arrayElemAt: [ - { $ifNull: ["$updatedAts", []] }, - { - $subtract: [{ $size: { $ifNull: ["$updatedAts", []] } }, 1], - }, - ], - }, - }, - in: { - $cond: [ - { $gt: [{ $subtract: ["$$tLast", "$$tFirst"] }, 0] }, - { - $divide: [{ $subtract: ["$$last", "$$first"] }, { $divide: [{ $subtract: ["$$tLast", "$$tFirst"] }, 1000] }], - }, - 0, - ], - }, - }, - }, - }, - }, - }, - firstUpdatedAt: 1, - lastUpdatedAt: 1, - }, - }, - ], - as: "hourlyStats", - }, - }, - { - $unwind: "$hourlyStats", - }, - { - $replaceRoot: { - newRoot: "$hourlyStats", - }, - }, - ], - }, - }, - { $unwind: "$checks" }, - { $sort: { "checks._id": 1 } }, - { - $group: { - _id: "$_id", - checks: { $push: "$checks" }, - aggregateData: { $first: "$aggregateData" }, - upChecks: { $first: "$upChecks" }, - }, - }, - { - $project: { - aggregateData: { - $arrayElemAt: ["$aggregateData", 0], - }, - upChecks: { - $arrayElemAt: ["$upChecks", 0], - }, - checks: 1, - }, - }, - ]; -}; - const buildMonitorStatsPipeline = (monitor) => { return [ { @@ -1208,7 +556,6 @@ const buildGetMonitorsByTeamIdPipeline = (req) => { export { buildUptimeDetailsPipeline, - buildHardwareDetailsPipeline, buildMonitorStatsPipeline, buildGetMonitorsByTeamIdPipeline, buildMonitorSummaryByTeamIdPipeline, @@ -1217,3 +564,177 @@ export { buildMonitorsWithChecksByTeamIdPipeline, buildFilteredMonitorsByTeamIdPipeline, }; + +export const getAggregateData = async (monitorId, dates) => { + const result = await CheckModel.aggregate([ + { + $match: { + "metadata.monitorId": new ObjectId(monitorId), + "metadata.type": "hardware", + createdAt: { $gte: dates.start, $lte: dates.end }, + }, + }, + { $sort: { createdAt: -1 } }, + { + $group: { + _id: null, + latestCheck: { $first: "$$ROOT" }, + totalChecks: { $sum: 1 }, + }, + }, + ]); + return result[0] || { totalChecks: 0, latestCheck: null }; +}; + +export const getUpChecks = async (monitorId, dates) => { + const count = await CheckModel.countDocuments({ + "metadata.monitorId": new ObjectId(monitorId), + "metadata.type": "hardware", + createdAt: { $gte: dates.start, $lte: dates.end }, + status: true, + }); + return { totalChecks: count }; +}; + +export const getHardwareStats = async (monitorId, dates, dateString) => { + return await CheckModel.aggregate([ + { + $match: { + "metadata.monitorId": new ObjectId(monitorId), + "metadata.type": "hardware", + createdAt: { $gte: dates.start, $lte: dates.end }, + }, + }, + { $sort: { createdAt: 1 } }, + { + $group: { + _id: { $dateToString: { format: dateString, date: "$createdAt" } }, + avgCpuUsage: { $avg: "$cpu.usage_percent" }, + avgMemoryUsage: { $avg: "$memory.usage_percent" }, + avgTemperatures: { $push: { $ifNull: ["$cpu.temperature", [0]] } }, + disks: { $push: "$disk" }, + net: { $push: "$net" }, + updatedAts: { $push: "$updatedAt" }, + sampleDoc: { $first: "$$ROOT" }, + }, + }, + { + $project: { + _id: 1, + avgCpuUsage: 1, + avgMemoryUsage: 1, + avgTemperature: { + $map: { + input: { $range: [0, { $size: { $ifNull: [{ $arrayElemAt: ["$avgTemperatures", 0] }, [0]] } }] }, + as: "idx", + in: { $avg: { $map: { input: "$avgTemperatures", as: "t", in: { $arrayElemAt: ["$$t", "$$idx"] } } } }, + }, + }, + disks: { + $map: { + input: { $range: [0, { $size: { $ifNull: ["$sampleDoc.disk", []] } }] }, + as: "dIdx", + in: { + name: { $concat: ["disk", { $toString: "$$dIdx" }] }, + readSpeed: { $avg: { $map: { input: "$disks", as: "dA", in: { $arrayElemAt: ["$$dA.read_speed_bytes", "$$dIdx"] } } } }, + writeSpeed: { $avg: { $map: { input: "$disks", as: "dA", in: { $arrayElemAt: ["$$dA.write_speed_bytes", "$$dIdx"] } } } }, + totalBytes: { $avg: { $map: { input: "$disks", as: "dA", in: { $arrayElemAt: ["$$dA.total_bytes", "$$dIdx"] } } } }, + freeBytes: { $avg: { $map: { input: "$disks", as: "dA", in: { $arrayElemAt: ["$$dA.free_bytes", "$$dIdx"] } } } }, + usagePercent: { $avg: { $map: { input: "$disks", as: "dA", in: { $arrayElemAt: ["$$dA.usage_percent", "$$dIdx"] } } } }, + }, + }, + }, + net: { + $map: { + input: { $range: [0, { $size: { $ifNull: ["$sampleDoc.net", []] } }] }, + as: "nIdx", + in: { + name: { $arrayElemAt: ["$sampleDoc.net.name", "$$nIdx"] }, + bytesSentPerSecond: { + $let: { + vars: { + tDiff: { $divide: [{ $subtract: [{ $last: "$updatedAts" }, { $first: "$updatedAts" }] }, 1000] }, + f: { $arrayElemAt: [{ $map: { input: { $first: "$net" }, as: "i", in: "$$i.bytes_sent" } }, "$$nIdx"] }, + l: { $arrayElemAt: [{ $map: { input: { $last: "$net" }, as: "i", in: "$$i.bytes_sent" } }, "$$nIdx"] }, + }, + in: { $cond: [{ $gt: ["$$tDiff", 0] }, { $divide: [{ $subtract: ["$$l", "$$f"] }, "$$tDiff"] }, 0] }, + }, + }, + deltaBytesRecv: { + $let: { + vars: { + tDiff: { $divide: [{ $subtract: [{ $last: "$updatedAts" }, { $first: "$updatedAts" }] }, 1000] }, + f: { $arrayElemAt: [{ $map: { input: { $first: "$net" }, as: "i", in: "$$i.bytes_recv" } }, "$$nIdx"] }, + l: { $arrayElemAt: [{ $map: { input: { $last: "$net" }, as: "i", in: "$$i.bytes_recv" } }, "$$nIdx"] }, + }, + in: { $cond: [{ $gt: ["$$tDiff", 0] }, { $divide: [{ $subtract: ["$$l", "$$f"] }, "$$tDiff"] }, 0] }, + }, + }, + deltaPacketsSent: { + $let: { + vars: { + tDiff: { $divide: [{ $subtract: [{ $last: "$updatedAts" }, { $first: "$updatedAts" }] }, 1000] }, + f: { $arrayElemAt: [{ $map: { input: { $first: "$net" }, as: "i", in: "$$i.packets_sent" } }, "$$nIdx"] }, + l: { $arrayElemAt: [{ $map: { input: { $last: "$net" }, as: "i", in: "$$i.packets_sent" } }, "$$nIdx"] }, + }, + in: { $cond: [{ $gt: ["$$tDiff", 0] }, { $divide: [{ $subtract: ["$$l", "$$f"] }, "$$tDiff"] }, 0] }, + }, + }, + deltaPacketsRecv: { + $let: { + vars: { + tDiff: { $divide: [{ $subtract: [{ $last: "$updatedAts" }, { $first: "$updatedAts" }] }, 1000] }, + f: { $arrayElemAt: [{ $map: { input: { $first: "$net" }, as: "i", in: "$$i.packets_recv" } }, "$$nIdx"] }, + l: { $arrayElemAt: [{ $map: { input: { $last: "$net" }, as: "i", in: "$$i.packets_recv" } }, "$$nIdx"] }, + }, + in: { $cond: [{ $gt: ["$$tDiff", 0] }, { $divide: [{ $subtract: ["$$l", "$$f"] }, "$$tDiff"] }, 0] }, + }, + }, + deltaErrIn: { + $let: { + vars: { + tDiff: { $divide: [{ $subtract: [{ $last: "$updatedAts" }, { $first: "$updatedAts" }] }, 1000] }, + f: { $arrayElemAt: [{ $map: { input: { $first: "$net" }, as: "i", in: "$$i.err_in" } }, "$$nIdx"] }, + l: { $arrayElemAt: [{ $map: { input: { $last: "$net" }, as: "i", in: "$$i.err_in" } }, "$$nIdx"] }, + }, + in: { $cond: [{ $gt: ["$$tDiff", 0] }, { $divide: [{ $subtract: ["$$l", "$$f"] }, "$$tDiff"] }, 0] }, + }, + }, + deltaErrOut: { + $let: { + vars: { + tDiff: { $divide: [{ $subtract: [{ $last: "$updatedAts" }, { $first: "$updatedAts" }] }, 1000] }, + f: { $arrayElemAt: [{ $map: { input: { $first: "$net" }, as: "i", in: "$$i.err_out" } }, "$$nIdx"] }, + l: { $arrayElemAt: [{ $map: { input: { $last: "$net" }, as: "i", in: "$$i.err_out" } }, "$$nIdx"] }, + }, + in: { $cond: [{ $gt: ["$$tDiff", 0] }, { $divide: [{ $subtract: ["$$l", "$$f"] }, "$$tDiff"] }, 0] }, + }, + }, + deltaDropIn: { + $let: { + vars: { + tDiff: { $divide: [{ $subtract: [{ $last: "$updatedAts" }, { $first: "$updatedAts" }] }, 1000] }, + f: { $arrayElemAt: [{ $map: { input: { $first: "$net" }, as: "i", in: "$$i.drop_in" } }, "$$nIdx"] }, + l: { $arrayElemAt: [{ $map: { input: { $last: "$net" }, as: "i", in: "$$i.drop_in" } }, "$$nIdx"] }, + }, + in: { $cond: [{ $gt: ["$$tDiff", 0] }, { $divide: [{ $subtract: ["$$l", "$$f"] }, "$$tDiff"] }, 0] }, + }, + }, + deltaDropOut: { + $let: { + vars: { + tDiff: { $divide: [{ $subtract: [{ $last: "$updatedAts" }, { $first: "$updatedAts" }] }, 1000] }, + f: { $arrayElemAt: [{ $map: { input: { $first: "$net" }, as: "i", in: "$$i.drop_out" } }, "$$nIdx"] }, + l: { $arrayElemAt: [{ $map: { input: { $last: "$net" }, as: "i", in: "$$i.drop_out" } }, "$$nIdx"] }, + }, + in: { $cond: [{ $gt: ["$$tDiff", 0] }, { $divide: [{ $subtract: ["$$l", "$$f"] }, "$$tDiff"] }, 0] }, + }, + }, + }, + }, + }, + }, + }, + { $sort: { _id: 1 } }, + ]); +}; From 117a2e00c44604028d4cc39af3a97d31c4c741e9 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Tue, 13 Jan 2026 19:01:56 +0000 Subject: [PATCH 7/9] status page fix --- server/src/db/modules/statusPageModule.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/db/modules/statusPageModule.js b/server/src/db/modules/statusPageModule.js index aadde0c81..999e0bdc9 100755 --- a/server/src/db/modules/statusPageModule.js +++ b/server/src/db/modules/statusPageModule.js @@ -153,7 +153,7 @@ class StatusPageModule { pipeline: [ { $match: { - $expr: { $eq: ["$monitorId", "$$monitorId"] }, + $expr: { $eq: ["$metadata.monitorId", "$$monitorId"] }, }, }, { $sort: { createdAt: -1 } }, From e79bf28bdc8b58ff5bdf5180fbc52f89e9acbd0f Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Tue, 13 Jan 2026 20:20:29 +0000 Subject: [PATCH 8/9] server format --- .../0002_convertChecksToTimeSeries.ts | 22 ++++++++++--------- server/src/db/migration/index.ts | 6 +---- server/src/db/models/Check.ts | 10 ++------- .../service/infrastructure/statusService.js | 2 +- 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/server/src/db/migration/0002_convertChecksToTimeSeries.ts b/server/src/db/migration/0002_convertChecksToTimeSeries.ts index 46e6fbc97..a6c503804 100644 --- a/server/src/db/migration/0002_convertChecksToTimeSeries.ts +++ b/server/src/db/migration/0002_convertChecksToTimeSeries.ts @@ -19,10 +19,10 @@ const backupAndDropExistingCollection = async () => { return false; } - await db.collection(CHECKS_COLLECTION).aggregate([ - { $match: {} }, - { $out: BACKUP_COLLECTION }, - ]).toArray(); + await db + .collection(CHECKS_COLLECTION) + .aggregate([{ $match: {} }, { $out: BACKUP_COLLECTION }]) + .toArray(); await db.collection(CHECKS_COLLECTION).drop(); return true; }; @@ -40,12 +40,14 @@ const createTimeSeriesCollection = async () => { }); } - await db.collection(CHECKS_COLLECTION).createIndexes([ - { key: { updatedAt: 1 } }, - { key: { "metadata.monitorId": 1, updatedAt: 1 } }, - { key: { "metadata.monitorId": 1, updatedAt: -1 } }, - { key: { "metadata.teamId": 1, updatedAt: -1 } }, - ]); + await db + .collection(CHECKS_COLLECTION) + .createIndexes([ + { key: { updatedAt: 1 } }, + { key: { "metadata.monitorId": 1, updatedAt: 1 } }, + { key: { "metadata.monitorId": 1, updatedAt: -1 } }, + { key: { "metadata.teamId": 1, updatedAt: -1 } }, + ]); }; const migrateBackupData = async () => { diff --git a/server/src/db/migration/index.ts b/server/src/db/migration/index.ts index de2a1dee7..c8e9e7c75 100644 --- a/server/src/db/migration/index.ts +++ b/server/src/db/migration/index.ts @@ -32,11 +32,7 @@ const runMigrations = async (logger?: { info: Function; error: Function }) => { logger?.info({ message: `Completed ${migration.name}`, service: "Migrations" }); } catch (error) { const err = error as Error; - await MigrationModel.findOneAndUpdate( - { name: migration.name }, - { status: "failed", error: err?.message }, - { upsert: true } - ); + await MigrationModel.findOneAndUpdate({ name: migration.name }, { status: "failed", error: err?.message }, { upsert: true }); throw error; } } diff --git a/server/src/db/models/Check.ts b/server/src/db/models/Check.ts index 3ebacd3f6..fe6f16836 100644 --- a/server/src/db/models/Check.ts +++ b/server/src/db/models/Check.ts @@ -1,8 +1,5 @@ import { Schema, model, Types } from "mongoose"; -import { - MonitorTypes, - type MonitorType, -} from "@/types/monitor.js"; +import { MonitorTypes, type MonitorType } from "@/types/monitor.js"; import type { Check, CheckAudits, @@ -25,10 +22,7 @@ type CheckMetadataDocument = Omit & { type: MonitorType; }; -type CheckDocumentBase = Omit< - Check, - "id" | "metadata" | "expiry" | "ackAt" | "createdAt" | "updatedAt" -> & { +type CheckDocumentBase = Omit & { metadata: CheckMetadataDocument; expiry: Date; ackAt?: Date | null; diff --git a/server/src/service/infrastructure/statusService.js b/server/src/service/infrastructure/statusService.js index 5b64c7419..3aa1ced52 100755 --- a/server/src/service/infrastructure/statusService.js +++ b/server/src/service/infrastructure/statusService.js @@ -374,7 +374,7 @@ class StatusService { return { id: audit.id, title: audit.title, - score: typeof audit.score === "number" ? audit.score : audit.score ?? null, + score: typeof audit.score === "number" ? audit.score : (audit.score ?? null), displayValue: audit.displayValue, numericValue: typeof audit.numericValue === "number" ? audit.numericValue : undefined, numericUnit: audit.numericUnit, From f763126b38daad0977b20383e2b4add98a8585ee Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Tue, 13 Jan 2026 20:20:50 +0000 Subject: [PATCH 9/9] format' --- .../src/Pages/Incidents/Components/IncidentTable/index.jsx | 6 +++++- client/src/Pages/Incidents/index.jsx | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/client/src/Pages/Incidents/Components/IncidentTable/index.jsx b/client/src/Pages/Incidents/Components/IncidentTable/index.jsx index 78d6d26be..e066049e6 100644 --- a/client/src/Pages/Incidents/Components/IncidentTable/index.jsx +++ b/client/src/Pages/Incidents/Components/IncidentTable/index.jsx @@ -18,7 +18,11 @@ import { useSelector } from "react-redux"; import { useState } from "react"; import PropTypes from "prop-types"; import { useTranslation } from "react-i18next"; -import { useFetchChecksTeam, useFetchChecksByMonitor, useResolveIncident } from "@/Hooks/checkHooks.js"; +import { + useFetchChecksTeam, + useFetchChecksByMonitor, + useResolveIncident, +} from "@/Hooks/checkHooks.js"; import { Button, Typography, useTheme } from "@mui/material"; import { lighten } from "@mui/material/styles"; diff --git a/client/src/Pages/Incidents/index.jsx b/client/src/Pages/Incidents/index.jsx index c8462f649..698fc4a2f 100644 --- a/client/src/Pages/Incidents/index.jsx +++ b/client/src/Pages/Incidents/index.jsx @@ -10,7 +10,10 @@ import { Box, Button } from "@mui/material"; //Utils import { useTheme } from "@emotion/react"; import { useFetchMonitorsByTeamId } from "@/Hooks/monitorHooks.js"; -import { useFetchChecksSummaryByTeamId, useAcknowledgeChecks } from "@/Hooks/checkHooks.js"; +import { + useFetchChecksSummaryByTeamId, + useAcknowledgeChecks, +} from "@/Hooks/checkHooks.js"; import { useState, useEffect } from "react"; import NetworkError from "@/Components/v1/GenericFallback/NetworkError.jsx"; import { useTranslation } from "react-i18next";