mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-25 08:48:13 +02:00
feat: agent stream for cloudonix OPBX (#261)
* feat: agent stream for cloudonix OPBX * feat: make cloudonix app name optional * feat: create application while configuring telephony config * fix: get telephony configuration from stamped workflow run * fix: fix vobiz hangup URL
This commit is contained in:
parent
5cfdbeff02
commit
7fd3b96470
48 changed files with 1529 additions and 545 deletions
|
|
@ -42,6 +42,7 @@ const edgeTypes = {
|
|||
interface RenderWorkflowProps {
|
||||
initialWorkflowName: string;
|
||||
workflowId: number;
|
||||
workflowUuid?: string;
|
||||
initialFlow?: {
|
||||
nodes: FlowNode[];
|
||||
edges: FlowEdge[];
|
||||
|
|
@ -58,7 +59,7 @@ interface RenderWorkflowProps {
|
|||
user: { id: string; email?: string };
|
||||
}
|
||||
|
||||
function RenderWorkflow({ initialWorkflowName, workflowId, initialFlow, initialTemplateContextVariables, initialWorkflowConfigurations, initialVersionNumber, initialVersionStatus, user }: RenderWorkflowProps) {
|
||||
function RenderWorkflow({ initialWorkflowName, workflowId, workflowUuid, initialFlow, initialTemplateContextVariables, initialWorkflowConfigurations, initialVersionNumber, initialVersionStatus, user }: RenderWorkflowProps) {
|
||||
const router = useRouter();
|
||||
const [isPhoneCallDialogOpen, setIsPhoneCallDialogOpen] = useState(false);
|
||||
const [isVersionPanelOpen, setIsVersionPanelOpen] = useState(false);
|
||||
|
|
@ -303,6 +304,7 @@ function RenderWorkflow({ initialWorkflowName, workflowId, initialFlow, initialT
|
|||
rfInstance={rfInstance}
|
||||
onRun={onRun}
|
||||
workflowId={workflowId}
|
||||
workflowUuid={workflowUuid}
|
||||
saveWorkflow={guardedSaveWorkflow}
|
||||
user={user}
|
||||
onPhoneCallClick={() => setIsPhoneCallDialogOpen(true)}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import { ReactFlowInstance } from "@xyflow/react";
|
||||
import { AlertCircle, ArrowLeft, ChevronDown, Copy, Download, Eye, History, LoaderCircle, Menu, MoreVertical, Phone, Rocket } from "lucide-react";
|
||||
import { AlertCircle, ArrowLeft, ChevronDown, Clipboard, Copy, Download, Eye, History, LoaderCircle, Menu, MoreVertical, Phone, Rocket } from "lucide-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import posthog from "posthog-js";
|
||||
import { useState } from "react";
|
||||
|
|
@ -37,6 +37,7 @@ interface WorkflowEditorHeaderProps {
|
|||
rfInstance: React.RefObject<ReactFlowInstance<FlowNode, FlowEdge> | null>;
|
||||
onRun: (mode: string) => Promise<void>;
|
||||
workflowId: number;
|
||||
workflowUuid?: string;
|
||||
saveWorkflow: (updateWorkflowDefinition?: boolean) => Promise<void>;
|
||||
user: { id: string; email?: string };
|
||||
onPhoneCallClick: () => void;
|
||||
|
|
@ -63,6 +64,7 @@ export const WorkflowEditorHeader = ({
|
|||
hasDraft,
|
||||
onPublished,
|
||||
workflowId,
|
||||
workflowUuid,
|
||||
}: WorkflowEditorHeaderProps) => {
|
||||
const router = useRouter();
|
||||
const { toggleSidebar } = useSidebar();
|
||||
|
|
@ -123,6 +125,19 @@ export const WorkflowEditorHeader = ({
|
|||
}
|
||||
};
|
||||
|
||||
const handleCopyAgentUuid = async () => {
|
||||
if (!workflowUuid) {
|
||||
toast.error("Agent UUID not available");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await navigator.clipboard.writeText(workflowUuid);
|
||||
toast.success("Agent UUID copied");
|
||||
} catch {
|
||||
toast.error("Failed to copy Agent UUID");
|
||||
}
|
||||
};
|
||||
|
||||
const handleDownloadWorkflow = () => {
|
||||
if (!rfInstance.current) return;
|
||||
|
||||
|
|
@ -380,6 +395,14 @@ export const WorkflowEditorHeader = ({
|
|||
<Download className="w-4 h-4 mr-2" />
|
||||
Download Workflow
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={handleCopyAgentUuid}
|
||||
disabled={!workflowUuid}
|
||||
className="text-white hover:bg-[#2a2a2a] cursor-pointer"
|
||||
>
|
||||
<Clipboard className="w-4 h-4 mr-2" />
|
||||
Copy Agent UUID
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ export default function WorkflowDetailPage() {
|
|||
<RenderWorkflow
|
||||
initialWorkflowName={workflow.name}
|
||||
workflowId={workflow.id}
|
||||
workflowUuid={workflow.workflow_uuid ?? undefined}
|
||||
initialFlow={{
|
||||
nodes: workflow.workflow_definition.nodes as FlowNode[],
|
||||
edges: workflow.workflow_definition.edges as FlowEdge[],
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import { format } from "date-fns";
|
||||
import { ArrowLeft, BookA, Brain, CalendarIcon, Download, ExternalLink, FileDown, Loader2, Mic, Pause, PhoneOff, Play, Rocket, Settings, Trash2Icon, Upload, Variable, X } from "lucide-react";
|
||||
import { ArrowLeft, BookA, Brain, CalendarIcon, Clipboard, Download, ExternalLink, FileDown, Fingerprint, Loader2, Mic, Pause, PhoneOff, Play, Rocket, Settings, Trash2Icon, Upload, Variable, X } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
|
|
@ -81,6 +81,7 @@ const NAV_ITEMS = [
|
|||
{ id: "recordings", label: "Recordings", icon: Mic },
|
||||
{ id: "deployment", label: "Deployment", icon: Rocket },
|
||||
{ id: "report", label: "Report", icon: FileDown },
|
||||
{ id: "identity", label: "Agent UUID", icon: Fingerprint },
|
||||
];
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -992,6 +993,53 @@ function VoicemailSection({
|
|||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Section: Agent UUID
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function AgentUuidSection({ workflowUuid }: { workflowUuid: string }) {
|
||||
const handleCopy = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(workflowUuid);
|
||||
toast.success("Agent UUID copied");
|
||||
} catch {
|
||||
toast.error("Failed to copy Agent UUID");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Card id="identity">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2 text-base">
|
||||
<Fingerprint className="h-4 w-4" />
|
||||
Agent UUID
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Stable identifier for this agent. Used in agent-stream URLs and
|
||||
other integrations where a numeric workflow ID isn't portable.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleCopy}
|
||||
title="Click to copy"
|
||||
className="group flex w-full items-center gap-2 rounded-md border bg-muted/20 p-2 text-left font-mono text-xs transition-colors hover:bg-muted/40"
|
||||
>
|
||||
<code className="flex-1 truncate">{workflowUuid}</code>
|
||||
<Clipboard className="h-3.5 w-3.5 shrink-0 text-muted-foreground transition-colors group-hover:text-foreground" />
|
||||
</button>
|
||||
</CardContent>
|
||||
<CardFooter className="border-t pt-6">
|
||||
<Button variant="outline" size="sm" onClick={handleCopy}>
|
||||
<Clipboard className="h-3.5 w-3.5 mr-2" />
|
||||
Copy UUID
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Main Page
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -1263,6 +1311,11 @@ function WorkflowSettingsInner({
|
|||
|
||||
{/* Report */}
|
||||
<ReportSection workflowId={workflowId} />
|
||||
|
||||
{/* Agent UUID */}
|
||||
{workflow.workflow_uuid && (
|
||||
<AgentUuidSection workflowUuid={workflow.workflow_uuid} />
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue