-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
feat: add Structurizr DSL export for C4 diagrams (#264) #320
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,127 @@ | ||||||||||
| "use client" | ||||||||||
|
|
||||||||||
| import { Check, Copy, Download } from "lucide-react" | ||||||||||
| import { useEffect, useState } from "react" | ||||||||||
| import { Button } from "@/components/ui/button" | ||||||||||
| import { | ||||||||||
| Dialog, | ||||||||||
| DialogContent, | ||||||||||
| DialogDescription, | ||||||||||
| DialogFooter, | ||||||||||
| DialogHeader, | ||||||||||
| DialogTitle, | ||||||||||
| } from "@/components/ui/dialog" | ||||||||||
| import { ScrollArea } from "@/components/ui/scroll-area" | ||||||||||
| import { convertToStructurizrDsl } from "@/lib/structurizr-utils" | ||||||||||
|
|
||||||||||
| interface ExportStructurizrDialogProps { | ||||||||||
| open: boolean | ||||||||||
| onOpenChange: (open: boolean) => void | ||||||||||
| xml: string | ||||||||||
| } | ||||||||||
|
|
||||||||||
| export function ExportStructurizrDialog({ | ||||||||||
| open, | ||||||||||
| onOpenChange, | ||||||||||
| xml, | ||||||||||
| }: ExportStructurizrDialogProps) { | ||||||||||
| const [dsl, setDsl] = useState("") | ||||||||||
| const [copied, setCopied] = useState(false) | ||||||||||
| const [error, setError] = useState("") | ||||||||||
|
|
||||||||||
| useEffect(() => { | ||||||||||
| if (open && xml) { | ||||||||||
| try { | ||||||||||
| const result = convertToStructurizrDsl(xml) | ||||||||||
| setDsl(result) | ||||||||||
| setError("") | ||||||||||
| } catch (err) { | ||||||||||
| setError("Failed to convert diagram to DSL format") | ||||||||||
| setDsl("") | ||||||||||
| console.error("DSL conversion error:", err) | ||||||||||
| } | ||||||||||
| } | ||||||||||
| }, [open, xml]) | ||||||||||
|
|
||||||||||
| const handleCopy = async () => { | ||||||||||
| try { | ||||||||||
| await navigator.clipboard.writeText(dsl) | ||||||||||
| setCopied(true) | ||||||||||
| setTimeout(() => setCopied(false), 2000) | ||||||||||
|
Comment on lines
+46
to
+50
|
||||||||||
| } catch (err) { | ||||||||||
| console.error("Failed to copy to clipboard:", err) | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| const handleDownload = () => { | ||||||||||
| const blob = new Blob([dsl], { type: "text/plain" }) | ||||||||||
| const url = URL.createObjectURL(blob) | ||||||||||
| const a = document.createElement("a") | ||||||||||
| a.href = url | ||||||||||
| a.download = "diagram.dsl" | ||||||||||
| document.body.appendChild(a) | ||||||||||
| a.click() | ||||||||||
| document.body.removeChild(a) | ||||||||||
| URL.revokeObjectURL(url) | ||||||||||
|
||||||||||
| URL.revokeObjectURL(url) | |
| setTimeout(() => { | |
| URL.revokeObjectURL(url) | |
| }, 1000) |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error state blocks display of action buttons, making it impossible for users to close the dialog using the footer buttons when an error occurs. Users would have to use the X button or press Escape. This is inconsistent with the "Close" button being visible when DSL content is successfully generated.
Consider displaying the action buttons even in the error state, or ensure the error message clearly indicates how to dismiss the dialog.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The copied state is not reset when the dialog is closed or when the xml prop changes. If a user copies the DSL, closes the dialog, then reopens it (either with the same or different diagram), the button will still show "Copied" for up to 2 seconds. This creates a confusing UX where the button state doesn't match the actual clipboard content.
Consider resetting the copied state when the dialog opens or when the xml/dsl changes.