import { useState } from "react"; import chartXkcd from "chart.xkcd"; const projectTypes = ["model", "dataset", "space"]; function transformLikesData(likesData) { // Step 1 likesData.sort((a, b) => new Date(a.likedAt) - new Date(b.likedAt)); // Step 2 const cumulativeLikes = {}; let cumulativeCount = 0; // Step 3 likesData.forEach(like => { const date = like.likedAt.split('T')[0]; cumulativeCount++; cumulativeLikes[date] = cumulativeCount; }); // Step 4 const transformedData = Object.keys(cumulativeLikes).map(date => ({ x: date, y: cumulativeLikes[date].toString() })); return transformedData; } /** * 1. User click enter key * 2. Get model/dataset/space name * 3. Get data from API(API format: https://huggingface.co/api/spaces/timqian/like-history/likers?expand[]=likeAt) * 4. Format data(to 20 points at most) * 5. Draw line chart */ function App() { const [projectType, setProjectType] = useState("models"); const [projectName, setProjectName] = useState("openai/whisper-large-v3"); const onSubmit = async () => { const svg = document.querySelector('.line-chart') const res = await fetch(`https://huggingface.co/api/${projectType}/${projectName}/likers?expand[]=likeAt`) /** * Format: * [{"user": "timqian", "likedAt": "2021-07-01T00:00:00.000Z"}, {"user": "yy", "likedAt": "2021-07-02T00:00:00.000Z"}] */ const likers = await res.json() let likeHistory = transformLikesData(likers) if (likeHistory.length > 40) { // sample 20 points const sampledLikeHistory = [] const step = Math.floor(likeHistory.length / 40) for (let i = 0; i < likeHistory.length; i += step) { sampledLikeHistory.push(likeHistory[i]) } likeHistory = sampledLikeHistory } // if likeHistory is empty, show error message if (likeHistory.length === 0) { alert("No like history found") return } new chartXkcd.XY(svg, { title: 'HF like history', xLabel: 'Time', yLabel: 'Likes', data: { datasets: [{ label: projectName, data: likeHistory, }], }, options: { xTickCount: 3, yTickCount: 4, legendPosition: chartXkcd.config.positionType.upLeft, showLine: true, timeFormat: 'MM/DD/YYYY', dotSize: 0.5, dataColors: ["#dd4528", "#28a3dd", "#f3db52" ] }, }); } return (