Skip to content

Commit addcc42

Browse files
committed
Update code editor and loading
1 parent 690666a commit addcc42

File tree

2 files changed

+175
-50
lines changed

2 files changed

+175
-50
lines changed

components/CodeEditor.tsx

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
/* eslint-disable react/jsx-props-no-spreading */
22
import Editor from 'react-simple-code-editor';
3-
import { highlight, languages, Grammar } from 'prismjs';
4-
import 'prismjs/themes/prism.css';
3+
import { highlight, Grammar } from 'prismjs';
4+
import 'prismjs/themes/prism-dark.css';
55
import 'prismjs/components/prism-typescript';
66

77
type CodeEditorProps = {
88
code: string;
99
// eslint-disable-next-line no-unused-vars
1010
setCode: (code: string) => void;
1111
placeholder: string;
12-
language: string;
12+
languageGrammar: Grammar;
1313
}
1414

1515
const hightlightWithLineNumbers = (
@@ -20,15 +20,14 @@ const hightlightWithLineNumbers = (
2020
.join('\n');
2121

2222
export default function CodeEditor({
23-
code, setCode, placeholder, language,
23+
code, setCode, placeholder, languageGrammar,
2424
}: CodeEditorProps) {
25-
console.log(language);
2625
return (
2726
<Editor
2827
value={code}
2928
onValueChange={(codeUpdated) => setCode(codeUpdated)}
3029
highlight={(codeToBeHighlighted) => hightlightWithLineNumbers(
31-
codeToBeHighlighted, languages.typescript, 'TypeScript',
30+
codeToBeHighlighted, languageGrammar, 'TypeScript',
3231
)}
3332
padding={12}
3433
textareaId="codeArea"

pages/index.tsx

+170-44
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,23 @@ import { useState, Fragment } from 'react';
22
import Head from 'next/head';
33
import Image from 'next/image';
44
import Link from 'next/link';
5-
import { Menu, Transition, Disclosure } from '@headlessui/react';
5+
import axios from 'axios';
6+
import {
7+
Menu, Transition, Disclosure, Switch,
8+
} from '@headlessui/react';
69
import { ChevronDownIcon } from '@heroicons/react/solid';
710
import {
811
MailIcon, PencilAltIcon,
912
} from '@heroicons/react/outline';
13+
import { languages, Grammar } from 'prismjs';
1014
import CodeEditor from '../components/CodeEditor';
1115
import Output from '../components/Output';
1216
import vscode from '../assets/vsc.svg';
1317

18+
const ENDPOINT = process.env.NODE_ENV === 'development'
19+
? 'http://localhost:5000'
20+
: 'https://api.mintlify.com';
21+
1422
const footer = {
1523
main: [
1624
{ name: 'Documentation', href: 'https://nicedoc.io/mintlify/inferapp' },
@@ -55,19 +63,86 @@ const footer = {
5563
],
5664
};
5765

66+
type LanguageOption = {
67+
name: string;
68+
id: string;
69+
grammar: Grammar;
70+
}
71+
72+
const languagesDropdown: LanguageOption[] = [
73+
{ name: 'Auto-detect', id: 'auto', grammar: languages.plain },
74+
{ name: 'JavaScript', id: 'javascript', grammar: languages.javascript },
75+
{ name: 'TypeScript', id: 'typescript', grammar: languages.typescript },
76+
{ name: 'Python', id: 'python', grammar: languages.python },
77+
];
78+
79+
const formats = [
80+
{ name: 'Auto-detect', id: 'auto' },
81+
{ name: 'JSDoc', id: 'JSDoc' },
82+
{ name: 'reST', id: 'reST' },
83+
{ name: 'Google', id: 'Google' },
84+
];
85+
5886
function classNames(...classes: any) {
5987
return classes.filter(Boolean).join(' ');
6088
}
6189

6290
export default function Example() {
6391
const [code, setCode] = useState('');
6492
const [outputDisplay, setOutputDisplay] = useState('');
93+
const [selectedLanguage, setSelectedLanguage] = useState(languagesDropdown[0]);
94+
const [selectedFormat, setSelectedFormat] = useState(formats[0]);
95+
const [commentsEnabled, setCommentsEnabled] = useState(true);
96+
const [isGenerating, setIsGenerating] = useState(false);
6597

66-
const codeOnChange = async (newCode: string) => {
98+
const onCodeChange = async (newCode: string) => {
6799
setCode(newCode);
100+
if (newCode.length < 30) return;
101+
102+
const { data: { language } }: { data: { language: string } } = await axios.post('https://figstack.uc.r.appspot.com/infer', {
103+
code: newCode.trim(),
104+
});
105+
106+
const languageToUse = languagesDropdown.find(
107+
(languageOption) => languageOption.name === language,
108+
);
109+
110+
if (languageToUse) {
111+
setSelectedLanguage({
112+
...languageToUse,
113+
name: `${language} (auto)`,
114+
});
115+
return;
116+
}
117+
118+
setSelectedLanguage({
119+
name: `${language} (auto)`,
120+
id: language,
121+
grammar: languages.plain,
122+
});
123+
};
124+
125+
const onClickGenerate = async () => {
126+
setIsGenerating(true);
127+
setOutputDisplay('');
128+
129+
try {
130+
const { data: { docstring } }: { data: { docstring: string } } = await axios.post(`${ENDPOINT}/web/write`, {
131+
code,
132+
languageId: selectedLanguage.id,
133+
commented: commentsEnabled,
134+
userId: 'web',
135+
docStyle: 'Auto-generate',
136+
context: code,
137+
});
68138

69-
const detectedLanguage = '';
70-
setOutputDisplay(detectedLanguage);
139+
setOutputDisplay(docstring);
140+
} catch (error: any) {
141+
const errorMessage = error.response?.data.error || 'An enexpected error occurred';
142+
alert(errorMessage);
143+
} finally {
144+
setIsGenerating(false);
145+
}
71146
};
72147

73148
return (
@@ -125,28 +200,28 @@ export default function Example() {
125200
<header className="relative py-6">
126201
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
127202
<h1 className="text-2xl font-bold text-white">Documentation Writer</h1>
128-
<p className="mt-1 text-gray-300">Add some code to get started</p>
203+
<p className="mt-1 text-gray-200">Add some code to get started</p>
129204
</div>
130205
</header>
131206
</>
132207
)}
133208
</Disclosure>
134-
<main className="relative -mt-32">
209+
<main className="relative -mt-32 z-10">
135210
<div className="max-w-screen-xl mx-auto pb-6 px-4 sm:px-6 lg:pb-16 lg:px-8">
136211
<div className="rounded-lg overflow-hidden">
137212
<div className="grid sm:grid-cols-2 sm:gap-4">
138213
<div className="h-full">
139214
<CodeEditor
140215
code={code}
141-
setCode={codeOnChange}
216+
setCode={onCodeChange}
142217
placeholder="Type or paste code here"
143-
language={outputDisplay}
218+
languageGrammar={selectedLanguage.grammar}
144219
/>
145220
</div>
146221
<div className="h-full mt-4 sm:m-0">
147222
<Output
148223
output={outputDisplay}
149-
isLoading={false}
224+
isLoading={isGenerating}
150225
/>
151226
</div>
152227
</div>
@@ -159,8 +234,10 @@ export default function Example() {
159234
<p className="text-sm text-gray-600 mb-1 font-medium">Language</p>
160235
<Menu as="div" className="relative inline-block text-left">
161236
<div>
162-
<Menu.Button className="inline-flex justify-center w-full rounded-md border border-gray-200 shadow-sm px-2 py-1 bg-white text-sm text-gray-700 hover:bg-gray-50 hover:border-gray-300">
163-
JavaScript (auto)
237+
<Menu.Button className="inline-flex items-stretch w-40 rounded-md border border-gray-200 shadow-sm px-2 py-1 bg-white text-sm text-gray-700 hover:bg-gray-50 hover:border-gray-300">
238+
<div className="flex-1 text-left text-gray-700">
239+
{selectedLanguage.name}
240+
</div>
164241
<ChevronDownIcon className="-mr-1 ml-2 h-5 w-5" aria-hidden="true" />
165242
</Menu.Button>
166243
</div>
@@ -174,20 +251,22 @@ export default function Example() {
174251
leaveFrom="transform opacity-100 scale-100"
175252
leaveTo="transform opacity-0 scale-95"
176253
>
177-
<Menu.Items className="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
254+
<Menu.Items className="origin-top-right w-40 absolute right-0 mt-2 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5">
178255
<div className="py-1">
179-
<Menu.Item>
180-
{({ active }) => (
181-
<span
256+
{languagesDropdown.map((language) => (
257+
<Menu.Item key={language.id}>
258+
<button
259+
type="button"
260+
onClick={() => setSelectedLanguage(language)}
182261
className={classNames(
183-
active ? 'bg-gray-100 text-gray-900' : 'text-gray-700',
184-
'block px-4 py-2 text-sm',
262+
selectedLanguage.id === language.id ? 'bg-gray-100 text-gray-900' : 'text-gray-700',
263+
'block px-4 py-2 text-sm w-full text-left hover:bg-gray-100',
185264
)}
186265
>
187-
Account settings
188-
</span>
189-
)}
190-
</Menu.Item>
266+
{language.name}
267+
</button>
268+
</Menu.Item>
269+
))}
191270
</div>
192271
</Menu.Items>
193272
</Transition>
@@ -197,8 +276,10 @@ export default function Example() {
197276
<p className="text-sm text-gray-600 mb-1 font-medium">Format</p>
198277
<Menu as="div" className="relative inline-block text-left">
199278
<div>
200-
<Menu.Button className="inline-flex justify-center w-full rounded-md border border-gray-200 shadow-sm px-2 py-1 bg-white text-sm text-gray-700 hover:bg-gray-50 hover:border-gray-300">
201-
JSDoc (auto)
279+
<Menu.Button className="inline-flex justify-center w-32 rounded-md border border-gray-200 shadow-sm px-2 py-1 bg-white text-sm hover:bg-gray-50 hover:border-gray-300">
280+
<div className="flex-1 text-left text-gray-700">
281+
{selectedFormat.name}
282+
</div>
202283
<ChevronDownIcon className="-mr-1 ml-2 h-5 w-5" aria-hidden="true" />
203284
</Menu.Button>
204285
</div>
@@ -212,43 +293,88 @@ export default function Example() {
212293
leaveFrom="transform opacity-100 scale-100"
213294
leaveTo="transform opacity-0 scale-95"
214295
>
215-
<Menu.Items className="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
296+
<Menu.Items className="origin-top-right w-32 absolute right-0 mt-2 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
216297
<div className="py-1">
217-
<Menu.Item>
218-
{({ active }) => (
219-
<span
220-
className={classNames(
221-
active ? 'bg-gray-100 text-gray-900' : 'text-gray-700',
222-
'block px-4 py-2 text-sm',
223-
)}
224-
>
225-
Account settings
226-
</span>
227-
)}
228-
</Menu.Item>
298+
{
299+
formats.map((format) => (
300+
<Menu.Item key={format.id}>
301+
<button
302+
type="button"
303+
onClick={() => setSelectedFormat(format)}
304+
className={classNames(
305+
format.id === selectedFormat.id ? 'bg-gray-100 text-gray-900' : 'text-gray-700',
306+
'block px-4 py-2 text-sm w-full text-left',
307+
)}
308+
>
309+
{format.name}
310+
</button>
311+
</Menu.Item>
312+
))
313+
}
229314
</div>
230315
</Menu.Items>
231316
</Transition>
232317
</Menu>
233318
</div>
319+
<div>
320+
<p className="text-sm text-gray-600 mb-1 font-medium">Commented</p>
321+
<div className="mt-2 flex">
322+
<Switch
323+
checked={commentsEnabled}
324+
onChange={setCommentsEnabled}
325+
className="flex-shrink-0 group relative rounded-full inline-flex items-center justify-center h-5 w-10 cursor-pointer"
326+
>
327+
<span className="sr-only">Use setting</span>
328+
<span aria-hidden="true" className="pointer-events-none absolute bg-white w-full h-full rounded-md" />
329+
<span
330+
aria-hidden="true"
331+
className={classNames(
332+
commentsEnabled ? 'bg-primary' : 'bg-gray-200',
333+
'pointer-events-none absolute h-4 w-9 mx-auto rounded-full transition-colors ease-in-out duration-200',
334+
)}
335+
/>
336+
<span
337+
aria-hidden="true"
338+
className={classNames(
339+
commentsEnabled ? 'translate-x-5' : 'translate-x-0',
340+
'pointer-events-none absolute left-0 inline-block h-5 w-5 border border-gray-200 rounded-full bg-white shadow transform ring-0 transition-transform ease-in-out duration-200',
341+
)}
342+
/>
343+
</Switch>
344+
</div>
345+
</div>
234346
<button
235347
type="button"
236-
className="inline-flex space-x-1 items-center px-4 py-2 text-sm rounded-md text-green-600 bg-green-500 bg-opacity-25 hover:bg-opacity-40 duration-200"
348+
className="relative flex w-32 space-x-1 justify-center items-center px-4 py-2 text-sm rounded-md text-green-600 bg-green-500 bg-opacity-25 hover:bg-opacity-40 duration-200"
349+
onClick={onClickGenerate}
237350
>
238-
<div>
239-
Write Docs
240-
</div>
241-
<div>
242-
<PencilAltIcon className="h-4 w-4" />
243-
</div>
351+
{
352+
isGenerating ? (
353+
<div className="absolute inset-0 flex items-center justify-center">
354+
<svg className="animate-spin h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
355+
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
356+
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
357+
</svg>
358+
</div>
359+
) : (
360+
<>
361+
<div>
362+
Write Docs
363+
</div>
364+
<div>
365+
<PencilAltIcon className="h-4 w-4" />
366+
</div>
367+
</>
368+
)
369+
}
244370
</button>
245371
</span>
246372
</span>
247373
</div>
248374
</div>
249375
</div>
250376
</main>
251-
<footer className="relative pb-8 z-10 bottom-0 w-full">
377+
<footer className="relative pb-8 bottom-0 w-full">
252378
<div className="max-w-7xl mx-auto px-4 overflow-hidden sm:px-6 lg:px-8">
253379
<div className="mt-8 flex justify-center space-x-6">
254380
{footer.social.map((item) => (

0 commit comments

Comments
 (0)