Esteves Enzo commited on
Commit
5be784e
1 Parent(s): 5916048

change structure, adding custom routes

Browse files
app/[type]/[index]/page.tsx ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export default async function RouteAPI({
2
+ params: { index, type },
3
+ }: {
4
+ params: { index: string; type: string };
5
+ }) {
6
+ return (
7
+ <div>
8
+ <p className="text-white">
9
+ Number is: {index}. Type is {type}
10
+ </p>
11
+ </div>
12
+ );
13
+ }
app/layout.tsx CHANGED
@@ -1,6 +1,7 @@
1
  import type { Metadata } from "next";
2
  import { Fira_Code, Inter } from "next/font/google";
3
  import "@/assets/globals.css";
 
4
 
5
  const inter = Inter({
6
  subsets: ["latin"],
@@ -27,8 +28,7 @@ export default function RootLayout({
27
  return (
28
  <html lang="en" className={`${inter.variable} ${fira_code.variable}`}>
29
  <body>
30
- <div id="background__noisy" />
31
- {children}
32
  </body>
33
  </html>
34
  );
 
1
  import type { Metadata } from "next";
2
  import { Fira_Code, Inter } from "next/font/google";
3
  import "@/assets/globals.css";
4
+ import { Editor } from "@/components/editor";
5
 
6
  const inter = Inter({
7
  subsets: ["latin"],
 
28
  return (
29
  <html lang="en" className={`${inter.variable} ${fira_code.variable}`}>
30
  <body>
31
+ <Editor>{children}</Editor>
 
32
  </body>
33
  </html>
34
  );
app/page.tsx CHANGED
@@ -2,9 +2,5 @@ import { Editor } from "@/components/editor";
2
  import Image from "next/image";
3
 
4
  export default function Home() {
5
- return (
6
- <section className="h-full">
7
- <Editor />
8
- </section>
9
- );
10
  }
 
2
  import Image from "next/image";
3
 
4
  export default function Home() {
5
+ return <section className="h-full">lol</section>;
 
 
 
 
6
  }
components/editor/index.tsx CHANGED
@@ -7,7 +7,7 @@ import { EditorMain } from "./main";
7
  import { ApiRoute } from "@/utils/type";
8
  import { API_COLLECTIONS } from "@/utils/datas/api_collections";
9
 
10
- export const Editor = () => {
11
  const [collections, setCollections] = useState<string[]>(["search"]);
12
  const [endpoint, setEndpoint] = useState<ApiRoute | null>(
13
  API_COLLECTIONS[0].endpoints[0]
@@ -23,14 +23,15 @@ export const Editor = () => {
23
  onCollections={setCollections}
24
  onEndpoint={setEndpoint}
25
  />
26
- {endpoint && (
27
  <EditorMain
28
  collections={collections}
29
  endpoint={endpoint}
30
  onCollections={setCollections}
31
  onEndpoint={setEndpoint}
32
  />
33
- )}
 
34
  </main>
35
  </div>
36
  );
 
7
  import { ApiRoute } from "@/utils/type";
8
  import { API_COLLECTIONS } from "@/utils/datas/api_collections";
9
 
10
+ export const Editor = ({ children }: any) => {
11
  const [collections, setCollections] = useState<string[]>(["search"]);
12
  const [endpoint, setEndpoint] = useState<ApiRoute | null>(
13
  API_COLLECTIONS[0].endpoints[0]
 
23
  onCollections={setCollections}
24
  onEndpoint={setEndpoint}
25
  />
26
+ {/* {endpoint && (
27
  <EditorMain
28
  collections={collections}
29
  endpoint={endpoint}
30
  onCollections={setCollections}
31
  onEndpoint={setEndpoint}
32
  />
33
+ )} */}
34
+ {children}
35
  </main>
36
  </div>
37
  );
components/editor/main/hooks/useRequest.ts ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useState } from "react"
2
+
3
+ import axios from "@/utils/axios";
4
+ import { ApiRoute } from "@/utils/type";
5
+
6
+ export const useRequest = (endpoint: string, params: any) => {
7
+ const [loading, setLoading] = useState<boolean>(false)
8
+ const [data, setData] = useState<any>(null)
9
+
10
+ const submit = async () => {
11
+ setLoading(true);
12
+ const url = new URL(endpoint, process.env.NEXT_PUBLIC_APP_APIURL);
13
+ if (params) {
14
+ const parameters = Object.entries(params).filter(
15
+ ([key, value]) =>
16
+ value !== "" &&
17
+ value !== null &&
18
+ value !== undefined &&
19
+ value !== false
20
+ );
21
+ parameters.forEach(([key, value]) => {
22
+ url.searchParams.append(key, value as string);
23
+ });
24
+ }
25
+
26
+ axios
27
+ .get(url.pathname, {
28
+ params: url.searchParams,
29
+ })
30
+ .then((res: any) => {
31
+ console.log("res ", res);
32
+ if (res.ok) {
33
+ setData(res.data);
34
+ }
35
+ })
36
+ .finally(() => setLoading(false));
37
+ };
38
+
39
+ return {
40
+ submit,
41
+ loading,
42
+ setLoading,
43
+ data
44
+ }
45
+ }
components/editor/main/index.tsx CHANGED
@@ -6,6 +6,8 @@ import axios from "@/utils/axios";
6
  import { Endpoint } from "./endpoint";
7
  import { Request } from "./request";
8
  import { Response } from "./response";
 
 
9
 
10
  export const EditorMain = ({
11
  collections,
@@ -18,50 +20,62 @@ export const EditorMain = ({
18
  onCollections: (collections: string[]) => void;
19
  onEndpoint: (endpoint: ApiRoute) => void;
20
  }) => {
21
- const [formattedEndpoint, setFormattedEndpoint] = useState<string | null>(
22
- null
23
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
- const [response, setResponse] = useState<any | null>(null);
 
 
 
 
26
 
27
- const handleRequest = async () => {
28
- const url = new URL(endpoint.path, process.env.NEXT_PUBLIC_APP_APIURL);
29
  if (endpoint?.parameters) {
30
- const parameters = Object.entries(endpoint.parameters).filter(
31
- ([key, value]) => value !== "" && value !== null
32
- );
33
- parameters.forEach(([key, value]) => {
34
- url.searchParams.append(key, value as string);
35
- });
36
  }
37
- console.log("url ", url);
38
-
39
- axios
40
- .get(url.pathname, {
41
- params: url.searchParams,
42
- })
43
- .then((res: any) => {
44
- console.log("res ", res);
45
- if (res.ok) {
46
- setResponse(res.data);
47
- }
48
- });
49
- };
50
 
51
  return (
52
  <div className="flex-1 bg-slate-900/50 h-[calc(100%-56px)]">
53
  <div className="h-full grid grid-cols-2">
54
- <Request endpoint={endpoint}>
 
 
 
 
 
 
 
 
55
  <Endpoint endpoint={endpoint}>
56
  <button
57
  className="bg-indigo-500 hover:bg-indigo-500/80 text-white px-3 py-1 rounded-lg text-sm"
58
- onClick={handleRequest}
59
  >
60
  Send
61
  </button>
62
  </Endpoint>
63
  </Request>
64
- <Response res={response} />
65
  </div>
66
  </div>
67
  );
 
6
  import { Endpoint } from "./endpoint";
7
  import { Request } from "./request";
8
  import { Response } from "./response";
9
+ import { useRequest } from "./hooks/useRequest";
10
+ import { useMount, useUpdateEffect } from "react-use";
11
 
12
  export const EditorMain = ({
13
  collections,
 
20
  onCollections: (collections: string[]) => void;
21
  onEndpoint: (endpoint: ApiRoute) => void;
22
  }) => {
23
+ const [formattedEndpoint, setFormattedEndpoint] = useState<string>(
24
+ endpoint.path
25
  );
26
+ const [formattedParameters, setFormattedParameters] = useState(
27
+ endpoint?.parameters ? { ...endpoint.parameters } : undefined
28
+ );
29
+ const { loading, submit, data } = useRequest(
30
+ formattedEndpoint,
31
+ formattedParameters
32
+ );
33
+
34
+ useMount(() => {
35
+ if (
36
+ endpoint?.path &&
37
+ endpoint?.method === "GET" &&
38
+ !endpoint?.path?.includes("{") &&
39
+ !endpoint?.path?.includes("}")
40
+ ) {
41
+ submit();
42
+ }
43
+ });
44
 
45
+ useUpdateEffect(() => {
46
+ if (endpoint?.path) {
47
+ setFormattedEndpoint(endpoint.path);
48
+ }
49
+ }, [endpoint.path]);
50
 
51
+ useUpdateEffect(() => {
 
52
  if (endpoint?.parameters) {
53
+ setFormattedParameters(endpoint.parameters);
 
 
 
 
 
54
  }
55
+ }, [endpoint.parameters]);
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
  return (
58
  <div className="flex-1 bg-slate-900/50 h-[calc(100%-56px)]">
59
  <div className="h-full grid grid-cols-2">
60
+ <Request
61
+ parameters={formattedParameters}
62
+ onChange={(k: string, v: string | boolean) => {
63
+ setFormattedParameters({
64
+ ...formattedParameters,
65
+ [k]: v,
66
+ });
67
+ }}
68
+ >
69
  <Endpoint endpoint={endpoint}>
70
  <button
71
  className="bg-indigo-500 hover:bg-indigo-500/80 text-white px-3 py-1 rounded-lg text-sm"
72
+ onClick={submit}
73
  >
74
  Send
75
  </button>
76
  </Endpoint>
77
  </Request>
78
+ <Response res={data} loading={loading} />
79
  </div>
80
  </div>
81
  );
components/editor/main/request.tsx CHANGED
@@ -1,33 +1,48 @@
1
  import { ApiRoute } from "@/utils/type";
2
 
3
  export const Request = ({
4
- endpoint,
5
  children,
 
6
  }: {
7
- endpoint: ApiRoute;
8
  children: React.ReactElement;
 
9
  }) => {
10
  return (
11
  <div className="h-full bg-slate-900 p-4">
12
  {children}
13
- {endpoint?.parameters && (
14
  <div className="mt-6 grid grid-cols-1 gap-4">
15
  <p className="text-slate-400 uppercase text-xs font-semibold">
16
  Optional parameters
17
  </p>
18
- {endpoint?.parameters &&
19
- Object.entries(endpoint.parameters).map(([key, value]) => (
20
  <div
21
  key={key}
22
  className="flex items-center justify-between gap-2"
23
  >
24
  <p className="text-slate-300 text-sm">{key}</p>
25
- <input
26
- value={value as string}
27
- type="text"
28
- className="bg-slate-950/50 w-full rounded-md px-2 py-1 text-slate-100 outline-none placeholder:text-slate-600"
29
- placeholder="value"
30
- />
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  </div>
32
  ))}
33
  </div>
 
1
  import { ApiRoute } from "@/utils/type";
2
 
3
  export const Request = ({
4
+ parameters,
5
  children,
6
+ onChange,
7
  }: {
8
+ parameters: any;
9
  children: React.ReactElement;
10
+ onChange: (key: string, value: string | boolean) => void;
11
  }) => {
12
  return (
13
  <div className="h-full bg-slate-900 p-4">
14
  {children}
15
+ {parameters && (
16
  <div className="mt-6 grid grid-cols-1 gap-4">
17
  <p className="text-slate-400 uppercase text-xs font-semibold">
18
  Optional parameters
19
  </p>
20
+ {parameters &&
21
+ Object.entries(parameters).map(([key, value]) => (
22
  <div
23
  key={key}
24
  className="flex items-center justify-between gap-2"
25
  >
26
  <p className="text-slate-300 text-sm">{key}</p>
27
+ {typeof value === "boolean" ? (
28
+ <div>
29
+ <input
30
+ type="checkbox"
31
+ checked={value}
32
+ onChange={(e) =>
33
+ onChange(key, e.target.checked as boolean)
34
+ }
35
+ />
36
+ </div>
37
+ ) : (
38
+ <input
39
+ value={value as string}
40
+ type="text"
41
+ className="bg-slate-950/50 w-full rounded-md px-2 py-1 text-slate-100 outline-none placeholder:text-slate-600"
42
+ placeholder="value"
43
+ onChange={(e) => onChange(key, e.target.value)}
44
+ />
45
+ )}
46
  </div>
47
  ))}
48
  </div>
components/editor/main/response.tsx CHANGED
@@ -1,11 +1,17 @@
1
  import Highlight from "react-highlight";
2
  import "node_modules/highlight.js/styles/atom-one-dark.css";
3
- export const Response = ({ res }: { res: any }) => {
 
4
  return (
5
- <div className="overflow-auto h-full">
6
  <Highlight className="json text-sm !bg-slate-950/10 !h-full !p-3">
7
  {JSON.stringify(res ?? {}, null, 2)}
8
  </Highlight>
 
 
 
 
 
9
  </div>
10
  );
11
  };
 
1
  import Highlight from "react-highlight";
2
  import "node_modules/highlight.js/styles/atom-one-dark.css";
3
+ import { Loading } from "@/components/loading";
4
+ export const Response = ({ res, loading }: { res: any; loading: boolean }) => {
5
  return (
6
+ <div className="overflow-auto h-full relative">
7
  <Highlight className="json text-sm !bg-slate-950/10 !h-full !p-3">
8
  {JSON.stringify(res ?? {}, null, 2)}
9
  </Highlight>
10
+ {loading && (
11
+ <Loading>
12
+ <p className="text-slate-400 text-lg mt-4">Processing...</p>
13
+ </Loading>
14
+ )}
15
  </div>
16
  );
17
  };
components/editor/sidebar.tsx CHANGED
@@ -5,6 +5,7 @@ import classNames from "classnames";
5
  import { API_COLLECTIONS } from "@/utils/datas/api_collections";
6
  import { Method } from "@/components/method";
7
  import { ApiRoute } from "@/utils/type";
 
8
 
9
  export const EditorSidebar = ({
10
  collections,
@@ -24,16 +25,6 @@ export const EditorSidebar = ({
24
  onCollections([...collections, key]);
25
  }
26
  };
27
-
28
- // useUpdateEffect(() => {
29
- // if (collections) {
30
- // const first_endpoint = API_COLLECTIONS.find(
31
- // (col) => col.key === collections
32
- // )?.endpoints[0];
33
- // if (first_endpoint) onEndpoint(first_endpoint);
34
- // }
35
- // }, [collections]);
36
-
37
  return (
38
  <ul className="min-w-[300px] max-w-sm w-full bg-slate-900 border-r border-slate-700/40 h-full overflow-auto">
39
  {API_COLLECTIONS.map((collection, c) => (
@@ -66,8 +57,9 @@ export const EditorSidebar = ({
66
  <div className="bg-slate-700/20 w-full p-3 border-b border-slate-700/70">
67
  <ul className="w-full">
68
  {collection.endpoints.map((end, e) => (
69
- <li
70
  key={e}
 
71
  className={classNames(
72
  "text-slate-400 font-semibold text-xs flex items-center justify-start gap-2 rounded-md p-2.5 hover:bg-slate-600 hover:bg-opacity-10 cursor-pointer border-t border-b border-transparent select-none",
73
  {
@@ -80,7 +72,7 @@ export const EditorSidebar = ({
80
  >
81
  <Method method={end.method} />
82
  <p className="truncate">{end.path}</p>
83
- </li>
84
  ))}
85
  </ul>
86
  </div>
 
5
  import { API_COLLECTIONS } from "@/utils/datas/api_collections";
6
  import { Method } from "@/components/method";
7
  import { ApiRoute } from "@/utils/type";
8
+ import Link from "next/link";
9
 
10
  export const EditorSidebar = ({
11
  collections,
 
25
  onCollections([...collections, key]);
26
  }
27
  };
 
 
 
 
 
 
 
 
 
 
28
  return (
29
  <ul className="min-w-[300px] max-w-sm w-full bg-slate-900 border-r border-slate-700/40 h-full overflow-auto">
30
  {API_COLLECTIONS.map((collection, c) => (
 
57
  <div className="bg-slate-700/20 w-full p-3 border-b border-slate-700/70">
58
  <ul className="w-full">
59
  {collection.endpoints.map((end, e) => (
60
+ <Link
61
  key={e}
62
+ href={`/${collection.key}/${e}`}
63
  className={classNames(
64
  "text-slate-400 font-semibold text-xs flex items-center justify-start gap-2 rounded-md p-2.5 hover:bg-slate-600 hover:bg-opacity-10 cursor-pointer border-t border-b border-transparent select-none",
65
  {
 
72
  >
73
  <Method method={end.method} />
74
  <p className="truncate">{end.path}</p>
75
+ </Link>
76
  ))}
77
  </ul>
78
  </div>
components/loading/index.tsx ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export const Loading = ({ children }: { children: React.ReactElement }) => (
2
+ <div className="absolute left-0 top-0 w-full h-full flex items-center justify-center bg-slate-950 bg-opacity-50 flex-col backdrop-blur-sm">
3
+ <svg
4
+ className="animate-spin -ml-1 mr-3 h-8 w-8 text-white"
5
+ xmlns="http://www.w3.org/2000/svg"
6
+ fill="none"
7
+ viewBox="0 0 24 24"
8
+ >
9
+ <circle
10
+ className="opacity-25"
11
+ cx="12"
12
+ cy="12"
13
+ r="10"
14
+ stroke="currentColor"
15
+ stroke-width="4"
16
+ ></circle>
17
+ <path
18
+ className="opacity-75"
19
+ fill="currentColor"
20
+ 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"
21
+ ></path>
22
+ </svg>
23
+ {children}
24
+ </div>
25
+ );
utils/datas/api_collections.ts CHANGED
@@ -11,7 +11,7 @@ export const API_COLLECTIONS: Array<ApiCollection> = [{
11
  filter: "",
12
  sort: "",
13
  direction: "",
14
- limit: 10,
15
  full: true,
16
  config: true
17
  }
@@ -23,7 +23,16 @@ export const API_COLLECTIONS: Array<ApiCollection> = [{
23
  path: '/api/models-tags-by-type'
24
  }, {
25
  method: 'GET',
26
- path: '/api/datasets'
 
 
 
 
 
 
 
 
 
27
  }, {
28
  method: 'GET',
29
  path: '/api/datasets/{repo_id}'
 
11
  filter: "",
12
  sort: "",
13
  direction: "",
14
+ limit: 5,
15
  full: true,
16
  config: true
17
  }
 
23
  path: '/api/models-tags-by-type'
24
  }, {
25
  method: 'GET',
26
+ path: '/api/datasets',
27
+ parameters: {
28
+ search: "",
29
+ author: "",
30
+ filter: "",
31
+ sort: "",
32
+ direction: "",
33
+ limit: 5,
34
+ full: true,
35
+ }
36
  }, {
37
  method: 'GET',
38
  path: '/api/datasets/{repo_id}'