mirror of
https://github.com/KSJaay/Lunalytics.git
synced 2026-04-27 05:59:16 -05:00
Adds support for parentId for monitors
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { toast } from 'react-toastify';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
// import local files
|
||||
import Dropdown from '../../ui/dropdown';
|
||||
@@ -88,4 +89,4 @@ const IncidentContentImpact = () => {
|
||||
|
||||
IncidentContentImpact.displayName = 'IncidentContentImpact';
|
||||
|
||||
export default IncidentContentImpact;
|
||||
export default observer(IncidentContentImpact);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Input } from '@lunalytics/ui';
|
||||
// import local files
|
||||
import MonitorInitialDropdown from './type';
|
||||
import MonitorIconSelect from './icons';
|
||||
import MonitorParentSelect from './parent';
|
||||
|
||||
interface MonitorInitialTypeProps {
|
||||
inputs: any;
|
||||
@@ -51,6 +52,8 @@ const MonitorInitialType = ({
|
||||
)}
|
||||
|
||||
<MonitorIconSelect inputs={inputs} handleInput={handleInput} />
|
||||
|
||||
<MonitorParentSelect inputs={inputs} handleInput={handleInput} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import useDropdown from '../../../../../hooks/useDropdown';
|
||||
import Dropdown from '../../../../ui/dropdown';
|
||||
import useContextStore from '../../../../../context';
|
||||
|
||||
const MonitorParentSelect = ({
|
||||
inputs,
|
||||
handleInput,
|
||||
}: {
|
||||
inputs: any;
|
||||
handleInput: (key: string, value: any) => void;
|
||||
}) => {
|
||||
const {
|
||||
globalStore: { allMonitors },
|
||||
} = useContextStore();
|
||||
const { toggleDropdown, dropdownIsOpen } = useDropdown(true);
|
||||
|
||||
const onSelect = (monitorId: string | null) => {
|
||||
handleInput('parentId', monitorId);
|
||||
toggleDropdown();
|
||||
};
|
||||
|
||||
const monitors = allMonitors.filter(
|
||||
(monitor) => monitor.monitorId !== inputs.monitorId
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="luna-input-wrapper">
|
||||
<label className="input-label">Monitor Parent</label>
|
||||
<label className="luna-input-subtitle">
|
||||
If parent is down notification won't be sent for this monitor
|
||||
</label>
|
||||
|
||||
<div>
|
||||
<Dropdown.Container
|
||||
isOpen={dropdownIsOpen}
|
||||
toggleDropdown={toggleDropdown}
|
||||
position="center"
|
||||
>
|
||||
<Dropdown.Trigger
|
||||
isOpen={dropdownIsOpen}
|
||||
toggleDropdown={toggleDropdown}
|
||||
color="var(--lunaui-accent-900)"
|
||||
asInput
|
||||
>
|
||||
{inputs.parentId
|
||||
? monitors.find(
|
||||
(monitor) => monitor.monitorId === inputs.parentId
|
||||
)?.name
|
||||
: 'No parent'}
|
||||
</Dropdown.Trigger>
|
||||
<Dropdown.List isOpen={dropdownIsOpen} fullWidth>
|
||||
<Dropdown.Item onClick={() => onSelect(null)}>
|
||||
No parent
|
||||
</Dropdown.Item>
|
||||
{monitors.map((monitor) => (
|
||||
<Dropdown.Item
|
||||
key={monitor.monitorId}
|
||||
onClick={() => onSelect(monitor.monitorId)}
|
||||
>
|
||||
{monitor.name}
|
||||
</Dropdown.Item>
|
||||
))}
|
||||
</Dropdown.List>
|
||||
</Dropdown.Container>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default observer(MonitorParentSelect);
|
||||
@@ -33,6 +33,7 @@ const handleMonitor = async (
|
||||
|
||||
const {
|
||||
name,
|
||||
parentId,
|
||||
type,
|
||||
url,
|
||||
method,
|
||||
@@ -57,6 +58,7 @@ const handleMonitor = async (
|
||||
|
||||
const query = await createPostRequest(apiPath, {
|
||||
name,
|
||||
parentId,
|
||||
type,
|
||||
url,
|
||||
method,
|
||||
|
||||
Generated
+29
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "lunalytics",
|
||||
"version": "0.10.12",
|
||||
"version": "0.10.13",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "lunalytics",
|
||||
"version": "0.10.12",
|
||||
"version": "0.10.13",
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"dependencies": {
|
||||
"@dnd-kit/core": "6.3.1",
|
||||
@@ -50,6 +50,7 @@
|
||||
"react-window": "1.8.11",
|
||||
"recharts": "3.2.1",
|
||||
"swapy": "1.0.5",
|
||||
"systeminformation": "^5.27.11",
|
||||
"ua-parser-js": "2.0.3",
|
||||
"uuid": "11.1.0",
|
||||
"winston": "3.17.0",
|
||||
@@ -12851,6 +12852,32 @@
|
||||
"integrity": "sha512-XEzy5HCw7yESb7QajKTBJ+NA/BL0kAKlE7XhSMPZawF740X4ws/5CFtXRsVDQ+EztISC759a9+DJM9mxjz4hXg==",
|
||||
"license": "GPL-3.0"
|
||||
},
|
||||
"node_modules/systeminformation": {
|
||||
"version": "5.27.11",
|
||||
"resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.11.tgz",
|
||||
"integrity": "sha512-K3Lto/2m3K2twmKHdgx5B+0in9qhXK4YnoT9rIlgwN/4v7OV5c8IjbeAUkuky/6VzCQC7iKCAqi8rZathCdjHg==",
|
||||
"license": "MIT",
|
||||
"os": [
|
||||
"darwin",
|
||||
"linux",
|
||||
"win32",
|
||||
"freebsd",
|
||||
"openbsd",
|
||||
"netbsd",
|
||||
"sunos",
|
||||
"android"
|
||||
],
|
||||
"bin": {
|
||||
"systeminformation": "lib/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "Buy me a coffee",
|
||||
"url": "https://www.buymeacoffee.com/systeminfo"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-fs": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lunalytics",
|
||||
"version": "0.10.12",
|
||||
"version": "0.10.13",
|
||||
"description": "Open source Node.js server/website monitoring tool",
|
||||
"private": true,
|
||||
"author": "KSJaay <ksjaay@gmail.com>",
|
||||
@@ -81,6 +81,7 @@
|
||||
"react-window": "1.8.11",
|
||||
"recharts": "3.2.1",
|
||||
"swapy": "1.0.5",
|
||||
"systeminformation": "^5.27.11",
|
||||
"ua-parser-js": "2.0.3",
|
||||
"uuid": "11.1.0",
|
||||
"winston": "3.17.0",
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// import local files
|
||||
import SQLite from '../../server/database/sqlite/setup.js';
|
||||
import logger from '../../server/utils/logger.js';
|
||||
|
||||
const infomation = {
|
||||
title: 'Add parentId to monitor table',
|
||||
description: 'Adds parentId to monitor table',
|
||||
version: '0.10.13',
|
||||
};
|
||||
|
||||
const migrate = async () => {
|
||||
const client = await SQLite.connect();
|
||||
|
||||
await client.schema.alterTable('monitor', (table) => {
|
||||
table.string('parentId').nullable().defaultTo(null);
|
||||
});
|
||||
|
||||
logger.info('Migrations', { message: '0.10.13 has been applied' });
|
||||
return;
|
||||
};
|
||||
|
||||
export { infomation, migrate };
|
||||
@@ -11,6 +11,7 @@ import { migrate as migrateIncidentEmail } from './0-9-4.js';
|
||||
import { migrate as migrateMonitor } from './0-9-5.js';
|
||||
import { migrate as migrateMonitorJson } from './0-9-7.js';
|
||||
import { migrate as migrateUiOverhaul } from './0-10-0.js';
|
||||
import { migrate as migrateMonitorParent } from './0-10-13.js';
|
||||
|
||||
const migrationList = {
|
||||
'0.4.0': migrateTcpUpdate,
|
||||
@@ -25,6 +26,7 @@ const migrationList = {
|
||||
'0.9.5': migrateMonitor,
|
||||
'0.9.7': migrateMonitorJson,
|
||||
'0.10.0': migrateUiOverhaul,
|
||||
'0.10.13': migrateMonitorParent,
|
||||
};
|
||||
|
||||
export default migrationList;
|
||||
|
||||
Vendored
+15
@@ -197,6 +197,21 @@ class Master {
|
||||
if (!hasOutage && !hasRecovered) return;
|
||||
if (!monitor.notificationId) return;
|
||||
|
||||
if (hasOutage && monitor.parentId) {
|
||||
const parentMonitor = await fetchMonitor(monitor.parentId).catch(
|
||||
() => false
|
||||
);
|
||||
|
||||
if (parentMonitor) {
|
||||
const isDown = await isMonitorDown(
|
||||
parentMonitor.monitorId,
|
||||
parentMonitor.retry
|
||||
);
|
||||
|
||||
if (isDown) return;
|
||||
}
|
||||
}
|
||||
|
||||
const notification = await fetchNotificationById(monitor.notificationId);
|
||||
|
||||
if (
|
||||
|
||||
@@ -2,6 +2,7 @@ import { parseJsonOrArray } from '../../utils/parser.js';
|
||||
|
||||
const clean = ({ heartbeats = [], ...monitor }, includeHeartbeats = true) => ({
|
||||
monitorId: monitor.monitorId,
|
||||
parentId: monitor.parentId || null,
|
||||
name: monitor.name,
|
||||
url: monitor.url,
|
||||
retry: parseInt(monitor.retry),
|
||||
|
||||
@@ -7,6 +7,7 @@ const clean = (
|
||||
includeCert = true
|
||||
) => ({
|
||||
monitorId: monitor.monitorId,
|
||||
parentId: monitor.parentId || null,
|
||||
name: monitor.name,
|
||||
url: monitor.url,
|
||||
retry: parseInt(monitor.retry),
|
||||
|
||||
@@ -7,6 +7,7 @@ export const clean = (
|
||||
includeCert = true
|
||||
) => ({
|
||||
monitorId: monitor.monitorId,
|
||||
parentId: monitor.parentId || null,
|
||||
name: monitor.name,
|
||||
url: monitor.url,
|
||||
retry: parseInt(monitor.retry),
|
||||
|
||||
@@ -5,6 +5,7 @@ export const clean = (
|
||||
includeHeartbeats = true
|
||||
) => ({
|
||||
monitorId: monitor.monitorId,
|
||||
parentId: monitor.parentId || null,
|
||||
name: monitor.name,
|
||||
url: monitor.url,
|
||||
retry: parseInt(monitor.retry),
|
||||
|
||||
@@ -2,6 +2,7 @@ import { parseJsonOrArray } from '../../utils/parser.js';
|
||||
|
||||
const clean = ({ heartbeats = [], ...monitor }, includeHeartbeats = true) => ({
|
||||
monitorId: monitor.monitorId,
|
||||
parentId: monitor.parentId || null,
|
||||
name: monitor.name,
|
||||
url: monitor.url,
|
||||
retry: parseInt(monitor.retry),
|
||||
|
||||
@@ -5,6 +5,7 @@ export const monitorTable = async (client) => {
|
||||
await client.schema.createTable('monitor', (table) => {
|
||||
table.increments('id');
|
||||
table.string('monitorId').notNullable().primary();
|
||||
table.string('parentId').defaultTo(null);
|
||||
table.string('name').notNullable();
|
||||
table.string('url').notNullable();
|
||||
table.integer('port').defaultTo(null);
|
||||
|
||||
+1
-4
@@ -17,10 +17,7 @@ import initialiseCronJobs from './utils/cron.js';
|
||||
import migrateDatabase from '../scripts/migrate.js';
|
||||
import addInviteToCookie from './middleware/addInviteToCookie.js';
|
||||
import { loadIcons } from './utils/icons.js';
|
||||
import {
|
||||
getVersionInfo,
|
||||
startVersionCheck
|
||||
} from './utils/checkVersion.js';
|
||||
import { getVersionInfo, startVersionCheck } from './utils/checkVersion.js';
|
||||
|
||||
const app = express();
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ export const defaultMonitorData = (body) => ({
|
||||
url: body.url,
|
||||
interval: body.interval ?? 60,
|
||||
monitorId: body.monitorId,
|
||||
parentId: body.parentId ?? null,
|
||||
retry: body.retry ?? 1,
|
||||
retryInterval: body.retryInterval ?? 60,
|
||||
requestTimeout: body.requestTimeout ?? 60,
|
||||
@@ -51,6 +52,7 @@ export const formatMonitorData = (body, email) => {
|
||||
url: body.url,
|
||||
interval: body.interval,
|
||||
monitorId: body.monitorId,
|
||||
parentId: body.parentId,
|
||||
retry: body.retry,
|
||||
retryInterval: body.retryInterval,
|
||||
requestTimeout: body.requestTimeout,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { cleanMonitor } from '../../../server/class/monitor/index';
|
||||
describe('Monitor - Class', () => {
|
||||
const monitor = {
|
||||
monitorId: '4d048471-9e85-428b-8050-4238f6033478',
|
||||
parentId: '4d048471-9e85-428b-8050-4238f6033479',
|
||||
name: 'Lunalytics',
|
||||
url: 'https://demo.lunalytics.xyz/api/status',
|
||||
createdAt: '2025-08-23T17:00:00.000Z',
|
||||
@@ -48,6 +49,7 @@ describe('Monitor - Class', () => {
|
||||
it('should return valid monitor using cleanPartialMonitor', () => {
|
||||
expect(cleanMonitor(monitor, false, false)).toEqual({
|
||||
monitorId: '4d048471-9e85-428b-8050-4238f6033478',
|
||||
parentId: '4d048471-9e85-428b-8050-4238f6033479',
|
||||
name: 'Lunalytics',
|
||||
url: 'https://demo.lunalytics.xyz/api/status',
|
||||
createdAt: '2025-08-23T17:00:00.000Z',
|
||||
@@ -87,6 +89,7 @@ describe('Monitor - Class', () => {
|
||||
})
|
||||
).toEqual({
|
||||
monitorId: '4d048471-9e85-428b-8050-4238f6033478',
|
||||
parentId: '4d048471-9e85-428b-8050-4238f6033479',
|
||||
name: 'Lunalytics',
|
||||
url: 'https://demo.lunalytics.xyz/api/status',
|
||||
createdAt: '2025-08-23T17:00:00.000Z',
|
||||
|
||||
@@ -154,6 +154,7 @@ describe('Add Monitor - Middleware', () => {
|
||||
requestTimeout: fakeRequest.body.requestTimeout,
|
||||
notificationId: fakeRequest.body.notificationId,
|
||||
notificationType: fakeRequest.body.notificationType,
|
||||
parentId: null,
|
||||
headers: JSON.stringify(fakeRequest.body.headers),
|
||||
body: JSON.stringify(fakeRequest.body.body),
|
||||
email: user.email,
|
||||
@@ -276,6 +277,7 @@ describe('Add Monitor - Middleware', () => {
|
||||
requestTimeout: fakeRequest.body.requestTimeout,
|
||||
notificationId: fakeRequest.body.notificationId,
|
||||
notificationType: fakeRequest.body.notificationType,
|
||||
parentId: null,
|
||||
email: user.email,
|
||||
port: fakeRequest.body.port,
|
||||
valid_status_codes: '',
|
||||
|
||||
@@ -154,6 +154,7 @@ describe('Edit Monitor - Middleware', () => {
|
||||
requestTimeout: fakeRequest.body.requestTimeout,
|
||||
notificationId: fakeRequest.body.notificationId,
|
||||
notificationType: fakeRequest.body.notificationType,
|
||||
parentId: null,
|
||||
body: JSON.stringify(fakeRequest.body.body),
|
||||
headers: JSON.stringify(fakeRequest.body.headers),
|
||||
email: user.email,
|
||||
@@ -275,6 +276,7 @@ describe('Edit Monitor - Middleware', () => {
|
||||
requestTimeout: fakeRequest.body.requestTimeout,
|
||||
notificationId: fakeRequest.body.notificationId,
|
||||
notificationType: fakeRequest.body.notificationType,
|
||||
parentId: null,
|
||||
email: user.email,
|
||||
port: fakeRequest.body.port,
|
||||
valid_status_codes: '',
|
||||
|
||||
Reference in New Issue
Block a user