dylanebert HF staff commited on
Commit
dd91ef9
1 Parent(s): 2425369

add dockerfile

.

.

.

.

set app port

.

checkbox

export condition

fix urls

.

.

.

docker fix

local svelte-table

.

fix local dev

automatic inference

.

.

.

access external data

echo test

.

.

.

.

.

.

.

..

.

.

.

.

.

no logging

.gitignore ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .vscode/*
2
+ !.vscode/settings.json
3
+ !.vscode/tasks.json
4
+ !.vscode/launch.json
5
+ !.vscode/extensions.json
6
+ !.vscode/*.code-snippets
7
+
8
+ # Local History for Visual Studio Code
9
+ .history/
10
+
11
+ # Built Visual Studio Code Extensions
12
+ *.vsix
.gitmodules ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ [submodule "viewer/svelte-table"]
2
+ path = viewer/svelte-table
3
+ url = https://github.com/dylanebert/svelte-table.git
4
+ branch = master
Dockerfile ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM node:alpine
2
+
3
+
4
+ WORKDIR /app
5
+ COPY viewer/package.json package.json
6
+ RUN npm install
7
+
8
+ RUN --mount=type=secret,id=VITE_HF_TOKEN,mode=0444,required=true \
9
+ echo "VITE_HF_TOKEN=$(cat /run/secrets/VITE_HF_TOKEN)" > /app/.env
10
+
11
+ COPY viewer/ /app
12
+ RUN npm run build
13
+
14
+ EXPOSE 3000
15
+ CMD ["npm", "start"]
README.md CHANGED
@@ -1,11 +1,12 @@
1
  ---
2
- title: 3d Projects
3
  emoji: 🚀
4
  colorFrom: gray
5
  colorTo: green
6
  sdk: docker
7
  pinned: false
8
  license: mit
 
9
  ---
10
 
11
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: Research Tracker Internal
3
  emoji: 🚀
4
  colorFrom: gray
5
  colorTo: green
6
  sdk: docker
7
  pinned: false
8
  license: mit
9
+ app_port: 3000
10
  ---
11
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
__pycache__/server.cpython-311.pyc ADDED
Binary file (759 Bytes). View file
 
viewer/.gitignore ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ .DS_Store
2
+ node_modules
3
+ /build
4
+ /.svelte-kit
5
+ /package
6
+ .env
7
+ .env.*
8
+ !.env.example
9
+ vite.config.js.timestamp-*
10
+ vite.config.ts.timestamp-*
viewer/.npmrc ADDED
@@ -0,0 +1 @@
 
 
1
+ engine-strict=true
viewer/README.md ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # create-svelte
2
+
3
+ Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
4
+
5
+ ## Creating a project
6
+
7
+ If you're seeing this, you've probably already done this step. Congrats!
8
+
9
+ ```bash
10
+ # create a new project in the current directory
11
+ npm create svelte@latest
12
+
13
+ # create a new project in my-app
14
+ npm create svelte@latest my-app
15
+ ```
16
+
17
+ ## Developing
18
+
19
+ Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
20
+
21
+ ```bash
22
+ npm run dev
23
+
24
+ # or start the server and open the app in a new browser tab
25
+ npm run dev -- --open
26
+ ```
27
+
28
+ ## Building
29
+
30
+ To create a production version of your app:
31
+
32
+ ```bash
33
+ npm run build
34
+ ```
35
+
36
+ You can preview the production build with `npm run preview`.
37
+
38
+ > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
viewer/package-lock.json ADDED
The diff for this file is too large to render. See raw diff
 
viewer/package.json ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "viewer",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "vite dev",
7
+ "build": "vite build",
8
+ "preview": "vite preview",
9
+ "start": "node ./build/index.js",
10
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
11
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
12
+ },
13
+ "devDependencies": {
14
+ "@sveltejs/adapter-auto": "^3.0.0",
15
+ "@sveltejs/adapter-node": "^4.0.0",
16
+ "@sveltejs/kit": "^2.0.0",
17
+ "@sveltejs/vite-plugin-svelte": "^3.0.0",
18
+ "svelte": "^4.2.7",
19
+ "svelte-check": "^3.6.0",
20
+ "tslib": "^2.4.1",
21
+ "typescript": "^5.0.0",
22
+ "vite": "^5.0.12"
23
+ },
24
+ "type": "module",
25
+ "dependencies": {
26
+ "esbuild": "^0.19.12",
27
+ "svelte-table": "file:./svelte-table"
28
+ }
29
+ }
viewer/src/app.d.ts ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // See https://kit.svelte.dev/docs/types#app
2
+ // for information about these interfaces
3
+ declare global {
4
+ namespace App {
5
+ // interface Error {}
6
+ // interface Locals {}
7
+ // interface PageData {}
8
+ // interface PageState {}
9
+ // interface Platform {}
10
+ }
11
+ }
12
+
13
+ export {};
viewer/src/app.html ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <link rel="icon" href="%sveltekit.assets%/favicon.png" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ %sveltekit.head%
8
+ </head>
9
+ <body data-sveltekit-preload-data="hover">
10
+ <div style="display: contents">%sveltekit.body%</div>
11
+ </body>
12
+ </html>
viewer/src/lib/index.ts ADDED
@@ -0,0 +1 @@
 
 
1
+ // place files you want to import through the `$lib` alias in this folder.
viewer/src/routes/+page.svelte ADDED
@@ -0,0 +1,318 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import { onMount } from "svelte";
3
+ import SvelteTable, { type TableColumn } from "svelte-table";
4
+
5
+ interface Row {
6
+ Name: string;
7
+ Orgs: string[];
8
+ Authors: string[];
9
+ Tags: string[];
10
+ CodeStatus: string;
11
+ Paper: string;
12
+ Code: string;
13
+ Space: string;
14
+ Model: string;
15
+ Dataset: string;
16
+ Project: string;
17
+ License: string;
18
+ Date: string;
19
+ }
20
+
21
+ let rows: Row[] = [];
22
+ let columns: TableColumn<Row>[] = [
23
+ {
24
+ key: "Name",
25
+ title: "Name",
26
+ value: (v: Row) => v.Name || v.Project || v.Code || v.Paper || "N/A",
27
+ sortable: true,
28
+ renderValue: (v: Row) => {
29
+ let url;
30
+ if (v.Project) {
31
+ url = v.Project;
32
+ } else if (v.Code) {
33
+ url = v.Code;
34
+ } else if (v.Paper) {
35
+ url = v.Paper;
36
+ } else if (v.Space) {
37
+ url = v.Space;
38
+ } else if (v.Model) {
39
+ url = v.Model;
40
+ } else if (v.Dataset) {
41
+ url = v.Dataset;
42
+ }
43
+ let name = v.Name || url || "";
44
+ let renderName = name;
45
+ if (name.length > 64) {
46
+ renderName = name.slice(0, 60) + "...";
47
+ }
48
+ return `<a href="${url}" target="_blank" title="${name}">${renderName}</a>`;
49
+ },
50
+ searchValue: (v: Row) => {
51
+ let searchValue = v.Name || "";
52
+ if (v.Project) {
53
+ searchValue += " " + v.Project;
54
+ }
55
+ if (v.Code) {
56
+ searchValue += " " + v.Code;
57
+ }
58
+ if (v.Paper) {
59
+ searchValue += " " + v.Paper;
60
+ }
61
+ if (v.Space) {
62
+ searchValue += " " + v.Space;
63
+ }
64
+ if (v.Model) {
65
+ searchValue += " " + v.Model;
66
+ }
67
+ if (v.Dataset) {
68
+ searchValue += " " + v.Dataset;
69
+ }
70
+ return searchValue;
71
+ },
72
+ parseHTML: true,
73
+ hideFilterHeader: true,
74
+ },
75
+ {
76
+ key: "Date",
77
+ title: "Date",
78
+ value: (v: Row) => v.Date || "",
79
+ sortable: true,
80
+ searchValue: (v: Row) => v.Date || "",
81
+ renderValue: (v: Row) => {
82
+ if (!v.Date) return "";
83
+ let renderDate = v.Date;
84
+
85
+ // Convert ISO to YYYY-MM-DD
86
+ if (v.Date.includes("T")) {
87
+ renderDate = v.Date.split("T")[0];
88
+ }
89
+
90
+ return `<span title="${v.Date}">${renderDate}</span>`;
91
+ },
92
+ parseHTML: true,
93
+ },
94
+ {
95
+ key: "Orgs",
96
+ title: "Orgs",
97
+ value: (v: Row) => v.Orgs.join(", "),
98
+ sortable: true,
99
+ searchValue: (v: Row) => v.Orgs.join(" "),
100
+ renderValue: (v: Row) => {
101
+ let orgs = v.Orgs.join(", ");
102
+ let renderOrgs = v.Orgs.join(", ");
103
+ if (orgs.length > 24) {
104
+ renderOrgs = renderOrgs.slice(0, 20) + "...";
105
+ }
106
+ return `<span title="${orgs}">${renderOrgs}</span>`;
107
+ },
108
+ parseHTML: true,
109
+ },
110
+ {
111
+ key: "Authors",
112
+ title: "Authors",
113
+ value: (v: Row) => v.Authors.join(", "),
114
+ sortable: true,
115
+ searchValue: (v: Row) => v.Authors.join(" "),
116
+ renderValue: (v: Row) => {
117
+ let authors = v.Authors.join(", ");
118
+ let renderAuthors = v.Authors.join(", ");
119
+ if (authors.length > 24) {
120
+ renderAuthors = renderAuthors.slice(0, 20) + "...";
121
+ }
122
+ return `<span title="${authors}">${renderAuthors}</span>`;
123
+ },
124
+ parseHTML: true,
125
+ },
126
+ {
127
+ key: "Paper",
128
+ title: "Paper",
129
+ value: (v: Row) => v.Paper || "",
130
+ sortable: true,
131
+ searchValue: (v: Row) => v.Paper || "",
132
+ renderValue: (v: Row) => {
133
+ if (!v.Paper) return "";
134
+ const url = v.Paper;
135
+ let name = v.Paper;
136
+ if (url.includes("arxiv.org/")) {
137
+ name = `arxiv/${url.split("arxiv.org/")[1]}`;
138
+ } else if (url.includes("huggingface.co/papers/")) {
139
+ name = `hf/${url.split("huggingface.co/papers/")[1]}`;
140
+ }
141
+ let displayName = name.replace(".pdf", "");
142
+ if (displayName.length > 24) {
143
+ displayName = displayName.slice(0, 20) + "...";
144
+ }
145
+ return `<a href="${url}" target="_blank" title="${name}">${displayName}</a>`;
146
+ },
147
+ parseHTML: true,
148
+ },
149
+ {
150
+ key: "Code",
151
+ title: "Code",
152
+ value: (v: Row) => v.CodeStatus || v.Code || "",
153
+ sortable: true,
154
+ searchValue: (v: Row) => {
155
+ let searchValue = v.Code || "";
156
+ if (v.CodeStatus === "Coming Soon") {
157
+ searchValue += " Coming Soon";
158
+ } else if (v.CodeStatus === "No") {
159
+ searchValue += " No";
160
+ }
161
+ return searchValue;
162
+ },
163
+ renderValue: (v: Row) => {
164
+ let codeUrl;
165
+ let codeDisplay;
166
+ if (v.Code) {
167
+ codeUrl = v.Code;
168
+ if (v.Code.includes("github.com")) {
169
+ codeDisplay = `git/${v.Code.split("github.com/")[1].slice(0, 16)}`;
170
+ } else {
171
+ codeDisplay = v.Code.slice(0, 16) + "...";
172
+ }
173
+ }
174
+ if (v.CodeStatus === "Coming Soon") {
175
+ codeDisplay = "Coming Soon";
176
+ } else if (v.CodeStatus === "No") {
177
+ codeDisplay = "No";
178
+ }
179
+ if (!codeDisplay) {
180
+ return "";
181
+ }
182
+ if (codeUrl) {
183
+ return `<a href="${codeUrl}" target="_blank" title="${codeUrl}">${codeDisplay}</a>`;
184
+ }
185
+ return codeDisplay;
186
+ },
187
+ parseHTML: true,
188
+ },
189
+ {
190
+ key: "Space",
191
+ title: "Space",
192
+ value: (v: Row) => v.Space || "",
193
+ sortable: true,
194
+ searchValue: (v: Row) => v.Space || "",
195
+ renderValue: (v: Row) => {
196
+ if (!v.Space) return "";
197
+ if (v.Space.includes("huggingface.co")) {
198
+ return `<a href="${v.Space}" target="_blank">hf/${v.Space.split("huggingface.co/")[1].slice(
199
+ 0,
200
+ 16
201
+ )}</a>`;
202
+ }
203
+ return `<a href="${v.Space}" target="_blank" title="${v.Space}">${v.Space.slice(0, 16)}...</a>`;
204
+ },
205
+ parseHTML: true,
206
+ },
207
+ {
208
+ key: "Model",
209
+ title: "Model",
210
+ value: (v: Row) => v.Model || "",
211
+ sortable: true,
212
+ searchValue: (v: Row) => v.Model || "",
213
+ renderValue: (v: Row) => {
214
+ if (!v.Model) return "";
215
+ if (v.Model.includes("huggingface.co")) {
216
+ return `<a href="${v.Model}" target="_blank">hf/${v.Model.split("huggingface.co/")[1].slice(
217
+ 0,
218
+ 16
219
+ )}</a>`;
220
+ }
221
+ return `<a href="${v.Model}" target="_blank" title="${v.Model}">${v.Model.slice(0, 16)}...</a>`;
222
+ },
223
+ parseHTML: true,
224
+ },
225
+ {
226
+ key: "Dataset",
227
+ title: "Dataset",
228
+ value: (v: Row) => v.Dataset || "",
229
+ sortable: true,
230
+ searchValue: (v: Row) => v.Dataset || "",
231
+ renderValue: (v: Row) => {
232
+ if (!v.Dataset) return "";
233
+ if (v.Dataset.includes("huggingface.co")) {
234
+ return `<a href="${v.Dataset}" target="_blank">hf/${v.Dataset.split("huggingface.co/")[1].slice(
235
+ 0,
236
+ 16
237
+ )}</a>`;
238
+ } else if (v.Dataset.includes("drive.google.com")) {
239
+ return `<a href="${v.Dataset}" target="_blank">drive/${v.Dataset.split(
240
+ "drive.google.com/"
241
+ )[1].slice(0, 16)}</a>`;
242
+ } else if (v.Dataset.includes("github.com")) {
243
+ return `<a href="${v.Dataset}" target="_blank">git/${v.Dataset.split("github.com/")[1].slice(
244
+ 0,
245
+ 16
246
+ )}</a>`;
247
+ }
248
+ return `<a href="${v.Dataset}" target="_blank" title="${v.Dataset}">${v.Dataset.slice(0, 16)}...</a>`;
249
+ },
250
+ parseHTML: true,
251
+ },
252
+ {
253
+ key: "ReachedOut",
254
+ title: "Reached Out",
255
+ value: (v: Row) => (v.Tags.includes("ReachedOut") ? "\u2705" : ""),
256
+ sortable: true,
257
+ filterValue: (v: Row) => (v.Tags.includes("ReachedOut") ? "Yes" : "No"),
258
+ filterOptions: ["Yes", "No"],
259
+ },
260
+ ];
261
+
262
+ let selection = {};
263
+ let overrideSelection = false;
264
+ let searchValue = "";
265
+
266
+ $: {
267
+ if (searchValue !== "") {
268
+ selection = { Name: searchValue };
269
+ overrideSelection = true;
270
+ } else {
271
+ if (overrideSelection) {
272
+ selection = {};
273
+ overrideSelection = false;
274
+ }
275
+ }
276
+ }
277
+
278
+ const addEntry = async () => {
279
+ if (!("Name" in selection)) return;
280
+ const value = selection["Name"];
281
+ const response = await fetch("/add-entry", {
282
+ method: "POST",
283
+ headers: {
284
+ "Content-Type": "application/json",
285
+ },
286
+ body: JSON.stringify({ value }),
287
+ });
288
+ const data = await response.json();
289
+ console.log(data);
290
+ };
291
+
292
+ onMount(async () => {
293
+ const url = "https://dylanebert-research-tracker-backend.hf.space/data";
294
+ const response = await fetch(url, {
295
+ method: "GET",
296
+ headers: {
297
+ "Authorization": "Bearer " + import.meta.env.VITE_HF_TOKEN,
298
+ },
299
+ });
300
+ rows = await response.json();
301
+ });
302
+ </script>
303
+
304
+ <div style="text-align: center; margin-top: 1rem;">
305
+ <input
306
+ type="text"
307
+ placeholder="Enter relevant project, code, paper, space, model, or dataset URL"
308
+ style="width: 100%; max-width: 512px; margin-bottom: 1rem;"
309
+ bind:value={searchValue}
310
+ />
311
+ <button on:click={addEntry}>New Entry</button>
312
+ </div>
313
+
314
+ <SvelteTable {columns} {rows} bind:filterSelections={selection} />
315
+
316
+ <div style="text-align: center; margin-top: 1rem;">
317
+ <button on:click={addEntry}>New Entry</button>
318
+ </div>
viewer/static/favicon.png ADDED
viewer/svelte-table ADDED
@@ -0,0 +1 @@
 
 
1
+ Subproject commit 0b3742da9031342a5ce9af34c673be8f48c1eefb
viewer/svelte.config.js ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import adapter from "@sveltejs/adapter-node";
2
+ import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
3
+
4
+ /** @type {import('@sveltejs/kit').Config} */
5
+ const config = {
6
+ // Consult https://kit.svelte.dev/docs/integrations#preprocessors
7
+ // for more information about preprocessors
8
+ preprocess: vitePreprocess(),
9
+
10
+ kit: {
11
+ // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
12
+ // If your environment is not supported or you settled on a specific environment, switch out the adapter.
13
+ // See https://kit.svelte.dev/docs/adapters for more information about adapters.
14
+ adapter: adapter(),
15
+ },
16
+ };
17
+
18
+ export default config;
viewer/tsconfig.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "extends": "./.svelte-kit/tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "build",
5
+ "allowJs": true,
6
+ "checkJs": true,
7
+ "esModuleInterop": true,
8
+ "forceConsistentCasingInFileNames": true,
9
+ "resolveJsonModule": true,
10
+ "skipLibCheck": true,
11
+ "sourceMap": true,
12
+ "strict": true,
13
+ }
14
+ // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
15
+ //
16
+ // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
17
+ // from the referenced tsconfig.json - TypeScript does not merge them in
18
+ }
viewer/vite.config.ts ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { sveltekit } from "@sveltejs/kit/vite";
2
+ import { defineConfig } from "vite";
3
+ import path from "path";
4
+
5
+ export default defineConfig({
6
+ plugins: [sveltekit()],
7
+ server: {
8
+ fs: {
9
+ allow: [path.resolve(__dirname, "svelte-table")],
10
+ },
11
+ },
12
+ });