Spaces:
Running
Running
functional
Browse files- asset-manifest.json +3 -3
- index.html +1 -1
- src/App.js +84 -22
- static/js/main.6c20428f.js +0 -0
- static/js/main.6c20428f.js.LICENSE.txt +41 -0
- static/js/main.6c20428f.js.map +0 -0
asset-manifest.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
| 1 |
{
|
| 2 |
"files": {
|
| 3 |
"main.css": "/static/css/main.1e103507.css",
|
| 4 |
-
"main.js": "/static/js/main.
|
| 5 |
"static/js/787.0bfccc2a.chunk.js": "/static/js/787.0bfccc2a.chunk.js",
|
| 6 |
"index.html": "/index.html",
|
| 7 |
"main.1e103507.css.map": "/static/css/main.1e103507.css.map",
|
| 8 |
-
"main.
|
| 9 |
"787.0bfccc2a.chunk.js.map": "/static/js/787.0bfccc2a.chunk.js.map"
|
| 10 |
},
|
| 11 |
"entrypoints": [
|
| 12 |
"static/css/main.1e103507.css",
|
| 13 |
-
"static/js/main.
|
| 14 |
]
|
| 15 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"files": {
|
| 3 |
"main.css": "/static/css/main.1e103507.css",
|
| 4 |
+
"main.js": "/static/js/main.6c20428f.js",
|
| 5 |
"static/js/787.0bfccc2a.chunk.js": "/static/js/787.0bfccc2a.chunk.js",
|
| 6 |
"index.html": "/index.html",
|
| 7 |
"main.1e103507.css.map": "/static/css/main.1e103507.css.map",
|
| 8 |
+
"main.6c20428f.js.map": "/static/js/main.6c20428f.js.map",
|
| 9 |
"787.0bfccc2a.chunk.js.map": "/static/js/787.0bfccc2a.chunk.js.map"
|
| 10 |
},
|
| 11 |
"entrypoints": [
|
| 12 |
"static/css/main.1e103507.css",
|
| 13 |
+
"static/js/main.6c20428f.js"
|
| 14 |
]
|
| 15 |
}
|
index.html
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="View the like history of a project on huggingface"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>Like History</title><script defer="defer" src="/static/js/main.
|
|
|
|
| 1 |
+
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="View the like history of a project on huggingface"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>Like History</title><script defer="defer" src="/static/js/main.6c20428f.js"></script><link href="/static/css/main.1e103507.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
src/App.js
CHANGED
|
@@ -3,36 +3,93 @@ import chartXkcd from "chart.xkcd";
|
|
| 3 |
|
| 4 |
const projectTypes = ["model", "dataset", "space"];
|
| 5 |
|
|
|
|
|
|
|
|
|
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
/**
|
| 8 |
* 1. User click enter key
|
| 9 |
* 2. Get model/dataset/space name
|
| 10 |
-
* 3. Get data from API
|
| 11 |
* 4. Format data(to 20 points at most)
|
| 12 |
* 5. Draw line chart
|
| 13 |
*/
|
| 14 |
function App() {
|
| 15 |
-
const [projectType, setProjectType] = useState("
|
| 16 |
-
const [projectName, setProjectName] = useState("");
|
| 17 |
|
| 18 |
-
const onSubmit = () => {
|
| 19 |
const svg = document.querySelector('.line-chart')
|
| 20 |
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
data: {
|
| 26 |
-
labels: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'],
|
| 27 |
datasets: [{
|
| 28 |
-
label:
|
| 29 |
-
data:
|
| 30 |
-
},
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
},
|
| 35 |
-
options: {}
|
| 36 |
});
|
| 37 |
}
|
| 38 |
return (
|
|
@@ -54,9 +111,9 @@ function App() {
|
|
| 54 |
className="h-full rounded-md border-0 bg-transparent py-0 pl-3 pr-7 text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm"
|
| 55 |
onChange={(e) => setProjectType(e.target.value)}
|
| 56 |
>
|
| 57 |
-
<option value="
|
| 58 |
-
<option value="
|
| 59 |
-
<option value="
|
| 60 |
</select>
|
| 61 |
</div>
|
| 62 |
<input
|
|
@@ -64,12 +121,17 @@ function App() {
|
|
| 64 |
name="phone-number"
|
| 65 |
id="phone-number"
|
| 66 |
className="block w-full rounded-md border-0 py-1.5 pl-24 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
| 67 |
-
placeholder="
|
| 68 |
value={projectName}
|
| 69 |
onChange={(e) => setProjectName(e.target.value)}
|
| 70 |
-
|
|
|
|
| 71 |
if (e.key === "Enter") {
|
| 72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
}
|
| 74 |
}}
|
| 75 |
/>
|
|
|
|
| 3 |
|
| 4 |
const projectTypes = ["model", "dataset", "space"];
|
| 5 |
|
| 6 |
+
function transformLikesData(likesData) {
|
| 7 |
+
// Step 1
|
| 8 |
+
likesData.sort((a, b) => new Date(a.likedAt) - new Date(b.likedAt));
|
| 9 |
|
| 10 |
+
// Step 2
|
| 11 |
+
const cumulativeLikes = {};
|
| 12 |
+
let cumulativeCount = 0;
|
| 13 |
+
|
| 14 |
+
// Step 3
|
| 15 |
+
likesData.forEach(like => {
|
| 16 |
+
const date = like.likedAt.split('T')[0];
|
| 17 |
+
cumulativeCount++;
|
| 18 |
+
cumulativeLikes[date] = cumulativeCount;
|
| 19 |
+
});
|
| 20 |
+
|
| 21 |
+
// Step 4
|
| 22 |
+
const transformedData = Object.keys(cumulativeLikes).map(date => ({
|
| 23 |
+
x: date,
|
| 24 |
+
y: cumulativeLikes[date].toString()
|
| 25 |
+
}));
|
| 26 |
+
|
| 27 |
+
return transformedData;
|
| 28 |
+
}
|
| 29 |
/**
|
| 30 |
* 1. User click enter key
|
| 31 |
* 2. Get model/dataset/space name
|
| 32 |
+
* 3. Get data from API(API format: https://huggingface.co/api/spaces/timqian/like-history/likers?expand[]=likeAt)
|
| 33 |
* 4. Format data(to 20 points at most)
|
| 34 |
* 5. Draw line chart
|
| 35 |
*/
|
| 36 |
function App() {
|
| 37 |
+
const [projectType, setProjectType] = useState("models");
|
| 38 |
+
const [projectName, setProjectName] = useState("openai/whisper-large-v3");
|
| 39 |
|
| 40 |
+
const onSubmit = async () => {
|
| 41 |
const svg = document.querySelector('.line-chart')
|
| 42 |
|
| 43 |
+
const res = await fetch(`https://huggingface.co/api/${projectType}/${projectName}/likers?expand[]=likeAt`)
|
| 44 |
+
|
| 45 |
+
/**
|
| 46 |
+
* Format:
|
| 47 |
+
* [{"user": "timqian", "likedAt": "2021-07-01T00:00:00.000Z"}, {"user": "yy", "likedAt": "2021-07-02T00:00:00.000Z"}]
|
| 48 |
+
*/
|
| 49 |
+
const likers = await res.json()
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
let likeHistory = transformLikesData(likers)
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
if (likeHistory.length > 40) {
|
| 56 |
+
// sample 20 points
|
| 57 |
+
const sampledLikeHistory = []
|
| 58 |
+
const step = Math.floor(likeHistory.length / 40)
|
| 59 |
+
for (let i = 0; i < likeHistory.length; i += step) {
|
| 60 |
+
sampledLikeHistory.push(likeHistory[i])
|
| 61 |
+
}
|
| 62 |
+
likeHistory = sampledLikeHistory
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
// if likeHistory is empty, show error message
|
| 66 |
+
if (likeHistory.length === 0) {
|
| 67 |
+
alert("No like history found")
|
| 68 |
+
return
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
new chartXkcd.XY(svg, {
|
| 72 |
+
title: 'HF like history',
|
| 73 |
+
xLabel: 'Time',
|
| 74 |
+
yLabel: 'Likes',
|
| 75 |
data: {
|
|
|
|
| 76 |
datasets: [{
|
| 77 |
+
label: projectName,
|
| 78 |
+
data: likeHistory,
|
| 79 |
+
}],
|
| 80 |
+
},
|
| 81 |
+
options: {
|
| 82 |
+
xTickCount: 3,
|
| 83 |
+
yTickCount: 4,
|
| 84 |
+
legendPosition: chartXkcd.config.positionType.upLeft,
|
| 85 |
+
showLine: true,
|
| 86 |
+
timeFormat: 'MM/DD/YYYY',
|
| 87 |
+
dotSize: 0.5,
|
| 88 |
+
dataColors: ["#dd4528",
|
| 89 |
+
"#28a3dd",
|
| 90 |
+
"#f3db52"
|
| 91 |
+
]
|
| 92 |
},
|
|
|
|
| 93 |
});
|
| 94 |
}
|
| 95 |
return (
|
|
|
|
| 111 |
className="h-full rounded-md border-0 bg-transparent py-0 pl-3 pr-7 text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm"
|
| 112 |
onChange={(e) => setProjectType(e.target.value)}
|
| 113 |
>
|
| 114 |
+
<option value="models">Model</option>
|
| 115 |
+
<option value="datasets">Dataset</option>
|
| 116 |
+
<option value="spaces">Space</option>
|
| 117 |
</select>
|
| 118 |
</div>
|
| 119 |
<input
|
|
|
|
| 121 |
name="phone-number"
|
| 122 |
id="phone-number"
|
| 123 |
className="block w-full rounded-md border-0 py-1.5 pl-24 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
| 124 |
+
placeholder="openai/whisper-large-v3"
|
| 125 |
value={projectName}
|
| 126 |
onChange={(e) => setProjectName(e.target.value)}
|
| 127 |
+
onFocus={(e) => e.target.select()}
|
| 128 |
+
onKeyDown={async (e) => {
|
| 129 |
if (e.key === "Enter") {
|
| 130 |
+
try {
|
| 131 |
+
await onSubmit();
|
| 132 |
+
} catch (err) {
|
| 133 |
+
alert(`No like history found for ${projectName}, please check the name and try again`);
|
| 134 |
+
}
|
| 135 |
}
|
| 136 |
}}
|
| 137 |
/>
|
static/js/main.6c20428f.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
static/js/main.6c20428f.js.LICENSE.txt
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* @license React
|
| 5 |
+
* react-dom.production.min.js
|
| 6 |
+
*
|
| 7 |
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
| 8 |
+
*
|
| 9 |
+
* This source code is licensed under the MIT license found in the
|
| 10 |
+
* LICENSE file in the root directory of this source tree.
|
| 11 |
+
*/
|
| 12 |
+
|
| 13 |
+
/**
|
| 14 |
+
* @license React
|
| 15 |
+
* react-jsx-runtime.production.min.js
|
| 16 |
+
*
|
| 17 |
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
| 18 |
+
*
|
| 19 |
+
* This source code is licensed under the MIT license found in the
|
| 20 |
+
* LICENSE file in the root directory of this source tree.
|
| 21 |
+
*/
|
| 22 |
+
|
| 23 |
+
/**
|
| 24 |
+
* @license React
|
| 25 |
+
* react.production.min.js
|
| 26 |
+
*
|
| 27 |
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
| 28 |
+
*
|
| 29 |
+
* This source code is licensed under the MIT license found in the
|
| 30 |
+
* LICENSE file in the root directory of this source tree.
|
| 31 |
+
*/
|
| 32 |
+
|
| 33 |
+
/**
|
| 34 |
+
* @license React
|
| 35 |
+
* scheduler.production.min.js
|
| 36 |
+
*
|
| 37 |
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
| 38 |
+
*
|
| 39 |
+
* This source code is licensed under the MIT license found in the
|
| 40 |
+
* LICENSE file in the root directory of this source tree.
|
| 41 |
+
*/
|
static/js/main.6c20428f.js.map
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|