enzostvs HF Staff commited on
Commit
1b00a6d
·
1 Parent(s): de9adca

load project

Browse files
server.js CHANGED
@@ -352,33 +352,42 @@ app.get("/api/remix/:username/:repo", async (req, res) => {
352
  const token = hf_token || process.env.DEFAULT_HF_TOKEN;
353
 
354
  const repoId = `${username}/${repo}`;
355
- const space = await spaceInfo({
356
- name: repoId,
357
- });
358
 
359
- if (!space || space.sdk !== "static" || space.private) {
360
- return res.status(404).send({
361
- ok: false,
362
- message: "Space not found",
 
363
  });
364
- }
365
 
366
- const url = `https://huggingface.co/spaces/${repoId}/raw/main/index.html`;
367
- const response = await fetch(url);
368
- if (!response.ok) {
369
- return res.status(404).send({
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
370
  ok: false,
371
- message: "Space not found",
372
  });
373
  }
374
- let html = await response.text();
375
- // remove the last p tag including this url https://enzostvs-deepsite.hf.space
376
- html = html.replace(getPTag(repoId), "");
377
-
378
- res.status(200).send({
379
- ok: true,
380
- html,
381
- });
382
  });
383
 
384
  app.get("*", (_req, res) => {
 
352
  const token = hf_token || process.env.DEFAULT_HF_TOKEN;
353
 
354
  const repoId = `${username}/${repo}`;
 
 
 
355
 
356
+ const url = `https://huggingface.co/spaces/${repoId}/raw/main/index.html`;
357
+ try {
358
+ const space = await spaceInfo({
359
+ name: repoId,
360
+ accessToken: token,
361
  });
 
362
 
363
+ if (!space || space.sdk !== "static" || space.private) {
364
+ return res.status(404).send({
365
+ ok: false,
366
+ message: "Space not found",
367
+ });
368
+ }
369
+
370
+ const response = await fetch(url);
371
+ if (!response.ok) {
372
+ return res.status(404).send({
373
+ ok: false,
374
+ message: "Space not found",
375
+ });
376
+ }
377
+ let html = await response.text();
378
+ // remove the last p tag including this url https://enzostvs-deepsite.hf.space
379
+ html = html.replace(getPTag(repoId), "");
380
+
381
+ res.status(200).send({
382
+ ok: true,
383
+ html,
384
+ });
385
+ } catch (error) {
386
+ return res.status(500).send({
387
  ok: false,
388
+ message: error.message,
389
  });
390
  }
 
 
 
 
 
 
 
 
391
  });
392
 
393
  app.get("*", (_req, res) => {
src/components/App.tsx CHANGED
@@ -18,6 +18,7 @@ import Tabs from "./tabs/tabs";
18
  import AskAI from "./ask-ai/ask-ai";
19
  import { Auth } from "./../../utils/types";
20
  import Preview from "./preview/preview";
 
21
 
22
  function App() {
23
  const [htmlStorage, , removeHtmlStorage] = useLocalStorage("html_content");
@@ -182,7 +183,10 @@ function App() {
182
  }
183
  }}
184
  >
185
- <DeployButton html={html} error={error} auth={auth} />
 
 
 
186
  </Header>
187
  <main className="max-lg:flex-col flex w-full">
188
  <div
 
18
  import AskAI from "./ask-ai/ask-ai";
19
  import { Auth } from "./../../utils/types";
20
  import Preview from "./preview/preview";
21
+ import LoadButton from "./load-button/load-button";
22
 
23
  function App() {
24
  const [htmlStorage, , removeHtmlStorage] = useLocalStorage("html_content");
 
183
  }
184
  }}
185
  >
186
+ <div className="flex items-center justify-end gap-5">
187
+ <LoadButton auth={auth} setHtml={setHtml} />
188
+ <DeployButton html={html} error={error} auth={auth} />
189
+ </div>
190
  </Header>
191
  <main className="max-lg:flex-col flex w-full">
192
  <div
