docs: add documentation links to nodes & tools (#184)

* docs: add documentation links to nodes & tools

* fix: add type hints to constants

---------

Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
This commit is contained in:
Sabiha Khan 2026-03-09 11:39:25 +05:30 committed by GitHub
parent 5114ca5ee7
commit 5698338215
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 64 additions and 6 deletions

4
ui/package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "ui",
"version": "1.15.0",
"version": "1.16.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ui",
"version": "1.15.0",
"version": "1.16.0",
"dependencies": {
"@dagrejs/dagre": "^1.1.4",
"@hey-api/client-fetch": "^0.10.0",

View file

@ -1,6 +1,6 @@
"use client";
import { ArrowLeft, Code, Loader2, Save } from "lucide-react";
import { ArrowLeft, Code, ExternalLink, Loader2, Save } from "lucide-react";
import { useParams, useRouter } from "next/navigation";
import { useCallback, useEffect, useState } from "react";
@ -20,6 +20,7 @@ import {
DialogTitle,
} from "@/components/ui/dialog";
import { Skeleton } from "@/components/ui/skeleton";
import { TOOL_DOCUMENTATION_URLS } from "@/constants/documentation";
import { useAuth } from "@/lib/auth";
import {
@ -439,6 +440,17 @@ const data = await response.json();`;
View Code
</Button>
)}
{TOOL_DOCUMENTATION_URLS[tool.category] && (
<a
href={TOOL_DOCUMENTATION_URLS[tool.category]}
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground transition-colors"
>
Docs
<ExternalLink className="h-3.5 w-3.5" />
</a>
)}
</div>
</div>

View file

@ -14,6 +14,7 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Textarea } from "@/components/ui/textarea";
import { NODE_DOCUMENTATION_URLS } from "@/constants/documentation";
import { NodeContent } from "./common/NodeContent";
import { NodeEditDialog } from "./common/NodeEditDialog";
@ -203,6 +204,7 @@ export const AgentNode = memo(({ data, selected, id }: AgentNodeProps) => {
title="Edit Agent"
onSave={handleSave}
isDirty={isDirty}
documentationUrl={NODE_DOCUMENTATION_URLS.agent}
>
{open && (
<AgentNodeEditForm

View file

@ -9,6 +9,7 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Textarea } from "@/components/ui/textarea";
import { NODE_DOCUMENTATION_URLS } from "@/constants/documentation";
import { NodeContent } from "./common/NodeContent";
import { NodeEditDialog } from "./common/NodeEditDialog";
@ -139,6 +140,7 @@ export const EndCall = memo(({ data, selected, id }: EndCallNodeProps) => {
title="End Call"
onSave={handleSave}
isDirty={isDirty}
documentationUrl={NODE_DOCUMENTATION_URLS.endCall}
>
{open && (
<EndCallEditForm

View file

@ -8,6 +8,7 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { NODE_DOCUMENTATION_URLS } from "@/constants/documentation";
import { NodeContent } from "./common/NodeContent";
import { NodeEditDialog } from "./common/NodeEditDialog";
@ -108,6 +109,7 @@ export const GlobalNode = memo(({ data, selected, id }: GlobalNodeProps) => {
title="Edit Global Node"
onSave={handleSave}
isDirty={isDirty}
documentationUrl={NODE_DOCUMENTATION_URLS.global}
>
{open && (
<GlobalNodeEditForm

View file

@ -10,6 +10,7 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Textarea } from "@/components/ui/textarea";
import { NODE_DOCUMENTATION_URLS } from "@/constants/documentation";
import { NodeContent } from "./common/NodeContent";
import { NodeEditDialog } from "./common/NodeEditDialog";
@ -147,6 +148,7 @@ export const QANode = memo(({ data, selected, id }: QANodeProps) => {
title="Edit QA Analysis"
onSave={handleSave}
isDirty={isDirty}
documentationUrl={NODE_DOCUMENTATION_URLS.qaAnalysis}
>
{open && (
<QANodeEditForm

View file

@ -14,6 +14,7 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Textarea } from "@/components/ui/textarea";
import { NODE_DOCUMENTATION_URLS } from "@/constants/documentation";
import { NodeContent } from "./common/NodeContent";
import { NodeEditDialog } from "./common/NodeEditDialog";
@ -216,6 +217,7 @@ export const StartCall = memo(({ data, selected, id }: StartCallNodeProps) => {
title="Start Call"
onSave={handleSave}
isDirty={isDirty}
documentationUrl={NODE_DOCUMENTATION_URLS.startCall}
>
{open && (
<StartCallEditForm

View file

@ -8,6 +8,7 @@ import { FlowNodeData } from "@/components/flow/types";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { NODE_DOCUMENTATION_URLS } from "@/constants/documentation";
import { useAppConfig } from "@/context/AppConfigContext";
import { NodeContent } from "./common/NodeContent";
@ -145,6 +146,7 @@ export const TriggerNode = memo(({ data, selected, id }: TriggerNodeProps) => {
title="Edit API Trigger"
onSave={handleSave}
isDirty={isDirty}
documentationUrl={NODE_DOCUMENTATION_URLS.apiTrigger}
>
{open && (
<TriggerNodeEditForm

View file

@ -19,6 +19,7 @@ import { JsonEditor, validateJson } from "@/components/ui/json-editor";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { NODE_DOCUMENTATION_URLS } from "@/constants/documentation";
import { NodeContent } from "./common/NodeContent";
import { NodeEditDialog } from "./common/NodeEditDialog";
@ -180,6 +181,7 @@ export const WebhookNode = memo(({ data, selected, id }: WebhookNodeProps) => {
onSave={handleSave}
error={endpointError || jsonError}
isDirty={isDirty}
documentationUrl={NODE_DOCUMENTATION_URLS.webhook}
>
{open && (
<WebhookNodeEditForm

View file

@ -1,4 +1,4 @@
import { AlertCircle } from "lucide-react";
import { AlertCircle, ExternalLink } from "lucide-react";
import { ReactNode, useCallback, useEffect, useState } from "react";
import { FlowNodeData } from "@/components/flow/types";
@ -24,6 +24,7 @@ interface NodeEditDialogProps {
onSave?: () => void;
error?: string | null;
isDirty?: boolean;
documentationUrl?: string;
}
export const NodeEditDialog = ({
@ -34,7 +35,8 @@ export const NodeEditDialog = ({
children,
onSave,
error,
isDirty = false
isDirty = false,
documentationUrl,
}: NodeEditDialogProps) => {
const [showDiscardAlert, setShowDiscardAlert] = useState(false);
@ -84,7 +86,20 @@ export const NodeEditDialog = ({
style={{ maxWidth: "1200px", width: "95vw" }}
>
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
<div className="flex items-center justify-between">
<DialogTitle>{title}</DialogTitle>
{documentationUrl && (
<a
href={documentationUrl}
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground transition-colors pr-6"
>
Docs
<ExternalLink className="h-3.5 w-3.5" />
</a>
)}
</div>
<DialogDescription>
Configure the settings for this node in your workflow.
</DialogDescription>

View file

@ -0,0 +1,17 @@
const DOCS_BASE = "https://docs.dograh.com";
export const NODE_DOCUMENTATION_URLS: Record<string, string> = {
startCall: `${DOCS_BASE}/voice-agent/start-call`,
endCall: `${DOCS_BASE}/voice-agent/end-call`,
agent: `${DOCS_BASE}/voice-agent/agent`,
global: `${DOCS_BASE}/voice-agent/global`,
apiTrigger: `${DOCS_BASE}/voice-agent/api-trigger`,
webhook: `${DOCS_BASE}/voice-agent/webhook`,
qaAnalysis: `${DOCS_BASE}/getting-started`,
};
export const TOOL_DOCUMENTATION_URLS: Record<string, string> = {
http_api: `${DOCS_BASE}/voice-agent/tools/http-api`,
end_call: `${DOCS_BASE}/voice-agent/tools/end-call`,
transfer_call: `${DOCS_BASE}/voice-agent/tools/call-transfer`,
};