From 0eb6833f560908610011769a46d6d6287ad009b7 Mon Sep 17 00:00:00 2001 From: xiaoAugenstern <1014708671@qq.com> Date: Sun, 28 Jul 2024 20:03:49 +0800 Subject: [PATCH] move data to ./public/tech-foundation --- .history/package_20240725151341.json | 52 + .history/package_20240728145142.json | 55 + .history/package_20240728195511.json | 52 + .../foundationchinese_20240728172909.json | 0 .../foundationchinese_20240728172930.json | 76 + .../foundationglobal_20240728172918.json | 0 .../foundationglobal_20240728173949.json | 5 + .../foundationglobal_20240728182812.json | 76 + .../foundationglobal_20240728182818.json | 76 + .../foundationglobal_20240728195837.json | 76 + .../technologyai_20240728172713.json | 0 .../technologyai_20240728173532.json | 77 + .../technologyai_20240728173534.json | 76 + .../technologyai_20240728173542.json | 76 + .../technologyai_20240728173926.json | 76 + .../technologybig-data_20240728172727.json | 0 .../technologybig-data_20240728173618.json | 77 + .../technologybig-data_20240728173633.json | 76 + .../technologybig-data_20240728195750.json | 76 + ...technologycloud-native_20240728172857.json | 0 ...technologycloud-native_20240728173058.json | 76 + ...technologycloud-native_20240728173847.json | 76 + .../technologydatabase_20240728172821.json | 0 .../technologydatabase_20240728173704.json | 77 + .../technologydatabase_20240728173710.json | 76 + .../technologydatabase_20240728195805.json | 76 + .../technologyfront-end_20240728172808.json | 0 .../technologyfront-end_20240728173446.json | 7 + .../technologyfront-end_20240728173736.json | 77 + .../technologyfront-end_20240728173741.json | 76 + .../technologyfront-end_20240728195817.json | 76 + .../technologyos_20240728172838.json | 0 .../technologyos_20240728173806.json | 77 + .../technologyos_20240728173810.json | 76 + .../technologyos_20240728195829.json | 76 + ...technologycloud-native_20240728153801.json | 0 ...technologycloud-native_20240728154040.json | 76 + ...technologycloud-native_20240728154042.json | 76 + .../src/components/data_20240728143018.js | 0 .../src/components/data_20240728171418.js | 218 +++ .../src/components/table_20240727221129.js | 1319 +++++++++++++++++ .../src/components/table_20240727221246.js | 1297 ++++++++++++++++ .../src/components/table_20240727224142.js | 653 ++++++++ .../src/components/table_20240727224145.js | 653 ++++++++ .../src/components/table_20240727224820.js | 651 ++++++++ .../src/components/table_20240727225058.js | 651 ++++++++ .../src/components/table_20240727225519.js | 651 ++++++++ .../src/components/table_20240727230659.js | 652 ++++++++ .../src/components/table_20240727230905.js | 653 ++++++++ .../src/components/table_20240727230907.js | 653 ++++++++ .../src/components/table_20240727230943.js | 653 ++++++++ .../src/components/table_20240727231007.js | 653 ++++++++ .../src/components/table_20240727231113.js | 653 ++++++++ .../src/components/table_20240727231156.js | 589 ++++++++ .../src/components/table_20240727231303.js | 589 ++++++++ .../src/components/table_20240727231305.js | 589 ++++++++ .../src/components/table_20240727231408.js | 589 ++++++++ .../src/components/table_20240727231449.js | 589 ++++++++ .../src/components/table_20240727231623.js | 589 ++++++++ .../src/components/table_20240728144201.js | 601 ++++++++ .../src/components/table_20240728144210.js | 601 ++++++++ .../src/components/table_20240728144254.js | 601 ++++++++ .../src/components/table_20240728144348.js | 601 ++++++++ .../src/components/table_20240728144514.js | 627 ++++++++ .../src/components/table_20240728144641.js | 615 ++++++++ .../src/components/table_20240728144736.js | 601 ++++++++ .../src/components/table_20240728150221.js | 627 ++++++++ .../src/components/table_20240728150719.js | 627 ++++++++ .../src/components/table_20240728150811.js | 627 ++++++++ .../src/components/table_20240728150851.js | 627 ++++++++ .../src/components/table_20240728151211.js | 650 ++++++++ .../src/components/table_20240728151214.js | 650 ++++++++ .../src/components/table_20240728151323.js | 651 ++++++++ .../src/components/table_20240728151410.js | 651 ++++++++ .../src/components/table_20240728151537.js | 645 ++++++++ .../src/components/table_20240728152336.js | 645 ++++++++ .../src/components/table_20240728152433.js | 645 ++++++++ .../src/components/table_20240728152504.js | 645 ++++++++ .../src/components/table_20240728152539.js | 645 ++++++++ .../src/components/table_20240728152542.js | 645 ++++++++ .../src/components/table_20240728152647.js | 650 ++++++++ .../src/components/table_20240728153148.js | 650 ++++++++ .../src/components/table_20240728153150.js | 650 ++++++++ .../src/components/table_20240728153730.js | 594 ++++++++ .../src/components/table_20240728171435.js | 594 ++++++++ .../src/components/table_20240728173002.js | 594 ++++++++ .../src/components/table_20240728173032.js | 594 ++++++++ .../src/components/table_20240728173107.js | 594 ++++++++ .../src/components/table_20240728173113.js | 593 ++++++++ .../src/components/table_20240728195002.js | 593 ++++++++ .../src/components/table_20240728195126.js | 593 ++++++++ .../src/components/table_20240728195614.js | 592 ++++++++ .../foundationChinese_20240728145456.json | 0 .../foundationChinese_20240728145600.json | 76 + .../foundationChinese_20240728145848.json | 76 + public/tech-foundation/foundationchinese.json | 76 + public/tech-foundation/foundationglobal.json | 76 + public/tech-foundation/technologyai.json | 76 + .../tech-foundation/technologybig-data.json | 76 + .../technologycloud-native.json | 76 + .../tech-foundation/technologydatabase.json | 76 + .../tech-foundation/technologyfront-end.json | 76 + public/tech-foundation/technologyos.json | 76 + src/components/table.js | 820 +--------- src/data/2023_field_ranking_top10.xlsx | Bin 14755 -> 0 bytes src/data/2023_foundation_ranking_top10.xlsx | Bin 10475 -> 0 bytes 106 files changed, 36831 insertions(+), 811 deletions(-) create mode 100644 .history/package_20240725151341.json create mode 100644 .history/package_20240728145142.json create mode 100644 .history/package_20240728195511.json create mode 100644 .history/public/tech-foundation/foundationchinese_20240728172909.json create mode 100644 .history/public/tech-foundation/foundationchinese_20240728172930.json create mode 100644 .history/public/tech-foundation/foundationglobal_20240728172918.json create mode 100644 .history/public/tech-foundation/foundationglobal_20240728173949.json create mode 100644 .history/public/tech-foundation/foundationglobal_20240728182812.json create mode 100644 .history/public/tech-foundation/foundationglobal_20240728182818.json create mode 100644 .history/public/tech-foundation/foundationglobal_20240728195837.json create mode 100644 .history/public/tech-foundation/technologyai_20240728172713.json create mode 100644 .history/public/tech-foundation/technologyai_20240728173532.json create mode 100644 .history/public/tech-foundation/technologyai_20240728173534.json create mode 100644 .history/public/tech-foundation/technologyai_20240728173542.json create mode 100644 .history/public/tech-foundation/technologyai_20240728173926.json create mode 100644 .history/public/tech-foundation/technologybig-data_20240728172727.json create mode 100644 .history/public/tech-foundation/technologybig-data_20240728173618.json create mode 100644 .history/public/tech-foundation/technologybig-data_20240728173633.json create mode 100644 .history/public/tech-foundation/technologybig-data_20240728195750.json create mode 100644 .history/public/tech-foundation/technologycloud-native_20240728172857.json create mode 100644 .history/public/tech-foundation/technologycloud-native_20240728173058.json create mode 100644 .history/public/tech-foundation/technologycloud-native_20240728173847.json create mode 100644 .history/public/tech-foundation/technologydatabase_20240728172821.json create mode 100644 .history/public/tech-foundation/technologydatabase_20240728173704.json create mode 100644 .history/public/tech-foundation/technologydatabase_20240728173710.json create mode 100644 .history/public/tech-foundation/technologydatabase_20240728195805.json create mode 100644 .history/public/tech-foundation/technologyfront-end_20240728172808.json create mode 100644 .history/public/tech-foundation/technologyfront-end_20240728173446.json create mode 100644 .history/public/tech-foundation/technologyfront-end_20240728173736.json create mode 100644 .history/public/tech-foundation/technologyfront-end_20240728173741.json create mode 100644 .history/public/tech-foundation/technologyfront-end_20240728195817.json create mode 100644 .history/public/tech-foundation/technologyos_20240728172838.json create mode 100644 .history/public/tech-foundation/technologyos_20240728173806.json create mode 100644 .history/public/tech-foundation/technologyos_20240728173810.json create mode 100644 .history/public/tech-foundation/technologyos_20240728195829.json create mode 100644 .history/public/technologycloud-native_20240728153801.json create mode 100644 .history/public/technologycloud-native_20240728154040.json create mode 100644 .history/public/technologycloud-native_20240728154042.json create mode 100644 .history/src/components/data_20240728143018.js create mode 100644 .history/src/components/data_20240728171418.js create mode 100644 .history/src/components/table_20240727221129.js create mode 100644 .history/src/components/table_20240727221246.js create mode 100644 .history/src/components/table_20240727224142.js create mode 100644 .history/src/components/table_20240727224145.js create mode 100644 .history/src/components/table_20240727224820.js create mode 100644 .history/src/components/table_20240727225058.js create mode 100644 .history/src/components/table_20240727225519.js create mode 100644 .history/src/components/table_20240727230659.js create mode 100644 .history/src/components/table_20240727230905.js create mode 100644 .history/src/components/table_20240727230907.js create mode 100644 .history/src/components/table_20240727230943.js create mode 100644 .history/src/components/table_20240727231007.js create mode 100644 .history/src/components/table_20240727231113.js create mode 100644 .history/src/components/table_20240727231156.js create mode 100644 .history/src/components/table_20240727231303.js create mode 100644 .history/src/components/table_20240727231305.js create mode 100644 .history/src/components/table_20240727231408.js create mode 100644 .history/src/components/table_20240727231449.js create mode 100644 .history/src/components/table_20240727231623.js create mode 100644 .history/src/components/table_20240728144201.js create mode 100644 .history/src/components/table_20240728144210.js create mode 100644 .history/src/components/table_20240728144254.js create mode 100644 .history/src/components/table_20240728144348.js create mode 100644 .history/src/components/table_20240728144514.js create mode 100644 .history/src/components/table_20240728144641.js create mode 100644 .history/src/components/table_20240728144736.js create mode 100644 .history/src/components/table_20240728150221.js create mode 100644 .history/src/components/table_20240728150719.js create mode 100644 .history/src/components/table_20240728150811.js create mode 100644 .history/src/components/table_20240728150851.js create mode 100644 .history/src/components/table_20240728151211.js create mode 100644 .history/src/components/table_20240728151214.js create mode 100644 .history/src/components/table_20240728151323.js create mode 100644 .history/src/components/table_20240728151410.js create mode 100644 .history/src/components/table_20240728151537.js create mode 100644 .history/src/components/table_20240728152336.js create mode 100644 .history/src/components/table_20240728152433.js create mode 100644 .history/src/components/table_20240728152504.js create mode 100644 .history/src/components/table_20240728152539.js create mode 100644 .history/src/components/table_20240728152542.js create mode 100644 .history/src/components/table_20240728152647.js create mode 100644 .history/src/components/table_20240728153148.js create mode 100644 .history/src/components/table_20240728153150.js create mode 100644 .history/src/components/table_20240728153730.js create mode 100644 .history/src/components/table_20240728171435.js create mode 100644 .history/src/components/table_20240728173002.js create mode 100644 .history/src/components/table_20240728173032.js create mode 100644 .history/src/components/table_20240728173107.js create mode 100644 .history/src/components/table_20240728173113.js create mode 100644 .history/src/components/table_20240728195002.js create mode 100644 .history/src/components/table_20240728195126.js create mode 100644 .history/src/components/table_20240728195614.js create mode 100644 .history/src/locales/foundationChinese_20240728145456.json create mode 100644 .history/src/locales/foundationChinese_20240728145600.json create mode 100644 .history/src/locales/foundationChinese_20240728145848.json create mode 100644 public/tech-foundation/foundationchinese.json create mode 100644 public/tech-foundation/foundationglobal.json create mode 100644 public/tech-foundation/technologyai.json create mode 100644 public/tech-foundation/technologybig-data.json create mode 100644 public/tech-foundation/technologycloud-native.json create mode 100644 public/tech-foundation/technologydatabase.json create mode 100644 public/tech-foundation/technologyfront-end.json create mode 100644 public/tech-foundation/technologyos.json delete mode 100644 src/data/2023_field_ranking_top10.xlsx delete mode 100644 src/data/2023_foundation_ranking_top10.xlsx diff --git a/.history/package_20240725151341.json b/.history/package_20240725151341.json new file mode 100644 index 0000000..ee4e31c --- /dev/null +++ b/.history/package_20240725151341.json @@ -0,0 +1,52 @@ +{ + "name": "open-insight-front", + "version": "0.1.0", + "private": true, + "engines": { + "node": "^16" + }, + "dependencies": { + "@ant-design/icons": "^5.0.1", + "@testing-library/jest-dom": "^5.16.1", + "@testing-library/react": "^12.1.2", + "@testing-library/user-event": "^13.5.0", + "antd": "^4.18.0", + "i18next": "^21.6.4", + "i18next-browser-languagedetector": "^6.1.2", + "i18next-http-backend": "^1.3.1", + "moment": "^2.29.4", + "prettier": "^2.8.4", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "react-i18next": "^11.15.2", + "react-router-dom": "^6.2.1", + "react-scripts": "5.0.0", + "web-vitals": "^2.1.2" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject", + "prettier": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,scss}\"", + "prettier:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,css,scss}\"" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/.history/package_20240728145142.json b/.history/package_20240728145142.json new file mode 100644 index 0000000..6e07233 --- /dev/null +++ b/.history/package_20240728145142.json @@ -0,0 +1,55 @@ +{ + "name": "open-insight-front", + "version": "0.1.0", + "private": true, + "engines": { + "node": "^16" + }, + "dependencies": { + "@ant-design/icons": "^5.0.1", + "@testing-library/jest-dom": "^5.16.1", + "@testing-library/react": "^12.1.2", + "@testing-library/user-event": "^13.5.0", + "antd": "^4.18.0", + "i18next": "^21.6.4", + "i18next-browser-languagedetector": "^6.1.2", + "i18next-http-backend": "^1.3.1", + "moment": "^2.29.4", + "prettier": "^2.8.4", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "react-i18next": "^11.15.2", + "react-router-dom": "^6.2.1", + "react-scripts": "5.0.0", + "web-vitals": "^2.1.2" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject", + "prettier": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,scss}\"", + "prettier:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,css,scss}\"" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ], + "rules":{ + "no-undef": "off" + } + } +} diff --git a/.history/package_20240728195511.json b/.history/package_20240728195511.json new file mode 100644 index 0000000..ee4e31c --- /dev/null +++ b/.history/package_20240728195511.json @@ -0,0 +1,52 @@ +{ + "name": "open-insight-front", + "version": "0.1.0", + "private": true, + "engines": { + "node": "^16" + }, + "dependencies": { + "@ant-design/icons": "^5.0.1", + "@testing-library/jest-dom": "^5.16.1", + "@testing-library/react": "^12.1.2", + "@testing-library/user-event": "^13.5.0", + "antd": "^4.18.0", + "i18next": "^21.6.4", + "i18next-browser-languagedetector": "^6.1.2", + "i18next-http-backend": "^1.3.1", + "moment": "^2.29.4", + "prettier": "^2.8.4", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "react-i18next": "^11.15.2", + "react-router-dom": "^6.2.1", + "react-scripts": "5.0.0", + "web-vitals": "^2.1.2" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject", + "prettier": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,scss}\"", + "prettier:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,css,scss}\"" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/.history/public/tech-foundation/foundationchinese_20240728172909.json b/.history/public/tech-foundation/foundationchinese_20240728172909.json new file mode 100644 index 0000000..e69de29 diff --git a/.history/public/tech-foundation/foundationchinese_20240728172930.json b/.history/public/tech-foundation/foundationchinese_20240728172930.json new file mode 100644 index 0000000..ce7dab2 --- /dev/null +++ b/.history/public/tech-foundation/foundationchinese_20240728172930.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "apache/doris", + "value": "4307.26", + "rankDelta": 1, + "valueDelta": 100 + }, + { + "rank": "2", + "name": "openharmony/docs", + "value": "3277.69", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "openharmony/arkui_ace_engine", + "value": "2818.09", + "rankDelta": -1, + "valueDelta": -3 + }, + { + "rank": "4", + "name": "milvus-io/milvus", + "value": "2001.11", + "rankDelta": 3, + "valueDelta": -100 + }, + { + "rank": "5", + "name": "apache/flink", + "value": "1816.72", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "apache/shardingsphere", + "value": "1662.8", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "apache/ozone", + "value": "1281.57", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "apache/iotdb", + "value": "1265.72", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "openharmony/graphic_graphic_2d", + "value": "1239.6", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "apache/pulsar", + "value": "1227.93", + "rankDelta": 0, + "valueDelta": 0 + } + ] + } \ No newline at end of file diff --git a/.history/public/tech-foundation/foundationglobal_20240728172918.json b/.history/public/tech-foundation/foundationglobal_20240728172918.json new file mode 100644 index 0000000..e69de29 diff --git a/.history/public/tech-foundation/foundationglobal_20240728173949.json b/.history/public/tech-foundation/foundationglobal_20240728173949.json new file mode 100644 index 0000000..6355a41 --- /dev/null +++ b/.history/public/tech-foundation/foundationglobal_20240728173949.json @@ -0,0 +1,5 @@ +{ + "type": "Foundation_Global", + "time": "2024", + "data": +} \ No newline at end of file diff --git a/.history/public/tech-foundation/foundationglobal_20240728182812.json b/.history/public/tech-foundation/foundationglobal_20240728182812.json new file mode 100644 index 0000000..833d3ab --- /dev/null +++ b/.history/public/tech-foundation/foundationglobal_20240728182812.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_Global", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "kubernetes/kubernetes", + "value": "5374.14", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "apache/doris", + "value": "4307.26", + "rankDelta": 2, + "valueDelta": 3 + }, + { + "rank": "3", + "name": "apache/airflow", + "value": "3642.9", + "rankDelta": -1, + "valueDelta": -3 + }, + { + "rank": "4", + "name": "openharmony/docs", + "value": "3277.69", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "openharmony/arkui_ace_engine", + "value": "2818.09", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "nodejs/node", + "value": "2736.37", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "apache/spark", + "value": "2654.02", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "apache/arrow", + "value": "2219.95", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "apache/beam", + "value": "2188.52", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "apache/hudi", + "value": "2124.67", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/.history/public/tech-foundation/foundationglobal_20240728182818.json b/.history/public/tech-foundation/foundationglobal_20240728182818.json new file mode 100644 index 0000000..1b2502b --- /dev/null +++ b/.history/public/tech-foundation/foundationglobal_20240728182818.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_Global", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "kubernetes/kubernetes", + "value": "5374.14", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "apache/doris", + "value": "4307.26", + "rankDelta": 2, + "valueDelta": 3 + }, + { + "rank": "3", + "name": "apache/airflow", + "value": "3642.9", + "rankDelta": -1, + "valueDelta": -3 + }, + { + "rank": "4", + "name": "openharmony/docs", + "value": "3277.69", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "openharmony/arkui_ace_engine", + "value": "2818.09", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "nodejs/node", + "value": "2736.37", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "apache/spark", + "value": "2654.02", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "apache/arrow", + "value": "2219.95", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "apache/beam", + "value": "2188.52", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "apache/hudi", + "value": "2124.67", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/.history/public/tech-foundation/foundationglobal_20240728195837.json b/.history/public/tech-foundation/foundationglobal_20240728195837.json new file mode 100644 index 0000000..1b2502b --- /dev/null +++ b/.history/public/tech-foundation/foundationglobal_20240728195837.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_Global", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "kubernetes/kubernetes", + "value": "5374.14", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "apache/doris", + "value": "4307.26", + "rankDelta": 2, + "valueDelta": 3 + }, + { + "rank": "3", + "name": "apache/airflow", + "value": "3642.9", + "rankDelta": -1, + "valueDelta": -3 + }, + { + "rank": "4", + "name": "openharmony/docs", + "value": "3277.69", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "openharmony/arkui_ace_engine", + "value": "2818.09", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "nodejs/node", + "value": "2736.37", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "apache/spark", + "value": "2654.02", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "apache/arrow", + "value": "2219.95", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "apache/beam", + "value": "2188.52", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "apache/hudi", + "value": "2124.67", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologyai_20240728172713.json b/.history/public/tech-foundation/technologyai_20240728172713.json new file mode 100644 index 0000000..e69de29 diff --git a/.history/public/tech-foundation/technologyai_20240728173532.json b/.history/public/tech-foundation/technologyai_20240728173532.json new file mode 100644 index 0000000..497d76f --- /dev/null +++ b/.history/public/tech-foundation/technologyai_20240728173532.json @@ -0,0 +1,77 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data":[ + { + "rank": "1", + "name": "pytorch/pytorch", + "value": "10182.45", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "langchain-ai/langchain", + "value": "6080.25", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "PaddlePaddle/Paddle", + "value": "5408.62", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "huggingface/transformers", + "value": "4422.84", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "AUTOMATIC1111/stable-diffusion-webui", + "value": "3881.6", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "openvinotoolkit/openvino", + "value": "3857.31", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "microsoft/onnxruntime", + "value": "3006.75", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "tensorflow/tensorflow", + "value": "2723.26", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "Significant-Gravitas/AutoGPT", + "value": "2664.85", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "ggerganov/llama.cpp", + "value": "2339.8", + "rankDelta": 0, + "valueDelta": 0 + } + ] + +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologyai_20240728173534.json b/.history/public/tech-foundation/technologyai_20240728173534.json new file mode 100644 index 0000000..72f1387 --- /dev/null +++ b/.history/public/tech-foundation/technologyai_20240728173534.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data":[ + { + "rank": "1", + "name": "pytorch/pytorch", + "value": "10182.45", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "langchain-ai/langchain", + "value": "6080.25", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "PaddlePaddle/Paddle", + "value": "5408.62", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "huggingface/transformers", + "value": "4422.84", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "AUTOMATIC1111/stable-diffusion-webui", + "value": "3881.6", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "openvinotoolkit/openvino", + "value": "3857.31", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "microsoft/onnxruntime", + "value": "3006.75", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "tensorflow/tensorflow", + "value": "2723.26", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "Significant-Gravitas/AutoGPT", + "value": "2664.85", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "ggerganov/llama.cpp", + "value": "2339.8", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologyai_20240728173542.json b/.history/public/tech-foundation/technologyai_20240728173542.json new file mode 100644 index 0000000..d1d2a6d --- /dev/null +++ b/.history/public/tech-foundation/technologyai_20240728173542.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "pytorch/pytorch", + "value": "10182.45", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "langchain-ai/langchain", + "value": "6080.25", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "PaddlePaddle/Paddle", + "value": "5408.62", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "huggingface/transformers", + "value": "4422.84", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "AUTOMATIC1111/stable-diffusion-webui", + "value": "3881.6", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "openvinotoolkit/openvino", + "value": "3857.31", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "microsoft/onnxruntime", + "value": "3006.75", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "tensorflow/tensorflow", + "value": "2723.26", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "Significant-Gravitas/AutoGPT", + "value": "2664.85", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "ggerganov/llama.cpp", + "value": "2339.8", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologyai_20240728173926.json b/.history/public/tech-foundation/technologyai_20240728173926.json new file mode 100644 index 0000000..5b5d101 --- /dev/null +++ b/.history/public/tech-foundation/technologyai_20240728173926.json @@ -0,0 +1,76 @@ +{ + "type": "Technology_ai", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "pytorch/pytorch", + "value": "10182.45", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "langchain-ai/langchain", + "value": "6080.25", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "PaddlePaddle/Paddle", + "value": "5408.62", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "huggingface/transformers", + "value": "4422.84", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "AUTOMATIC1111/stable-diffusion-webui", + "value": "3881.6", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "openvinotoolkit/openvino", + "value": "3857.31", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "microsoft/onnxruntime", + "value": "3006.75", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "tensorflow/tensorflow", + "value": "2723.26", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "Significant-Gravitas/AutoGPT", + "value": "2664.85", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "ggerganov/llama.cpp", + "value": "2339.8", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologybig-data_20240728172727.json b/.history/public/tech-foundation/technologybig-data_20240728172727.json new file mode 100644 index 0000000..e69de29 diff --git a/.history/public/tech-foundation/technologybig-data_20240728173618.json b/.history/public/tech-foundation/technologybig-data_20240728173618.json new file mode 100644 index 0000000..4da1df0 --- /dev/null +++ b/.history/public/tech-foundation/technologybig-data_20240728173618.json @@ -0,0 +1,77 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data":[ + { + "rank": "1", + "name": "elastic/kibana", + "value": "7601.04", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "grafana/grafana", + "value": "7134.37", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "ClickHouse/ClickHouse", + "value": "4941.99", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "airbytehq/airbyte", + "value": "4658.86", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "apache/doris", + "value": "4307.26", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "elastic/elasticsearch", + "value": "3729.39", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "apache/airflow", + "value": "3642.9", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "StarRocks/starrocks", + "value": "3194.56", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "trinodb/trino", + "value": "2703.4", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "apache/spark", + "value": "2654.02", + "rankDelta": 0, + "valueDelta": 0 + } + ] + +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologybig-data_20240728173633.json b/.history/public/tech-foundation/technologybig-data_20240728173633.json new file mode 100644 index 0000000..a694155 --- /dev/null +++ b/.history/public/tech-foundation/technologybig-data_20240728173633.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "elastic/kibana", + "value": "7601.04", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "grafana/grafana", + "value": "7134.37", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "ClickHouse/ClickHouse", + "value": "4941.99", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "airbytehq/airbyte", + "value": "4658.86", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "apache/doris", + "value": "4307.26", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "elastic/elasticsearch", + "value": "3729.39", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "apache/airflow", + "value": "3642.9", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "StarRocks/starrocks", + "value": "3194.56", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "trinodb/trino", + "value": "2703.4", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "apache/spark", + "value": "2654.02", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologybig-data_20240728195750.json b/.history/public/tech-foundation/technologybig-data_20240728195750.json new file mode 100644 index 0000000..08dd4a7 --- /dev/null +++ b/.history/public/tech-foundation/technologybig-data_20240728195750.json @@ -0,0 +1,76 @@ +{ + "type": "Technology_big-data", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "elastic/kibana", + "value": "7601.04", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "grafana/grafana", + "value": "7134.37", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "ClickHouse/ClickHouse", + "value": "4941.99", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "airbytehq/airbyte", + "value": "4658.86", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "apache/doris", + "value": "4307.26", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "elastic/elasticsearch", + "value": "3729.39", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "apache/airflow", + "value": "3642.9", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "StarRocks/starrocks", + "value": "3194.56", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "trinodb/trino", + "value": "2703.4", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "apache/spark", + "value": "2654.02", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologycloud-native_20240728172857.json b/.history/public/tech-foundation/technologycloud-native_20240728172857.json new file mode 100644 index 0000000..e69de29 diff --git a/.history/public/tech-foundation/technologycloud-native_20240728173058.json b/.history/public/tech-foundation/technologycloud-native_20240728173058.json new file mode 100644 index 0000000..fccc6d9 --- /dev/null +++ b/.history/public/tech-foundation/technologycloud-native_20240728173058.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "grafana/grafana", + "value": "7134.37", + "rankDelta": 1, + "valueDelta": 100 + }, + { + "rank": "2", + "name": "llvm/llvm-project", + "value": "7049.62", + "rankDelta": -2, + "valueDelta": -220 + }, + { + "rank": "3", + "name": "kubernetes/kubernetes", + "value": "5374.14", + "rankDelta": 3, + "valueDelta": 300 + }, + { + "rank": "4", + "name": "ClickHouse/ClickHouse", + "value": "4941.99", + "rankDelta": -4, + "valueDelta": 400 + }, + { + "rank": "5", + "name": "cilium/cilium", + "value": "3215.42", + "rankDelta": 5, + "valueDelta": -500 + }, + { + "rank": "6", + "name": "ceph/ceph", + "value": "3172.49", + "rankDelta": -6, + "valueDelta": 600 + }, + { + "rank": "7", + "name": "keycloak/keycloak", + "value": "3095.56", + "rankDelta": 7, + "valueDelta": 700 + }, + { + "rank": "8", + "name": "gravitational/teleport", + "value": "3082.18", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "envoyproxy/envoy", + "value": "2929.08", + "rankDelta": 9, + "valueDelta": -900 + }, + { + "rank": "10", + "name": "backstage/backstage", + "value": "2903.39", + "rankDelta": 10, + "valueDelta": 100 + } + ] + } \ No newline at end of file diff --git a/.history/public/tech-foundation/technologycloud-native_20240728173847.json b/.history/public/tech-foundation/technologycloud-native_20240728173847.json new file mode 100644 index 0000000..c6d4351 --- /dev/null +++ b/.history/public/tech-foundation/technologycloud-native_20240728173847.json @@ -0,0 +1,76 @@ +{ + "type": "Technology_cloud-native", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "grafana/grafana", + "value": "7134.37", + "rankDelta": 1, + "valueDelta": 100 + }, + { + "rank": "2", + "name": "llvm/llvm-project", + "value": "7049.62", + "rankDelta": -2, + "valueDelta": -220 + }, + { + "rank": "3", + "name": "kubernetes/kubernetes", + "value": "5374.14", + "rankDelta": 3, + "valueDelta": 300 + }, + { + "rank": "4", + "name": "ClickHouse/ClickHouse", + "value": "4941.99", + "rankDelta": -4, + "valueDelta": 400 + }, + { + "rank": "5", + "name": "cilium/cilium", + "value": "3215.42", + "rankDelta": 5, + "valueDelta": -500 + }, + { + "rank": "6", + "name": "ceph/ceph", + "value": "3172.49", + "rankDelta": -6, + "valueDelta": 600 + }, + { + "rank": "7", + "name": "keycloak/keycloak", + "value": "3095.56", + "rankDelta": 7, + "valueDelta": 700 + }, + { + "rank": "8", + "name": "gravitational/teleport", + "value": "3082.18", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "envoyproxy/envoy", + "value": "2929.08", + "rankDelta": 9, + "valueDelta": -900 + }, + { + "rank": "10", + "name": "backstage/backstage", + "value": "2903.39", + "rankDelta": 10, + "valueDelta": 100 + } + ] + } \ No newline at end of file diff --git a/.history/public/tech-foundation/technologydatabase_20240728172821.json b/.history/public/tech-foundation/technologydatabase_20240728172821.json new file mode 100644 index 0000000..e69de29 diff --git a/.history/public/tech-foundation/technologydatabase_20240728173704.json b/.history/public/tech-foundation/technologydatabase_20240728173704.json new file mode 100644 index 0000000..01acd8b --- /dev/null +++ b/.history/public/tech-foundation/technologydatabase_20240728173704.json @@ -0,0 +1,77 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data":[ + { + "rank": "1", + "name": "ClickHouse/ClickHouse", + "value": "4941.99", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "apache/doris", + "value": "4307.26", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "elastic/elasticsearch", + "value": "3729.39", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "cockroachdb/cockroach", + "value": "3443.7", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "StarRocks/starrocks", + "value": "3194.56", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "trinodb/trino", + "value": "2703.4", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "apache/spark", + "value": "2654.02", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "pingcap/tidb", + "value": "2200.38", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "milvus-io/milvus", + "value": "2001.11", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "yugabyte/yugabyte-db", + "value": "1940.75", + "rankDelta": 0, + "valueDelta": 0 + } + ] + +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologydatabase_20240728173710.json b/.history/public/tech-foundation/technologydatabase_20240728173710.json new file mode 100644 index 0000000..0674215 --- /dev/null +++ b/.history/public/tech-foundation/technologydatabase_20240728173710.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "ClickHouse/ClickHouse", + "value": "4941.99", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "apache/doris", + "value": "4307.26", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "elastic/elasticsearch", + "value": "3729.39", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "cockroachdb/cockroach", + "value": "3443.7", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "StarRocks/starrocks", + "value": "3194.56", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "trinodb/trino", + "value": "2703.4", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "apache/spark", + "value": "2654.02", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "pingcap/tidb", + "value": "2200.38", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "milvus-io/milvus", + "value": "2001.11", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "yugabyte/yugabyte-db", + "value": "1940.75", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologydatabase_20240728195805.json b/.history/public/tech-foundation/technologydatabase_20240728195805.json new file mode 100644 index 0000000..2d6a2a7 --- /dev/null +++ b/.history/public/tech-foundation/technologydatabase_20240728195805.json @@ -0,0 +1,76 @@ +{ + "type": "Technology_database", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "ClickHouse/ClickHouse", + "value": "4941.99", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "apache/doris", + "value": "4307.26", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "elastic/elasticsearch", + "value": "3729.39", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "cockroachdb/cockroach", + "value": "3443.7", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "StarRocks/starrocks", + "value": "3194.56", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "trinodb/trino", + "value": "2703.4", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "apache/spark", + "value": "2654.02", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "pingcap/tidb", + "value": "2200.38", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "milvus-io/milvus", + "value": "2001.11", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "yugabyte/yugabyte-db", + "value": "1940.75", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologyfront-end_20240728172808.json b/.history/public/tech-foundation/technologyfront-end_20240728172808.json new file mode 100644 index 0000000..e69de29 diff --git a/.history/public/tech-foundation/technologyfront-end_20240728173446.json b/.history/public/tech-foundation/technologyfront-end_20240728173446.json new file mode 100644 index 0000000..46296d7 --- /dev/null +++ b/.history/public/tech-foundation/technologyfront-end_20240728173446.json @@ -0,0 +1,7 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data":[ + + ] +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologyfront-end_20240728173736.json b/.history/public/tech-foundation/technologyfront-end_20240728173736.json new file mode 100644 index 0000000..d182bfb --- /dev/null +++ b/.history/public/tech-foundation/technologyfront-end_20240728173736.json @@ -0,0 +1,77 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data":[ + { + "rank": "1", + "name": "flutter/flutter", + "value": "9361.81", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "vercel/next.js", + "value": "6638.65", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "appsmithorg/appsmith", + "value": "3474.07", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "nuxt/nuxt", + "value": "3387.23", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "facebook/react-native", + "value": "3260.55", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "ant-design/ant-design", + "value": "3053.25", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "nodejs/node", + "value": "2736.37", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "angular/angular", + "value": "2273.82", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "electron/electron", + "value": "1773.31", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "denoland/deno", + "value": "1654.01", + "rankDelta": 0, + "valueDelta": 0 + } + ] + +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologyfront-end_20240728173741.json b/.history/public/tech-foundation/technologyfront-end_20240728173741.json new file mode 100644 index 0000000..b3eee58 --- /dev/null +++ b/.history/public/tech-foundation/technologyfront-end_20240728173741.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "flutter/flutter", + "value": "9361.81", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "vercel/next.js", + "value": "6638.65", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "appsmithorg/appsmith", + "value": "3474.07", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "nuxt/nuxt", + "value": "3387.23", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "facebook/react-native", + "value": "3260.55", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "ant-design/ant-design", + "value": "3053.25", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "nodejs/node", + "value": "2736.37", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "angular/angular", + "value": "2273.82", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "electron/electron", + "value": "1773.31", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "denoland/deno", + "value": "1654.01", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologyfront-end_20240728195817.json b/.history/public/tech-foundation/technologyfront-end_20240728195817.json new file mode 100644 index 0000000..88e549f --- /dev/null +++ b/.history/public/tech-foundation/technologyfront-end_20240728195817.json @@ -0,0 +1,76 @@ +{ + "type": "Technology_front-end", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "flutter/flutter", + "value": "9361.81", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "vercel/next.js", + "value": "6638.65", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "appsmithorg/appsmith", + "value": "3474.07", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "nuxt/nuxt", + "value": "3387.23", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "facebook/react-native", + "value": "3260.55", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "ant-design/ant-design", + "value": "3053.25", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "nodejs/node", + "value": "2736.37", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "angular/angular", + "value": "2273.82", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "electron/electron", + "value": "1773.31", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "denoland/deno", + "value": "1654.01", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologyos_20240728172838.json b/.history/public/tech-foundation/technologyos_20240728172838.json new file mode 100644 index 0000000..e69de29 diff --git a/.history/public/tech-foundation/technologyos_20240728173806.json b/.history/public/tech-foundation/technologyos_20240728173806.json new file mode 100644 index 0000000..3b5d996 --- /dev/null +++ b/.history/public/tech-foundation/technologyos_20240728173806.json @@ -0,0 +1,77 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data":[ + { + "rank": "1", + "name": "openharmony/docs", + "value": "3277.69", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "openharmony/arkui_ace_engine", + "value": "2818.09", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "SerenityOS/serenity", + "value": "2257.68", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "openharmony/graphic_graphic_2d", + "value": "1239.6", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "openeuler/docs", + "value": "1206.9", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "openharmony/xts_acts", + "value": "1186.06", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "openharmony/arkcompiler_ets_runtime", + "value": "961.99", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "openharmony/interface_sdk-js", + "value": "910.91", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "reactos/reactos", + "value": "745.23", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "armbian/build", + "value": "679.1", + "rankDelta": 0, + "valueDelta": 0 + } + ] + +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologyos_20240728173810.json b/.history/public/tech-foundation/technologyos_20240728173810.json new file mode 100644 index 0000000..9659408 --- /dev/null +++ b/.history/public/tech-foundation/technologyos_20240728173810.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "openharmony/docs", + "value": "3277.69", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "openharmony/arkui_ace_engine", + "value": "2818.09", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "SerenityOS/serenity", + "value": "2257.68", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "openharmony/graphic_graphic_2d", + "value": "1239.6", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "openeuler/docs", + "value": "1206.9", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "openharmony/xts_acts", + "value": "1186.06", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "openharmony/arkcompiler_ets_runtime", + "value": "961.99", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "openharmony/interface_sdk-js", + "value": "910.91", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "reactos/reactos", + "value": "745.23", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "armbian/build", + "value": "679.1", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/.history/public/tech-foundation/technologyos_20240728195829.json b/.history/public/tech-foundation/technologyos_20240728195829.json new file mode 100644 index 0000000..93a8e86 --- /dev/null +++ b/.history/public/tech-foundation/technologyos_20240728195829.json @@ -0,0 +1,76 @@ +{ + "type": "Technology_os", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "openharmony/docs", + "value": "3277.69", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "openharmony/arkui_ace_engine", + "value": "2818.09", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "SerenityOS/serenity", + "value": "2257.68", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "openharmony/graphic_graphic_2d", + "value": "1239.6", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "openeuler/docs", + "value": "1206.9", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "openharmony/xts_acts", + "value": "1186.06", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "openharmony/arkcompiler_ets_runtime", + "value": "961.99", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "openharmony/interface_sdk-js", + "value": "910.91", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "reactos/reactos", + "value": "745.23", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "armbian/build", + "value": "679.1", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/.history/public/technologycloud-native_20240728153801.json b/.history/public/technologycloud-native_20240728153801.json new file mode 100644 index 0000000..e69de29 diff --git a/.history/public/technologycloud-native_20240728154040.json b/.history/public/technologycloud-native_20240728154040.json new file mode 100644 index 0000000..fccc6d9 --- /dev/null +++ b/.history/public/technologycloud-native_20240728154040.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "grafana/grafana", + "value": "7134.37", + "rankDelta": 1, + "valueDelta": 100 + }, + { + "rank": "2", + "name": "llvm/llvm-project", + "value": "7049.62", + "rankDelta": -2, + "valueDelta": -220 + }, + { + "rank": "3", + "name": "kubernetes/kubernetes", + "value": "5374.14", + "rankDelta": 3, + "valueDelta": 300 + }, + { + "rank": "4", + "name": "ClickHouse/ClickHouse", + "value": "4941.99", + "rankDelta": -4, + "valueDelta": 400 + }, + { + "rank": "5", + "name": "cilium/cilium", + "value": "3215.42", + "rankDelta": 5, + "valueDelta": -500 + }, + { + "rank": "6", + "name": "ceph/ceph", + "value": "3172.49", + "rankDelta": -6, + "valueDelta": 600 + }, + { + "rank": "7", + "name": "keycloak/keycloak", + "value": "3095.56", + "rankDelta": 7, + "valueDelta": 700 + }, + { + "rank": "8", + "name": "gravitational/teleport", + "value": "3082.18", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "envoyproxy/envoy", + "value": "2929.08", + "rankDelta": 9, + "valueDelta": -900 + }, + { + "rank": "10", + "name": "backstage/backstage", + "value": "2903.39", + "rankDelta": 10, + "valueDelta": 100 + } + ] + } \ No newline at end of file diff --git a/.history/public/technologycloud-native_20240728154042.json b/.history/public/technologycloud-native_20240728154042.json new file mode 100644 index 0000000..fccc6d9 --- /dev/null +++ b/.history/public/technologycloud-native_20240728154042.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "grafana/grafana", + "value": "7134.37", + "rankDelta": 1, + "valueDelta": 100 + }, + { + "rank": "2", + "name": "llvm/llvm-project", + "value": "7049.62", + "rankDelta": -2, + "valueDelta": -220 + }, + { + "rank": "3", + "name": "kubernetes/kubernetes", + "value": "5374.14", + "rankDelta": 3, + "valueDelta": 300 + }, + { + "rank": "4", + "name": "ClickHouse/ClickHouse", + "value": "4941.99", + "rankDelta": -4, + "valueDelta": 400 + }, + { + "rank": "5", + "name": "cilium/cilium", + "value": "3215.42", + "rankDelta": 5, + "valueDelta": -500 + }, + { + "rank": "6", + "name": "ceph/ceph", + "value": "3172.49", + "rankDelta": -6, + "valueDelta": 600 + }, + { + "rank": "7", + "name": "keycloak/keycloak", + "value": "3095.56", + "rankDelta": 7, + "valueDelta": 700 + }, + { + "rank": "8", + "name": "gravitational/teleport", + "value": "3082.18", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "envoyproxy/envoy", + "value": "2929.08", + "rankDelta": 9, + "valueDelta": -900 + }, + { + "rank": "10", + "name": "backstage/backstage", + "value": "2903.39", + "rankDelta": 10, + "valueDelta": 100 + } + ] + } \ No newline at end of file diff --git a/.history/src/components/data_20240728143018.js b/.history/src/components/data_20240728143018.js new file mode 100644 index 0000000..e69de29 diff --git a/.history/src/components/data_20240728171418.js b/.history/src/components/data_20240728171418.js new file mode 100644 index 0000000..99d263b --- /dev/null +++ b/.history/src/components/data_20240728171418.js @@ -0,0 +1,218 @@ +export const foundationChineseData = [ + { + rank: '1', + name: 'apache/doris', + value: '4307.26', + rankDelta: 1, + valueDelta: +100, + }, + { + rank: '2', + name: 'openharmony/docs', + value: '3277.69', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '3', + name: 'openharmony/arkui_ace_engine', + value: '2818.09', + rankDelta: -1, + valueDelta: -3, + }, + { + rank: '4', + name: 'milvus-io/milvus', + value: '2001.11', + rankDelta: 3, + valueDelta: -100, + }, + { + rank: '5', + name: 'apache/flink', + value: '1816.72', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '6', + name: 'apache/shardingsphere', + value: '1662.8', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '7', + name: 'apache/ozone', + value: '1281.57', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '8', + name: 'apache/iotdb', + value: '1265.72', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'openharmony/graphic_graphic_2d', + value: '1239.6', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '10', + name: 'apache/pulsar', + value: '1227.93', + rankDelta: 0, + valueDelta: 0, + }, + ] + + export const foundationGlobalData = [ + { + rank: '1', + name: 'kubernetes/kubernetes', + value: '5374.14', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '2', + name: 'apache/doris', + value: '4307.26', + rankDelta: 2, + valueDelta: 3, + }, + { + rank: '3', + name: 'apache/airflow', + value: '3642.9', + rankDelta: -1, + valueDelta: -3, + }, + { + rank: '4', + name: 'openharmony/docs', + value: '3277.69', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '5', + name: 'openharmony/arkui_ace_engine', + value: '2818.09', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '6', + name: 'nodejs/node', + value: '2736.37', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '7', + name: 'apache/spark', + value: '2654.02', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '8', + name: 'apache/arrow', + value: '2219.95', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'apache/beam', + value: '2188.52', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '10', + name: 'apache/hudi', + value: '2124.67', + rankDelta: 0, + valueDelta: 0, + }, + ] + + export const cloudNative = [ + { + rank: '1', + name: 'grafana/grafana', + value: '7134.37', + rankDelta: 1, + valueDelta: 100, + }, + { + rank: '2', + name: 'llvm/llvm-project', + value: '7049.62', + rankDelta: -2, + valueDelta: -220, + }, + { + rank: '3', + name: 'kubernetes/kubernetes', + value: '5374.14', + rankDelta: 3, + valueDelta: 300, + }, + { + rank: '4', + name: 'ClickHouse/ClickHouse', + value: '4941.99', + rankDelta: -4, + valueDelta: 400, + }, + { + rank: '5', + name: 'cilium/cilium', + value: '3215.42', + rankDelta: 5, + valueDelta: -500, + }, + { + rank: '6', + name: 'ceph/ceph', + value: '3172.49', + rankDelta: -6, + valueDelta: 600, + }, + { + rank: '7', + name: 'keycloak/keycloak', + value: '3095.56', + rankDelta: 7, + valueDelta: 700, + }, + { + rank: '8', + name: 'gravitational/teleport', + value: '3082.18', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'envoyproxy/envoy', + value: '2929.08', + rankDelta: 9, + valueDelta: -900, + }, + { + rank: '10', + name: 'backstage/backstage', + value: '2903.39', + rankDelta: 10, + valueDelta: 100, + }, + ] \ No newline at end of file diff --git a/.history/src/components/table_20240727221129.js b/.history/src/components/table_20240727221129.js new file mode 100644 index 0000000..2c4f26f --- /dev/null +++ b/.history/src/components/table_20240727221129.js @@ -0,0 +1,1319 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + let data = new Array(); + url = 'https://github.com/xiaoAugenstern/open-leadboard-data/blob/main/foundation.json' + // 预处理数据,对新上榜单数据进行特殊标记处理 + + data = data.data; + let dataSource = []; + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } else if (object == 'foundation' && region == 'global') { + let data = new Array(); + // 预处理数据,对新上榜单数据进行特殊标记处理 + data = { + type: 'Foundation_China', + time: '2024', + data: [ + { + rank: '1', + name: 'kubernetes/kubernetes', + value: '5374.14', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '2', + name: 'apache/doris', + value: '4307.26', + rankDelta: 2, + valueDelta: 3, + }, + { + rank: '3', + name: 'apache/airflow', + value: '3642.9', + rankDelta: -1, + valueDelta: -3, + }, + { + rank: '4', + name: 'openharmony/docs', + value: '3277.69', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '5', + name: 'openharmony/arkui_ace_engine', + value: '2818.09', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '6', + name: 'nodejs/node', + value: '2736.37', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '7', + name: 'apache/spark', + value: '2654.02', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '8', + name: 'apache/arrow', + value: '2219.95', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'apache/beam', + value: '2188.52', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '10', + name: 'apache/hudi', + value: '2124.67', + rankDelta: 0, + valueDelta: 0, + }, + ], + }; + data = data.data; + let dataSource = []; + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } else if (object == 'technology' && category == 'cloud-native') { + let data = new Array(); + // 预处理数据,对新上榜单数据进行特殊标记处理 + data = { + type: 'Foundation_China', + time: '2024', + data: [ + { + rank: '1', + name: 'grafana/grafana', + value: '7134.37', + rankDelta: 1, + valueDelta: 100, + }, + { + rank: '2', + name: 'llvm/llvm-project', + value: '7049.62', + rankDelta: -2, + valueDelta: -220, + }, + { + rank: '3', + name: 'kubernetes/kubernetes', + value: '5374.14', + rankDelta: 3, + valueDelta: 300, + }, + { + rank: '4', + name: 'ClickHouse/ClickHouse', + value: '4941.99', + rankDelta: -4, + valueDelta: 400, + }, + { + rank: '5', + name: 'cilium/cilium', + value: '3215.42', + rankDelta: 5, + valueDelta: -500, + }, + { + rank: '6', + name: 'ceph/ceph', + value: '3172.49', + rankDelta: -6, + valueDelta: 600, + }, + { + rank: '7', + name: 'keycloak/keycloak', + value: '3095.56', + rankDelta: 7, + valueDelta: 700, + }, + { + rank: '8', + name: 'gravitational/teleport', + value: '3082.18', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'envoyproxy/envoy', + value: '2929.08', + rankDelta: 9, + valueDelta: -900, + }, + { + rank: '10', + name: 'backstage/backstage', + value: '2903.39', + rankDelta: 10, + valueDelta: 100, + }, + ], + }; + data = data.data; + let dataSource = []; + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } else if (object == 'technology' && category == 'ai') { + let data = new Array(); + // 预处理数据,对新上榜单数据进行特殊标记处理 + data = { + type: 'Foundation_China', + time: '2024', + data: [ + { + rank: '1', + name: 'pytorch/pytorch', + value: '10182.45', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '2', + name: 'langchain-ai/langchain', + value: '6080.25', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '3', + name: 'PaddlePaddle/Paddle', + value: '5408.62', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '4', + name: 'huggingface/transformers', + value: '4422.84', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '5', + name: 'AUTOMATIC1111/stable-diffusion-webui', + value: '3881.6', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '6', + name: 'openvinotoolkit/openvino', + value: '3857.31', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '7', + name: 'microsoft/onnxruntime', + value: '3006.75', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '8', + name: 'tensorflow/tensorflow', + value: '2723.26', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'Significant-Gravitas/AutoGPT', + value: '2664.85', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '10', + name: 'ggerganov/llama.cpp', + value: '2339.8', + rankDelta: 0, + valueDelta: 0, + }, + ], + }; + data = data.data; + let dataSource = []; + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } else if (object == 'technology' && category == 'big-data') { + let data = new Array(); + // 预处理数据,对新上榜单数据进行特殊标记处理 + data = { + type: 'Foundation_China', + time: '2024', + data: [ + { + rank: '1', + name: 'elastic/kibana', + value: '7601.04', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '2', + name: 'grafana/grafana', + value: '7134.37', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '3', + name: 'ClickHouse/ClickHouse', + value: '4941.99', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '4', + name: 'airbytehq/airbyte', + value: '4658.86', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '5', + name: 'apache/doris', + value: '4307.26', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '6', + name: 'elastic/elasticsearch', + value: '3729.39', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '7', + name: 'apache/airflow', + value: '3642.9', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '8', + name: 'StarRocks/starrocks', + value: '3194.56', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'trinodb/trino', + value: '2703.4', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '10', + name: 'apache/spark', + value: '2654.02', + rankDelta: 0, + valueDelta: 0, + }, + ], + }; + data = data.data; + let dataSource = []; + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } else if (object == 'technology' && category == 'database') { + let data = new Array(); + // 预处理数据,对新上榜单数据进行特殊标记处理 + data = { + type: 'Foundation_China', + time: '2024', + data: [ + { + rank: '1', + name: 'ClickHouse/ClickHouse', + value: '4941.99', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '2', + name: 'apache/doris', + value: '4307.26', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '3', + name: 'elastic/elasticsearch', + value: '3729.39', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '4', + name: 'cockroachdb/cockroach', + value: '3443.7', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '5', + name: 'StarRocks/starrocks', + value: '3194.56', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '6', + name: 'trinodb/trino', + value: '2703.4', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '7', + name: 'apache/spark', + value: '2654.02', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '8', + name: 'pingcap/tidb', + value: '2200.38', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'milvus-io/milvus', + value: '2001.11', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '10', + name: 'yugabyte/yugabyte-db', + value: '1940.75', + rankDelta: 0, + valueDelta: 0, + }, + ], + }; + data = data.data; + let dataSource = []; + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } else if (object == 'technology' && category == 'front-end') { + let data = new Array(); + // 预处理数据,对新上榜单数据进行特殊标记处理 + data = { + type: 'Foundation_China', + time: '2024', + data: [ + { + rank: '1', + name: 'flutter/flutter', + value: '9361.81', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '2', + name: 'vercel/next.js', + value: '6638.65', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '3', + name: 'appsmithorg/appsmith', + value: '3474.07', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '4', + name: 'nuxt/nuxt', + value: '3387.23', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '5', + name: 'facebook/react-native', + value: '3260.55', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '6', + name: 'ant-design/ant-design', + value: '3053.25', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '7', + name: 'nodejs/node', + value: '2736.37', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '8', + name: 'angular/angular', + value: '2273.82', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'electron/electron', + value: '1773.31', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '10', + name: 'denoland/deno', + value: '1654.01', + rankDelta: 0, + valueDelta: 0, + }, + ], + }; + data = data.data; + let dataSource = []; + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } else if (object == 'technology' && category == 'os') { + let data = new Array(); + // 预处理数据,对新上榜单数据进行特殊标记处理 + data = { + type: 'Foundation_China', + time: '2024', + data: [ + { + rank: '1', + name: 'openharmony/docs', + value: '3277.69', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '2', + name: 'openharmony/arkui_ace_engine', + value: '2818.09', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '3', + name: 'SerenityOS/serenity', + value: '2257.68', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '4', + name: 'openharmony/graphic_graphic_2d', + value: '1239.6', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '5', + name: 'openeuler/docs', + value: '1206.9', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '6', + name: 'openharmony/xts_acts', + value: '1186.06', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '7', + name: 'openharmony/arkcompiler_ets_runtime', + value: '961.99', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '8', + name: 'openharmony/interface_sdk-js', + value: '910.91', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'reactos/reactos', + value: '745.23', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '10', + name: 'armbian/build', + value: '679.1', + rankDelta: 0, + valueDelta: 0, + }, + ], + }; + data = data.data; + let dataSource = []; + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } else { + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + + record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727221246.js b/.history/src/components/table_20240727221246.js new file mode 100644 index 0000000..6728cfe --- /dev/null +++ b/.history/src/components/table_20240727221246.js @@ -0,0 +1,1297 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + let data = new Array(); + url = 'https://github.com/xiaoAugenstern/open-leadboard-data/blob/main/foundation.json' + // 预处理数据,对新上榜单数据进行特殊标记处理 + + } else if (object == 'foundation' && region == 'global') { + let data = new Array(); + // 预处理数据,对新上榜单数据进行特殊标记处理 + data = { + type: 'Foundation_China', + time: '2024', + data: [ + { + rank: '1', + name: 'kubernetes/kubernetes', + value: '5374.14', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '2', + name: 'apache/doris', + value: '4307.26', + rankDelta: 2, + valueDelta: 3, + }, + { + rank: '3', + name: 'apache/airflow', + value: '3642.9', + rankDelta: -1, + valueDelta: -3, + }, + { + rank: '4', + name: 'openharmony/docs', + value: '3277.69', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '5', + name: 'openharmony/arkui_ace_engine', + value: '2818.09', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '6', + name: 'nodejs/node', + value: '2736.37', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '7', + name: 'apache/spark', + value: '2654.02', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '8', + name: 'apache/arrow', + value: '2219.95', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'apache/beam', + value: '2188.52', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '10', + name: 'apache/hudi', + value: '2124.67', + rankDelta: 0, + valueDelta: 0, + }, + ], + }; + data = data.data; + let dataSource = []; + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } else if (object == 'technology' && category == 'cloud-native') { + let data = new Array(); + // 预处理数据,对新上榜单数据进行特殊标记处理 + data = { + type: 'Foundation_China', + time: '2024', + data: [ + { + rank: '1', + name: 'grafana/grafana', + value: '7134.37', + rankDelta: 1, + valueDelta: 100, + }, + { + rank: '2', + name: 'llvm/llvm-project', + value: '7049.62', + rankDelta: -2, + valueDelta: -220, + }, + { + rank: '3', + name: 'kubernetes/kubernetes', + value: '5374.14', + rankDelta: 3, + valueDelta: 300, + }, + { + rank: '4', + name: 'ClickHouse/ClickHouse', + value: '4941.99', + rankDelta: -4, + valueDelta: 400, + }, + { + rank: '5', + name: 'cilium/cilium', + value: '3215.42', + rankDelta: 5, + valueDelta: -500, + }, + { + rank: '6', + name: 'ceph/ceph', + value: '3172.49', + rankDelta: -6, + valueDelta: 600, + }, + { + rank: '7', + name: 'keycloak/keycloak', + value: '3095.56', + rankDelta: 7, + valueDelta: 700, + }, + { + rank: '8', + name: 'gravitational/teleport', + value: '3082.18', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'envoyproxy/envoy', + value: '2929.08', + rankDelta: 9, + valueDelta: -900, + }, + { + rank: '10', + name: 'backstage/backstage', + value: '2903.39', + rankDelta: 10, + valueDelta: 100, + }, + ], + }; + data = data.data; + let dataSource = []; + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } else if (object == 'technology' && category == 'ai') { + let data = new Array(); + // 预处理数据,对新上榜单数据进行特殊标记处理 + data = { + type: 'Foundation_China', + time: '2024', + data: [ + { + rank: '1', + name: 'pytorch/pytorch', + value: '10182.45', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '2', + name: 'langchain-ai/langchain', + value: '6080.25', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '3', + name: 'PaddlePaddle/Paddle', + value: '5408.62', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '4', + name: 'huggingface/transformers', + value: '4422.84', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '5', + name: 'AUTOMATIC1111/stable-diffusion-webui', + value: '3881.6', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '6', + name: 'openvinotoolkit/openvino', + value: '3857.31', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '7', + name: 'microsoft/onnxruntime', + value: '3006.75', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '8', + name: 'tensorflow/tensorflow', + value: '2723.26', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'Significant-Gravitas/AutoGPT', + value: '2664.85', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '10', + name: 'ggerganov/llama.cpp', + value: '2339.8', + rankDelta: 0, + valueDelta: 0, + }, + ], + }; + data = data.data; + let dataSource = []; + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } else if (object == 'technology' && category == 'big-data') { + let data = new Array(); + // 预处理数据,对新上榜单数据进行特殊标记处理 + data = { + type: 'Foundation_China', + time: '2024', + data: [ + { + rank: '1', + name: 'elastic/kibana', + value: '7601.04', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '2', + name: 'grafana/grafana', + value: '7134.37', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '3', + name: 'ClickHouse/ClickHouse', + value: '4941.99', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '4', + name: 'airbytehq/airbyte', + value: '4658.86', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '5', + name: 'apache/doris', + value: '4307.26', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '6', + name: 'elastic/elasticsearch', + value: '3729.39', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '7', + name: 'apache/airflow', + value: '3642.9', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '8', + name: 'StarRocks/starrocks', + value: '3194.56', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'trinodb/trino', + value: '2703.4', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '10', + name: 'apache/spark', + value: '2654.02', + rankDelta: 0, + valueDelta: 0, + }, + ], + }; + data = data.data; + let dataSource = []; + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } else if (object == 'technology' && category == 'database') { + let data = new Array(); + // 预处理数据,对新上榜单数据进行特殊标记处理 + data = { + type: 'Foundation_China', + time: '2024', + data: [ + { + rank: '1', + name: 'ClickHouse/ClickHouse', + value: '4941.99', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '2', + name: 'apache/doris', + value: '4307.26', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '3', + name: 'elastic/elasticsearch', + value: '3729.39', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '4', + name: 'cockroachdb/cockroach', + value: '3443.7', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '5', + name: 'StarRocks/starrocks', + value: '3194.56', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '6', + name: 'trinodb/trino', + value: '2703.4', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '7', + name: 'apache/spark', + value: '2654.02', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '8', + name: 'pingcap/tidb', + value: '2200.38', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'milvus-io/milvus', + value: '2001.11', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '10', + name: 'yugabyte/yugabyte-db', + value: '1940.75', + rankDelta: 0, + valueDelta: 0, + }, + ], + }; + data = data.data; + let dataSource = []; + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } else if (object == 'technology' && category == 'front-end') { + let data = new Array(); + // 预处理数据,对新上榜单数据进行特殊标记处理 + data = { + type: 'Foundation_China', + time: '2024', + data: [ + { + rank: '1', + name: 'flutter/flutter', + value: '9361.81', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '2', + name: 'vercel/next.js', + value: '6638.65', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '3', + name: 'appsmithorg/appsmith', + value: '3474.07', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '4', + name: 'nuxt/nuxt', + value: '3387.23', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '5', + name: 'facebook/react-native', + value: '3260.55', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '6', + name: 'ant-design/ant-design', + value: '3053.25', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '7', + name: 'nodejs/node', + value: '2736.37', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '8', + name: 'angular/angular', + value: '2273.82', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'electron/electron', + value: '1773.31', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '10', + name: 'denoland/deno', + value: '1654.01', + rankDelta: 0, + valueDelta: 0, + }, + ], + }; + data = data.data; + let dataSource = []; + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } else if (object == 'technology' && category == 'os') { + let data = new Array(); + // 预处理数据,对新上榜单数据进行特殊标记处理 + data = { + type: 'Foundation_China', + time: '2024', + data: [ + { + rank: '1', + name: 'openharmony/docs', + value: '3277.69', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '2', + name: 'openharmony/arkui_ace_engine', + value: '2818.09', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '3', + name: 'SerenityOS/serenity', + value: '2257.68', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '4', + name: 'openharmony/graphic_graphic_2d', + value: '1239.6', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '5', + name: 'openeuler/docs', + value: '1206.9', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '6', + name: 'openharmony/xts_acts', + value: '1186.06', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '7', + name: 'openharmony/arkcompiler_ets_runtime', + value: '961.99', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '8', + name: 'openharmony/interface_sdk-js', + value: '910.91', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'reactos/reactos', + value: '745.23', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '10', + name: 'armbian/build', + value: '679.1', + rankDelta: 0, + valueDelta: 0, + }, + ], + }; + data = data.data; + let dataSource = []; + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727224142.js b/.history/src/components/table_20240727224142.js new file mode 100644 index 0000000..df163be --- /dev/null +++ b/.history/src/components/table_20240727224142.js @@ -0,0 +1,653 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + url = 'https://github.com/xiaoAugenstern/open-leadboard-data/blob/main/foundation.json' + fetch(url, { + method: 'post', // 如果是get方式的话,只能把参数拼接在url里传过去,get方式不能有body + "Access-Control-Allow-Origin" : "*", + "Access-Control-Allow-Credentials" : true, + headers: { + 'Content-Type': 'application/json' + },}) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727224145.js b/.history/src/components/table_20240727224145.js new file mode 100644 index 0000000..df163be --- /dev/null +++ b/.history/src/components/table_20240727224145.js @@ -0,0 +1,653 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + url = 'https://github.com/xiaoAugenstern/open-leadboard-data/blob/main/foundation.json' + fetch(url, { + method: 'post', // 如果是get方式的话,只能把参数拼接在url里传过去,get方式不能有body + "Access-Control-Allow-Origin" : "*", + "Access-Control-Allow-Credentials" : true, + headers: { + 'Content-Type': 'application/json' + },}) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727224820.js b/.history/src/components/table_20240727224820.js new file mode 100644 index 0000000..57eb0fa --- /dev/null +++ b/.history/src/components/table_20240727224820.js @@ -0,0 +1,651 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + url = 'https://github.com/xiaoAugenstern/open-leadboard-data/blob/main/foundation.json' + fetch(url, { + "Access-Control-Allow-Origin" : "*", + "Access-Control-Allow-Credentials" : true, + mode: 'cors', + }) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727225058.js b/.history/src/components/table_20240727225058.js new file mode 100644 index 0000000..bbc6406 --- /dev/null +++ b/.history/src/components/table_20240727225058.js @@ -0,0 +1,651 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + url = 'https://github.com/xiaoAugenstern/open-leadboard-data/blob/main/foundation.json' + fetch(url, { + "Access-Control-Allow-Origin" : "*", + "Access-Control-Allow-Credentials" : true, + mode: "no-cors", + }) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727225519.js b/.history/src/components/table_20240727225519.js new file mode 100644 index 0000000..ec95856 --- /dev/null +++ b/.history/src/components/table_20240727225519.js @@ -0,0 +1,651 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + url = 'https://github.com/xiaoAugenstern/open-leadboard-data/blob/main/foundation.json' + fetch(url, { + "Access-Control-Allow-Origin" : "*", + "Access-Control-Allow-Credentials" : true, + mode: "cors", + }) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727230659.js b/.history/src/components/table_20240727230659.js new file mode 100644 index 0000000..74e7f63 --- /dev/null +++ b/.history/src/components/table_20240727230659.js @@ -0,0 +1,652 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + url = 'https://github.com/xiaoAugenstern/open-leadboard-data/blob/main/foundation.json' + fetch(url, { + method: 'GET', + "Access-Control-Allow-Origin" : "*", + "Access-Control-Allow-Credentials" : true, + mode: "cors", + }) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727230905.js b/.history/src/components/table_20240727230905.js new file mode 100644 index 0000000..aac4c4d --- /dev/null +++ b/.history/src/components/table_20240727230905.js @@ -0,0 +1,653 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + url = 'https://github.com/xiaoAugenstern/open-leadboard-data/blob/main/foundation.json' + fetch(url, { + method: 'GET', + "Access-Control-Allow-Origin" : "*", + "Access-Control-Allow-Credentials" : true, + "Access-Control-Allow-Methods":"POST, GET, OPTIONS, DELETE, HEAD", + mode: "cors", + }) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727230907.js b/.history/src/components/table_20240727230907.js new file mode 100644 index 0000000..aac4c4d --- /dev/null +++ b/.history/src/components/table_20240727230907.js @@ -0,0 +1,653 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + url = 'https://github.com/xiaoAugenstern/open-leadboard-data/blob/main/foundation.json' + fetch(url, { + method: 'GET', + "Access-Control-Allow-Origin" : "*", + "Access-Control-Allow-Credentials" : true, + "Access-Control-Allow-Methods":"POST, GET, OPTIONS, DELETE, HEAD", + mode: "cors", + }) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727230943.js b/.history/src/components/table_20240727230943.js new file mode 100644 index 0000000..2914bd4 --- /dev/null +++ b/.history/src/components/table_20240727230943.js @@ -0,0 +1,653 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + url = 'https://github.com/xiaoAugenstern/open-leadboard-data/blob/main/foundation.json' + fetch(url, { + method: 'GET', + "Access-Control-Allow-Origin" : "*", + "Access-Control-Allow-Credentials" : true, + "Access-Control-Allow-Methods":"POST, GET, OPTIONS, DELETE, HEAD", + mode: "no-cors", + }) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727231007.js b/.history/src/components/table_20240727231007.js new file mode 100644 index 0000000..aac4c4d --- /dev/null +++ b/.history/src/components/table_20240727231007.js @@ -0,0 +1,653 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + url = 'https://github.com/xiaoAugenstern/open-leadboard-data/blob/main/foundation.json' + fetch(url, { + method: 'GET', + "Access-Control-Allow-Origin" : "*", + "Access-Control-Allow-Credentials" : true, + "Access-Control-Allow-Methods":"POST, GET, OPTIONS, DELETE, HEAD", + mode: "cors", + }) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727231113.js b/.history/src/components/table_20240727231113.js new file mode 100644 index 0000000..17eb9f8 --- /dev/null +++ b/.history/src/components/table_20240727231113.js @@ -0,0 +1,653 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + url = 'https://oss.x-lab.info/open_leaderboard/open_rank/repo/chinese/20246.json' + fetch(url, { + method: 'GET', + "Access-Control-Allow-Origin" : "*", + "Access-Control-Allow-Credentials" : true, + "Access-Control-Allow-Methods":"POST, GET, OPTIONS, DELETE, HEAD", + mode: "cors", + }) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727231156.js b/.history/src/components/table_20240727231156.js new file mode 100644 index 0000000..ee8e5c0 --- /dev/null +++ b/.history/src/components/table_20240727231156.js @@ -0,0 +1,589 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + url = 'https://oss.x-lab.info/open_leaderboard/open_rank/repo/chinese/20246.json' + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + } + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727231303.js b/.history/src/components/table_20240727231303.js new file mode 100644 index 0000000..1762022 --- /dev/null +++ b/.history/src/components/table_20240727231303.js @@ -0,0 +1,589 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + url = 'https://oss.x-lab.info/open_leaderboard/open_rank/repo/chinese/20246.json' + } + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727231305.js b/.history/src/components/table_20240727231305.js new file mode 100644 index 0000000..1762022 --- /dev/null +++ b/.history/src/components/table_20240727231305.js @@ -0,0 +1,589 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + url = 'https://oss.x-lab.info/open_leaderboard/open_rank/repo/chinese/20246.json' + } + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727231408.js b/.history/src/components/table_20240727231408.js new file mode 100644 index 0000000..29bc824 --- /dev/null +++ b/.history/src/components/table_20240727231408.js @@ -0,0 +1,589 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' || category != null) { + url = 'https://oss.x-lab.info/open_leaderboard/open_rank/repo/chinese/20246.json' + } + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727231449.js b/.history/src/components/table_20240727231449.js new file mode 100644 index 0000000..3e535ee --- /dev/null +++ b/.history/src/components/table_20240727231449.js @@ -0,0 +1,589 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' || category != '') { + url = 'https://oss.x-lab.info/open_leaderboard/open_rank/repo/chinese/20246.json' + } + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240727231623.js b/.history/src/components/table_20240727231623.js new file mode 100644 index 0000000..ed7a8b5 --- /dev/null +++ b/.history/src/components/table_20240727231623.js @@ -0,0 +1,589 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' || object == 'technology') { + url = 'https://oss.x-lab.info/open_leaderboard/open_rank/repo/chinese/20246.json' + } + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728144201.js b/.history/src/components/table_20240728144201.js new file mode 100644 index 0000000..f38476e --- /dev/null +++ b/.history/src/components/table_20240728144201.js @@ -0,0 +1,601 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' || region == 'chinese') { + dataSource = foundationChineseData; + + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728144210.js b/.history/src/components/table_20240728144210.js new file mode 100644 index 0000000..f69ea81 --- /dev/null +++ b/.history/src/components/table_20240728144210.js @@ -0,0 +1,601 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + dataSource = foundationChineseData; + + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728144254.js b/.history/src/components/table_20240728144254.js new file mode 100644 index 0000000..f69ea81 --- /dev/null +++ b/.history/src/components/table_20240728144254.js @@ -0,0 +1,601 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == 'foundation' && region == 'chinese') { + dataSource = foundationChineseData; + + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728144348.js b/.history/src/components/table_20240728144348.js new file mode 100644 index 0000000..d1449bc --- /dev/null +++ b/.history/src/components/table_20240728144348.js @@ -0,0 +1,601 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + dataSource = foundationChineseData; + + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728144514.js b/.history/src/components/table_20240728144514.js new file mode 100644 index 0000000..9933683 --- /dev/null +++ b/.history/src/components/table_20240728144514.js @@ -0,0 +1,627 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + data = foundationChineseData; + + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728144641.js b/.history/src/components/table_20240728144641.js new file mode 100644 index 0000000..7fdb8c7 --- /dev/null +++ b/.history/src/components/table_20240728144641.js @@ -0,0 +1,615 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + dataSource = foundationChineseData; + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728144736.js b/.history/src/components/table_20240728144736.js new file mode 100644 index 0000000..0c81980 --- /dev/null +++ b/.history/src/components/table_20240728144736.js @@ -0,0 +1,601 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + dataSource = foundationChineseData; + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728150221.js b/.history/src/components/table_20240728150221.js new file mode 100644 index 0000000..260dad2 --- /dev/null +++ b/.history/src/components/table_20240728150221.js @@ -0,0 +1,627 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + useEffect(() => { + // 这里可以进行数据请求 + fetch('../lacales/foundationChinese.json') + .then(response => response.json()) + .then(data => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + }, []); + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728150719.js b/.history/src/components/table_20240728150719.js new file mode 100644 index 0000000..3b0d213 --- /dev/null +++ b/.history/src/components/table_20240728150719.js @@ -0,0 +1,627 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + onth) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + + // 这里可以进行数据请求 + fetch('../lacales/foundationChinese.json') + .then(response => response.json()) + .then(data => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728150811.js b/.history/src/components/table_20240728150811.js new file mode 100644 index 0000000..5014bce --- /dev/null +++ b/.history/src/components/table_20240728150811.js @@ -0,0 +1,627 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + + // 这里可以进行数据请求 + fetch('../lacales/foundationChinese.json') + .then(response => response.json()) + .then(data => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728150851.js b/.history/src/components/table_20240728150851.js new file mode 100644 index 0000000..e63e7a0 --- /dev/null +++ b/.history/src/components/table_20240728150851.js @@ -0,0 +1,627 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + + // 这里可以进行数据请求 + fetch('../locales/foundationChinese.json') + .then(response => response.json()) + .then(data => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728151211.js b/.history/src/components/table_20240728151211.js new file mode 100644 index 0000000..8dd2f0a --- /dev/null +++ b/.history/src/components/table_20240728151211.js @@ -0,0 +1,650 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + + // 这里可以进行数据请求 + fetch('../locales/foundationChinese.json') + ..then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728151214.js b/.history/src/components/table_20240728151214.js new file mode 100644 index 0000000..08497b8 --- /dev/null +++ b/.history/src/components/table_20240728151214.js @@ -0,0 +1,650 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + + // 这里可以进行数据请求 + fetch('../locales/foundationChinese.json') + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728151323.js b/.history/src/components/table_20240728151323.js new file mode 100644 index 0000000..9b4ad7d --- /dev/null +++ b/.history/src/components/table_20240728151323.js @@ -0,0 +1,651 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + + // 这里可以进行数据请求 + fetch('../locales/foundationChinese.json') + .then((res) => { + console.log(res); + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728151410.js b/.history/src/components/table_20240728151410.js new file mode 100644 index 0000000..2e5f393 --- /dev/null +++ b/.history/src/components/table_20240728151410.js @@ -0,0 +1,651 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + + // 这里可以进行数据请求 + fetch('../locales/foundationChinese.json') + .then((res) => { + console.log(res.json); + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728151537.js b/.history/src/components/table_20240728151537.js new file mode 100644 index 0000000..ddbedfb --- /dev/null +++ b/.history/src/components/table_20240728151537.js @@ -0,0 +1,645 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + + // 这里可以进行数据请求 + fetch('../locales/foundationChinese.json') + .then(response => {response.json() + console.log(response.json); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728152336.js b/.history/src/components/table_20240728152336.js new file mode 100644 index 0000000..7e65223 --- /dev/null +++ b/.history/src/components/table_20240728152336.js @@ -0,0 +1,645 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + + // 这里可以进行数据请求 + fetch('../foundationChinese.json') + .then(response => {response.json() + console.log(response.json); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728152433.js b/.history/src/components/table_20240728152433.js new file mode 100644 index 0000000..1d1294c --- /dev/null +++ b/.history/src/components/table_20240728152433.js @@ -0,0 +1,645 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + + // 这里可以进行数据请求 + fetch('./foundationChinese.json') + .then(response => {response.json() + console.log(response.json); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728152504.js b/.history/src/components/table_20240728152504.js new file mode 100644 index 0000000..7e7825c --- /dev/null +++ b/.history/src/components/table_20240728152504.js @@ -0,0 +1,645 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + + // 这里可以进行数据请求 + fetch('/foundationChinese.json') + .then(response => {response.json() + console.log(response.json); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728152539.js b/.history/src/components/table_20240728152539.js new file mode 100644 index 0000000..1d1294c --- /dev/null +++ b/.history/src/components/table_20240728152539.js @@ -0,0 +1,645 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + + // 这里可以进行数据请求 + fetch('./foundationChinese.json') + .then(response => {response.json() + console.log(response.json); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728152542.js b/.history/src/components/table_20240728152542.js new file mode 100644 index 0000000..1d1294c --- /dev/null +++ b/.history/src/components/table_20240728152542.js @@ -0,0 +1,645 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + + // 这里可以进行数据请求 + fetch('./foundationChinese.json') + .then(response => {response.json() + console.log(response.json); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728152647.js b/.history/src/components/table_20240728152647.js new file mode 100644 index 0000000..defa9c4 --- /dev/null +++ b/.history/src/components/table_20240728152647.js @@ -0,0 +1,650 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + + // 这里可以进行数据请求 + fetch('./foundationChinese.json') + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728153148.js b/.history/src/components/table_20240728153148.js new file mode 100644 index 0000000..fb4a8fa --- /dev/null +++ b/.history/src/components/table_20240728153148.js @@ -0,0 +1,650 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + url = './'+ object + region +'.json' + // 这里可以进行数据请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728153150.js b/.history/src/components/table_20240728153150.js new file mode 100644 index 0000000..fb4a8fa --- /dev/null +++ b/.history/src/components/table_20240728153150.js @@ -0,0 +1,650 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation" && region == 'chinese') { + url = './'+ object + region +'.json' + // 这里可以进行数据请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + } + // fetch 异步请求 + else{fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + } + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728153730.js b/.history/src/components/table_20240728153730.js new file mode 100644 index 0000000..690efe4 --- /dev/null +++ b/.history/src/components/table_20240728153730.js @@ -0,0 +1,594 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation") { + url = './'+ object + region +'.json' + } + else if (object == "technology") { + url = './'+ object + category +'.json' + } + + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728171435.js b/.history/src/components/table_20240728171435.js new file mode 100644 index 0000000..690efe4 --- /dev/null +++ b/.history/src/components/table_20240728171435.js @@ -0,0 +1,594 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation") { + url = './'+ object + region +'.json' + } + else if (object == "technology") { + url = './'+ object + category +'.json' + } + + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728173002.js b/.history/src/components/table_20240728173002.js new file mode 100644 index 0000000..0ee7e71 --- /dev/null +++ b/.history/src/components/table_20240728173002.js @@ -0,0 +1,594 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation") { + url = './tech-foundation'+ object + region +'.json' + } + else if (object == "technology") { + url = './'+ object + category +'.json' + } + + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728173032.js b/.history/src/components/table_20240728173032.js new file mode 100644 index 0000000..07e2ae2 --- /dev/null +++ b/.history/src/components/table_20240728173032.js @@ -0,0 +1,594 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation") { + url = './tech-foundation/'+ object + region +'.json' + } + else if (object == "technology") { + url = './'+ object + category +'.json' + } + + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728173107.js b/.history/src/components/table_20240728173107.js new file mode 100644 index 0000000..84ae65c --- /dev/null +++ b/.history/src/components/table_20240728173107.js @@ -0,0 +1,594 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation") { + url = './tech-foundation/'+ object + region +'.json' + } + else if (object == "technology") { + url = './tech-foundation/'+ object + category +'.json' + } + + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728173113.js b/.history/src/components/table_20240728173113.js new file mode 100644 index 0000000..24f1e5d --- /dev/null +++ b/.history/src/components/table_20240728173113.js @@ -0,0 +1,593 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation") { + url = './tech-foundation/'+ object + region +'.json' + } + else if (object == "technology") { + url = './tech-foundation/'+ object + category +'.json' + } + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728195002.js b/.history/src/components/table_20240728195002.js new file mode 100644 index 0000000..24f1e5d --- /dev/null +++ b/.history/src/components/table_20240728195002.js @@ -0,0 +1,593 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation") { + url = './tech-foundation/'+ object + region +'.json' + } + else if (object == "technology") { + url = './tech-foundation/'+ object + category +'.json' + } + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728195126.js b/.history/src/components/table_20240728195126.js new file mode 100644 index 0000000..24f1e5d --- /dev/null +++ b/.history/src/components/table_20240728195126.js @@ -0,0 +1,593 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; +import { foundationChineseData } from './data'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation") { + url = './tech-foundation/'+ object + region +'.json' + } + else if (object == "technology") { + url = './tech-foundation/'+ object + category +'.json' + } + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/components/table_20240728195614.js b/.history/src/components/table_20240728195614.js new file mode 100644 index 0000000..a4b0fc6 --- /dev/null +++ b/.history/src/components/table_20240728195614.js @@ -0,0 +1,592 @@ +import React, { useState, useEffect } from 'react'; +import { Col, message, Row, Table, Card } from 'antd'; +import MyAvatar from './avatar'; +import 'antd/dist/antd.css'; +import QAmiss from './QA2'; +import TablePanel from './TablePanel'; +import ArrowRender from './arrow'; +import PointRender from './changeNumber'; +import RoundFloat from './resolveFloat'; +import Trophy from './rankTrophy'; +import expandObject from '../util/expandObject'; +import { t } from 'i18next'; +import './table.css'; + +const activityColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '20%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'right', + width: '20%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, +]; +const activityDetailColumns = (object, t_month) => [ + { + title: t('rank'), + dataIndex: 'rank', + width: '5%', + align: 'center', + render: Trophy, + fixed: 'left', + }, + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + { + title: t(object), + dataIndex: 'name', + align: 'center', + width: '5%', + render: function (text, row, index) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + { + title: t('activity'), + dataIndex: 'value', + align: 'center', + width: '10%', + }, + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: PointRender, + }, + { + title: t('issue_comments'), + dataIndex: 'issue_comment', + width: '10%', + align: 'center', + }, + { + title: t('open_issues'), + dataIndex: 'open_issue', + width: '10%', + align: 'center', + }, + { + title: t('open_pulls'), + dataIndex: 'open_pull', + width: '10%', + align: 'center', + }, + { + title: t('merge_pulls'), + dataIndex: 'merged_pull', + width: '10%', + align: 'center', + }, + { + title: t('pr_reviews'), + dataIndex: 'review_comment', + width: '10%', + align: 'center', + }, +]; +const open_rankColumns = (object, t_month) => [ + { + // 第一列:排名 + title: t('rank'), + dataIndex: 'rank', + width: '5%', + render: Trophy, + align: 'center', + fixed: 'left', + }, + // 如果 object 是 'actor',则添加头像列 + ...(object == 'actor' + ? [ + { + title: t('avatar'), + dataIndex: 'id', + width: '5%', + align: 'center', + render: MyAvatar, + fixed: 'left', + }, + ] + : []), + // 第二列:排名变化 + { + title: '', + dataIndex: 'rankDelta', + render: ArrowRender, + align: 'left', + width: '5%', + fixed: 'left', + }, + // 第三列:对象名称(可能是 actor, repo 或 company) + { + title: t(object), + dataIndex: 'name', + width: '20%', + align: 'center', + render: function (text) { + if (object !== 'company') { + return ( + + {text} + + ); + } else { + return text; + } + }, + }, + // 如果 object 是 'repo',则添加 insight_board 列 + ...(object == 'repo' + ? [ + { + title: t('insight_board'), + dataIndex: 'name', + align: 'center', + width: '10%', + render: function (text, row, index) { + return dashboard(text, index, t_month); + }, + }, + ] + : []), + // 第四列:影响力 + { + title: t('influence'), + dataIndex: 'value', + width: '20%', + align: 'right', + render: (text, row, index) => { + return RoundFloat(text); + }, + }, + // 第五列:影响力变化 + { + title: '', + dataIndex: 'valueDelta', + width: '10%', + align: 'left', + render: (text, row, index) => { + text = RoundFloat(text); + return PointRender(text, row, index); + }, + }, +]; + +const solveDate = (year, month) => { + if (year === null && month === null) { + return 'not found'; + } + if (month === null) { + return year + '年'; + } + return year + '年' + (month + 1) + '月'; +}; + +function dashboard(text, index, t_month) { + if (index < 300) { + let [org_name, repo_name] = text.split('/'); + const t_month_copy = t_month + ' ' + '00:00:00'; + let params = { + org_name, + repo_name, + t_month_copy, + t_month, + }; + return ( + + + ); + } +} + +function DateTitle(props) { + return