src/components/load-button/load-button.tsx ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import classNames from "classnames";
2
+ import { useState } from "react";
3
+ import { toast } from "react-toastify";
4
+
5
+ import SpaceIcon from "@/assets/space.svg";
6
+ import Loading from "../loading/loading";
7
+ import { Auth } from "../../../utils/types";
8
+
9
+ function LoadButton({
10
+ auth,
11
+ setHtml,
12
+ }: {
13
+ auth?: Auth;
14
+ setHtml: (html: string) => void;
15
+ }) {
16
+ const [open, setOpen] = useState(false);
17
+ const [loading, setLoading] = useState(false);
18
+ const [error, setError] = useState(false);
19
+ const [path, setPath] = useState<string | undefined>(undefined);
20
+
21
+ const loadSpace = async () => {
22
+ setLoading(true);
23
+ try {
24
+ const res = await fetch(`/api/remix/${path}`);
25
+ const data = await res.json();
26
+ if (res.ok) {
27
+ if (data.html) {
28
+ setHtml(data.html);
29
+ toast.success("Project loaded successfully.");
30
+ }
31
+ setOpen(false);
32
+ } else {
33
+ toast.error(data.message);
34
+ setError(data.message);
35
+ }
36
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
+ } catch (error: any) {
38
+ toast.error(error.message);
39
+ setError(error.message);
40
+ }
41
+ setLoading(false);
42
+ };
43
+
44
+ return (
45
+ <div
46
+ className={classNames("max-md:hidden", {
47
+ "border-r border-gray-700 pr-5": auth,
48
+ })}
49
+ >
50
+ <p
51
+ className="underline hover:text-white cursor-pointer text-xs lg:text-sm text-gray-300"
52
+ onClick={() => setOpen(!open)}
53
+ >
54
+ Load project
55
+ </p>
56
+ <div
57
+ className={classNames(
58
+ "h-screen w-screen bg-black/20 fixed left-0 top-0 z-10",
59
+ {
60
+ "opacity-0 pointer-events-none": !open,
61
+ }
62
+ )}
63
+ onClick={() => setOpen(false)}
64
+ ></div>
65
+ <div
66
+ className={classNames(
67
+ "absolute top-[calc(100%+8px)] right-2 z-10 w-80 bg-white border border-gray-200 rounded-lg shadow-lg transition-all duration-75 overflow-hidden",
68
+ {
69
+ "opacity-0 pointer-events-none": !open,
70
+ }
71
+ )}
72
+ >
73
+ <>
74
+ <header className="flex items-center text-sm px-4 py-2 border-b border-gray-200 gap-2 bg-gray-100 font-semibold text-gray-700">
75
+ <span className="text-xs bg-pink-500/10 text-pink-500 rounded-full pl-1.5 pr-2.5 py-0.5 flex items-center justify-start gap-1.5">
76
+ <img src={SpaceIcon} alt="Space Icon" className="size-4" />
77
+ Space
78
+ </span>
79
+ Load Project
80
+ </header>
81
+ <main className="px-4 pt-3 pb-4 space-y-3">
82
+ <label className="block">
83
+ <p className="text-gray-600 text-sm font-medium mb-1.5">
84
+ Space URL
85
+ </p>
86
+ <input
87
+ type="text"
88
+ value={path}
89
+ className="mr-2 border rounded-md px-3 py-1.5 border-gray-300 w-full text-sm"
90
+ placeholder="https://huggingface.co/spaces/username/space-name"
91
+ onChange={(e) => setPath(e.target.value)}
92
+ onFocus={() => setError(false)}
93
+ onBlur={(e) => {
94
+ const pathParts = e.target.value.split("/");
95
+ setPath(
96
+ `${pathParts[pathParts.length - 2]}/${
97
+ pathParts[pathParts.length - 1]
98
+ }`
99
+ );
100
+ setError(false);
101
+ }}
102
+ />
103
+ </label>
104
+ {error && (
105
+ <p className="text-red-500 text-xs bg-red-500/10 rounded-md p-2 break-all">
106
+ {error}
107
+ </p>
108
+ )}
109
+ <div className="pt-2 text-right">
110
+ <button
111
+ disabled={error || loading || !path}
112
+ className="relative rounded-full bg-black px-5 py-2 text-white font-semibold text-xs hover:bg-black/90 transition-all duration-100 disabled:bg-gray-300 disabled:text-gray-500 disabled:cursor-not-allowed disabled:hover:bg-gray-300"
113
+ onClick={loadSpace}
114
+ >
115
+ Load Project
116
+ {loading && <Loading />}
117
+ </button>
118
+ </div>
119
+ </main>
120
+ </>
121
+ </div>
122
+ </div>
123
+ );
124
+ }
125
+ export default LoadButton;