added download code button

This commit is contained in:
Waseem Anjum 2024-10-19 12:26:29 +05:00
parent 4f7a06f56a
commit 21dbd42184
4 changed files with 96 additions and 9 deletions

View File

@ -122,15 +122,26 @@ export const Workbench = memo(({ chatStarted, isStreaming }: WorkspaceProps) =>
<Slider selected={selectedView} options={sliderOptions} setSelected={setSelectedView} />
<div className="ml-auto" />
{selectedView === 'code' && (
<PanelHeaderButton
className="mr-1 text-sm"
onClick={() => {
workbenchStore.toggleTerminal(!workbenchStore.showTerminal.get());
}}
>
<div className="i-ph:terminal" />
Toggle Terminal
</PanelHeaderButton>
<>
<PanelHeaderButton
className="mr-1 text-sm"
onClick={() => {
workbenchStore.downloadZip();
}}
>
<div className="i-ph:code" />
Download Code
</PanelHeaderButton>
<PanelHeaderButton
className="mr-1 text-sm"
onClick={() => {
workbenchStore.toggleTerminal(!workbenchStore.showTerminal.get());
}}
>
<div className="i-ph:terminal" />
Toggle Terminal
</PanelHeaderButton>
</>
)}
<IconButton
icon="i-ph:x-circle"

View File

@ -9,6 +9,8 @@ import { EditorStore } from './editor';
import { FilesStore, type FileMap } from './files';
import { PreviewsStore } from './previews';
import { TerminalStore } from './terminal';
import JSZip from 'jszip';
import { saveAs } from 'file-saver';
export interface ArtifactState {
id: string;
@ -271,6 +273,36 @@ export class WorkbenchStore {
const artifacts = this.artifacts.get();
return artifacts[id];
}
async downloadZip() {
const zip = new JSZip();
const files = this.files.get();
for (const [filePath, dirent] of Object.entries(files)) {
if (dirent?.type === 'file' && !dirent.isBinary) {
// Remove '/home/project/' from the beginning of the path
const relativePath = filePath.replace(/^\/home\/project\//, '');
// Split the path into segments
const pathSegments = relativePath.split('/');
// If there's more than one segment, we need to create folders
if (pathSegments.length > 1) {
let currentFolder = zip;
for (let i = 0; i < pathSegments.length - 1; i++) {
currentFolder = currentFolder.folder(pathSegments[i])!;
}
currentFolder.file(pathSegments[pathSegments.length - 1], dirent.content);
} else {
// If there's only one segment, it's a file in the root
zip.file(relativePath, dirent.content);
}
}
}
const content = await zip.generateAsync({ type: 'blob' });
saveAs(content, 'project.zip');
}
}
export const workbenchStore = new WorkbenchStore();

View File

@ -59,10 +59,12 @@
"ai": "^3.4.9",
"date-fns": "^3.6.0",
"diff": "^5.2.0",
"file-saver": "^2.0.5",
"framer-motion": "^11.2.12",
"isbot": "^4.1.0",
"istextorbinary": "^9.5.0",
"jose": "^5.6.3",
"jszip": "^3.10.1",
"nanostores": "^0.10.3",
"ollama-ai-provider": "^0.15.2",
"react": "^18.2.0",
@ -84,6 +86,7 @@
"@cloudflare/workers-types": "^4.20240620.0",
"@remix-run/dev": "^2.10.0",
"@types/diff": "^5.2.1",
"@types/file-saver": "^2.0.7",
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"fast-glob": "^3.3.2",

View File

@ -119,6 +119,9 @@ importers:
diff:
specifier: ^5.2.0
version: 5.2.0
file-saver:
specifier: ^2.0.5
version: 2.0.5
framer-motion:
specifier: ^11.2.12
version: 11.2.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -131,6 +134,9 @@ importers:
jose:
specifier: ^5.6.3
version: 5.6.3
jszip:
specifier: ^3.10.1
version: 3.10.1
nanostores:
specifier: ^0.10.3
version: 0.10.3
@ -189,6 +195,9 @@ importers:
'@types/diff':
specifier: ^5.2.1
version: 5.2.1
'@types/file-saver':
specifier: ^2.0.7
version: 2.0.7
'@types/react':
specifier: ^18.2.20
version: 18.3.3
@ -1772,6 +1781,9 @@ packages:
'@types/estree@1.0.6':
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
'@types/file-saver@2.0.7':
resolution: {integrity: sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==}
'@types/hast@2.3.10':
resolution: {integrity: sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==}
@ -2900,6 +2912,9 @@ packages:
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
engines: {node: '>=16.0.0'}
file-saver@2.0.5:
resolution: {integrity: sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==}
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
@ -3181,6 +3196,9 @@ packages:
resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
engines: {node: '>= 4'}
immediate@3.0.6:
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
immutable@4.3.7:
resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==}
@ -3396,6 +3414,9 @@ packages:
jsonfile@6.1.0:
resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
jszip@3.10.1:
resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==}
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
@ -3410,6 +3431,9 @@ packages:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
lie@3.3.0:
resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==}
lilconfig@3.1.2:
resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==}
engines: {node: '>=14'}
@ -6912,6 +6936,8 @@ snapshots:
'@types/estree@1.0.6': {}
'@types/file-saver@2.0.7': {}
'@types/hast@2.3.10':
dependencies:
'@types/unist': 2.0.10
@ -8396,6 +8422,8 @@ snapshots:
dependencies:
flat-cache: 4.0.1
file-saver@2.0.5: {}
fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
@ -8747,6 +8775,8 @@ snapshots:
ignore@5.3.1: {}
immediate@3.0.6: {}
immutable@4.3.7:
optional: true
@ -8915,6 +8945,13 @@ snapshots:
optionalDependencies:
graceful-fs: 4.2.11
jszip@3.10.1:
dependencies:
lie: 3.3.0
pako: 1.0.11
readable-stream: 2.3.8
setimmediate: 1.0.5
keyv@4.5.4:
dependencies:
json-buffer: 3.0.1
@ -8928,6 +8965,10 @@ snapshots:
prelude-ls: 1.2.1
type-check: 0.4.0
lie@3.3.0:
dependencies:
immediate: 3.0.6
lilconfig@3.1.2: {}
loader-utils@3.3.1: {}