split code tab into separate component and clean up code

This commit is contained in:
Abi Raja 2023-11-26 22:30:11 -05:00 committed by dialmedu
parent f14fdfc4e4
commit 82f839a35f
2 changed files with 94 additions and 81 deletions

View File

@ -1,4 +1,4 @@
import { useRef, useState, useCallback } from "react"; import { useRef, useState } from "react";
import ImageUpload from "./components/ImageUpload"; import ImageUpload from "./components/ImageUpload";
import CodePreview from "./components/CodePreview"; import CodePreview from "./components/CodePreview";
import Preview from "./components/Preview"; import Preview from "./components/Preview";
@ -7,7 +7,6 @@ import Spinner from "./components/Spinner";
import classNames from "classnames"; import classNames from "classnames";
import { import {
FaCode, FaCode,
FaCopy,
FaDesktop, FaDesktop,
FaDownload, FaDownload,
FaMobile, FaMobile,
@ -15,12 +14,9 @@ import {
} from "react-icons/fa"; } from "react-icons/fa";
import { Switch } from "./components/ui/switch"; import { Switch } from "./components/ui/switch";
import copy from "copy-to-clipboard";
import toast from "react-hot-toast";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./components/ui/tabs"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "./components/ui/tabs";
import CodeMirror from "./components/CodeMirror";
import SettingsDialog from "./components/SettingsDialog"; import SettingsDialog from "./components/SettingsDialog";
import { Settings, EditorTheme, AppState } from "./types"; import { Settings, EditorTheme, AppState } from "./types";
import { IS_RUNNING_ON_CLOUD } from "./config"; import { IS_RUNNING_ON_CLOUD } from "./config";
@ -31,7 +27,7 @@ import { UrlInputSection } from "./components/UrlInputSection";
import TermsOfServiceDialog from "./components/TermsOfServiceDialog"; import TermsOfServiceDialog from "./components/TermsOfServiceDialog";
import html2canvas from "html2canvas"; import html2canvas from "html2canvas";
import { USER_CLOSE_WEB_SOCKET_CODE } from "./constants"; import { USER_CLOSE_WEB_SOCKET_CODE } from "./constants";
import OpenInCodepenio from "./components/OpenInCodepenio"; import CodeTab from "./components/CodeTab";
function App() { function App() {
const [appState, setAppState] = useState<AppState>(AppState.INITIAL); const [appState, setAppState] = useState<AppState>(AppState.INITIAL);
@ -98,49 +94,6 @@ function App() {
setAppState(AppState.CODE_READY); setAppState(AppState.CODE_READY);
}; };
function doOpenInCodepenio() {
const code = generatedCode;
const form = document.createElement("form");
form.setAttribute("method", "POST");
form.setAttribute("action", "https://codepen.io/pen/define");
form.setAttribute("target", "_blank"); // open in new window
const data = {
html: code,
editors: "100", // 1:Open html, 0:close CSS, 0:Close Js
layout: "left",
css_external:
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" +
(generatedCode.includes("<ion-")
? ",https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css"
: ""),
js_external:
"https://cdn.tailwindcss.com " +
(generatedCode.includes("<ion-")
? ",https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js,https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js"
: ""),
};
// test have html to json
try {
JSON.stringify(data);
} catch (error) {
data.html = "<!-- Copy your code here -->";
}
// Crear un input tipo hidden
const input = document.createElement("input");
input.setAttribute("type", "hidden");
input.setAttribute("name", "data");
input.setAttribute("value", JSON.stringify(data));
// Agregar el input al formulario
form.appendChild(input);
// Agregar el formulario al documento y enviarlo automáticamente
document.body.appendChild(form);
form.submit();
}
function doGenerateCode(params: CodeGenerationParams) { function doGenerateCode(params: CodeGenerationParams) {
setExecutionConsole([]); setExecutionConsole([]);
setAppState(AppState.CODING); setAppState(AppState.CODING);
@ -196,11 +149,6 @@ function App() {
setUpdateInstruction(""); setUpdateInstruction("");
} }
const doCopyCode = useCallback(() => {
copy(generatedCode);
toast.success("Copied to clipboard");
}, [generatedCode]);
const handleTermDialogOpenChange = (open: boolean) => { const handleTermDialogOpenChange = (open: boolean) => {
setSettings((s) => ({ setSettings((s) => ({
...s, ...s,
@ -360,33 +308,11 @@ function App() {
<Preview code={generatedCode} device="mobile" /> <Preview code={generatedCode} device="mobile" />
</TabsContent> </TabsContent>
<TabsContent value="code"> <TabsContent value="code">
<div className="relative"> <CodeTab
<div className="flex justify-start items-center px-4 mb-2"> code={generatedCode}
<span setCode={setGeneratedCode}
title="Copy Code" settings={settings}
className="bg-black text-white flex items-center justify-center hover:text-black hover:bg-gray-100 cursor-pointer rounded-lg text-sm p-2.5" />
onClick={doCopyCode}
>
Copy Code <FaCopy className="ml-2" />
</span>
<Button
onClick={doOpenInCodepenio}
className="bg-gray-100 text-black ml-2 py-2 px-4 border border-black rounded-md hover:bg-gray-400 focus:outline-none"
>
Open in{" "}
<img
src="https://assets.codepen.io/t-1/codepen-logo.svg"
alt="codepen.io"
className="h-4 ml-1"
/>
</Button>
</div>
<CodeMirror
code={generatedCode}
editorTheme={settings.editorTheme}
onCodeChange={setGeneratedCode}
/>
</div>
</TabsContent> </TabsContent>
</Tabs> </Tabs>
</div> </div>

View File

@ -0,0 +1,87 @@
import { FaCopy } from "react-icons/fa";
import CodeMirror from "./CodeMirror";
import { Button } from "./ui/button";
import { Settings } from "../types";
import copy from "copy-to-clipboard";
import { useCallback } from "react";
import toast from "react-hot-toast";
interface Props {
code: string;
setCode: React.Dispatch<React.SetStateAction<string>>;
settings: Settings;
}
function CodeTab({ code, setCode, settings }: Props) {
const copyCode = useCallback(() => {
copy(code);
toast.success("Copied to clipboard");
}, [code]);
const doOpenInCodepenio = useCallback(async () => {
// TODO: Update CSS and JS external links depending on the framework being used
const data = {
html: code,
editors: "100", // 1: Open HTML, 0: Close CSS, 0: Close JS
layout: "left",
css_external:
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" +
(code.includes("<ion-")
? ",https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css"
: ""),
js_external:
"https://cdn.tailwindcss.com " +
(code.includes("<ion-")
? ",https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js,https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js"
: ""),
};
// Create a hidden form and submit it to open the code in CodePen
// Can't use fetch API directly because we want to open the URL in a new tab
const input = document.createElement("input");
input.setAttribute("type", "hidden");
input.setAttribute("name", "data");
input.setAttribute("value", JSON.stringify(data));
const form = document.createElement("form");
form.setAttribute("method", "POST");
form.setAttribute("action", "https://codepen.io/pen/define");
form.setAttribute("target", "_blank");
form.appendChild(input);
document.body.appendChild(form);
form.submit();
}, [code]);
return (
<div className="relative">
<div className="flex justify-start items-center px-4 mb-2">
<span
title="Copy Code"
className="bg-black text-white flex items-center justify-center hover:text-black hover:bg-gray-100 cursor-pointer rounded-lg text-sm p-2.5"
onClick={copyCode}
>
Copy Code <FaCopy className="ml-2" />
</span>
<Button
onClick={doOpenInCodepenio}
className="bg-gray-100 text-black ml-2 py-2 px-4 border border-black rounded-md hover:bg-gray-400 focus:outline-none"
>
Open in{" "}
<img
src="https://assets.codepen.io/t-1/codepen-logo.svg"
alt="codepen.io"
className="h-4 ml-1"
/>
</Button>
</div>
<CodeMirror
code={code}
editorTheme={settings.editorTheme}
onCodeChange={setCode}
/>
</div>
);
}
export default CodeTab;