From c4d978cc3bf40b660b997b0b07bf384925a0639c Mon Sep 17 00:00:00 2001 From: Nawaz Dhandala Date: Mon, 9 Feb 2026 14:11:02 +0000 Subject: [PATCH] feat: add API and Website monitor documentation with dynamic URL placeholders --- .../Markdown.tsx/MarkdownEditor.tsx | 30 +++-- .../TinyFormDocumentation.tsx | 21 ++++ .../Components/Form/Monitor/MonitorStep.tsx | 42 +++++++ Docs/Content/monitor/api-monitor.md | 104 ++++++++++++++++++ Docs/Content/monitor/website-monitor.md | 81 ++++++++++++++ Docs/Utils/Nav.ts | 8 ++ Probe/Utils/Monitors/Monitor.ts | 32 +++++- 7 files changed, 300 insertions(+), 18 deletions(-) create mode 100644 Common/UI/Components/TinyFormDocumentation/TinyFormDocumentation.tsx create mode 100644 Docs/Content/monitor/api-monitor.md create mode 100644 Docs/Content/monitor/website-monitor.md diff --git a/Common/UI/Components/Markdown.tsx/MarkdownEditor.tsx b/Common/UI/Components/Markdown.tsx/MarkdownEditor.tsx index ee7c4397fd..7c0bca70e0 100644 --- a/Common/UI/Components/Markdown.tsx/MarkdownEditor.tsx +++ b/Common/UI/Components/Markdown.tsx/MarkdownEditor.tsx @@ -1,5 +1,6 @@ import Icon from "../Icon/Icon"; import IconProp from "../../../Types/Icon/IconProp"; +import TinyFormDocumentation from "../TinyFormDocumentation/TinyFormDocumentation"; import React, { FunctionComponent, ReactElement, @@ -649,23 +650,20 @@ const MarkdownEditor: FunctionComponent = ( )} {/* Help Text */} -
-
- Markdown help -
-
- **bold** or *italic* -
-
- `code` or - ```code block``` -
-
# Heading 1, ## Heading 2, ### Heading 3
-
- Bullet list or 1. Numbered list
-
[Link text](url) or > Quote
+ + <> +
+ **bold** or *italic*
-
-
+
+ `code` or + ```code block``` +
+
# Heading 1, ## Heading 2, ### Heading 3
+
- Bullet list or 1. Numbered list
+
[Link text](url) or > Quote
+ + ); }; diff --git a/Common/UI/Components/TinyFormDocumentation/TinyFormDocumentation.tsx b/Common/UI/Components/TinyFormDocumentation/TinyFormDocumentation.tsx new file mode 100644 index 0000000000..4e268c9508 --- /dev/null +++ b/Common/UI/Components/TinyFormDocumentation/TinyFormDocumentation.tsx @@ -0,0 +1,21 @@ +import React, { FunctionComponent, ReactElement } from "react"; + +export interface ComponentProps { + title: string; + children: ReactElement; +} + +const TinyFormDocumentation: FunctionComponent = ( + props: ComponentProps, +): ReactElement => { + return ( +
+
+ {props.title} +
{props.children}
+
+
+ ); +}; + +export default TinyFormDocumentation; diff --git a/Dashboard/src/Components/Form/Monitor/MonitorStep.tsx b/Dashboard/src/Components/Form/Monitor/MonitorStep.tsx index 0f6b8d58f2..01df9abbda 100644 --- a/Dashboard/src/Components/Form/Monitor/MonitorStep.tsx +++ b/Dashboard/src/Components/Form/Monitor/MonitorStep.tsx @@ -66,6 +66,7 @@ import MonitorStepMetricMonitor, { MonitorStepMetricMonitorUtil, } from "Common/Types/Monitor/MonitorStepMetricMonitor"; import Link from "Common/UI/Components/Link/Link"; +import TinyFormDocumentation from "Common/UI/Components/TinyFormDocumentation/TinyFormDocumentation"; import ExceptionMonitorStepForm from "./ExceptionMonitor/ExceptionMonitorStepForm"; import MonitorStepExceptionMonitor, { MonitorStepExceptionMonitorUtil, @@ -437,6 +438,47 @@ return { /> + {(props.monitorType === MonitorType.API || + props.monitorType === MonitorType.Website) && ( + + <> +
+ + {"{{timestamp}}"} + {" "} + — replaced with current Unix timestamp +
+
+ + {"{{random}}"} + {" "} + — replaced with a random unique string +
+
+ Example:{" "} + + {"https://example.com?cb={{timestamp}}"} + +
+
+ Useful for busting CDN or proxy caches on each check.{" "} + + Learn more. + +
+ +
+ )} + {props.monitorType === MonitorType.Port && (
> { @@ -378,8 +398,12 @@ export default class MonitorUtil { result.monitorDestination = monitorStep.data.monitorDestination; - const response: ProbeWebsiteResponse | null = await WebsiteMonitor.ping( + const websiteUrl: URL = MonitorUtil.resolveUrlPlaceholders( monitorStep.data?.monitorDestination as URL, + ); + + const response: ProbeWebsiteResponse | null = await WebsiteMonitor.ping( + websiteUrl, { isHeadRequest: MonitorUtil.isHeadRequest(monitorStep), monitorId: monitorId, @@ -410,6 +434,10 @@ export default class MonitorUtil { result.monitorDestination = monitorStep.data.monitorDestination; + const apiUrl: URL = MonitorUtil.resolveUrlPlaceholders( + monitorStep.data?.monitorDestination as URL, + ); + let requestBody: JSONObject | undefined = undefined; if ( monitorStep.data?.requestBody && @@ -421,7 +449,7 @@ export default class MonitorUtil { } const response: APIResponse | null = await ApiMonitor.ping( - monitorStep.data?.monitorDestination as URL, + apiUrl, { requestHeaders: monitorStep.data?.requestHeaders || {}, requestBody: requestBody || undefined,