{solveDate(props.year, props.month)}

; +} + +function MyTable(props) { + const [state, setState] = useState({ + object: 'technology', + index: 'open_rank', + region: 'global', + showDetail: false, + hasDetail: true, + data: [], + showSize: 25, + loading: true, + url: '', // base + index + object + region + yearmonth + .json + base: 'https://oss.x-lab.info/open_leaderboard/', + year: null, // 字符串格式 + month: null, // 整数格式,0表示1月,1表示2月..., null for year type time + type: 'month', + search: null, + category: 'cloud-native', + }); + + // 请求一次数据更新表格。如果还没读取好配置文件则不请求数据。 + useEffect(() => { + if (props.year == null && props.month == null) { + console.log('the first loading'); + return; + } + updateDate({ + year: String(props.year), + month: props.month, + }); + }, [props]); + + const expandData = () => { + setState({ + ...state, + showSize: state.showSize + 25, + }); + }; + const updateDate = (newstate) => { + console.log('table update', newstate); + // 先获取原先的表格属性 + let { + base, + object, + index, + region, + month, + year, + columns, + showDetail, + hasDetail, + type, + search, + category, + } = state; + // 然后把表格改为加载中的状态 + setState({ ...state, ...newstate, loading: true }); + // 如果 newstate 有对应的属性,则进行更新 + if (newstate.hasOwnProperty('object')) object = newstate.object; + if (newstate.hasOwnProperty('index')) index = newstate.index; + if (newstate.hasOwnProperty('region')) region = newstate.region; + if (newstate.hasOwnProperty('month')) month = newstate.month; + if (newstate.hasOwnProperty('year')) year = newstate.year; + if (newstate.hasOwnProperty('showDetail')) showDetail = newstate.showDetail; + if (newstate.hasOwnProperty('type')) type = newstate.type; + if (newstate.hasOwnProperty('search')) search = newstate.search; + if (newstate.hasOwnProperty('category')) category = newstate.category; + + //获取数据大屏的‘t_month’参数 + let myyear = newstate.year == null ? state.year : newstate.year; + let mymonth = newstate.month == null ? state.month : newstate.month; + + mymonth = ('' + (1 + mymonth)).padStart(2, '0'); + let t_month = `${myyear}-${mymonth}-01`; + + // 根据 index 和 showDetail 改变表格的 columns 格式 + if (index == 'activity') { + columns = activityColumns(object, t_month); + hasDetail = true; + } + if (index == 'activity' && showDetail == true) { + columns = activityDetailColumns(object, t_month); + hasDetail = true; + } + if (index == 'open_rank') { + columns = open_rankColumns(object, t_month); + hasDetail = false; + showDetail = false; + } + // 如果是年份数据,则把 month 置为 null。 + // TODO:待验证,如果从年份数据切换到月份数据,似乎会自动回到原来 month 值? + if (type == 'year') { + month = null; + } + // 以当前的属性构造请求 url + let url = base + index + '/' + object + '/' + region + '/'; + if (month === null) { + url += year + '.json'; + } else { + url += year + (1 + month) + '.json'; + } + console.log(url); + console.log(region); + if (object == "foundation") { + url = './tech-foundation/'+ object + region +'.json' + } + else if (object == "technology") { + url = './tech-foundation/'+ object + category +'.json' + } + // fetch 异步请求 + fetch(url) + .then((res) => { + // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, + if (res.status == 404) { + message.warning(t('no_result')); + return ''; + } + return res.json(); + }) + .then((data) => { + data = data.data; + let dataSource = []; + // 预处理数据,对新上榜单数据进行特殊标记处理 + data.map((obj) => { + obj = expandObject(obj); + if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { + obj.rankDelta = -10000000; + obj.valueDelta = 0; + } + dataSource.push(obj); + }); + console.log(dataSource); + + //搜索特定数据 + let queryData; + if (search) { + queryData = dataSource.filter((dataSource) => { + let reg = new RegExp(search.trim(), 'i'); + return reg.test(dataSource.name); + }); + if (queryData.length == 0) { + message.warning(t('no_result')); + } else { + dataSource = queryData; + } + } + + // 更新属性和表格数据 + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + showDetail: showDetail, + hasDetail: hasDetail, + data: dataSource, + }); + }) + .catch((err) => { + console.log('hi!' + err); + setState({ + ...state, + ...newstate, + loading: false, + columns: columns, + data: [], + }); + }); + + + }; + + const { + object, + index, + region, + data, + columns, + loading, + showSize, + showDetail, + hasDetail, + month, + year, + type, + category, + } = state; + return ( +
+
+ + +
record.rank} + dataSource={data.slice(0, Math.min(showSize, data.length))} + pagination={false} + loading={loading} + scroll={{ x: 'max-content' }} + /> + + + + + {showSize < data.length ? ( + + {t('showMore') + '>>'} + + ) : ( + + {t('noMore')} + + )} + + + + + + + + + + + + + + + ); +} + +export default MyTable; diff --git a/.history/src/locales/foundationChinese_20240728145456.json b/.history/src/locales/foundationChinese_20240728145456.json new file mode 100644 index 0000000..e69de29 diff --git a/.history/src/locales/foundationChinese_20240728145600.json b/.history/src/locales/foundationChinese_20240728145600.json new file mode 100644 index 0000000..8156e09 --- /dev/null +++ b/.history/src/locales/foundationChinese_20240728145600.json @@ -0,0 +1,76 @@ +{ + "type": 'Foundation_China', + "time": '2024', + "data": [ + { + rank: '1', + name: 'apache/doris', + value: '4307.26', + rankDelta: 1, + valueDelta: +100, + }, + { + rank: '2', + name: 'openharmony/docs', + value: '3277.69', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '3', + name: 'openharmony/arkui_ace_engine', + value: '2818.09', + rankDelta: -1, + valueDelta: -3, + }, + { + rank: '4', + name: 'milvus-io/milvus', + value: '2001.11', + rankDelta: 3, + valueDelta: -100, + }, + { + rank: '5', + name: 'apache/flink', + value: '1816.72', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '6', + name: 'apache/shardingsphere', + value: '1662.8', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '7', + name: 'apache/ozone', + value: '1281.57', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '8', + name: 'apache/iotdb', + value: '1265.72', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '9', + name: 'openharmony/graphic_graphic_2d', + value: '1239.6', + rankDelta: 0, + valueDelta: 0, + }, + { + rank: '10', + name: 'apache/pulsar', + value: '1227.93', + rankDelta: 0, + valueDelta: 0, + }, + ], + } \ No newline at end of file diff --git a/.history/src/locales/foundationChinese_20240728145848.json b/.history/src/locales/foundationChinese_20240728145848.json new file mode 100644 index 0000000..ce7dab2 --- /dev/null +++ b/.history/src/locales/foundationChinese_20240728145848.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "apache/doris", + "value": "4307.26", + "rankDelta": 1, + "valueDelta": 100 + }, + { + "rank": "2", + "name": "openharmony/docs", + "value": "3277.69", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "openharmony/arkui_ace_engine", + "value": "2818.09", + "rankDelta": -1, + "valueDelta": -3 + }, + { + "rank": "4", + "name": "milvus-io/milvus", + "value": "2001.11", + "rankDelta": 3, + "valueDelta": -100 + }, + { + "rank": "5", + "name": "apache/flink", + "value": "1816.72", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "apache/shardingsphere", + "value": "1662.8", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "apache/ozone", + "value": "1281.57", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "apache/iotdb", + "value": "1265.72", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "openharmony/graphic_graphic_2d", + "value": "1239.6", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "apache/pulsar", + "value": "1227.93", + "rankDelta": 0, + "valueDelta": 0 + } + ] + } \ No newline at end of file diff --git a/public/tech-foundation/foundationchinese.json b/public/tech-foundation/foundationchinese.json new file mode 100644 index 0000000..ce7dab2 --- /dev/null +++ b/public/tech-foundation/foundationchinese.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_China", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "apache/doris", + "value": "4307.26", + "rankDelta": 1, + "valueDelta": 100 + }, + { + "rank": "2", + "name": "openharmony/docs", + "value": "3277.69", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "openharmony/arkui_ace_engine", + "value": "2818.09", + "rankDelta": -1, + "valueDelta": -3 + }, + { + "rank": "4", + "name": "milvus-io/milvus", + "value": "2001.11", + "rankDelta": 3, + "valueDelta": -100 + }, + { + "rank": "5", + "name": "apache/flink", + "value": "1816.72", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "apache/shardingsphere", + "value": "1662.8", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "apache/ozone", + "value": "1281.57", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "apache/iotdb", + "value": "1265.72", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "openharmony/graphic_graphic_2d", + "value": "1239.6", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "apache/pulsar", + "value": "1227.93", + "rankDelta": 0, + "valueDelta": 0 + } + ] + } \ No newline at end of file diff --git a/public/tech-foundation/foundationglobal.json b/public/tech-foundation/foundationglobal.json new file mode 100644 index 0000000..1b2502b --- /dev/null +++ b/public/tech-foundation/foundationglobal.json @@ -0,0 +1,76 @@ +{ + "type": "Foundation_Global", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "kubernetes/kubernetes", + "value": "5374.14", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "apache/doris", + "value": "4307.26", + "rankDelta": 2, + "valueDelta": 3 + }, + { + "rank": "3", + "name": "apache/airflow", + "value": "3642.9", + "rankDelta": -1, + "valueDelta": -3 + }, + { + "rank": "4", + "name": "openharmony/docs", + "value": "3277.69", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "openharmony/arkui_ace_engine", + "value": "2818.09", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "nodejs/node", + "value": "2736.37", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "apache/spark", + "value": "2654.02", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "apache/arrow", + "value": "2219.95", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "apache/beam", + "value": "2188.52", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "apache/hudi", + "value": "2124.67", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/public/tech-foundation/technologyai.json b/public/tech-foundation/technologyai.json new file mode 100644 index 0000000..5b5d101 --- /dev/null +++ b/public/tech-foundation/technologyai.json @@ -0,0 +1,76 @@ +{ + "type": "Technology_ai", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "pytorch/pytorch", + "value": "10182.45", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "langchain-ai/langchain", + "value": "6080.25", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "PaddlePaddle/Paddle", + "value": "5408.62", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "huggingface/transformers", + "value": "4422.84", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "AUTOMATIC1111/stable-diffusion-webui", + "value": "3881.6", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "openvinotoolkit/openvino", + "value": "3857.31", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "microsoft/onnxruntime", + "value": "3006.75", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "tensorflow/tensorflow", + "value": "2723.26", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "Significant-Gravitas/AutoGPT", + "value": "2664.85", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "ggerganov/llama.cpp", + "value": "2339.8", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/public/tech-foundation/technologybig-data.json b/public/tech-foundation/technologybig-data.json new file mode 100644 index 0000000..08dd4a7 --- /dev/null +++ b/public/tech-foundation/technologybig-data.json @@ -0,0 +1,76 @@ +{ + "type": "Technology_big-data", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "elastic/kibana", + "value": "7601.04", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "grafana/grafana", + "value": "7134.37", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "ClickHouse/ClickHouse", + "value": "4941.99", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "airbytehq/airbyte", + "value": "4658.86", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "apache/doris", + "value": "4307.26", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "elastic/elasticsearch", + "value": "3729.39", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "apache/airflow", + "value": "3642.9", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "StarRocks/starrocks", + "value": "3194.56", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "trinodb/trino", + "value": "2703.4", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "apache/spark", + "value": "2654.02", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/public/tech-foundation/technologycloud-native.json b/public/tech-foundation/technologycloud-native.json new file mode 100644 index 0000000..c6d4351 --- /dev/null +++ b/public/tech-foundation/technologycloud-native.json @@ -0,0 +1,76 @@ +{ + "type": "Technology_cloud-native", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "grafana/grafana", + "value": "7134.37", + "rankDelta": 1, + "valueDelta": 100 + }, + { + "rank": "2", + "name": "llvm/llvm-project", + "value": "7049.62", + "rankDelta": -2, + "valueDelta": -220 + }, + { + "rank": "3", + "name": "kubernetes/kubernetes", + "value": "5374.14", + "rankDelta": 3, + "valueDelta": 300 + }, + { + "rank": "4", + "name": "ClickHouse/ClickHouse", + "value": "4941.99", + "rankDelta": -4, + "valueDelta": 400 + }, + { + "rank": "5", + "name": "cilium/cilium", + "value": "3215.42", + "rankDelta": 5, + "valueDelta": -500 + }, + { + "rank": "6", + "name": "ceph/ceph", + "value": "3172.49", + "rankDelta": -6, + "valueDelta": 600 + }, + { + "rank": "7", + "name": "keycloak/keycloak", + "value": "3095.56", + "rankDelta": 7, + "valueDelta": 700 + }, + { + "rank": "8", + "name": "gravitational/teleport", + "value": "3082.18", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "envoyproxy/envoy", + "value": "2929.08", + "rankDelta": 9, + "valueDelta": -900 + }, + { + "rank": "10", + "name": "backstage/backstage", + "value": "2903.39", + "rankDelta": 10, + "valueDelta": 100 + } + ] + } \ No newline at end of file diff --git a/public/tech-foundation/technologydatabase.json b/public/tech-foundation/technologydatabase.json new file mode 100644 index 0000000..2d6a2a7 --- /dev/null +++ b/public/tech-foundation/technologydatabase.json @@ -0,0 +1,76 @@ +{ + "type": "Technology_database", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "ClickHouse/ClickHouse", + "value": "4941.99", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "apache/doris", + "value": "4307.26", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "elastic/elasticsearch", + "value": "3729.39", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "cockroachdb/cockroach", + "value": "3443.7", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "StarRocks/starrocks", + "value": "3194.56", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "trinodb/trino", + "value": "2703.4", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "apache/spark", + "value": "2654.02", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "pingcap/tidb", + "value": "2200.38", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "milvus-io/milvus", + "value": "2001.11", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "yugabyte/yugabyte-db", + "value": "1940.75", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/public/tech-foundation/technologyfront-end.json b/public/tech-foundation/technologyfront-end.json new file mode 100644 index 0000000..88e549f --- /dev/null +++ b/public/tech-foundation/technologyfront-end.json @@ -0,0 +1,76 @@ +{ + "type": "Technology_front-end", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "flutter/flutter", + "value": "9361.81", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "vercel/next.js", + "value": "6638.65", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "appsmithorg/appsmith", + "value": "3474.07", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "nuxt/nuxt", + "value": "3387.23", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "facebook/react-native", + "value": "3260.55", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "ant-design/ant-design", + "value": "3053.25", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "nodejs/node", + "value": "2736.37", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "angular/angular", + "value": "2273.82", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "electron/electron", + "value": "1773.31", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "denoland/deno", + "value": "1654.01", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/public/tech-foundation/technologyos.json b/public/tech-foundation/technologyos.json new file mode 100644 index 0000000..93a8e86 --- /dev/null +++ b/public/tech-foundation/technologyos.json @@ -0,0 +1,76 @@ +{ + "type": "Technology_os", + "time": "2024", + "data": [ + { + "rank": "1", + "name": "openharmony/docs", + "value": "3277.69", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "2", + "name": "openharmony/arkui_ace_engine", + "value": "2818.09", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "3", + "name": "SerenityOS/serenity", + "value": "2257.68", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "4", + "name": "openharmony/graphic_graphic_2d", + "value": "1239.6", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "5", + "name": "openeuler/docs", + "value": "1206.9", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "6", + "name": "openharmony/xts_acts", + "value": "1186.06", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "7", + "name": "openharmony/arkcompiler_ets_runtime", + "value": "961.99", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "8", + "name": "openharmony/interface_sdk-js", + "value": "910.91", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "9", + "name": "reactos/reactos", + "value": "745.23", + "rankDelta": 0, + "valueDelta": 0 + }, + { + "rank": "10", + "name": "armbian/build", + "value": "679.1", + "rankDelta": 0, + "valueDelta": 0 + } + ] +} \ No newline at end of file diff --git a/src/components/table.js b/src/components/table.js index 841cabc..a4b0fc6 100644 --- a/src/components/table.js +++ b/src/components/table.js @@ -432,817 +432,14 @@ function MyTable(props) { } console.log(url); console.log(region); - if (object == 'foundation' && region == 'chinese') { - let data = new Array(); - - // 预处理数据,对新上榜单数据进行特殊标记处理 - data = { - type: 'Foundation_China', - time: '2024', - data: [ - { - rank: '1', - name: 'apache/doris', - value: '4307.26', - rankDelta: 1, - valueDelta: +100, - }, - { - rank: '2', - name: 'openharmony/docs', - value: '3277.69', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '3', - name: 'openharmony/arkui_ace_engine', - value: '2818.09', - rankDelta: -1, - valueDelta: -3, - }, - { - rank: '4', - name: 'milvus-io/milvus', - value: '2001.11', - rankDelta: 3, - valueDelta: -100, - }, - { - rank: '5', - name: 'apache/flink', - value: '1816.72', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '6', - name: 'apache/shardingsphere', - value: '1662.8', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '7', - name: 'apache/ozone', - value: '1281.57', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '8', - name: 'apache/iotdb', - value: '1265.72', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '9', - name: 'openharmony/graphic_graphic_2d', - value: '1239.6', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '10', - name: 'apache/pulsar', - value: '1227.93', - rankDelta: 0, - valueDelta: 0, - }, - ], - }; - data = data.data; - let dataSource = []; - data.map((obj) => { - obj = expandObject(obj); - if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { - obj.rankDelta = -10000000; - obj.valueDelta = 0; - } - dataSource.push(obj); - }); - console.log(dataSource); - - // 更新属性和表格数据 - setState({ - ...state, - ...newstate, - loading: false, - columns: columns, - showDetail: showDetail, - hasDetail: hasDetail, - data: dataSource, - }); - } else if (object == 'foundation' && region == 'global') { - let data = new Array(); - // 预处理数据,对新上榜单数据进行特殊标记处理 - data = { - type: 'Foundation_China', - time: '2024', - data: [ - { - rank: '1', - name: 'kubernetes/kubernetes', - value: '5374.14', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '2', - name: 'apache/doris', - value: '4307.26', - rankDelta: 2, - valueDelta: 3, - }, - { - rank: '3', - name: 'apache/airflow', - value: '3642.9', - rankDelta: -1, - valueDelta: -3, - }, - { - rank: '4', - name: 'openharmony/docs', - value: '3277.69', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '5', - name: 'openharmony/arkui_ace_engine', - value: '2818.09', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '6', - name: 'nodejs/node', - value: '2736.37', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '7', - name: 'apache/spark', - value: '2654.02', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '8', - name: 'apache/arrow', - value: '2219.95', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '9', - name: 'apache/beam', - value: '2188.52', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '10', - name: 'apache/hudi', - value: '2124.67', - rankDelta: 0, - valueDelta: 0, - }, - ], - }; - data = data.data; - let dataSource = []; - data.map((obj) => { - obj = expandObject(obj); - if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { - obj.rankDelta = -10000000; - obj.valueDelta = 0; - } - dataSource.push(obj); - }); - console.log(dataSource); - - // 更新属性和表格数据 - setState({ - ...state, - ...newstate, - loading: false, - columns: columns, - showDetail: showDetail, - hasDetail: hasDetail, - data: dataSource, - }); - } else if (object == 'technology' && category == 'cloud-native') { - let data = new Array(); - // 预处理数据,对新上榜单数据进行特殊标记处理 - data = { - type: 'Foundation_China', - time: '2024', - data: [ - { - rank: '1', - name: 'grafana/grafana', - value: '7134.37', - rankDelta: 1, - valueDelta: 100, - }, - { - rank: '2', - name: 'llvm/llvm-project', - value: '7049.62', - rankDelta: -2, - valueDelta: -220, - }, - { - rank: '3', - name: 'kubernetes/kubernetes', - value: '5374.14', - rankDelta: 3, - valueDelta: 300, - }, - { - rank: '4', - name: 'ClickHouse/ClickHouse', - value: '4941.99', - rankDelta: -4, - valueDelta: 400, - }, - { - rank: '5', - name: 'cilium/cilium', - value: '3215.42', - rankDelta: 5, - valueDelta: -500, - }, - { - rank: '6', - name: 'ceph/ceph', - value: '3172.49', - rankDelta: -6, - valueDelta: 600, - }, - { - rank: '7', - name: 'keycloak/keycloak', - value: '3095.56', - rankDelta: 7, - valueDelta: 700, - }, - { - rank: '8', - name: 'gravitational/teleport', - value: '3082.18', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '9', - name: 'envoyproxy/envoy', - value: '2929.08', - rankDelta: 9, - valueDelta: -900, - }, - { - rank: '10', - name: 'backstage/backstage', - value: '2903.39', - rankDelta: 10, - valueDelta: 100, - }, - ], - }; - data = data.data; - let dataSource = []; - data.map((obj) => { - obj = expandObject(obj); - if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { - obj.rankDelta = -10000000; - obj.valueDelta = 0; - } - dataSource.push(obj); - }); - console.log(dataSource); - - // 更新属性和表格数据 - setState({ - ...state, - ...newstate, - loading: false, - columns: columns, - showDetail: showDetail, - hasDetail: hasDetail, - data: dataSource, - }); - } else if (object == 'technology' && category == 'ai') { - let data = new Array(); - // 预处理数据,对新上榜单数据进行特殊标记处理 - data = { - type: 'Foundation_China', - time: '2024', - data: [ - { - rank: '1', - name: 'pytorch/pytorch', - value: '10182.45', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '2', - name: 'langchain-ai/langchain', - value: '6080.25', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '3', - name: 'PaddlePaddle/Paddle', - value: '5408.62', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '4', - name: 'huggingface/transformers', - value: '4422.84', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '5', - name: 'AUTOMATIC1111/stable-diffusion-webui', - value: '3881.6', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '6', - name: 'openvinotoolkit/openvino', - value: '3857.31', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '7', - name: 'microsoft/onnxruntime', - value: '3006.75', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '8', - name: 'tensorflow/tensorflow', - value: '2723.26', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '9', - name: 'Significant-Gravitas/AutoGPT', - value: '2664.85', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '10', - name: 'ggerganov/llama.cpp', - value: '2339.8', - rankDelta: 0, - valueDelta: 0, - }, - ], - }; - data = data.data; - let dataSource = []; - data.map((obj) => { - obj = expandObject(obj); - if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { - obj.rankDelta = -10000000; - obj.valueDelta = 0; - } - dataSource.push(obj); - }); - console.log(dataSource); - - // 更新属性和表格数据 - setState({ - ...state, - ...newstate, - loading: false, - columns: columns, - showDetail: showDetail, - hasDetail: hasDetail, - data: dataSource, - }); - } else if (object == 'technology' && category == 'big-data') { - let data = new Array(); - // 预处理数据,对新上榜单数据进行特殊标记处理 - data = { - type: 'Foundation_China', - time: '2024', - data: [ - { - rank: '1', - name: 'elastic/kibana', - value: '7601.04', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '2', - name: 'grafana/grafana', - value: '7134.37', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '3', - name: 'ClickHouse/ClickHouse', - value: '4941.99', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '4', - name: 'airbytehq/airbyte', - value: '4658.86', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '5', - name: 'apache/doris', - value: '4307.26', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '6', - name: 'elastic/elasticsearch', - value: '3729.39', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '7', - name: 'apache/airflow', - value: '3642.9', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '8', - name: 'StarRocks/starrocks', - value: '3194.56', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '9', - name: 'trinodb/trino', - value: '2703.4', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '10', - name: 'apache/spark', - value: '2654.02', - rankDelta: 0, - valueDelta: 0, - }, - ], - }; - data = data.data; - let dataSource = []; - data.map((obj) => { - obj = expandObject(obj); - if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { - obj.rankDelta = -10000000; - obj.valueDelta = 0; - } - dataSource.push(obj); - }); - console.log(dataSource); - - // 更新属性和表格数据 - setState({ - ...state, - ...newstate, - loading: false, - columns: columns, - showDetail: showDetail, - hasDetail: hasDetail, - data: dataSource, - }); - } else if (object == 'technology' && category == 'database') { - let data = new Array(); - // 预处理数据,对新上榜单数据进行特殊标记处理 - data = { - type: 'Foundation_China', - time: '2024', - data: [ - { - rank: '1', - name: 'ClickHouse/ClickHouse', - value: '4941.99', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '2', - name: 'apache/doris', - value: '4307.26', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '3', - name: 'elastic/elasticsearch', - value: '3729.39', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '4', - name: 'cockroachdb/cockroach', - value: '3443.7', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '5', - name: 'StarRocks/starrocks', - value: '3194.56', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '6', - name: 'trinodb/trino', - value: '2703.4', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '7', - name: 'apache/spark', - value: '2654.02', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '8', - name: 'pingcap/tidb', - value: '2200.38', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '9', - name: 'milvus-io/milvus', - value: '2001.11', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '10', - name: 'yugabyte/yugabyte-db', - value: '1940.75', - rankDelta: 0, - valueDelta: 0, - }, - ], - }; - data = data.data; - let dataSource = []; - data.map((obj) => { - obj = expandObject(obj); - if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { - obj.rankDelta = -10000000; - obj.valueDelta = 0; - } - dataSource.push(obj); - }); - console.log(dataSource); - // 更新属性和表格数据 - setState({ - ...state, - ...newstate, - loading: false, - columns: columns, - showDetail: showDetail, - hasDetail: hasDetail, - data: dataSource, - }); - } else if (object == 'technology' && category == 'front-end') { - let data = new Array(); - // 预处理数据,对新上榜单数据进行特殊标记处理 - data = { - type: 'Foundation_China', - time: '2024', - data: [ - { - rank: '1', - name: 'flutter/flutter', - value: '9361.81', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '2', - name: 'vercel/next.js', - value: '6638.65', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '3', - name: 'appsmithorg/appsmith', - value: '3474.07', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '4', - name: 'nuxt/nuxt', - value: '3387.23', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '5', - name: 'facebook/react-native', - value: '3260.55', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '6', - name: 'ant-design/ant-design', - value: '3053.25', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '7', - name: 'nodejs/node', - value: '2736.37', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '8', - name: 'angular/angular', - value: '2273.82', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '9', - name: 'electron/electron', - value: '1773.31', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '10', - name: 'denoland/deno', - value: '1654.01', - rankDelta: 0, - valueDelta: 0, - }, - ], - }; - data = data.data; - let dataSource = []; - data.map((obj) => { - obj = expandObject(obj); - if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { - obj.rankDelta = -10000000; - obj.valueDelta = 0; - } - dataSource.push(obj); - }); - console.log(dataSource); - - // 更新属性和表格数据 - setState({ - ...state, - ...newstate, - loading: false, - columns: columns, - showDetail: showDetail, - hasDetail: hasDetail, - data: dataSource, - }); - } else if (object == 'technology' && category == 'os') { - let data = new Array(); - // 预处理数据,对新上榜单数据进行特殊标记处理 - data = { - type: 'Foundation_China', - time: '2024', - data: [ - { - rank: '1', - name: 'openharmony/docs', - value: '3277.69', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '2', - name: 'openharmony/arkui_ace_engine', - value: '2818.09', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '3', - name: 'SerenityOS/serenity', - value: '2257.68', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '4', - name: 'openharmony/graphic_graphic_2d', - value: '1239.6', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '5', - name: 'openeuler/docs', - value: '1206.9', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '6', - name: 'openharmony/xts_acts', - value: '1186.06', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '7', - name: 'openharmony/arkcompiler_ets_runtime', - value: '961.99', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '8', - name: 'openharmony/interface_sdk-js', - value: '910.91', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '9', - name: 'reactos/reactos', - value: '745.23', - rankDelta: 0, - valueDelta: 0, - }, - { - rank: '10', - name: 'armbian/build', - value: '679.1', - rankDelta: 0, - valueDelta: 0, - }, - ], - }; - data = data.data; - let dataSource = []; - data.map((obj) => { - obj = expandObject(obj); - if (obj.rankDelta == 0 && obj.value == obj.valueDelta) { - obj.rankDelta = -10000000; - obj.valueDelta = 0; - } - dataSource.push(obj); - }); - console.log(dataSource); - - // 更新属性和表格数据 - setState({ - ...state, - ...newstate, - loading: false, - columns: columns, - showDetail: showDetail, - hasDetail: hasDetail, - data: dataSource, - }); - } else { + if (object == "foundation") { + url = './tech-foundation/'+ object + region +'.json' + } + else if (object == "technology") { + url = './tech-foundation/'+ object + category +'.json' + } // fetch 异步请求 - fetch(url) + fetch(url) .then((res) => { // Todo:最好的情况是在日期选择器中,只显示可以查询的日期, if (res.status == 404) { @@ -1300,7 +497,8 @@ function MyTable(props) { data: [], }); }); - } + + }; const { diff --git a/src/data/2023_field_ranking_top10.xlsx b/src/data/2023_field_ranking_top10.xlsx deleted file mode 100644 index c93d73c59f7be3306800938b88c4c95e08eeb80b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14755 zcmaJ|1y~*3uEpK0IF#bgzPdW-kR>%R`jw>O`x^kr?WtnFxI-^5VfK7jZsmVU8oYy$`Y zFaZPrfbgGUde+v|&KBlr(R>m;wAg*;KI>UK?FMid^hG~;_-ppiTlqo7Q zxWt1u_z()RC?Keu5NS`$W-SqVOWh~ABv!9GT-u)JGB;m4?`sk4_|Ta;h1&obB`x+4 zmKZwqoEqvu8Q&v1L=KQLcOpPf(9O@=htvSriB(Q0f}nyONMO{yM{&e^5}k>YjN76= z`%o0#3Z8U~gmq5)G&7*sZJ0CZ^tBrsv;MI&(6%>zECw80#_=H7Iiucf> z1e}BZh>z6LQ0#`>69L`7mJhy z+(%rlo?JD1n5q^UDr3v0LrFIQ?vcmnkb)ZogL91Ch#Rhs!n?|SW?kLMIJe568P}=6 zBYVMdRi{{g&j+F%=y=t#<7n^5osrG?en?I-CGi zct7wKTx7%AlMcZv*q^R%Y`pFwd2>D7o9mJPaJ_?_y_Lle=jTOfy^-UG^IrvqJdz`* z>u@XvmMrnLS*_37a}Sk`qoZ@D-@iC9?4i)KPLA}rxHzxbRri%(`{dBp&y#}__TnQ1 zAJ?lqVRKr|(*k-sgqf!BQAGL1RO-sDtbM}D5z*76G2cKO-rLw%VHFv?@{J6GeO7;z zDhM-A#T&ytEI)24WXi~ug_8@_?;(v6N>%t z8#A~SQ^`@X9@rsy8Gcu;pGoW*U#hO8gnHTZ?hy{iHk%}0Cgx$ux(dfQd-Ef0yQ)zz z2m`ak7X6nG%pYP2582g~9Y*8P3+#m$ZqmjkW;ZjKCujFI4<{4MNzR6g@RrhOd3Hz* zQIL?nMFgx-8FnmYUKdeEP;vwO@asP>Ou%n`bvFOGB>l4h+%EwqD_b)=V*>;Gzn3re z&?9`MHSSLo6}H4$+Re~v~f zo9xJBAvgea6G(RBd3!fzi*TiOiarha=|IujQT^UYudo=$tf)KN2uGEfzh1GYWF??D zA#{$p(4w0)*icWxB~UYfoJ*q4%%ZZ&7fZ&HyepUW4&Pobl>1(+^4A4h z8J|SlYnYzTf!dqJ9L20=2uXpG75CyHcj>0V$`VhY?Zeh}rEK<-?%#N;rM$T#TbSNM zz|8HE82Pfh!7+Nceu6DwEYVYz)ivA@3o_b%fQ%=ISz%9%t)2SbIag`|r5KH}chHcR zXvFK6Zu8>4#kJ7%NbZ|#anL?#Hu-(4ZVi=Gq@d2~>~1+o*G>Pkj5rtM3T9QDW~9fee~lyx=1?Xq?47qA?ayGo^Bk$+jt3 zA3|pkAC{ub7#O}2jO z;zRL^TY997ui~05L2P33siSSDKyfRAN#yV)a%oa3J{2N)+-U+$K`ya-&dmK+e|kafA7S-dM;l$sgM zCLWf!xGlVNYXoZ!A|%F;)-l1CJPj+}Lt~QDezQTXAooN2KXh;x8l> zo3L>#r_cU&qH>!)H4KRc6C&jqjJ)BO@nA{j)g^zzNrL`QFs-_XjZc=Hx{ISvg6<}* zA}gP^%Odz}aQ9hV!|sPC`6#W_`5?isF|1R8<|QhZw30+1rG?ANd7WmO^-Bsg?)-3>mCE+T~$VPIXR`TX;DZC`HyHUHB1Qspvx5~WkErxQ?;Dl}T7)XFxQ^{TWD-olv# zkc-jR`wYF0M%NE(Giymh=^@M_AmD@g7G&gWxVAUvJT!RpJGa60sAWPUwl}`F2R2Xp zcqx2?4KIUj+4Y zzxh~UO@_Iy-cn(ET0!E#yqh+`UxP`$F1-qlaF*GqqHTBE6YIv*8#|2=00^%YF><%H zmCr|bo3xbXN|bC=OuA$_iuFMGe44*CA@qF2HFU@3N&wHnk3g9iX_X55JXTk*{#b%w z<+`a5m%|%Ul^oangzI0yuw2#rRSvOS&+>(#_!}nSv)uLFx8m22dpk8ZZgLw zX(~sF9}t>3p9lgXLh-_(z?ixzcD}?EyNtYiG*TAe59fy^7lJLmIAp>$WEa#HSRcFB zMcoD{Fo`E76dh!j29Qm@)BKzd*sesE?yy{sMFs{h9L%eQGYc$(OHkM`1D~-$)_An} z(hAG`f+0>xW7cFkqM=K4#LI*jN-i8_|5G=gd9DSqHI~?0iuX{861|*`) z`gD3~E}j^G2&W}LObH~i1_Xn9oRyJ8V_)0Tq`WBBO6V_!w0-ift_!SX@I!!zAu0;{ z3gD`<&Sz$d&}=5hu&Ucd*m+BB9IncaBF>BYd((Pwz6IbYl2c35^0ytc}{n zHJr@}!^$C0bk9q-_cOO(cj{$NaYYLI4z>DM6t8$MA3CuRqkAsRrFXF%_{qhZrc!E9 z-RQ`_$)djsn|lHMS+3M=B7YEiqhHW}rys*F`mMiZ!Z-SnoOhLVA!6ch7tZHKd-=P^uD|-Z~DWgk~`6Ou5qvMreth6>?!-mLKw{zWer7E)W!~b{!Hj0U}N1-^yoSFvN6y<2zJ}eUR z!GB6e^6Avg|Grmh@iiT%ZI6b()wE}xlP?`jA9Te276-};JiaVLF zF_9vJ7Is%C*dCbRu@QMNyp}250AmmMNw(77^pFDa8V=imBm*@n_w|;J)N6`PvQNl^ zToo5tI@81Bze>V$cajRuc0TDHQmp{zCgNC>*kLu*=It|g)HHP-eMWeNm|!XNUV++k z)O+A7F#0H2Cc${Cn-G|G>Vq0uZJ!)yfR`Sn(X|rJB&Ze<1o9p(+a~rb;+Q=Ej4AT% zV>qVM9dqTm51|4;Axn$Y)jrY~d{QvQG=5`mh@@V+k`dI?LonmtSgBQ~<>qE8iM5>L zLG9e;Iuq3sXfFs()^&w)N(U=l-;MY*ahd79Sx0!JgR`8G)d8L#VPYut^rwQ}yDRmk ztE28>yt#x$IT=7yG?%U6gVeK(z(iL#Mv7$Zjp5!6*(I=E59`!bZE(lSl#(1jvjH}9 zwZHm6)9JCVxn-G(+q*G1J7nX@2?AWgT{PC7D$Rd#+cFJwYGNi+o@}}3MBdP9n(AYL z4-7BBBkC5LY(!+r0CoCGfTD?7(15eD03*!`-{ZLsktI!IJz=_Plz&&JFr7SP^a9U~ zpeyv2`dCsZ*!b!q#pTOyhRpkL!-Crpo2`O&z5b-0|H}7amN)9@|99#!{$J|R=;9+} zM;6N}rPPYe*5Zv*CxW2TGDsi1JiRdwoIkIfv2*n&^HxuvH54>RhM$7#AiL{BD3|t1 z3zs~6JfGd0H9nNQ%cT+>Q%}zHsuj6!8PBK(-mZA|me=#r|PxM4mv zhK`TE41jRnbt^b$CGv+dH65^9oiGudB`B-h#GBMLP}{wU+8qd}=MS+~M+SVn4=g^W zF}3Ooyn&JiE4+;!R|<|;qCeW)AnwQ?W;<3RJ4s~aAz+4gorD5kjuxZMUb+`b7~QFmcEst_r!^hd2`=oiG0KiXxLhd`Q#!W}?Pba8~&$YGu#v@|^{H=)b!zya-! zmpk=EU|keCe8HUCaR$&UR`4%;NQ0x|N-WbJ zi}Avh<%kBU&+1cQ(In9W=s5`X@vPj9MW}hWJ5>gY1MjE5uCkL9vhplXnPH_bRhy-- zEMe=0@eXj(~!%W%Y`MN4!!3A&WX$<)}3 zZnQ+5CUFv%>PDfG#`DBUbj??WrW>XS5YW^=I~_&mxU?8j^g$U?Uf`&`ly)S+UHW!5 znu~p_+;mp?F(i)mWOH&Fu3^v=j%3b zC$-_{zxhq$bC(g@bq#mk)bfU*LUNifK%j*=vC**G{zGSQpwX)Mrg=M1a^2*uw~`^` zhpnY33~Jb!f(q_t_UeLl$aNJ9tJzvVq)!0VjogyAA-ZYotJ;a5Qv|qhH}3MSTbr&b zsW6Ze-mx0gor-zH20lNWcb)P4Nw$DFD`AE=vKjt&vN8Q4o5im@C$r?l>#5`Gk`Gk` zrBx@EqA2C&eCiXE31qn8cei|QPGW}Fwl-1#kQ%OV)UF|u#T zCqb!2YVuqsf`zUcjBh!5uGN6dRUf!n!|SCM)8&=^1RWWTv{oS4k>9?do(qLzZUXQ+ zyiRxVqCE@9@~Mo=o+~Hsjcm&fsS}pQZ)CGx_7e29Vpi(Hb*{2frKlAhHzmh^)l+fk z5j(B>9;v-JjcCfXYZtZUTc3IxWMLz05l%;7>Lq=&cd!IeV}k8?AXd1AnZ|AMBo{Nw$4Y8^?{+6O zxR!Gd(pUEU@M%dCcu=tdL(C-79~t&(rY_1PqdxShjzKMYgmlk)@0OM;-1LR%TE37e zxxhx>sa;=v%Y7}}+bL=gug`i?-)Vi(i2In34Z>lG{$PXN#E0&h>1O{pG*D5xbOth7 z76|<5vaPTr-opr7S-?G5bBM|r7U7{b8A^CXNLfH<_P!9XJTS&Dvh&hoJ|Y`L&HrdF zs^XiT8LE=c$(HNv^`sBv2U$ar-S06P@Jn)of%g|E)tDPEm5$1HfaKKS^(Rxp`SstY z_R=kwE5H7v8~GdEfY$ry!YJEA6Ou!OpNo#1qI|v%Wl30oowzzl>UON=KEsk9(%7H5PZvd<&N8C zGAc#9NlQ7jJM744a=HM{maujZ7cy%Rv}ZJQsbH0%NVIo_-dF(R{Cnz7YjbmCG;fxT zx0-XLC<8~FxDEDe=x6FvbU}g*m;5ub^E6m~l!#GjV&7YLz*N{0%{6)npeG~_yG-p) zS2qXy5zh%vjXGbY8ray44G7`3`6tD7h_xcn`%%zV&Y4{}?F|@a>{0w`=G2gBSW0yZ zH%0i}cAi%O)mQL8iH3tgtwZ@nH0}RRH0GZ~Q(pZ+G_Q=>SHQRIPg|Z z7PK%`yYi)^D!1yp1$}X)tUuzyIykL*lwIL*DcoJnakj%vIYhRiTbaNkAeM)0&^%!_@ z6%My?o4qf-l@lK7+}kp#lAt!=rVWvLximLrsU_^lc&TQ@!V5iCY;x~veh$zGYDZ(B z6zny8CWL?t_LkE)Yq`EA*94bek!Z z-oC+8#O88Vnu>a(`XyGyYgiNeBZ}Stth*JCUpXE~34)fq=fx&8#r<1KYw6~$evnf% z=xMJ)F3IE;F5ek*1|_^OnI#Hs3@J@+FFNN#E+xQr_7>>I4~76tm1H`WtXR@BL)hhI zwrMzh(Czw+XuT-U_VTI5$MVzFCNL+c9M?*QV_E6T}s{CR5(&Qpm51QqECRhBF$ zv?3rOCXOf&Ti7_0nEWZCUI!p^eq{0oJ<3KX)Ht~UExt3+-Em^ZSt7qu;FH8|$b|1U z>*3GpHe+yv-kLp3Sd)qgf`DC<9QD~k#iDX!Uq5(j3NWQiynWi+6(vV!Beb#GpbL#V z@`dG_J-k7^UdouUD>W1sUJEgEo|};if{=*eKy>HF_N|n$BF$y_PYA-!XVNsdQmtga%f%h$ z;(1|Mc>c+-f8OZ)@rdSaC)D29z{23KM>G#F*a%@@0042p?khGYuUlK9>-m3*V!f zz7P3D&$3s@54AN|*M#%}a3XAB$~LdM8AT7%jkF&zvW**4E+ccF=jGmK|^pTM?Hay&~Q0L#5FHjits$ zzxin)Nh(zh)p@22d#z?&R&8cZA=<$t<(9gB|FYC}Kw74VV|(^fX{G`rfQ5TL1qz8M z!?G4-3j;=I{3lkK7Of%`Q|fkJF9Yd4;gZ>67I`&FIpFGuI=1iX26gpKCmXPXTgP?} z>Si^o+71_BpDs)69?tyxO~?AMWCx8o(*?`|9b3q5vFW$WTTt4;F6zXgGP3Y7uMVat zg*lZ&K2mizG#vo(0%IsM3Y#WJBHq1ETxP|D2xbCqmA2OFhkLZO6usu3ddDayb>0Ia z@Nx8@&GYW`*hpsL*eC-2oQtdVzGw6KDe%6%p*GcjnH4S=TF2vg2v284sDtP6YPM&5 z__8|a^|l3k{H;F0hQMHqIq2Ju@N)b1(3caT<9S^P(oS}f32{ChBx)aqoympkZP`y- zzViuRx*;3y<56kn`w8mzt8!Vut;~I;F!KcEmzGeZxCWggG0WklZL*RmRGaQZq1YR6 z`=xzCMS$hT+Mv+)BsQ{NH6?=^xkB$poEvOT8tWOvGEEKn4j0;SkVHnc0`&cXk&yjw zu5CC_qQZ+cJ&N@&1+iR;;GN(WA;OHbn}2SQEmcMdMf!CB(R0ljxi z`PboS%xfQpRb`|wn#iTjsq}y`9ra`@7>s11@p_{Xa2<$&fx+KFn9t#N&59`cw;_;B zG^lV%5k`_7@@D%dw9RH~CD*;8i9PRc&89#NVjX5P1@bt%V$*_-qG3dY9+qO9#d-C+p3 zk25+byS)01)Gp+*Tdi3%z*$rt&!lbNLy<{(_@jX|Vp$+8n1>^0zbU9CtkfMKx(j3>j+6-6yO@~1gUmywqY(%AM^+Qp53J-p`mvwq^DK$!pf{F= zRJsG6tA@<0-S@_X^Al4*lp3Ea9WxXbih#dFnnI6E1Oz0B3w-WNj*0VXf-~fz02MEu z9LiNy^VNMA$OYhNE+@)Cyi}T8^hdPdcuJ0!=av(^>D~myto*Xjv*C$ToH-sT-grri z%Gc3(n_6F=WE*0aY~LqA=UcO#Nc3KMq)d8}GKOjeC07&dS{VV}o+56Q)X7yzayTQ3 zypQ%JqbU0xxzR@z!xa9(T8xr*DrxGbQTBZxd92^eIg~NBe?snvA?e|OA4=o&cDWjRO8i7&*F^fF!=&axk zTZ*-;;*H#_&%xX;4lmTkGl_x}}Uton;ca_a3=2H7dZY5bSwp#mX6IlcyH3{E8 z!{70cy9-OAAH&v--)GhnJUsIw`&N1vavNd6=R)V=VDoN&0=J+wk)NwIInFJMx0o|p zIoxxPK-Z9PMDog*T5z%3tG2Vfqzp?_U#P0X(J(f>IGIH8&ysVDqzk9xNksJ;-SS=D zIG}o1)a{O~t%Wt-mie=c?4oozym-rQ>{0*#u)mU=oxO{>f!&YVaaPkJVp$dSCA`N@VZyJWL<6`V3zF6R6b~GY)D#J4{JTww;)lUa*msX@3|?-gc+z6q6R_goDt6~&O&|J;8gD4wnAT}y*lX&nu3d=$ zyCL|Cv!Fl9NifAoKt1kpa5WYdL79}{+yD$y?ZWO3HZX<=R$ zWmtWIQ9WsEyiKwyN=sTF2UN(KTwOZ?=Z3B>=Zl?;J1x7w*>xNMela2CU+shr5C>uO zA>F3%G}?&d=r`(cy*vSIKdxke@%9j$pq*qI<#OHcy!CzGtoojPPFmr1mI@R1q(O0+ zd1JaT#}JME;xi#poW08z@GA!~HT?X{^;3JEK6OSz~K)KcT< zxB*QLtI=2T+6op&Xu<-)tgsg?Vy(U0s$Dgwtl_kplyN$k;&8_%y_B3$(|NOmJQ#RM zestib^aL0WSm3bWjp4gFIg;SiEUTU`{1H~^*jgiF-gL#$DYq8h0ZpCD zm(`YUOOI#|PO=cRKk}5OSA*o+- zY-z*RFbnM&sf)XUGSsudQ~&bPUwkuAHD~dFf^AlO> z4<0QZr8!@}D>PbjY3(Z26Xd!v%gs9IMYszwc@|U-1!g02-w_U|W4lX_C_d-C#6KAXL!&OjlIOYO!BUE$T(IA=kr7kNQD1dV)M*#@k)vfu;^O`oa|SC2wlD7Q-#`K)V;T#?+H`Br*~ChXjdn0&?fd=dYaFRjqEwq@i7U#W z8wuz2mn)NfGrseayPMC(HivQ{=7c+$<%TWzHKw&+OsU^H8oV+H2{!QRQLOHK%X18 zoUV3;+DlIeFx@8fNowF=L^urL3;MeZY<)mahD%SsItaQ&r)o6WU2_nX8qppqJAyV% zW&$`_=I)tBL3F8BETdI^IPTC@$m4fJwj?4F0BHJtB`$PJBhtsTSi#WC-%#+K@vGq4 zcNaPz(K;EJd7o2ba(kn7cx|>2Y(1cG{b>EHN3i`kBygMoDw#q!jiCq zn?f>A-;)LU&K6GD7;({#EZa47Bx|EDBbAud^NvEG&ww*leOQcvJ3TK=%2aJzr;(ea zRe}mvO@OIU8!c#MLDIJ|AtsXj(~dK1ew<_V$i0Q0C-A|(pPNxp4S2g%f@5%xTXn5I zCLH0Gk(e9YG3y1;9Oh?`iumam&4J1JEZgI}vK99MGOM9Yc4-p|xbdMWWo+)1yfW5S z5(y0(*2sQ#MeLkf)WG|lVG3z~9S;(-%N2S~SBr03B^SdsuRtT0=zs@1%s@fQ07!mN zuFws6;Tha%+@2~@wWLoU=6$(l1xd`)M4=^LZ=Jv2?DLequ*UPv=+ZmGo2Uy{cnU1a z_Um}kJwL4uol6hM;HG_ip4@@Ld}Rci<`gJxr{tr7W!(3 zmLsI}d9_^PdAKKRSN5Z!?T*$&?1y9Ms_fn&OuF5#&-ZQD;Nv76(gZ#k^>kz=Fgh=r zY|c(s4eJRX975szXA(BMy# z#Peq7SG$3Tu#0}5*S8ZheJ$fv(OIS_nv3M3L}77$Gn6sV@d&^^ytCaw>_gyj08gC@ zBvDI5K;XZT^||-!;r4hZQw&Fh!jT~6Y%XVZKOazL|Cd_t$2P(DsNyR@Mw+1j7qp@T zu^3^3Ea}KqhA^$WG^eV?DF!%E9LcfONzE~tTWTQFuo|BTi8D_ez6qU>bLJZneAXtm zy(>sCf=5P-VsBpQ9zT_l=%Qp5B!iATdwin+rUOE&64 zGXXsx6}OHor8n~(q`t@$bi9g~9!h)dcfMQ*zOJqX55?n>ID2Q7L``(@n5NU}{EZM1 zkt|n&EcQ?hg6xvg*++&rU$LgQ2J&^21@{5W-UN5Fw<{S@3=A%om91v3%22Sq>q2fy zk~rCqI$)6HiUaLXI_*mUQ_RP-R4_YX64_FheIUv&Y|#gV7(nEt>i{Q`F^rLi@N=Pq zG7FYuCdAWtr5I5)l_ug-p}nboWyUF}D&HiF1Q={84F$g@%QqP2>%7UTDJ+2!?Gc*5 zx~Axc*Pee$?ny>mRF45;o5p@SJBJBJpQ6?|!F|-3ZqYi#g0T$T;VRw1aFv}hlt2}S zavMyi(7sBWa$|r zi)2rcg=$^eYFP5(+TvJpo{zu{95CIPcovSE4pEuwPAy+g zWJ1(XDPC;ojCV{Ay0ipLDM7t_wakiEAiX07H31iPyvzlOBt37;pI-kg4FO6!fYIJ| z7%#v90Dkn5ylrgQ8SB{^d{VHtHL*1MSt0r>by=P$26phPZcsLrFv%_ zprZL%aMNlBLm>rFRRZw?sscwJ^pY?M&agRocwV8{Yq>R&Xr0$S>5Qm=S*^p`vvoLM z5-gX;td_gD-QNeczn^kzBGcy13@%@Sc% zKXtTR@2cJLfNA)oioBGSdGLj->%&a0gpt&f2RhQ*TSEOb9QMSqZZQvFVYE|Y6Gm!X zXp&4w`Gqz5>Kh~+TDBtr%~(E9JYlj++HS5HIVi@m+E!v`-sGtW>}-<_4YvJT?$C%`l|Lljqft1)$<+TX_U0OHM^&65XMyY&YAmpCC=A>dM;6 zO8LegOPZ7*slnhXwAYO-wG>Jx1KUWEI5-(RD#&(dtC%L1_!Z0AjP>d0na($Y(EMTEl6+;4GA$P zRELRfH}~vh=cVbUTL50Jo@oEt{2XbEr7OI|1IHv?08SD~qpxVGn-3vUA}}b)w9`55 zJ#P6fPk+7Ot1ScU0P-B-cWd25w9~|L0YrXidPUfMZR+oyS%YGqh=`)FIr(wK!ZR$9 zC52mdpy1(h%-b85sA~GGVQ{5+k;Sk0$~_^GC%zt*GoiO^h#+RFVUH_x+;~-TkhzFx z2Xqlkng#DrMX1b2hF`pLlQ2|Ul`f{8Twir8FtVDQ?#pvnNB2J19i~j&DsP>NK4hTd z%TUy7+cPn_Bn&g_1n;+>z8^b<52+YwLPO&k9JP}P27Vk^dx8FwM{K6SD0y$4s`GE1 zs_?&?AU|4Jnf=_Lk8ZPErbY3;2l4>-apQlKF@YTc^r<(F#}_yrEw#5m%o6p^EwMj~ z?E($X75EIGhG|ba0XB%x>Al`xeU07}ecj`FB)B@_#=T~jxppTYbDZ^#Q- zs7k^gM)2*jrzK1!R&_wBJ5L#5l1BH?@pU&uJ8Nu{qzoPsC^pRaNOR3#w4dzLiscbD z${I}FP-D+jXyO>`MQ=U;bxbJ+$or8-S$m;_VrU7Rk#T2>@J>IxIo_=(3 z^-fZuJKZ9OT`8fs=s6({gSx8FRbSJj{+jQkW0anMXkv=jp8x&P?DDN*f82(o4J!~) zKaMEPA36L&V(jK~*PO|jPU-b}n_ps%$7MfP@Qx(r@xz(<-Gj{CIpB|o{`1c8+s-e5j;(?D->t81td6a(Z|BzEq7MCU8R{RB zWzpl}y|f7Z=RW5Md+kzAsECX9Gz2G7pFBP%O1@4IBS)*9wzu)gQO-1jM%)mDy? zUO!O&*x<_?fa( zu;<@zEpH{w1TL0^E_uKBPp zFV+iQc#5I1u#{hb-`ZvbDoF?-NxNw{G?%`9pEgZ(47;a;HX$A>EHI4r*?gj-^&kuljW*jfjBKQ>;XXBIGz%#a9XeT=ew%#ra4xI~ z)s~>YlcP*IK_Z9C81ISQ_tq^U@{7q~P5~R2b}}nzlo0$#7!!p-_fmCacMMsENgdx8 z6+b`n9^6sr5S84n2W9@YD-K#zcX51>5c9fFYMKt z9ElM@c>wTWBTgMEj9qHIq7*$rcfoS8li&{OaFvhuZtqEQT8{VTJgwt$ez$+pk(B@h zLit&6{Tc!KJ7RA^0{{fTfBWrB|Bvze1@PZjs~-Trrit2Uey?4B8vT3q`l0d5=;pt5 zezNWVGxmedzm6ZHOFxePm~#5l-rsXhKZJkTBl%CY|DAgJ+eLqm;r!O_fBUNc+vvZB za{gBTdz9q2I^SFQ`&<3rgC+mpO}}aU@A2cNlR*A=g5t;R{&PtF^b#c9PlbOifq#1G z??v#3pe zp6{EUnJ(#G)w_1ht|c!64gm-9GJ@qc1z(Q;Ghm-T7}*-i+uPbXFv>rRp+Els^HU5W zyT@Av6a>T#3uTiL_!iY9aI!eB$c$g!_ z0qk6Y=9GIn#R~l}>ij3fR7>lgD9n%APvazIwc%_|u3H&T_y|8Q9tQcM_{Su$zOq)f z901v|kFIG5l+%Dt)Hae7OO^l|>k#IPDKfXUNsd}afe{nJY4($P<&+SHgC)}lP8_Rj z&3bgB6(G8=P{(}j`K^oJg;7`!Zr-vUA6^@B1iTWJ{*}VyLddMQ4BxSd$9dgsI9rwV zv6zCOcFslORf>a^2ZBWHZfNMR`*&nX=SGpDm96EO4! z|7Q#W`1j`{>@cDu%JuOgRK+{*NLE7%d;T26<47p#kCQpAbx3xF7m}lU;F3G@vPAK$y zZ{zc2Xd81#C}ne1j;}RN-Q_DZAFbf$itnTS_dAzg4~|%S+eO}4ZflZ-bR0~mczs$% z7#k}@OQ0mf4%()AyGe~b$ypGQ$C}Q_>4ZHpYkTjQIzBhybhp=##G-ZtaZf?L(k=y+$9)75CgBz_Occ-0R zrxtz4Kzac6`=T2Co-EBaoAf@$M!D%_XnmQDjU|ksY zd8lrdD@t&PXuyPD4fj~73rwFwvTzp8e#u&Gx*`6N1(t3^dQB4?7^(za+0Z$Ifm7Q6 zEzTUILqH3hxnFxNY#aB(w8@8hH`kAjSyZtcLBs-0xq`pmJVjd#*TlcsZ+@k7}aMhk1!x0SpQ4* zrwa4WnUbU%oy&pVyGDD-L)2c`DM*AJSSBr=t74I_+~}Rbw@x+(QqTum`*`8*$tS3X zWv+|b5&Rv{--dOSse3R4fL)QAH42#Yam}GtqE2%V|MBBse>%xEeM5GTb~Yr!0}cPy z1=d5YFW&Jw&s*8%?9G@Ln;;FiHpTOh&W>_8bBtnIvbm#8tk{8(4>n^@w=~P=R7b?l*!NL>wrAB=E z)JB?Pije#^rhZFPrN;pT%3!{V4$LFMtNZ}w-{!O`e!i(^kx+i5 zm2nsxh=QO0q4ZcOoWTgi&7On1SzKCdMCyh4Mxhe{8AXmke>= z27RPUn6X^`jik2dV7aqgdJgBeEJ2H8;YLp%S(R#7155?`(saXV=J0MrIIV1Y;M6*} zRdbju3Sb~k^9T>1tp^QhFin*`skC4fcT~Fl7+))P==jRy*;dr^{HpT@s~)5%=$uJp zr8^{~UBEZMRDZFzxM|Lhh`JqQCE+qHJ=z4nnoq0OWM!+}GpNui$e3}wRV2g#wAtVB zAE^qjtii7NlwzO2xE^1dcA~Jgt`G0Nw*bq~1l(A$Sv;@3@js}w;;uxcT!;pPOV3%k zitHD!cf}z1WNN(r$o5%#omHr#0!MyqmJ}=bjNXz1`!OGN#fINo-X8Js4Bz-T)adwk<^ z#s^n%-UE!7dA`*RZVV)=z>G1Z@yhc=Iy9~GR(n>Rj~q*vRG(Ju znZ{TEEUC$5aUr|!J;D3f;cfci3Uo&8fPzYw{Ib(cvh*uuA7wr;3vr$oNxxG(JI|o< zYIS4RnL2Pss+ zbgKt+V~xkgr|f?OPlY`z3m+^i{80P4HF9Wgsf&DB6sF(EN(!$fls=u z!DYyJ8hp>IbZf&y*Um1XxS-Qplc$Co;x#L@ zD}h&d@l=*_vMf(7S=T%F;ETyMYdI&-S(8KI_AF>$ zP=GTW5~D5WZ(J!@E1MsM00B!DHsndT46ErT@cjo6SgDt}p7a_u3egj}j^>5chl^83 zl*UX(3-gqd3t4Bg6!~9Cuc$KlY0CO)^l`PX0&O>(;~Q~JWDzfTP@q+$3bWi7;yf_n z#1`!yE8G|5q;w~=6C}AzZcw>ivM}Rbu=@!HvXgHzxjcO90>&i zl8pPS-uX-Hr|{2J^hkZp7MC5*TVm6@>e$nAibDH6eR?XJy8eL*`{D#adbq=GuM7X8 z9H2!OxJ5?RBj_$9+;ZyUBb5e$x|Nx2Xa;Zo1f~mg`Q+e`eWc>+Bc|+N>izKe_;_cz zyP3~}B62S(IkZ)v%BOpV9O}uR_hI6~<^r%g$4iD06`XvQ%+^XByP6+)y#@%GSC%C4 z)AOX8|1kY3QF`uEQXW#bTE;GHsJ=~)SO7*#n4US+Ddv8IE@QN`Fq^JPu`vS{9w}CRT zM;|zHAIY&7nu07`3%#e6i8Uz)s8}1by&}5jd4cB3<+^+0@jm#vt+DQNAdnL= z?3J$P;~=5#vRJ#o?fGo?_|RER$kQbNdffX*9UcreTl`+{ZnU@i-A!+9w653pDu_1f z(=3>i=@3cBNW3gQ0$-axriyJNBDuyKLW6H*9mEq1#48Hf;4K`zW$^PP6=ybZR0PHy z!|}kVvR3)G==2*Nprk7>OPYvPNz9(HZ~aM;wqDwSnn zBDBBIhL0*Sq8(%y2#$&tc!5WVrkJxrFO3g4me;i#lz>~wDGD?%mb!CXhnTXOxl^q>#H7m>e+?Is?&!Sn9CC9iC3M|S!sZg1iP39*B){p z37LTivsJ`OrkGUzg+Xx5Z@N;iNHyPPO@Deo3{I@yn61)aEPQ~T-zJz-dZ>yICs^zd z+8&-bY?49M_!R%xB*Y6^VBIwvV5_*q+3Cor~2^1UFyw}L9UXDgyyZgo=WU;Lk7ljDCNNj zP@c}beHM^52(nl7P3b*SV$SuDhb$+pk)LW{GTdN`@MR@lW5&n#?q%(>e;al}y5%(g zNXkjmZJ6LQpKn9K{Azt^P_--Qv3k&|#$#txydXIZLb>U&$~p7>LNRz~jK!i&8+{dpif%@yRiC}+x(i-9QCJol+diu?+q7hM~m zI8~tw-RoZXC0XM!(oJVf7((qGm!BINQtZPWQXP9`nEh+FlF5nXhRfw9>Eh{^(et#R zzN;W3InpMsP`P|memj&IOVi8rBeOW?8m-As4ch|g#!iZkX)0yvqDh`Om?j}$<^;|R z@9mL~nJ=wQa!{6Esl|8tfwmtFT&Cv9bwTlYOSzz^=vSl|aKg^nbSZm0L2B$P06M88 zR2CFvWK{~4L(oOavP#SKl2srdx^PjNMO+f7KM#)gv3shJzu+6LUJnNv^|tFJyc+-y zVcJMmf@ZL+Nc^GzCbKP)37|yVHp$f8Rsn^N*|OF`T?M4JOJzcG`Uip-=T{X=+PTkt z!ag%0({-me1KaeoE6{0^O>y4&q2)1S zjhA%`+w@@RY(m)vD71H@qdCh_T4LbN*M8y(ZGD-ZHYYBl+*NdN38*+(w7%>?oV5h% zJ}s$Wr8iwgiU6a~1T5QbvnXaeFD^HIGIlOm=1BC2lW5tuOf=GGES*XjMxZ z6W&amA-%b&wf*6`En#aFBXARSvaC2GZ51|OT6l??UD@U#is;J9s(Yql+D3+H&!r&4 zBUEmq^8T#)mEV=+{0_8v-sL!F_+)tfxQEQv$b(lDD@N+dQMvC)HQ52T5w`Z?D%_f~ zjf?hrW)REFcWnWAk}MP>Y~8bFk+fxI{`<>tQ>0Vv;1wc>E0oSu-wOTXNuJ=SUFbc7 zzy)Obl(f-163uz=!ULKUSHwDKO}7K_B;{h?uYu=7NhO&65sheghmFd^C7p$ff)=k$ z_AVn+(rJ_;av~L$^j#Qfi%@b30yfdbU`j32KVdI``O`BkG|#|Xvy$YQ&Dld1YS*F2 zV417KjB4%Jvnaxp2eQ4o+>aA+VDZUQGS}F9ujX1yeiqk_*3r`(4)MOK&xu~^vIGNq zr%dSJqeG*hy)?YW-kR~0u^hIhjw2=x&bHN#1DL;#1Yo&tl-a}?=W>`O2%3Tzz6Nhz zwr{Q;2gkWH@u)o427S@jv@=vV+BO5PGi%ttn%_V+aJg~)*gwlXXTQmL8x6*DexH;P zk^4cuGMgsWKj>+8w7@)-zI@W6{%vl-M)eAR>*CqnRW-tQU#K>%4Znc{yCwc|=%m^G zWQs6=pk@Ls*T_(C7Dx2frQbn89NrV>XfJ`M}@oSHU zDV~l^S%NClXgF{}`tXgavA|fpO=sb{)_cwQgT41v^r@=x8_mm0l1G^M6oGZq3$<{J zGR(?lt@sX7#-JHFy`%Qz`?Sr_>E-;iaIC&=Us^4uq*3o_Lo*LNRZzVRxq7R<(6N?| zQp|s?iz_CQUPN%ePY+|i+`IucYH5Is8WI6 zY-ZFI5vR4ZYJVgI@x7^oi&NB_^a*D4+XK~ku-$}9Gj!X$(?%7lOpkXgS($6+rix}H z;@Kv;o2Zxs!Xc~{oygeu0ZdZL7*=sP z659x5p9oOqI1#`}L{JA#+`19Gh?#Fw4OX8jTdWcuINu&qs(8Km%q3JOudV9`JeJg) zMC@}bR$Dl(P!H;D2>XJV_$IRmPw%>uC8-KC!)!~j*e}9- z-$;(MQzIcnXjw5`QA7-X&HVZKD<_vmS02|DO2y9Qq=vJ4@S^;3b@@AJ2-ZudjwD0y zV0vW#YS4;tYDI%jx`MksZUgnyKA+rR8b{9TOpC#hL{*lGKYfw?P-L;^I;tfO)SMqN zu5c@V#oQ!Rx6Y!KIlW4k?M>A{(%}rvg)+27qFR^5QKmWx<|q?qhA5^~IRu;A7n!Z! zPQFX-!3;g%2ZV`EU!R?#Of4$Rj;3O>IV~2lHo}H3g9(R&{G%_oLGPCsf?aCr_z>U7Ps;$eP9>8X z`Zr?ftfRZR)HQ<%3RRW}f+g&~^2r72dQpa-EpzjJWWL`VJ{>w+SDxSURUgDll|`KL z2)~REg?E!Ae0Tk&A0f4B$ZHRJ48SBHp$RrYfWqz`4gv+Kx6VNsqKSq&fqr3Pr-?7% z$?f@&kqS|97>$Q{<%Wi($0MPkcX!giRVZ*TbSY5{Z$KO0d9N|e^6?UPD2V09=J$Pp zV>vHxZm;vxhxq7%_Pe*fBofF%RtC}*+xWAt?vPGScMqL6tGQ}mqFk_8(k6E}GFchv ziygqh>8PlaHP5rdA2*-cIiF6!8ANARSfpA+IO)yl;8Adp3iE;*-xkzIJh{Ji59g*Z zLA#@t@@N56<9(w|#&Z*3hcq(Gt}IGoB@e<|ep=@7KJ_?HBO|>5C5n&RIsHnQ3Emvv z?u`rx&+KO=eu(O$qsf#VZ{ziLy*lr{E?`v=`zEQM{%}yaTX;fAA@S!}Nc@Q%@66^I?{~jU?X}z9!L2(e*A5Xl2y!O6`ah6V-wtxtYTG8 z2`YP#6qQX3kryFhq>U(_c+;0}bq^T{jz3VzXm;F8)^2-MGfwA2@V9^ej`=Q=jD#f6 zkvfniHZTFz2o$z08B1{()d=lJ_levooTEAZ$c29~iWC%xwBXp`K{8IPEmKZn(clF| zwv6mH?yYsCWA4~RP_b0CoSZ*bF4|t1n_VZp6ldHa83x!#c^%Nhq1PA)ndvs!Wo+3dFa|h^_tN?BZ&m%4K0B zmYi9-^({mj=JKV+;Dd`%7B%{%OycpemL#+nB%$K@6f)6^0zd}U0PAUtwNR7K-GJjWx_zIzcQrqeHOZGZ*#HmmM>x=yexVDcP?=~rszoHCxCkh&qV;Jx=!O4EIhJn zMfFOzAm6L|POn`@I-viXBsr}_DVWta1w*z+5&Al?12WssZBjd$Cn=>`?uX2!+E zA~fc)0@>3DMC%LZ40nY_(z$R*$WSO&(;|ehxM-Tn6&;2QQ5zhnV-H<_!?21dRX?q; z@{eF*KcA0wWGzAvT9rhoSd-#yaOP!pt*_;w(i2HVH*X?D#jiv3dqSrA`DfPwO?n!! z9VYT!l8Bq#pvESe)C-6W-`XiOr`U>th=HQkJLci2L!Pl(^18tc&WF-ogij-KzE{H5 zc3*1-6J1jgvt^qpcF}FDL2H%ZIZH!K<96rA!vUqYTleQXURP(Q>;&Tljl+eFz1y?P zWRcb8c{`EEH0(%=7p#XI1{|I#@A#jDIWpU!4k|v9dACluOu&+$-^#I$R%J% z>d(BYXyR8(P?qn5%5#jHV zyU>n&DFy|_HE!?3KYZdM9b8s!LXRM(6`1@!Z27BJ`v3`IGJpv==p^t*Fw-?oJz+x42gdxWdFOj@zbJ7Pw86Im57+p-Wf-sB zV|Bnz;N8|JSr?Dm@8vuV@;F?<)#Lnxb%RPSBYm&8hDS-M3=U|4kkL@$WDA({ssPnP zx?ytrBSC2`UTnLO?)W(+?n8QVeL==_?w-|}frY)!BuZe`*z|=^{~Ccj9q(*53o_Cy zU(pt)gPzc)(;80u~@(bB3!iuG-4=E>>Zo;SOh#NJ8zly z>u-ScTk6gM4tHdijwY7yw@L82#2Ev`=OZ5&Vy$GjZ*ksUjWg{I?)6?Xdj0G(|7Ngs zUX#MxJm-!?$Y1-}nj*F~j>a~Qx=L<##tzyq`J+5x*rtmKS?oIT4k@-#*+5T08N*kM zaQJoc1-O>GFx_S_Z&25o3u+c>0+_;rsQuxW-LXqUPMs7Qbz#9HtFb%vXmY*$_e*2; zS6rU5glc{YYUDJg#HN;l90V(?@P(F0$@2BRpA(tyB*qky^dL;e{PR<~AW2COx+C0) zcMYICCJt5{_N^drr`0U0CQq^9s*4QHYjW0bDM4wB2B%H*M~6~Q+olvn?T0?8;LA_Z z6Xy<@AS5kq;V}PF7n=F0#Jm*^vF(aMsQCODVmCHE`><{ZC9Q(04q{3T zD~!m$*%*@Mk_?vE;^xvLj$Yg6>Qr0Y$;omPESL2t1sY*kd`I}EWK%5+b@W;*iXfF5Nb5{Zs4E^VV`HN!oXMmm`Xb?~k zqUZO05)hDo3D++J|91v@G4PA6Bt`T)AN|wmpBd>z}|Md4KkLpGEmp{tCtNn*n^(RDsGJt+-mp(t)e>wdhKG2`)e^OX}t5ZK`kl*Tm z5nBG+O+Rb=XT03BFT{VC8!xx}?;-goN{PgO%U6G1=%0!0#nCU6TK=x~ztY^FcK)o) ze%lej|MxoWPYZwUBmTB9kNV5PU%QI`4Xl6O`}yH4-ej(fZ8ZQyf`4!=RP;dVEZ2w8VdC~n9wXy%D`