diff --git a/docusaurus.config.js b/docusaurus.config.js index b577f31..c16d760 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -42,6 +42,10 @@ const config = { }, }, + customFields: { + ossBaseUrl: 'https://oss.x-lab.info/open_digger/', + }, + presets: [ [ 'classic', diff --git a/i18n/en/code.json b/i18n/en/code.json index 446bfb2..347c050 100644 --- a/i18n/en/code.json +++ b/i18n/en/code.json @@ -325,12 +325,15 @@ "metricCharts.dataNotFound": { "message": "Data not found" }, - "metricCharts.input.placeholder": { - "message": "Repo name or user login" + "metricCharts.invalidInput": { + "message": "Invalid input, please check your input." }, - "metricCharts.submit": { + "searchInput.submit": { "message": "Submit" }, + "searchInput.placeholder": { + "message": "Search for a name..." + }, "leaderboard.dataInputPlaceHolder": { "message": "Data input, JSON format with each item as a row in the table" }, diff --git a/i18n/en/docusaurus-plugin-content-docs/current/user_docs/metrics/playground.mdx b/i18n/en/docusaurus-plugin-content-docs/current/user_docs/playground.mdx similarity index 100% rename from i18n/en/docusaurus-plugin-content-docs/current/user_docs/metrics/playground.mdx rename to i18n/en/docusaurus-plugin-content-docs/current/user_docs/playground.mdx diff --git a/i18n/zh/code.json b/i18n/zh/code.json index 13846d1..fb57290 100644 --- a/i18n/zh/code.json +++ b/i18n/zh/code.json @@ -325,12 +325,15 @@ "metricCharts.dataNotFound": { "message": "数据未找到" }, - "metricCharts.input.placeholder": { - "message": "请输入要查询的项目或开发者名称" + "metricCharts.invalidInput": { + "message": "请检查输入参数" }, - "metricCharts.submit": { + "searchInput.submit": { "message": "提交" }, + "searchInput.placeholder": { + "message": "键入搜索名称..." + }, "leaderboard.dataInputPlaceHolder": { "message": "数据输入,内容为 JSON 数据,每项为表格一行内容" }, diff --git a/package-lock.json b/package-lock.json index bac8be1..d95ba8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "prism-react-renderer": "^2.3.1", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-select": "^5.8.0", "rehype-katex": "^7.0.0", "remark-math": "^6.0.0", "stackedit-js": "^1.0.7" @@ -2813,6 +2814,154 @@ "tslib": "^2.4.0" } }, + "node_modules/@emotion/babel-plugin": { + "version": "11.12.0", + "resolved": "https://registry.npmmirror.com/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", + "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.2.0", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/@emotion/cache": { + "version": "11.13.1", + "resolved": "https://registry.npmmirror.com/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache/node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmmirror.com/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmmirror.com/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" + }, + "node_modules/@emotion/react": { + "version": "11.13.0", + "resolved": "https://registry.npmmirror.com/@emotion/react/-/react-11.13.0.tgz", + "integrity": "sha512-WkL+bw1REC2VNV1goQyfxjx1GYJkcc23CRQkXX+vZNLINyfI7o+uUn/rTGPt/xJ3bJHd5GcljgnxHf4wRw5VWQ==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/cache": "^11.13.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/@emotion/serialize/-/serialize-1.3.0.tgz", + "integrity": "sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA==", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.9.0", + "@emotion/utils": "^1.4.0", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==" + }, + "node_modules/@emotion/unitless": { + "version": "0.9.0", + "resolved": "https://registry.npmmirror.com/@emotion/unitless/-/unitless-0.9.0.tgz", + "integrity": "sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", + "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/@emotion/utils/-/utils-1.4.0.tgz", + "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==" + }, + "node_modules/@floating-ui/core": { + "version": "1.6.7", + "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.6.7.tgz", + "integrity": "sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==", + "dependencies": { + "@floating-ui/utils": "^0.2.7" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.10", + "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.6.10.tgz", + "integrity": "sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.7" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.7", + "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.7.tgz", + "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==" + }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -3934,6 +4083,14 @@ "@types/react-router": "*" } }, + "node_modules/@types/react-transition-group": { + "version": "4.4.11", + "resolved": "https://registry.npmmirror.com/@types/react-transition-group/-/react-transition-group-4.4.11.tgz", + "integrity": "sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/retry": { "version": "0.12.0", "resolved": "https://registry.npmmirror.com/@types/retry/-/retry-0.12.0.tgz", @@ -4498,6 +4655,35 @@ "object.assign": "^4.1.0" } }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.8", "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz", @@ -6432,6 +6618,15 @@ "utila": "~0.4" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -7162,6 +7357,11 @@ "node": ">=14.16" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, "node_modules/find-up": { "version": "6.3.0", "resolved": "https://registry.npmmirror.com/find-up/-/find-up-6.3.0.tgz", @@ -9466,6 +9666,11 @@ "node": ">= 4.0.0" } }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -13394,6 +13599,41 @@ "react": ">=15" } }, + "node_modules/react-select": { + "version": "5.8.0", + "resolved": "https://registry.npmmirror.com/react-select/-/react-select-5.8.0.tgz", + "integrity": "sha512-TfjLDo58XrhP6VG5M/Mi56Us0Yt8X7xD6cDybC7yoRMUNm7BGO7qk8J0TLQOua/prb8vUOtsfnXZwfm30HGsAA==", + "dependencies": { + "@babel/runtime": "^7.12.0", + "@emotion/cache": "^11.4.0", + "@emotion/react": "^11.8.1", + "@floating-ui/dom": "^1.0.1", + "@types/react-transition-group": "^4.4.0", + "memoize-one": "^6.0.0", + "prop-types": "^15.6.0", + "react-transition-group": "^4.3.0", + "use-isomorphic-layout-effect": "^1.1.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmmirror.com/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", @@ -15319,6 +15559,19 @@ "node": ">= 10.13.0" } }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index d117f73..c4b85d0 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "prism-react-renderer": "^2.3.1", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-select": "^5.8.0", "rehype-katex": "^7.0.0", "remark-math": "^6.0.0", "stackedit-js": "^1.0.7" diff --git a/src/components/OpenDiggerMetricCharts/index.js b/src/components/OpenDiggerMetricCharts/index.js index 3ab94d4..f7314e4 100644 --- a/src/components/OpenDiggerMetricCharts/index.js +++ b/src/components/OpenDiggerMetricCharts/index.js @@ -1,36 +1,22 @@ -import { useEffect, useState, useRef } from 'react'; +import { useState, useRef } from 'react'; import axios from 'axios'; import ReactECharts from 'echarts-for-react'; import { translate } from '@docusaurus/Translate'; +import SearchInput, { repoMetricOptionMap, userMetricOptionMap } from '../SearchInput'; import styles from './styles.module.css'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; export default () => { const echartsRef = useRef(null); - const platformOptionMap = new Map([ - ['GitHub', 'github'], - ['Gitee', 'gitee'], - ]); - const metricOptionMap = new Map([ - ['OpenRank', 'openrank'], - ['Activity', 'activity'], - ['Stars', 'stars'], - ['Forks', 'technical_fork'], - ['Attention', 'attention'], - ['Bus Factor', 'bus_factor'], - ['Contributors', 'new_contributors'], - ['Issues', ['issues_new', 'issues_closed', 'issue_comments']], - ['Issue Response Time', 'issue_response_time'], - ['Issue Resolution Duration', 'issue_resolution_duration'], - ['Change Requests', ['change_requests', 'change_requests_accepted', 'change_requests_reviews']], - ['Change Request Response Time', 'change_request_response_time'], - ['Change Request Resolution Duration', 'change_request_resolution_duration'], - ['Code Change Lines', ['code_change_lines_add', 'code_change_lines_remove']], - ]); + const { siteConfig } = useDocusaurusContext(); + const { customFields } = siteConfig; + const defaultRepoName = 'X-lab2017/open-digger'; const optionGeneratorMap = new Map(); + let repoName = ''; ['OpenRank', 'Activity', 'Bus Factor'].forEach(m => optionGeneratorMap.set(m, data => ({ xAxis: { @@ -135,7 +121,7 @@ export default () => { color: 'green', }, data: issuesNew, - markPoint: name === defaultRepoName ? { + markPoint: repoName === defaultRepoName ? { data: [ { value: 'Start CHAOSS impl', @@ -164,7 +150,7 @@ export default () => { type: 'line', data: issueComment, yAxisIndex: 1, - markPoint: name === defaultRepoName ? { + markPoint: repoName === defaultRepoName ? { data: [ { value: 'Disscussion for COSAR2020', @@ -336,15 +322,17 @@ export default () => { })); const [options, setOptions] = useState({}); - const [platform, setPlatform] = useState('GitHub'); - const [name, setName] = useState('X-lab2017/open-digger'); - const [metric, setMetric] = useState('OpenRank'); - const fetchData = () => { - const p = platformOptionMap.get(platform); - let m = metricOptionMap.get(metric); + const fetchData = (platform, type, name, metric) => { + if (!platform || !type || !name || !metric) { + alert(translate({ id: 'metricCharts.invalidInput' })); + return; + } + platform = platform.toLowerCase(); + repoName = name; + let m = type === 'Repo' ? repoMetricOptionMap.get(metric) : userMetricOptionMap.get(metric); if (typeof m === 'string') m = [m]; - Promise.all(m.map(m => axios.get(`https://oss.x-lab.info/open_digger/${p}/${name}/${m}.json`))).then(res => { + Promise.all(m.map(m => axios.get(`${customFields.ossBaseUrl}${platform}/${name}/${m}.json`))).then(res => { const data = res.map(r => r.data); const options = { title: { text: translate({ id: 'metricCharts.title' }, { metric, name }), left: "center" }, @@ -361,25 +349,10 @@ export default () => { }); }; - useEffect(() => { - fetchData(); - }, []); - return ( <>
- - setName(e.target.value)} /> - - + fetchData(v.platform, v.type, v.name, v.metricDisplayName)} />
diff --git a/src/components/SearchInput/index.js b/src/components/SearchInput/index.js new file mode 100644 index 0000000..69704ff --- /dev/null +++ b/src/components/SearchInput/index.js @@ -0,0 +1,222 @@ +import React, { useState, useEffect } from 'react'; +import axios from 'axios'; +import Select from 'react-select'; +import { translate } from '@docusaurus/Translate'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; + +const selectStyles = width => ({ + container: (provided) => ({ + ...provided, + display: 'inline-block', + height: '50px', + margin: '0px 10px 0px 0px', + width, + }), + control: (provided) => ({ + ...provided, + height: '100%', + }), + option: (provided, state) => ({ + ...provided, + backgroundColor: state.isSelected ? '#4CAF50' : state.isFocused ? '#f0f0f0' : null, + color: state.isSelected ? 'white' : 'black', + }), + singleValue: (provided) => ({ + ...provided, + color: '#000', + }), +}); + +const submitStyles = { + padding: '0px 15px 0px 15px', + borderRadius: '5px', + background: 'blue', + color: 'white', + border: 'none', + height: '50px', +}; + +const platforms = ['GitHub', 'Gitee']; +const types = ['Repo', 'User']; +export const repoMetricOptionMap = new Map([ + ['OpenRank', 'openrank'], + ['Activity', 'activity'], + ['Stars', 'stars'], + ['Forks', 'technical_fork'], + ['Attention', 'attention'], + ['Bus Factor', 'bus_factor'], + ['Contributors', 'new_contributors'], + ['Issues', ['issues_new', 'issues_closed', 'issue_comments']], + ['Issue Response Time', 'issue_response_time'], + ['Issue Resolution Duration', 'issue_resolution_duration'], + ['Change Requests', ['change_requests', 'change_requests_accepted', 'change_requests_reviews']], + ['Change Request Response Time', 'change_request_response_time'], + ['Change Request Resolution Duration', 'change_request_resolution_duration'], + ['Code Change Lines', ['code_change_lines_add', 'code_change_lines_remove']], +]); +export const userMetricOptionMap = new Map([ + ['OpenRank', 'openrank'], + ['Activity', 'activity'], +]); + +export default ({ platform, type, metric, onSubmit }) => { + const optionsLimitCount = 20; + const [repoList, setRepoList] = useState([]); + const [userList, setUserList] = useState([]); + const [selectOptions, setSelectOptions] = useState([]); + const [searchInputValue, setSearchInputvalue] = useState(''); + const [selectedName, setSelectedName] = useState(null); + const [selectedPlatform, setSelectedPlatform] = useState(null); + const [selectedType, setSelectedType] = useState(null); + const [metricOptions, setMetricOptions] = useState([]); + const [selectedMetric, setSelectedMetric] = useState(null); + + const { siteConfig } = useDocusaurusContext(); + const { customFields } = siteConfig; + + useEffect(() => { + let typeValue = type; + if (type) { + if (!types.includes(type)) { + typeValue = types[0]; + if (type !== true) { + alert(`Invalid type: ${type}`); + } + } + } else { + typeValue = types[0]; + } + setSelectedType({ value: typeValue, label: typeValue }); + + if (platform) { + if (platforms.includes(platform)) { + setSelectedPlatform({ value: platform, label: platform }); + } else { + setSelectedPlatform({ value: platforms[0], label: platforms[0] }); + if (platform !== true) { + alert(`Invalid platform: ${platform}`); + } + } + } else { + setSelectedPlatform({ value: platforms[0], label: platforms[0] }); + } + + const fetchRepoList = async () => { + try { + const response = await axios.get(`${customFields.ossBaseUrl}repo_list.csv`); + const data = response.data; + const parsedRepoList = data.split('\n') + .slice(1) + .map(line => line.trim().split(',')) + .filter(line => line.length === 3 && line[1] != '' && line[2] != '') + .map(line => ({ platform: line[1], name: line[2] })); + setRepoList(parsedRepoList); + } catch (error) { + console.error('Error fetching repo list:', error); + } + } + const fetchUserList = async () => { + try { + const response = await axios.get(`${customFields.ossBaseUrl}user_list.csv`); + const data = response.data; + const parsedUserList = data.split('\n') + .slice(1) + .map(line => line.trim().split(',')) + .filter(line => line.length === 3 && line[1] != '' && line[2] != '') + .map(line => ({ platform: line[1], name: line[2] })); + setUserList(parsedUserList); + } catch (error) { + console.error('Error fetching user list:', error); + } + } + fetchRepoList(); + fetchUserList(); + }, []); + + useEffect(() => { + if (!selectedPlatform || !selectedType) return; + const options = []; + const list = selectedType.value === 'Repo' ? repoList : userList; + for (const r of list) { + if (r.platform === selectedPlatform.value.toLowerCase()) { + if (searchInputValue) { + if (r.name.toLowerCase().includes(searchInputValue.toLowerCase())) { + options.push({ value: r.name, label: r.name }); + } + } else { + options.push({ value: r.name, label: r.name }); + } + } + if (options.length >= optionsLimitCount) break; + } + setSelectOptions(options); + }, [selectedPlatform, selectedType, repoList, userList, searchInputValue]); + + useEffect(() => { + if (!selectedType) return; + console.log(selectedType); + const map = selectedType.value === 'Repo' ? repoMetricOptionMap : userMetricOptionMap; + const options = [...map.entries()].map(m => ({ value: m[1], label: m[0] })); + setMetricOptions(options); + setSelectedMetric({ value: 'openrank', label: 'OpenRank' }); + }, [selectedType]); + + return ( +
+ {!((platform && platforms.includes(platform)) || platform === true) && ( + ({ value: p, label: p }))} + value={selectedType} + onChange={(selectedOption) => { setSelectedType(selectedOption); setSelectedName(null); }} + isSearchable={false} + isClearable={false} + styles={selectStyles('100px')} + /> + )} + { setSelectedMetric(selectedOption); }} + isSearchable={false} + isClearable={false} + styles={selectStyles('200px')} + /> + )} + +
+ ); +};