Skip to content

Commit 177d1a8

Browse files
authored
Merge pull request #34 from coder/brett/add-all-snippets-and-docs
feat: add snippets for all form types and add docs links
2 parents 6c6b912 + c52f435 commit 177d1a8

File tree

4 files changed

+251
-81
lines changed

4 files changed

+251
-81
lines changed

src/client/App.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,14 +186,16 @@ export const App = () => {
186186
rel="noreferrer"
187187
className="font-light text-content-secondary text-sm hover:text-content-primary"
188188
>
189+
<span className="sr-only"> (link opens in new tab)</span>
189190
Coder
190191
</a>
191192
<a
192-
href="https://coder.com"
193+
href="https://coder.com/docs/admin/templates/extending-templates/parameters"
193194
target="_blank"
194195
rel="noreferrer"
195196
className="font-light text-content-secondary text-sm hover:text-content-primary"
196197
>
198+
<span className="sr-only"> (link opens in new tab)</span>
197199
Docs
198200
</a>
199201
<ExampleSelector />
@@ -203,7 +205,7 @@ export const App = () => {
203205

204206
<ResizablePanelGroup direction={"horizontal"}>
205207
{/* EDITOR */}
206-
<Editor code={code} setCode={setCode} />
208+
<Editor code={code} setCode={setCode} parameters={parameters} />
207209

208210
<ResizableHandle className="bg-surface-quaternary" />
209211

@@ -333,6 +335,7 @@ const ExampleSelector: FC = () => {
333335
return (
334336
<DropdownMenuItem key={slug} asChild={true}>
335337
<a href={href} target="_blank" rel="noreferrer">
338+
<span className="sr-only"> (link opens in new tab)</span>
336339
<ExternalLinkIcon />
337340
{title}
338341
</a>

src/client/Editor.tsx

Lines changed: 37 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
import { Editor as MonacoEditor } from "@monaco-editor/react";
2+
import {
3+
CheckIcon,
4+
ChevronDownIcon,
5+
CopyIcon,
6+
FileJsonIcon,
7+
SettingsIcon,
8+
ZapIcon,
9+
} from "lucide-react";
10+
import { type FC, useEffect, useState } from "react";
111
import { Button } from "@/client/components/Button";
212
import {
313
DropdownMenu,
@@ -13,71 +23,50 @@ import {
1323
TooltipContent,
1424
TooltipTrigger,
1525
} from "@/client/components/Tooltip";
26+
import { useEditor } from "@/client/contexts/editor";
1627
import { useTheme } from "@/client/contexts/theme";
17-
import { multiSelect, radio, switchInput, textInput } from "@/client/snippets";
18-
import type { ParameterFormType } from "@/gen/types";
28+
import { type SnippetFunc, snippets } from "@/client/snippets";
29+
import type { ParameterWithSource } from "@/gen/types";
1930
import { cn } from "@/utils/cn";
20-
import { Editor as MonacoEditor } from "@monaco-editor/react";
21-
import {
22-
CheckIcon,
23-
ChevronDownIcon,
24-
CopyIcon,
25-
FileJsonIcon,
26-
RadioIcon,
27-
SettingsIcon,
28-
SquareMousePointerIcon,
29-
TextCursorInputIcon,
30-
ToggleLeftIcon,
31-
ZapIcon,
32-
} from "lucide-react";
33-
import { type FC, useEffect, useRef, useState } from "react";
34-
import { useEditor } from "@/client/contexts/editor";
3531

3632
type EditorProps = {
3733
code: string;
3834
setCode: React.Dispatch<React.SetStateAction<string>>;
35+
parameters: ParameterWithSource[];
3936
};
4037

41-
export const Editor: FC<EditorProps> = ({ code, setCode }) => {
38+
export const Editor: FC<EditorProps> = ({ code, setCode, parameters }) => {
4239
const { appliedTheme } = useTheme();
4340
const editorRef = useEditor();
4441

45-
const [codeCopied, setCodeCopied] = useState(() => false);
46-
const copyTimeoutId = useRef<ReturnType<typeof setTimeout> | undefined>(
47-
undefined,
48-
);
49-
5042
const [tab, setTab] = useState(() => "code");
5143

44+
const [codeCopied, setCodeCopied] = useState(() => false);
45+
5246
const onCopy = () => {
5347
navigator.clipboard.writeText(code);
5448
setCodeCopied(() => true);
5549
};
5650

57-
const onAddSnippet = (formType: ParameterFormType) => {
58-
if (formType === "input") {
59-
setCode(`${code.trimEnd()}\n\n${textInput}\n`);
60-
} else if (formType === "radio") {
61-
setCode(`${code.trimEnd()}\n\n${radio}\n`);
62-
} else if (formType === "multi-select") {
63-
setCode(`${code.trimEnd()}\n\n${multiSelect}\n`);
64-
} else if (formType === "switch") {
65-
setCode(`${code.trimEnd()}\n\n${switchInput}\n`);
66-
}
51+
const onAddSnippet = (name: string, snippet: SnippetFunc) => {
52+
const nameCount = parameters.filter((p) => p.name.startsWith(name)).length;
53+
54+
const nextInOrder = 1 + Math.max(0, ...parameters.map((p) => p.order));
55+
const newName = nameCount > 0 ? `${name}-${nameCount}` : name;
56+
const newSnippet = snippet(newName, nextInOrder);
57+
setCode(`${code.trimEnd()}\n\n${newSnippet}\n`);
6758
};
6859

6960
useEffect(() => {
7061
if (!codeCopied) {
7162
return;
7263
}
7364

74-
clearTimeout(copyTimeoutId.current);
75-
76-
copyTimeoutId.current = setTimeout(() => {
65+
const copyTimeoutId = setTimeout(() => {
7766
setCodeCopied(() => false);
7867
}, 1000);
7968

80-
return () => clearTimeout(copyTimeoutId.current);
69+
return () => clearTimeout(copyTimeoutId);
8170
}, [codeCopied]);
8271

8372
return (
@@ -116,23 +105,17 @@ export const Editor: FC<EditorProps> = ({ code, setCode }) => {
116105

117106
<DropdownMenuPortal>
118107
<DropdownMenuContent align="start">
119-
<DropdownMenuItem onClick={() => onAddSnippet("input")}>
120-
<TextCursorInputIcon width={24} height={24} />
121-
Text input
122-
</DropdownMenuItem>
123-
<DropdownMenuItem
124-
onClick={() => onAddSnippet("multi-select")}
125-
>
126-
<SquareMousePointerIcon width={24} height={24} />
127-
Multi-select
128-
</DropdownMenuItem>
129-
<DropdownMenuItem onClick={() => onAddSnippet("radio")}>
130-
<RadioIcon width={24} height={24} />
131-
Radio
132-
</DropdownMenuItem>
133-
<DropdownMenuItem onClick={() => onAddSnippet("switch")}>
134-
<ToggleLeftIcon width={24} height={24} /> Switches
135-
</DropdownMenuItem>
108+
{snippets.map(
109+
({ name, label, icon: Icon, snippet }, index) => (
110+
<DropdownMenuItem
111+
key={index}
112+
onClick={() => onAddSnippet(name, snippet)}
113+
>
114+
<Icon size={24} />
115+
{label}
116+
</DropdownMenuItem>
117+
),
118+
)}
136119
</DropdownMenuContent>
137120
</DropdownMenuPortal>
138121
</DropdownMenu>

src/client/Preview.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,12 @@ const PreviewEmptyState = () => {
239239
</p>
240240
</div>
241241
<a
242-
href="#todo"
242+
href="https://coder.com/docs/admin/templates/extending-templates/parameters"
243+
target="_blank"
244+
rel="noreferrer"
243245
className="flex items-center gap-0.5 text-content-link text-sm"
244246
>
247+
<span className="sr-only"> (link opens in new tab)</span>
245248
Read the docs
246249
<span className="inline">
247250
<ExternalLinkIcon width={16} />

0 commit comments

Comments
 (0)