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 c93d73c..0000000 Binary files a/src/data/2023_field_ranking_top10.xlsx and /dev/null differ diff --git a/src/data/2023_foundation_ranking_top10.xlsx b/src/data/2023_foundation_ranking_top10.xlsx deleted file mode 100644 index 6bc1cb2..0000000 Binary files a/src/data/2023_foundation_ranking_top10.xlsx and /dev/null differ