diff --git a/apps/web/i18n b/apps/web/i18n index fb051d77..7ef2f39b 160000 --- a/apps/web/i18n +++ b/apps/web/i18n @@ -1 +1 @@ -Subproject commit fb051d770a4a34d12eb0ee606d3b5c35e07b362d +Subproject commit 7ef2f39b81adf8d0c089b97a2b9637d73843a611 diff --git a/apps/web/src/common/components/Header/MobileHeader.tsx b/apps/web/src/common/components/Header/MobileHeader.tsx index 0213b2a6..bece94aa 100644 --- a/apps/web/src/common/components/Header/MobileHeader.tsx +++ b/apps/web/src/common/components/Header/MobileHeader.tsx @@ -34,13 +34,18 @@ const MobileHeader: React.FC = ({ children }) => { icon: null, }, { - title: t('common:header.explore'), + title: t('common:header.docs'), + href: '/docs/dimensions-define', + icon: null, + }, + { + title: t('common:header.projects'), href: '/explore', icon: null, }, { - title: t('common:header.metrics_models'), - href: '/docs/dimensions-define', + title: t('common:header.lab'), + href: '/lab', icon: null, }, { @@ -53,11 +58,6 @@ const MobileHeader: React.FC = ({ children }) => { href: '/blog', icon: null, }, - { - title: t('common:header.lab'), - href: '/lab', - icon: null, - }, { title: t('common:header.about'), href: '/about', diff --git a/apps/web/src/common/components/Header/index.tsx b/apps/web/src/common/components/Header/index.tsx index d9f7c080..ec3f7381 100644 --- a/apps/web/src/common/components/Header/index.tsx +++ b/apps/web/src/common/components/Header/index.tsx @@ -30,23 +30,30 @@ const Header: React.FC<{ - - {t('common:header.explore')} - - - {t('common:header.metrics_models')} + {t('common:header.docs')} + + {t('common:header.projects')} + + + + {t('common:header.lab')} + + @@ -59,13 +66,6 @@ const Header: React.FC<{ - - {t('common:header.lab')} - - ; - legendselectchanged?: any; + filterData?: any; } const MetricChart: React.FC = ({ @@ -23,7 +23,7 @@ const MetricChart: React.FC = ({ loading, theme, containerRef, - legendselectchanged, + filterData, }) => { const inView = useInViewportDebounce(containerRef); const chartRef = useRef(null); @@ -54,18 +54,17 @@ const MetricChart: React.FC = ({ if (inView && chartRef.current !== null) { const chart = getInstanceByDom(chartRef.current)!; chart.setOption(option, settings); - if (legendselectchanged) { - const chart = getInstanceByDom(chartRef.current)!; + if (filterData) { chart.on('legendselectchanged', function (params: any) { - let selected = params.selected!; - let options = chart.getOption(); - let selectedList = Object.keys(selected).filter( + const selected = params.selected!; + const options = chart.getOption(); + const selectedList = Object.keys(selected).filter( (item) => selected[item] ); - options.series[1].data = legendselectchanged.filter((item) => - selectedList.includes(item.org) + options.series[1].data = filterData.filter((item) => + selectedList.includes(item.parentName) ); - this.setOption(options); + chart.setOption(options); }); } } diff --git a/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorContribution.tsx b/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorContribution.tsx index 59af1152..ea02499c 100644 --- a/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorContribution.tsx +++ b/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorContribution.tsx @@ -1,8 +1,10 @@ import React, { useRef, useMemo } from 'react'; -import { usePullsCommentQuery } from '@oss-compass/graphql'; +import { useEcoContributorsOverviewQuery } from '@oss-compass/graphql'; import client from '@common/gqlClient'; import { useTranslation } from 'next-i18next'; import MetricChart from '@modules/analyze/components/MetricDetail/MetricChart'; +import { useEcologicalType } from './contribution'; +import { gradientRamp } from '@common/options'; import type { EChartsOption } from 'echarts'; const ContributorContribution: React.FC<{ @@ -13,789 +15,65 @@ const ContributorContribution: React.FC<{ mileage: string[]; }> = ({ label, level, beginDate, endDate, mileage }) => { const { t } = useTranslation(); + const ecologicalOptions = useEcologicalType(); const chartRef = useRef(null); - const { data, isLoading } = usePullsCommentQuery(client, { + const { data, isLoading } = useEcoContributorsOverviewQuery(client, { label: label, level: level, beginDate: beginDate, endDate: endDate, + filterOpts: [{ type: 'mileage_type', values: mileage }], }); - const data1 = [ - { - name: '个人管理者', - value: 4455, - itemStyle: { - color: '#ee6666', - }, - userList: [ - { - name: 'aramase', - count: 170, - }, - { - name: 'alexzielenski', - count: 170, - }, - { - name: 'mrunalp', - count: 161, - }, - { - name: 'p0lyn0mial', - count: 155, - }, - { - name: 'danwinship', - count: 154, - }, - { - name: 'Jefftree', - count: 145, - }, - { - name: 'gjkim42', - count: 145, - }, - { - name: 'uablrek', - count: 145, - }, - { - name: 'neolit123', - count: 132, - }, - { - name: 'AxeZhan', - count: 125, - }, - { - name: 'mengjiao-liu', - count: 123, - }, - { - name: 'tallclair', - count: 118, - }, - { - name: 'seans3', - count: 117, - }, - { - name: 'MikeSpreitzer', - count: 113, - }, - { - name: 'tkashem', - count: 107, - }, - { - name: 'Damans227', - count: 99, - }, - { - name: 'Verolop', - count: 94, - }, - { - name: 'xingyang', - count: 93, - }, - { - name: 'KnVerey', - count: 91, - }, - { - name: 'MadhavJivrajani', - count: 90, - }, - { - name: 'SataQiu', - count: 88, - }, - { - name: 'yue9944882', - count: 83, - }, - { - name: 'ritazh', - count: 74, - }, - { - name: 'jsturtevant', - count: 72, - }, - { - name: 'ahmedtd', - count: 69, - }, - { - name: 'sding3', - count: 68, - }, - { - name: 'andrewsykim', - count: 64, - }, - { - name: 'heyymonth', - count: 64, - }, - { - name: 'chendave', - count: 61, - }, - { - name: 'cyclinder', - count: 60, - }, - { - name: 'cvvz', - count: 60, - }, - { - name: 'davidmccormick', - count: 59, - }, - { - name: 'haoruan', - count: 57, - }, - { - name: 'humblec', - count: 57, - }, - { - name: 'vaibhav2107', - count: 56, - }, - { - name: 'brianpursley', - count: 55, - }, - { - name: 'odinuge', - count: 55, - }, - { - name: 'WangXiangUSTC', - count: 54, - }, - { - name: 'kkkkun', - count: 49, - }, - { - name: 'marosset', - count: 48, - }, - { - name: 'wzshiming', - count: 47, - }, - { - name: 'nikhita', - count: 46, - }, - { - name: 'mochizuki875', - count: 45, - }, - { - name: 'Vyom-Yadav', - count: 45, - }, - { - name: 'ncdc', - count: 42, - }, - { - name: 'lauralorenz', - count: 38, - }, - { - name: 'jayunit100', - count: 37, - }, - { - name: 'denkensk', - count: 36, - }, - { - name: 'mowangdk', - count: 33, - }, - { - name: 'shaneutt', - count: 33, - }, - { - name: 'harshanarayana', - count: 31, - }, - { - name: 'aimuz', - count: 30, - }, - { - name: 'carlory', - count: 28, - }, - { - name: 'deads2k', - count: 28, - }, - { - name: 'verb', - count: 28, - }, - { - name: 'mmiranda96', - count: 28, - }, - { - name: 'mikedanese', - count: 27, - }, - { - name: 'matthyx', - count: 27, - }, - { - name: 'justaugustus', - count: 26, - }, - ], - }, - { - name: '个人参与者', - value: 786, - itemStyle: { - color: '#9fe080', - }, - userList: [ - { - name: 'TommyStarK', - count: 122, - }, - { - name: 'fedebongio', - count: 66, - }, - { - name: 'sourcelliu', - count: 63, - }, - { - name: 'calvin0327', - count: 51, - }, - { - name: 'nilekhc', - count: 45, - }, - { - name: 'helayoty', - count: 41, - }, - { - name: 'xiaomudk', - count: 37, - }, - { - name: 'marquiz', - count: 36, - }, - { - name: 'tenzen-y', - count: 33, - }, - { - name: 'nikhilno1', - count: 32, - }, - { - name: 'eddycharly', - count: 32, - }, - { - name: 'czybjtu', - count: 31, - }, - { - name: 'tangwz', - count: 31, - }, - { - name: 'knelasevero', - count: 29, - }, - { - name: 'hysyeah', - count: 29, - }, - { - name: 'lanycrost', - count: 27, - }, - { - name: 'MikeZappa87', - count: 27, - }, - { - name: 'akhilerm', - count: 27, - }, - { - name: 'freddie400', - count: 27, - }, - ], - }, - { - name: '组织管理者', - value: 2689, - itemStyle: { - color: '#fac858', - }, - userList: [ - { - name: 'fromanirh', - count: 172, - }, - { - name: 'logicalhan', - count: 168, - }, - { - name: 'sathyanarays', - count: 165, - }, - { - name: 'swatisehgal', - count: 139, - }, - { - name: 'tzneal', - count: 127, - }, - { - name: 'ahg-g', - count: 126, - }, - { - name: 'Huang-Wei', - count: 123, - }, - { - name: 'jsafrane', - count: 112, - }, - { - name: 'robscott', - count: 108, - }, - { - name: 'dgrisonnet', - count: 97, - }, - { - name: 'DangerOnTheRanger', - count: 85, - }, - { - name: 'justinsb', - count: 80, - }, - { - name: 'claudiubelu', - count: 80, - }, - { - name: 'aaron-prindle', - count: 77, - }, - { - name: 'darkowlzz', - count: 77, - }, - { - name: 'maxsmythe', - count: 75, - }, - { - name: 'yangjunmyfm192085', - count: 75, - }, - { - name: 'alexanderConstantinescu', - count: 73, - }, - { - name: 'akremsa', - count: 64, - }, - { - name: 'harche', - count: 59, - }, - { - name: 'ruiwen-zhao', - count: 53, - }, - { - name: 'jkh52', - count: 50, - }, - { - name: 'zhangbanger', - count: 47, - }, - { - name: 'pbetkier', - count: 44, - }, - { - name: 'mattcary', - count: 41, - }, - { - name: 'linxiulei', - count: 41, - }, - { - name: 'nckturner', - count: 40, - }, - { - name: 'haircommander', - count: 39, - }, - { - name: 'howardjohn', - count: 36, - }, - { - name: 'stlaz', - count: 33, - }, - { - name: 'tosi3k', - count: 32, - }, - { - name: 'princepereira', - count: 32, - }, - { - name: 'rphillips', - count: 31, - }, - { - name: 'benluddy', - count: 31, - }, - { - name: 'RomanBednar', - count: 29, - }, - { - name: 'pwschuurman', - count: 28, - }, - ], - }, - { - name: '组织参与者', - value: 470, - itemStyle: { - color: '#5c6bc0', - }, - userList: [ - { - name: 'danielvegamyhre', - count: 112, - }, - { - name: 'moshe010', - count: 99, - }, - { - name: 'bketelsen', - count: 86, - }, - { - name: 'skitt', - count: 69, - }, - { - name: 'adrianreber', - count: 58, - }, - { - name: 'yt2985', - count: 46, - }, - ], - }, - ]; - let data2 = [ - { - name: 'aramase', - value: 170, - org: '个人管理者', - }, - { - name: 'alexzielenski', - value: 170, - org: '个人管理者', - }, - { - name: 'mrunalp', - value: 161, - org: '个人管理者', - }, - { - name: 'p0lyn0mial', - value: 155, - org: '个人管理者', - }, - { - name: 'danwinship', - value: 154, - org: '个人管理者', - }, - { - name: 'Jefftree', - value: 145, - org: '个人管理者', - }, - { - name: 'gjkim42', - value: 145, - org: '个人管理者', - }, - { - name: 'uablrek', - value: 145, - org: '个人管理者', - }, - { - name: 'neolit123', - value: 132, - org: '个人管理者', - }, - { - name: 'AxeZhan', - value: 125, - org: '个人管理者', - }, - { - name: 'mengjiao-liu', - value: 123, - org: '个人管理者', - }, - { - name: 'other', - value: 2830, - org: '个人管理者', - }, - { - name: 'TommyStarK', - value: 122, - org: '个人参与者', - }, - { - name: 'fedebongio', - value: 66, - org: '个人参与者', - }, - { - name: 'sourcelliu', - value: 63, - org: '个人参与者', - }, - { - name: 'calvin0327', - value: 51, - org: '个人参与者', - }, - { - name: 'nilekhc', - value: 45, - org: '个人参与者', - }, - { - name: 'helayoty', - value: 41, - org: '个人参与者', - }, - { - name: 'xiaomudk', - value: 37, - org: '个人参与者', - }, - { - name: 'marquiz', - value: 36, - org: '个人参与者', - }, - { - name: 'tenzen-y', - value: 33, - org: '个人参与者', - }, - { - name: 'nikhilno1', - value: 32, - org: '个人参与者', - }, - { - name: 'eddycharly', - value: 32, - org: '个人参与者', - }, - { - name: 'other', - value: 228, - org: '个人参与者', - }, - { - name: 'fromanirh', - value: 172, - org: '组织管理者', - }, - { - name: 'logicalhan', - value: 168, - org: '组织管理者', - }, - { - name: 'sathyanarays', - value: 165, - org: '组织管理者', - }, - { - name: 'swatisehgal', - value: 139, - org: '组织管理者', - }, - { - name: 'tzneal', - value: 127, - org: '组织管理者', - }, - { - name: 'ahg-g', - value: 126, - org: '组织管理者', - }, - { - name: 'Huang-Wei', - value: 123, - org: '组织管理者', - }, - { - name: 'jsafrane', - value: 112, - org: '组织管理者', - }, - { - name: 'robscott', - value: 108, - org: '组织管理者', - }, - { - name: 'dgrisonnet', - value: 97, - org: '组织管理者', - }, - { - name: 'DangerOnTheRanger', - value: 85, - org: '组织管理者', - }, - { - name: 'other', - value: 1267, - org: '组织管理者', - }, - { - name: 'danielvegamyhre', - value: 112, - org: '组织参与者', - }, - { - name: 'moshe010', - value: 99, - org: '组织参与者', - }, - { - name: 'bketelsen', - value: 86, - org: '组织参与者', - }, - { - name: 'skitt', - value: 69, - org: '组织参与者', - }, - { - name: 'adrianreber', - value: 58, - org: '组织参与者', - }, - { - name: 'yt2985', - value: 46, - org: '组织参与者', - }, - ]; - let legend = []; - data1.forEach((z) => { - legend.push(z.name); - }); - var option1: EChartsOption = { + const getEcologicalText = (text) => { + return ecologicalOptions.find((i) => i.value === text)?.text || text; + }; + const getSeries = useMemo(() => { + const legend = []; + const ecoData = []; + const contributorsData = []; + if (data?.ecoContributorsOverview?.length > 0) { + const ecoContributorsOverview = data.ecoContributorsOverview; + ecoContributorsOverview.forEach((item, i) => { + const { subTypeName, topContributorDistribution } = item; + const colorList = gradientRamp[i]; + let count = 0; + topContributorDistribution.forEach(({ subCount, subName }, index) => { + count += subCount; + contributorsData.push({ + parentName: getEcologicalText(subTypeName), + name: subName, + value: subCount, + itemStyle: { color: colorList[index + 1] }, + }); + }); + legend.push({ + name: getEcologicalText(subTypeName), + itemStyle: { color: colorList[0] }, + }); + ecoData.push({ + name: getEcologicalText(subTypeName), + value: count, + itemStyle: { color: colorList[0] }, + }); + }); + } + return { + legend, + ecoData, + contributorsData, + }; + }, [data]); + + const option: EChartsOption = { tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)', }, - color: [ - // "#5470c6", - // "#91cc75", - // "#fac858", - // "#ee6666", - '#2ec7c9', - '#b6a2de', - '#5ab1ef', - '#ffb980', - '#d87a80', - '#8d98b3', - '#e5cf0d', - '#97b552', - '#95706d', - '#dc69aa', - '#07a2a4', - '#9a7fd1', - '#588dd5', - '#f5994e', - '#c05050', - '#59678c', - '#c9ab00', - '#7eb00a', - '#6f5553', - '#c14089', - ], legend: { top: '2%', left: 'center', - type: 'scroll', - data: legend, + data: getSeries.legend, }, - // title: { - // top: 10, - // // text: title, - // left: "center", - // }, series: [ { name: '生态类型', @@ -815,7 +93,7 @@ const ContributorContribution: React.FC<{ hideOverlap: false, moveOverlap: 'shiftY', }, - data: data1, + data: getSeries.ecoData, }, { name: '贡献者', @@ -828,77 +106,19 @@ const ContributorContribution: React.FC<{ formatter: '{b}: {c} ({d}%)', color: '#333', }, - data: data2, - }, - ], - }; - const getSeries = useMemo(() => { - const distribution = data?.pullsDetailOverview?.pullCommentDistribution; - if (data && distribution?.length > 0) { - return distribution.map(({ subCount, subName }) => { - return { name: subName, value: subCount, count: subCount }; - }); - } else { - return []; - } - }, [data]); - - const option: EChartsOption = { - tooltip: { - trigger: 'item', - formatter: '{b}: {c} ({d}%)', - }, - color: [ - '#2ec7c9', - '#b6a2de', - '#5ab1ef', - '#ffb980', - '#d87a80', - '#8d98b3', - '#e5cf0d', - '#97b552', - '#95706d', - '#dc69aa', - '#07a2a4', - '#9a7fd1', - '#588dd5', - '#f5994e', - '#c05050', - '#59678c', - '#c9ab00', - '#7eb00a', - '#6f5553', - '#c14089', - ], - legend: { - top: '2%', - left: 'center', - }, - series: [ - { - name: '', - type: 'pie', - selectedMode: 'single', - radius: [0, '65%'], - label: { - position: 'inner', - fontSize: 14, - color: '#333', - }, - data: getSeries, + data: getSeries.contributorsData, }, ], }; - const legendselectchanged = () => {}; return (
); diff --git a/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorContributors.tsx b/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorContributors.tsx index 1de67753..a3f4e615 100644 --- a/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorContributors.tsx +++ b/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorContributors.tsx @@ -1,8 +1,9 @@ import React, { useRef, useMemo } from 'react'; -import { useContributorsOrganizationQuery } from '@oss-compass/graphql'; +import { useContributorsOverviewQuery } from '@oss-compass/graphql'; import client from '@common/gqlClient'; import { useTranslation } from 'next-i18next'; import MetricChart from '@modules/analyze/components/MetricDetail/MetricChart'; +import { useEcologicalType } from './contribution'; import type { EChartsOption } from 'echarts'; const ContributorContributors: React.FC<{ @@ -13,24 +14,25 @@ const ContributorContributors: React.FC<{ mileage: string[]; }> = ({ label, level, beginDate, endDate, mileage }) => { const { t } = useTranslation(); + const ecologicalOptions = useEcologicalType(); const chartRef = useRef(null); - const { data, isLoading } = useContributorsOrganizationQuery(client, { + const { data, isLoading } = useContributorsOverviewQuery(client, { label: label, level: level, beginDate: beginDate, endDate: endDate, + filterOpts: [{ type: 'mileage_type', values: mileage }], }); - + const getEcologicalText = (text) => { + return ecologicalOptions.find((i) => i.value === text)?.text || text; + }; const getSeries = useMemo(() => { - const distribution = - data?.contributorsDetailOverview?.ecologicalDistribution; - if (data && distribution?.length > 0) { - return distribution.map(({ subCount, subName }) => { - return { name: subName, value: subCount, count: subCount }; - }); - } else { - return []; - } + return data?.ecoDistributionOverview?.map(({ subCount, subName }) => { + return { + name: getEcologicalText(subName), + value: subCount, + }; + }); }, [data]); const option: EChartsOption = { diff --git a/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorOrganizations.tsx b/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorOrganizations.tsx index 70d77c5a..69c4cf48 100644 --- a/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorOrganizations.tsx +++ b/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorOrganizations.tsx @@ -1,8 +1,9 @@ import React, { useRef, useMemo } from 'react'; -import { usePullsCommentQuery } from '@oss-compass/graphql'; +import { useOrgContributorsOverviewQuery } from '@oss-compass/graphql'; import client from '@common/gqlClient'; import { useTranslation } from 'next-i18next'; import MetricChart from '@modules/analyze/components/MetricDetail/MetricChart'; +import { gradientRamp } from '@common/options'; import type { EChartsOption } from 'echarts'; const ContributorContribution: React.FC<{ @@ -14,502 +15,60 @@ const ContributorContribution: React.FC<{ }> = ({ label, level, beginDate, endDate, mileage }) => { const { t } = useTranslation(); const chartRef = useRef(null); - const { data, isLoading } = usePullsCommentQuery(client, { + const { data, isLoading } = useOrgContributorsOverviewQuery(client, { label: label, level: level, beginDate: beginDate, endDate: endDate, + filterOpts: [{ type: 'mileage_type', values: mileage }], }); - const data1 = [ - { - name: 'Google, Inc.', - value: 1396, - userList: [ - { - name: 'logicalhan', - value: 168, - org: 'Google, Inc.', - }, - { - name: 'ahg-g', - value: 126, - org: 'Google, Inc.', - }, - { - name: 'danielvegamyhre', - value: 112, - org: 'Google, Inc.', - }, - { - name: 'robscott', - value: 108, - org: 'Google, Inc.', - }, - { - name: 'bketelsen', - value: 86, - org: 'Google, Inc.', - }, - { - name: 'DangerOnTheRanger', - value: 85, - org: 'Google, Inc.', - }, - { - name: 'justinsb', - value: 80, - org: 'Google, Inc.', - }, - { - name: 'aaron-prindle', - value: 77, - org: 'Google, Inc.', - }, - { - name: 'darkowlzz', - value: 77, - org: 'Google, Inc.', - }, - { - name: 'maxsmythe', - value: 75, - org: 'Google, Inc.', - }, - { - name: 'ruiwen-zhao', - value: 53, - org: 'Google, Inc.', - }, - { - name: 'jkh52', - value: 50, - org: 'Google, Inc.', - }, - { - name: 'yt2985', - value: 46, - org: 'Google, Inc.', - }, - { - name: 'pbetkier', - value: 44, - org: 'Google, Inc.', - }, - { - name: 'mattcary', - value: 41, - org: 'Google, Inc.', - }, - { - name: 'linxiulei', - value: 41, - org: 'Google, Inc.', - }, - { - name: 'howardjohn', - value: 36, - org: 'Google, Inc.', - }, - { - name: 'tosi3k', - value: 32, - org: 'Google, Inc.', - }, - { - name: 'benluddy', - value: 31, - org: 'Google, Inc.', - }, - { - name: 'pwschuurman', - value: 28, - org: 'Google, Inc.', - }, - ], - }, - { - name: 'Red Hat', - value: 902, - userList: [ - { - name: 'fromanirh', - value: 172, - org: 'Red Hat', - }, - { - name: 'swatisehgal', - value: 139, - org: 'Red Hat', - }, - { - name: 'jsafrane', - value: 112, - org: 'Red Hat', - }, - { - name: 'dgrisonnet', - value: 97, - org: 'Red Hat', - }, - { - name: 'skitt', - value: 69, - org: 'Red Hat', - }, - { - name: 'akremsa', - value: 64, - org: 'Red Hat', - }, - { - name: 'harche', - value: 59, - org: 'Red Hat', - }, - { - name: 'adrianreber', - value: 58, - org: 'Red Hat', - }, - { - name: 'haircommander', - value: 39, - org: 'Red Hat', - }, - { - name: 'stlaz', - value: 33, - org: 'Red Hat', - }, - { - name: 'rphillips', - value: 31, - org: 'Red Hat', - }, - { - name: 'RomanBednar', - value: 29, - org: 'Red Hat', - }, - ], - }, - { - name: 'Amazon.com', - value: 167, - userList: [ - { - name: 'tzneal', - value: 127, - org: 'Amazon.com', - }, - { - name: 'nckturner', - value: 40, - org: 'Amazon.com', - }, - ], - }, - { - name: 'VMware', - value: 165, - userList: [ - { - name: 'sathyanarays', - value: 165, - org: 'VMware', - }, - ], - }, - { - name: 'Apple', - value: 123, - userList: [ - { - name: 'Huang-Wei', - value: 123, - org: 'Apple', - }, - ], - }, - { - name: 'NVidia', - value: 99, - userList: [ - { - name: 'moshe010', - value: 99, - org: 'NVidia', - }, - ], - }, - { - name: 'Cloudbase Solutions', - value: 80, - userList: [ - { - name: 'claudiubelu', - value: 80, - org: 'Cloudbase Solutions', - }, - ], - }, - { - name: 'Microsoft', - value: 79, - userList: [ - { - name: 'zhangbanger', - value: 47, - org: 'Microsoft', - }, - { - name: 'princepereira', - value: 32, - org: 'Microsoft', - }, - ], - }, - { - name: 'ZTE', - value: 75, - userList: [ - { - name: 'yangjunmyfm192085', - value: 75, - org: 'ZTE', - }, - ], - }, - { - name: 'Confluent', - value: 73, - userList: [ - { - name: 'alexanderConstantinescu', - value: 73, - org: 'Confluent', - }, - ], - }, - ]; - let data2 = [ - { - name: 'logicalhan', - value: 168, - org: 'Google, Inc.', - }, - { - name: 'ahg-g', - value: 126, - org: 'Google, Inc.', - }, - { - name: 'danielvegamyhre', - value: 112, - org: 'Google, Inc.', - }, - { - name: 'robscott', - value: 108, - org: 'Google, Inc.', - }, - { - name: 'bketelsen', - value: 86, - org: 'Google, Inc.', - }, - { - name: 'DangerOnTheRanger', - value: 85, - org: 'Google, Inc.', - }, - { - name: 'justinsb', - value: 80, - org: 'Google, Inc.', - }, - { - name: 'aaron-prindle', - value: 77, - org: 'Google, Inc.', - }, - { - name: 'darkowlzz', - value: 77, - org: 'Google, Inc.', - }, - { - name: 'maxsmythe', - value: 75, - org: 'Google, Inc.', - }, - { - name: 'ruiwen-zhao', - value: 53, - org: 'Google, Inc.', - }, - { - name: 'Google, Inc.-other', - value: 349, - org: 'Google, Inc.', - }, - { - name: 'fromanirh', - value: 172, - org: 'Red Hat', - }, - { - name: 'swatisehgal', - value: 139, - org: 'Red Hat', - }, - { - name: 'jsafrane', - value: 112, - org: 'Red Hat', - }, - { - name: 'dgrisonnet', - value: 97, - org: 'Red Hat', - }, - { - name: 'skitt', - value: 69, - org: 'Red Hat', - }, - { - name: 'akremsa', - value: 64, - org: 'Red Hat', - }, - { - name: 'harche', - value: 59, - org: 'Red Hat', - }, - { - name: 'adrianreber', - value: 58, - org: 'Red Hat', - }, - { - name: 'haircommander', - value: 39, - org: 'Red Hat', - }, - { - name: 'stlaz', - value: 33, - org: 'Red Hat', - }, - { - name: 'rphillips', - value: 31, - org: 'Red Hat', - }, - { - name: 'Red Hat-other', - value: 29, - org: 'Red Hat', - }, - { - name: 'tzneal', - value: 127, - org: 'Amazon.com', - }, - { - name: 'nckturner', - value: 40, - org: 'Amazon.com', - }, - { - name: 'sathyanarays', - value: 165, - org: 'VMware', - }, - { - name: 'Huang-Wei', - value: 123, - org: 'Apple', - }, - { - name: 'moshe010', - value: 99, - org: 'NVidia', - }, - { - name: 'claudiubelu', - value: 80, - org: 'Cloudbase Solutions', - }, - { - name: 'zhangbanger', - value: 47, - org: 'Microsoft', - }, - { - name: 'princepereira', - value: 32, - org: 'Microsoft', - }, - { - name: 'yangjunmyfm192085', - value: 75, - org: 'ZTE', - }, - { - name: 'alexanderConstantinescu', - value: 73, - org: 'Confluent', - }, - ]; - let legend = []; - data1.forEach((z) => { - legend.push(z.name); - }); - var option1: EChartsOption = { + const getSeries = useMemo(() => { + const legend = []; + const ecoData = []; + const contributorsData = []; + if (data?.orgContributorsOverview?.length > 0) { + const ecoContributorsOverview = data.orgContributorsOverview; + ecoContributorsOverview.forEach((item, i) => { + const { subTypeName, topContributorDistribution } = item; + const colorList = gradientRamp[i]; + let count = 0; + topContributorDistribution.forEach(({ subCount, subName }, index) => { + count += subCount; + contributorsData.push({ + parentName: subTypeName, + name: subName, + value: subCount, + itemStyle: { color: colorList[index + 1] }, + }); + }); + legend.push({ + name: subTypeName, + itemStyle: { color: colorList[0] }, + }); + ecoData.push({ + name: subTypeName, + value: count, + itemStyle: { color: colorList[0] }, + }); + }); + } + return { + legend, + ecoData, + contributorsData, + }; + }, [data]); + + const option: EChartsOption = { tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)', }, - color: [ - // "#5470c6", - // "#91cc75", - // "#fac858", - // "#ee6666", - '#2ec7c9', - '#b6a2de', - '#5ab1ef', - '#ffb980', - '#d87a80', - '#8d98b3', - '#e5cf0d', - '#97b552', - '#95706d', - '#dc69aa', - '#07a2a4', - '#9a7fd1', - '#588dd5', - '#f5994e', - '#c05050', - '#59678c', - '#c9ab00', - '#7eb00a', - '#6f5553', - '#c14089', - ], legend: { top: '2%', left: 'center', - type: 'scroll', - data: legend, + data: getSeries.legend, }, - // title: { - // top: 10, - // // text: title, - // left: "center", - // }, series: [ { name: '生态类型', @@ -520,6 +79,7 @@ const ContributorContribution: React.FC<{ position: 'inner', fontSize: 12, color: '#333', + formatter: '{b}: {c} ({d}%)', }, labelLine: { show: false, @@ -528,7 +88,7 @@ const ContributorContribution: React.FC<{ hideOverlap: false, moveOverlap: 'shiftY', }, - data: data1, + data: getSeries.ecoData, }, { name: '贡献者', @@ -541,81 +101,19 @@ const ContributorContribution: React.FC<{ formatter: '{b}: {c} ({d}%)', color: '#333', }, - data: data2, - }, - ], - }; - const getSeries = useMemo(() => { - const distribution = data?.pullsDetailOverview?.pullCommentDistribution; - if (data && distribution?.length > 0) { - return distribution.map(({ subCount, subName }) => { - return { name: subName, value: subCount, count: subCount }; - }); - } else { - return []; - } - }, [data]); - - const option: EChartsOption = { - tooltip: { - trigger: 'item', - formatter: '{b}: {c} ({d}%)', - }, - color: [ - // '#5470c6', - // '#91cc75', - // '#fac858', - // '#ee6666', - '#2ec7c9', - '#b6a2de', - '#5ab1ef', - '#ffb980', - '#d87a80', - '#8d98b3', - '#e5cf0d', - '#97b552', - '#95706d', - '#dc69aa', - '#07a2a4', - '#9a7fd1', - '#588dd5', - '#f5994e', - '#c05050', - '#59678c', - '#c9ab00', - '#7eb00a', - '#6f5553', - '#c14089', - ], - legend: { - top: '2%', - left: 'center', - }, - series: [ - { - name: '', - type: 'pie', - selectedMode: 'single', - radius: [0, '65%'], - label: { - position: 'inner', - fontSize: 14, - color: '#333', - }, - data: getSeries, + data: getSeries.contributorsData, }, ], }; - const legendselectchanged = () => {}; return (
); diff --git a/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorTable.tsx b/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorTable.tsx index 7e91258b..ea76428a 100644 --- a/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorTable.tsx +++ b/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/ContributorTable.tsx @@ -95,6 +95,14 @@ const MetricTable: React.FC<{ }, }); }, + onError(res: any) { + // toast.error( + // getErrorMessage(res) || (() => <>{t('lab:create_failed')}), + // { + // position: 'top-center', + // } + // ); + }, }); const handleTableChange = ( pagination: TablePaginationConfig, @@ -133,14 +141,14 @@ const MetricTable: React.FC<{ title: t('analyze:metric_detail:contributor'), dataIndex: 'contributor', align: 'center', - width: '15%', + width: '200px', sorter: true, }, { title: t('analyze:metric_detail:role_persona'), dataIndex: 'ecologicalType', align: 'center', - width: '15%', + width: '200px', filters: ecologicalOptions, render: (text) => { return ecologicalOptions.find((i) => i.value === text).text; @@ -154,7 +162,7 @@ const MetricTable: React.FC<{ return mileageOptions.find((i) => i.value === text).label; }, align: 'center', - width: '10%', + width: '200px', }, { title: t('analyze:metric_detail:domain_persona'), @@ -186,13 +194,13 @@ const MetricTable: React.FC<{ filters: useContributionTypeLsit(), filterMode: 'tree', align: 'center', - width: '20%', + width: '220px', }, { title: t('analyze:metric_detail:organization'), dataIndex: 'organization', align: 'center', - width: '20%', + width: '160px', }, { title: t('analyze:metric_detail:contribution'), @@ -210,7 +218,7 @@ const MetricTable: React.FC<{ } }, align: 'center', - width: '10%', + width: '100px', sorter: true, }, ]; diff --git a/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/index.tsx b/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/index.tsx index 1b403b19..6cda24ad 100644 --- a/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/index.tsx +++ b/apps/web/src/modules/analyze/components/MetricDetail/MetricContributor/index.tsx @@ -9,6 +9,8 @@ import MetricTable from './ContributorTable'; import ContributorContribution from './ContributorContribution'; import ContributorOrganizations from './ContributorOrganizations'; import ContributorContributors from './ContributorContributors'; +import { AiOutlineQuestionCircle } from 'react-icons/ai'; +import Tooltip from '@common/components/Tooltip'; const MetricContributor: React.FC<{ label: string; @@ -121,11 +123,38 @@ const MetricContributor: React.FC<{ value="4" /> -
- +
+ {/* {t('analyze:metric_detail:milestone_persona_filter')}: + */} + + {t('analyze:metric_detail:milestone_persona_filter')} + +
+ + {t('analyze:metric_detail:core')} : + + {t('analyze:metric_detail:core_desc')} +
+
+ + {t('analyze:metric_detail:regular')} : + + {t('analyze:metric_detail:regular_desc')} +
+ + } + placement="right" + > + + + +
- + : { } return (
-
+
+ {t('analyze:metric_detail:project_deep_dive_insight')} +
+
- - +
+ + +
); @@ -63,21 +68,23 @@ const MetricBoxContributors: React.FC<{ const slugs = router.query.slugs; return ( -
+
-
- {t('analyze:metric_detail:contributors_persona')} +
+ {t('analyze:metric_detail:contributor')}
{ - router.push('/analyze/metric/' + slugs); + router.push( + '/analyze/metric/' + slugs + '?range=1M&type=contributor' + ); }} > {t('analyze:metric_detail:details')}
-
+
@@ -138,21 +145,21 @@ const MetricBoxIssues: React.FC<{ const slugs = router.query.slugs; return ( -
+
-
+
{t('analyze:metric_detail:issues')}
{ - router.push('/analyze/metric/' + slugs); + router.push('/analyze/metric/' + slugs + '?range=1M&type=issue'); }} > {t('analyze:metric_detail:details')}
-
+
@@ -216,21 +223,21 @@ const MetricBoxPr: React.FC<{ const router = useRouter(); const slugs = router.query.slugs; return ( -
+
-
+
{t('analyze:metric_detail:pull_requests')}
{ - router.push('/analyze/metric/' + slugs); + router.push('/analyze/metric/' + slugs + '?range=1M&type=pr'); }} className="cursor-pointer pt-1 text-sm text-[#585858]" > {t('analyze:metric_detail:details')}
-
+
diff --git a/apps/web/src/modules/analyze/components/MetricDetail/MetricDetailMore.tsx b/apps/web/src/modules/analyze/components/MetricDetail/MetricDetailMore.tsx index 0926f502..47279587 100644 --- a/apps/web/src/modules/analyze/components/MetricDetail/MetricDetailMore.tsx +++ b/apps/web/src/modules/analyze/components/MetricDetail/MetricDetailMore.tsx @@ -13,30 +13,34 @@ const MetricDetailPage = () => { const { t } = useTranslation(); const router = useRouter(); const slugs = router.query.slugs; + const type = (router.query.type as string) || 'contributor'; const { isLoading, verifiedItems } = useLabelStatus(); - const [tab, setTab] = useState('1'); + const [tab, setTab] = useState(type); if (isLoading || verifiedItems.length > 1) { return null; } const { label, level } = verifiedItems[0]; const tabOptions = [ - { label: t('analyze:metric_detail:contributors_persona'), value: '1' }, - { label: t('analyze:metric_detail:issues'), value: '2' }, - { label: t('analyze:metric_detail:pull_requests'), value: '3' }, + { + label: t('analyze:metric_detail:contributors_persona'), + value: 'contributor', + }, + { label: t('analyze:metric_detail:issues'), value: 'issue' }, + { label: t('analyze:metric_detail:pull_requests'), value: 'pr' }, ]; let source; switch (tab) { - case '1': { + case 'contributor': { source = ; break; } - case '2': { + case 'issue': { source = ; break; } - case '3': { + case 'pr': { source = ; break; } diff --git a/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/IssueComments.tsx b/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/IssueComments.tsx index 49d331b4..60f8c648 100644 --- a/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/IssueComments.tsx +++ b/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/IssueComments.tsx @@ -24,7 +24,11 @@ const IssueCompletion: React.FC<{ const distribution = data?.issuesDetailOverview?.issueCommentDistribution; if (data && distribution?.length > 0) { return distribution.map(({ subCount, subName }) => { - return { name: subName, value: subCount, count: subCount }; + return { + name: subName + t('analyze:metric_detail:comments'), + value: subCount, + count: subCount, + }; }); } else { return []; @@ -34,7 +38,7 @@ const IssueCompletion: React.FC<{ const option: EChartsOption = { tooltip: { trigger: 'item', - formatter: '{b}: {c} ({d}%)', + formatter: '{b} : {c} ({d}%)', }, color: [ // '#5470c6', @@ -76,7 +80,7 @@ const IssueCompletion: React.FC<{ position: 'inner', fontSize: 14, color: '#333', - formatter: '{b}: {c} ({d}%)', + formatter: '{b} : {c} ({d}%)', }, data: getSeries, }, diff --git a/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/IssueCompletion.tsx b/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/IssueCompletion.tsx index 0803ea6b..70d68bcf 100644 --- a/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/IssueCompletion.tsx +++ b/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/IssueCompletion.tsx @@ -4,6 +4,7 @@ import client from '@common/gqlClient'; import { useTranslation } from 'next-i18next'; import MetricChart from '@modules/analyze/components/MetricDetail/MetricChart'; import type { EChartsOption } from 'echarts'; +import { useStateType } from './issue'; const IssueCompletion: React.FC<{ label: string; @@ -12,6 +13,7 @@ const IssueCompletion: React.FC<{ endDate: Date; }> = ({ label, level, beginDate, endDate }) => { const { t } = useTranslation(); + const stateOption = useStateType(); const chartRef = useRef(null); const { data, isLoading } = useIssueCompletionQuery(client, { label: label, @@ -19,12 +21,17 @@ const IssueCompletion: React.FC<{ beginDate: beginDate, endDate: endDate, }); - + const getStateText = (text) => { + return stateOption.find((i) => i.value === text)?.text || text; + }; const getSeries = useMemo(() => { const distribution = data?.issuesDetailOverview?.issueStateDistribution; if (data && distribution?.length > 0) { return distribution.map(({ subCount, subName }) => { - return { name: subName, value: subCount, count: subCount }; + return { + name: getStateText(subName), + value: subCount, + }; }); } else { return []; diff --git a/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/IssueTable.tsx b/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/IssueTable.tsx index 59d8d848..d0b49ee8 100644 --- a/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/IssueTable.tsx +++ b/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/IssueTable.tsx @@ -28,10 +28,6 @@ const MetricTable: React.FC<{ }> = ({ label, level, beginDate, endDate }) => { const { t } = useTranslation(); const stateOption = useStateType(); - const filterMap = { - ecologicalType: 'ecological_type', - contributionTypeList: 'contribution_type', - }; const [tableData, setData] = useState(); const [tableParams, setTableParams] = useState({ pagination: { @@ -104,19 +100,21 @@ const MetricTable: React.FC<{ title: t('analyze:metric_detail:issue_title'), dataIndex: 'title', align: 'center', - width: '15%', + width: '200px', + sorter: true, }, { title: 'URL', dataIndex: 'url', align: 'center', - width: '15%', + width: '250px', }, { title: t('analyze:metric_detail:state'), dataIndex: 'state', align: 'center', - width: '6%', + width: '100px', + sorter: true, filters: stateOption, render: (text) => { return stateOption.find((i) => i.value === text)?.text || text; @@ -126,51 +124,59 @@ const MetricTable: React.FC<{ title: t('analyze:metric_detail:created_time'), dataIndex: 'createdAt', align: 'center', - width: '8%', + sorter: true, + width: '120px', render: (time) => format(parseJSON(time)!, 'yyyy-MM-dd'), }, { title: t('analyze:metric_detail:close_time'), dataIndex: 'closedAt', align: 'center', - width: '8%', + sorter: true, + width: '120px', render: (time) => (time ? format(parseJSON(time)!, 'yyyy-MM-dd') : ''), }, { title: t('analyze:metric_detail:processing_time'), dataIndex: 'timeToCloseDays', align: 'center', - width: '8%', + sorter: true, + width: '140px', }, { title: t('analyze:metric_detail:first_response_time'), dataIndex: 'timeToFirstAttentionWithoutBot', align: 'center', - width: '8%', + sorter: true, + width: '170px', }, { title: t('analyze:metric_detail:comments_count'), dataIndex: 'numOfCommentsWithoutBot', align: 'center', - width: '6%', + sorter: true, + width: '120px', }, { title: t('analyze:metric_detail:tags'), dataIndex: 'labels', align: 'center', - width: '12%', + render: (list) => list?.join(', ') || '', + width: '100px', }, { title: t('analyze:metric_detail:creator'), dataIndex: 'userLogin', align: 'center', - width: '8%', + sorter: true, + width: '100px', }, { title: t('analyze:metric_detail:assignee'), dataIndex: 'assigneeLogin', align: 'center', - width: '12%', + sorter: true, + width: '100px', }, ]; return ( diff --git a/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/issue.ts b/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/issue.ts index 97864bf1..32cf630d 100644 --- a/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/issue.ts +++ b/apps/web/src/modules/analyze/components/MetricDetail/MetricIssue/issue.ts @@ -12,5 +12,13 @@ export const useStateType = () => { text: t('analyze:metric_detail:closed'), value: 'closed', }, + { + text: t('analyze:metric_detail:progressing'), + value: 'progressing', + }, + { + text: t('analyze:metric_detail:rejected'), + value: 'rejected', + }, ]; }; diff --git a/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/PR.ts b/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/PR.ts new file mode 100644 index 00000000..edbbe5ba --- /dev/null +++ b/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/PR.ts @@ -0,0 +1,20 @@ +import { useTranslation } from 'react-i18next'; + +export const useStateType = () => { + const { t } = useTranslation(); + + return [ + { + text: t('analyze:metric_detail:open'), + value: 'open', + }, + { + text: t('analyze:metric_detail:closed'), + value: 'closed', + }, + { + text: t('analyze:metric_detail:merged'), + value: 'merged', + }, + ]; +}; diff --git a/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/PrComments.tsx b/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/PrComments.tsx index 17b2ffce..bd12784a 100644 --- a/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/PrComments.tsx +++ b/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/PrComments.tsx @@ -19,12 +19,14 @@ const PrComments: React.FC<{ beginDate: beginDate, endDate: endDate, }); - const getSeries = useMemo(() => { const distribution = data?.pullsDetailOverview?.pullCommentDistribution; if (data && distribution?.length > 0) { return distribution.map(({ subCount, subName }) => { - return { name: subName, value: subCount, count: subCount }; + return { + name: subName + t('analyze:metric_detail:comments'), + value: subCount, + }; }); } else { return []; @@ -34,7 +36,7 @@ const PrComments: React.FC<{ const option: EChartsOption = { tooltip: { trigger: 'item', - formatter: '{b}: {c} ({d}%)', + formatter: `{b} : {c} ({d}%)`, }, color: [ // '#5470c6', @@ -76,7 +78,7 @@ const PrComments: React.FC<{ position: 'inner', fontSize: 14, color: '#333', - formatter: '{b}: {c} ({d}%)', + formatter: '{b} : {c} ({d}%)', }, data: getSeries, }, diff --git a/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/PrCompletion.tsx b/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/PrCompletion.tsx index 3f1a2ffc..de2ff163 100644 --- a/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/PrCompletion.tsx +++ b/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/PrCompletion.tsx @@ -3,6 +3,7 @@ import { usePullsCompletionQuery } from '@oss-compass/graphql'; import client from '@common/gqlClient'; import { useTranslation } from 'next-i18next'; import MetricChart from '@modules/analyze/components/MetricDetail/MetricChart'; +import { useStateType } from '@modules/analyze/components/MetricDetail/MetricPr/PR'; import type { EChartsOption } from 'echarts'; const PrCompletion: React.FC<{ @@ -12,6 +13,7 @@ const PrCompletion: React.FC<{ endDate: Date; }> = ({ label, level, beginDate, endDate }) => { const { t } = useTranslation(); + const stateOption = useStateType(); const chartRef = useRef(null); const { data, isLoading } = usePullsCompletionQuery(client, { label: label, @@ -19,12 +21,14 @@ const PrCompletion: React.FC<{ beginDate: beginDate, endDate: endDate, }); - + const getStateText = (text) => { + return stateOption.find((i) => i.value === text)?.text || text; + }; const getSeries = useMemo(() => { const distribution = data?.pullsDetailOverview?.pullStateDistribution; if (data && distribution?.length > 0) { return distribution.map(({ subCount, subName }) => { - return { name: subName, value: subCount, count: subCount }; + return { name: getStateText(subName), value: subCount }; }); } else { return []; @@ -34,7 +38,7 @@ const PrCompletion: React.FC<{ const option: EChartsOption = { tooltip: { trigger: 'item', - formatter: '{b}: {c} ({d}%)', + formatter: '{b} : {c} ({d}%)', }, color: [ // '#5470c6', @@ -76,7 +80,7 @@ const PrCompletion: React.FC<{ position: 'inner', fontSize: 14, color: '#333', - formatter: '{b}: {c} ({d}%)', + formatter: '{b} : {c} ({d}%)', }, data: getSeries, }, diff --git a/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/PrTable.tsx b/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/PrTable.tsx index 9b56f268..0be01219 100644 --- a/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/PrTable.tsx +++ b/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/PrTable.tsx @@ -11,7 +11,7 @@ import type { ColumnsType, TablePaginationConfig } from 'antd/es/table'; import type { FilterValue, SorterResult } from 'antd/es/table/interface'; import { useTranslation } from 'next-i18next'; import { format, parseJSON } from 'date-fns'; -import { useStateType } from '@modules/analyze/components/MetricDetail/MetricIssue/issue'; +import { useStateType } from '@modules/analyze/components/MetricDetail/MetricPr/PR'; interface TableParams { pagination?: TablePaginationConfig; @@ -28,10 +28,6 @@ const MetricTable: React.FC<{ }> = ({ label, level, beginDate, endDate }) => { const { t } = useTranslation(); const stateOption = useStateType(); - const filterMap = { - ecologicalType: 'ecological_type', - contributionTypeList: 'contribution_type', - }; const [tableData, setData] = useState(); const [tableParams, setTableParams] = useState({ pagination: { @@ -43,6 +39,10 @@ const MetricTable: React.FC<{ }, }, filterOpts: [], + sortOpts: { + type: 'state', + direction: 'desc', + }, }); const query = { page: tableParams.pagination.current, @@ -100,20 +100,22 @@ const MetricTable: React.FC<{ title: t('analyze:metric_detail:pr_title'), dataIndex: 'title', align: 'center', - width: '12%', + width: '200px', + sorter: true, }, { title: 'URL', dataIndex: 'url', align: 'center', - width: '12%', + width: '250px', }, { title: t('analyze:metric_detail:state'), dataIndex: 'state', align: 'center', - width: '5%', + width: '100px', filters: stateOption, + sorter: true, render: (text) => { return stateOption.find((i) => i.value === text)?.text || text; }, @@ -122,58 +124,66 @@ const MetricTable: React.FC<{ title: t('analyze:metric_detail:created_time'), dataIndex: 'createdAt', align: 'center', - width: '8%', - render: (time) => format(parseJSON(time)!, 'yyyy-MM-dd'), + width: '120px', + sorter: true, + render: (time) => (time ? format(parseJSON(time)!, 'yyyy-MM-dd') : ''), }, { title: t('analyze:metric_detail:close_time'), dataIndex: 'closedAt', align: 'center', - width: '8%', + width: '120px', + sorter: true, render: (time) => (time ? format(parseJSON(time)!, 'yyyy-MM-dd') : ''), }, { title: t('analyze:metric_detail:processing_time'), dataIndex: 'timeToCloseDays', align: 'center', - width: '8%', + width: '140px', + sorter: true, }, { title: t('analyze:metric_detail:first_response_time'), dataIndex: 'timeToFirstAttentionWithoutBot', align: 'center', - width: '8%', + width: '160px', + sorter: true, }, { title: t('analyze:metric_detail:comments_count'), dataIndex: 'numReviewComments', align: 'center', - width: '8%', + width: '120px', + sorter: true, }, { title: t('analyze:metric_detail:tags'), dataIndex: 'labels', align: 'center', - width: '10%', + width: '100px', + render: (list) => list?.join(', ') || '', }, { title: t('analyze:metric_detail:creator'), dataIndex: 'userLogin', align: 'center', - width: '10%', + width: '100px', + sorter: true, }, { title: t('analyze:metric_detail:reviewer'), dataIndex: 'reviewersLogin', align: 'center', - width: '8%', - render: (list) => list.join(','), + width: '100px', + render: (list) => list?.join(',') || '', }, { title: t('analyze:metric_detail:merge_author'), dataIndex: 'mergeAuthorLogin', align: 'center', - width: '10%', + width: '100px', + sorter: true, }, ]; return ( diff --git a/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/issue.ts b/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/issue.ts deleted file mode 100644 index cb0ff5c3..00000000 --- a/apps/web/src/modules/analyze/components/MetricDetail/MetricPr/issue.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/apps/web/src/modules/analyze/components/NavBar/useI18RangeTag.tsx b/apps/web/src/modules/analyze/components/NavBar/useI18RangeTag.tsx index 5e5c059e..729bb098 100644 --- a/apps/web/src/modules/analyze/components/NavBar/useI18RangeTag.tsx +++ b/apps/web/src/modules/analyze/components/NavBar/useI18RangeTag.tsx @@ -4,10 +4,11 @@ import { useTranslation } from 'react-i18next'; const useI18RangeTag = () => { const { t } = useTranslation(); const i18RangeTag: Record = { + '1M': t('common:range.1M'), '3M': t('common:range.3M'), '6M': t('common:range.6M'), '1Y': t('common:range.1Y'), - '2Y': t('common:range.2Y'), + // '2Y': t('common:range.2Y'), '3Y': t('common:range.3Y'), '5Y': t('common:range.5Y'), 'Since 2000': t('common:range.Since2000'), diff --git a/apps/web/src/modules/analyze/constant.ts b/apps/web/src/modules/analyze/constant.ts index 625bd22e..cfbddd73 100644 --- a/apps/web/src/modules/analyze/constant.ts +++ b/apps/web/src/modules/analyze/constant.ts @@ -1,6 +1,10 @@ import { subMonths, subYears } from 'date-fns'; export const timeRange = { + '1M': { + start: subMonths(new Date(), 1), + end: new Date(), + }, '3M': { start: subMonths(new Date(), 3), end: new Date(), @@ -13,10 +17,10 @@ export const timeRange = { start: subYears(new Date(), 1), end: new Date(), }, - '2Y': { - start: subYears(new Date(), 2), - end: new Date(), - }, + // '2Y': { + // start: subYears(new Date(), 2), + // end: new Date(), + // }, '3Y': { start: subYears(new Date(), 3), end: new Date(), diff --git a/apps/web/src/modules/home/Purpose/assets/icon1.svg b/apps/web/src/modules/home/Purpose/assets/icon1.svg new file mode 100644 index 00000000..f5c22ece --- /dev/null +++ b/apps/web/src/modules/home/Purpose/assets/icon1.svg @@ -0,0 +1,28 @@ + + + icon1 + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/web/src/modules/home/Purpose/assets/icon2.svg b/apps/web/src/modules/home/Purpose/assets/icon2.svg new file mode 100644 index 00000000..28d39e1b --- /dev/null +++ b/apps/web/src/modules/home/Purpose/assets/icon2.svg @@ -0,0 +1,46 @@ + + + icon2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/web/src/modules/home/Purpose/assets/icon3.svg b/apps/web/src/modules/home/Purpose/assets/icon3.svg new file mode 100644 index 00000000..7f81410f --- /dev/null +++ b/apps/web/src/modules/home/Purpose/assets/icon3.svg @@ -0,0 +1,45 @@ + + + icon3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/web/src/modules/home/Purpose/index.tsx b/apps/web/src/modules/home/Purpose/index.tsx new file mode 100644 index 00000000..e5248c47 --- /dev/null +++ b/apps/web/src/modules/home/Purpose/index.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import Svg1 from './assets/icon1.svg'; +import Svg2 from './assets/icon2.svg'; +import Svg3 from './assets/icon3.svg'; + +const Purpose = () => { + const { t } = useTranslation(); + + return ( +
+
+
+ +
+
+ {t('home:open_source_manage')} +
+
+ {t('home:open_source_manage_desc')} +
+
+
+
+ +
+
+ {t('home:data_decision')} +
+
{t('home:data_decision_desc')}
+
+
+
+ +
+
+ {t('home:academic_research')} +
+
{t('home:academic_research_desc')}
+
+
+ ); +}; + +export default Purpose; diff --git a/apps/web/src/pages/analyze/metric/[slugs].tsx b/apps/web/src/pages/analyze/metric/[slugs].tsx index 08b00c3f..342ebbab 100644 --- a/apps/web/src/pages/analyze/metric/[slugs].tsx +++ b/apps/web/src/pages/analyze/metric/[slugs].tsx @@ -2,6 +2,7 @@ import React from 'react'; import { GetServerSideProps } from 'next'; import getLocalesFile from '@common/utils/getLocalesFile'; import MetricDetailPage from '@modules/analyze/MetricDetailPage'; +import AuthRequire from '@modules/auth/AuthRequire'; export const getServerSideProps: GetServerSideProps = async ({ req, res }) => { return { @@ -12,7 +13,11 @@ export const getServerSideProps: GetServerSideProps = async ({ req, res }) => { }; const MetricDetail = () => { - return ; + return ( + + + + ); }; export default MetricDetail; diff --git a/apps/web/src/pages/index.tsx b/apps/web/src/pages/index.tsx index 0d6061e2..3f867e72 100644 --- a/apps/web/src/pages/index.tsx +++ b/apps/web/src/pages/index.tsx @@ -11,6 +11,7 @@ import HotFields from '@modules/home/HotFields'; import Trending from '@modules/home/Trending'; import Explain from '@modules/home/Explain'; import LatestNews from '@modules/home/LatestNews'; +import Purpose from '@modules/home/Purpose'; import ExplainMobile from '@modules/home/Explain/Mobile'; import SpecialThank from '@modules/home/SpecialThank'; @@ -34,6 +35,7 @@ const Home: React.FC = (props) => {
+ diff --git a/packages/graphql/src/generated.ts b/packages/graphql/src/generated.ts index 1aa314f1..139b9360 100644 --- a/packages/graphql/src/generated.ts +++ b/packages/graphql/src/generated.ts @@ -469,7 +469,6 @@ export type ContributorDetail = { export type ContributorDetailOverview = { __typename?: 'ContributorDetailOverview'; contributorAllCount?: Maybe; - ecologicalDistribution?: Maybe>; highestContributionContributor?: Maybe; highestContributionOrganization?: Maybe; orgAllCount?: Maybe; @@ -1364,6 +1363,8 @@ export type Query = { datasetOverview?: Maybe>; /** Get contributors overview by ecological type */ ecoContributorsOverview: Array; + /** Get contributors overview by ecological type */ + ecoDistributionOverview: Array; /** Fuzzy search project by keyword */ fuzzySearch: Array; /** Get invitations data of a lab model */ @@ -1520,6 +1521,14 @@ export type QueryEcoContributorsOverviewArgs = { level?: InputMaybe; }; +export type QueryEcoDistributionOverviewArgs = { + beginDate?: InputMaybe; + endDate?: InputMaybe; + filterOpts?: InputMaybe>; + label: Scalars['String']; + level?: InputMaybe; +}; + export type QueryFuzzySearchArgs = { keyword: Scalars['String']; level?: InputMaybe; @@ -4323,25 +4332,73 @@ export type ContributorsDetailListQuery = { }; }; -export type ContributorsOrganizationQueryVariables = Exact<{ +export type EcoContributorsOverviewQueryVariables = Exact<{ label: Scalars['String']; level?: InputMaybe; + filterOpts?: InputMaybe | FilterOptionInput>; beginDate?: InputMaybe; endDate?: InputMaybe; }>; -export type ContributorsOrganizationQuery = { +export type EcoContributorsOverviewQuery = { __typename?: 'Query'; - contributorsDetailOverview: { - __typename?: 'ContributorDetailOverview'; - ecologicalDistribution?: Array<{ + ecoContributorsOverview: Array<{ + __typename?: 'ContributorTopOverview'; + overviewName?: string | null; + subTypeName?: string | null; + subTypePercentage?: number | null; + topContributorDistribution?: Array<{ __typename?: 'Distribution'; subCount?: number | null; subName?: string | null; subRatio?: number | null; totalCount?: number | null; }> | null; - }; + }>; +}; + +export type OrgContributorsOverviewQueryVariables = Exact<{ + label: Scalars['String']; + level?: InputMaybe; + filterOpts?: InputMaybe | FilterOptionInput>; + beginDate?: InputMaybe; + endDate?: InputMaybe; +}>; + +export type OrgContributorsOverviewQuery = { + __typename?: 'Query'; + orgContributorsOverview: Array<{ + __typename?: 'ContributorTopOverview'; + overviewName?: string | null; + subTypeName?: string | null; + subTypePercentage?: number | null; + topContributorDistribution?: Array<{ + __typename?: 'Distribution'; + subCount?: number | null; + subName?: string | null; + subRatio?: number | null; + totalCount?: number | null; + }> | null; + }>; +}; + +export type ContributorsOverviewQueryVariables = Exact<{ + label: Scalars['String']; + level?: InputMaybe; + filterOpts?: InputMaybe | FilterOptionInput>; + beginDate?: InputMaybe; + endDate?: InputMaybe; +}>; + +export type ContributorsOverviewQuery = { + __typename?: 'Query'; + ecoDistributionOverview: Array<{ + __typename?: 'Distribution'; + subCount?: number | null; + subName?: string | null; + subRatio?: number | null; + totalCount?: number | null; + }>; }; export type IssuesDetailListQueryVariables = Exact<{ @@ -7863,15 +7920,19 @@ useContributorsDetailListQuery.fetcher = ( variables, headers ); -export const ContributorsOrganizationDocument = /*#__PURE__*/ ` - query contributorsOrganization($label: String!, $level: String = "repo", $beginDate: ISO8601DateTime, $endDate: ISO8601DateTime) { - contributorsDetailOverview( +export const EcoContributorsOverviewDocument = /*#__PURE__*/ ` + query ecoContributorsOverview($label: String!, $level: String = "repo", $filterOpts: [FilterOptionInput!], $beginDate: ISO8601DateTime, $endDate: ISO8601DateTime) { + ecoContributorsOverview( label: $label level: $level + filterOpts: $filterOpts beginDate: $beginDate endDate: $endDate ) { - ecologicalDistribution { + overviewName + subTypeName + subTypePercentage + topContributorDistribution { subCount subName subRatio @@ -7880,36 +7941,141 @@ export const ContributorsOrganizationDocument = /*#__PURE__*/ ` } } `; -export const useContributorsOrganizationQuery = < - TData = ContributorsOrganizationQuery, +export const useEcoContributorsOverviewQuery = < + TData = EcoContributorsOverviewQuery, TError = unknown >( client: GraphQLClient, - variables: ContributorsOrganizationQueryVariables, - options?: UseQueryOptions, + variables: EcoContributorsOverviewQueryVariables, + options?: UseQueryOptions, headers?: RequestInit['headers'] ) => - useQuery( - ['contributorsOrganization', variables], + useQuery( + ['ecoContributorsOverview', variables], fetcher< - ContributorsOrganizationQuery, - ContributorsOrganizationQueryVariables - >(client, ContributorsOrganizationDocument, variables, headers), + EcoContributorsOverviewQuery, + EcoContributorsOverviewQueryVariables + >(client, EcoContributorsOverviewDocument, variables, headers), options ); -useContributorsOrganizationQuery.getKey = ( - variables: ContributorsOrganizationQueryVariables -) => ['contributorsOrganization', variables]; -useContributorsOrganizationQuery.fetcher = ( +useEcoContributorsOverviewQuery.getKey = ( + variables: EcoContributorsOverviewQueryVariables +) => ['ecoContributorsOverview', variables]; +useEcoContributorsOverviewQuery.fetcher = ( client: GraphQLClient, - variables: ContributorsOrganizationQueryVariables, + variables: EcoContributorsOverviewQueryVariables, headers?: RequestInit['headers'] ) => - fetcher< - ContributorsOrganizationQuery, - ContributorsOrganizationQueryVariables - >(client, ContributorsOrganizationDocument, variables, headers); + fetcher( + client, + EcoContributorsOverviewDocument, + variables, + headers + ); +export const OrgContributorsOverviewDocument = /*#__PURE__*/ ` + query orgContributorsOverview($label: String!, $level: String = "repo", $filterOpts: [FilterOptionInput!], $beginDate: ISO8601DateTime, $endDate: ISO8601DateTime) { + orgContributorsOverview( + label: $label + level: $level + filterOpts: $filterOpts + beginDate: $beginDate + endDate: $endDate + ) { + overviewName + subTypeName + subTypePercentage + topContributorDistribution { + subCount + subName + subRatio + totalCount + } + } +} + `; +export const useOrgContributorsOverviewQuery = < + TData = OrgContributorsOverviewQuery, + TError = unknown +>( + client: GraphQLClient, + variables: OrgContributorsOverviewQueryVariables, + options?: UseQueryOptions, + headers?: RequestInit['headers'] +) => + useQuery( + ['orgContributorsOverview', variables], + fetcher< + OrgContributorsOverviewQuery, + OrgContributorsOverviewQueryVariables + >(client, OrgContributorsOverviewDocument, variables, headers), + options + ); + +useOrgContributorsOverviewQuery.getKey = ( + variables: OrgContributorsOverviewQueryVariables +) => ['orgContributorsOverview', variables]; +useOrgContributorsOverviewQuery.fetcher = ( + client: GraphQLClient, + variables: OrgContributorsOverviewQueryVariables, + headers?: RequestInit['headers'] +) => + fetcher( + client, + OrgContributorsOverviewDocument, + variables, + headers + ); +export const ContributorsOverviewDocument = /*#__PURE__*/ ` + query contributorsOverview($label: String!, $level: String = "repo", $filterOpts: [FilterOptionInput!], $beginDate: ISO8601DateTime, $endDate: ISO8601DateTime) { + ecoDistributionOverview( + label: $label + level: $level + filterOpts: $filterOpts + beginDate: $beginDate + endDate: $endDate + ) { + subCount + subName + subRatio + totalCount + } +} + `; +export const useContributorsOverviewQuery = < + TData = ContributorsOverviewQuery, + TError = unknown +>( + client: GraphQLClient, + variables: ContributorsOverviewQueryVariables, + options?: UseQueryOptions, + headers?: RequestInit['headers'] +) => + useQuery( + ['contributorsOverview', variables], + fetcher( + client, + ContributorsOverviewDocument, + variables, + headers + ), + options + ); + +useContributorsOverviewQuery.getKey = ( + variables: ContributorsOverviewQueryVariables +) => ['contributorsOverview', variables]; +useContributorsOverviewQuery.fetcher = ( + client: GraphQLClient, + variables: ContributorsOverviewQueryVariables, + headers?: RequestInit['headers'] +) => + fetcher( + client, + ContributorsOverviewDocument, + variables, + headers + ); export const IssuesDetailListDocument = /*#__PURE__*/ ` query issuesDetailList($label: String!, $level: String = "repo", $page: Int, $per: Int, $filterOpts: [FilterOptionInput!], $sortOpts: [SortOptionInput!], $beginDate: ISO8601DateTime, $endDate: ISO8601DateTime) { issuesDetailList( diff --git a/packages/graphql/src/gql/query.graphql b/packages/graphql/src/gql/query.graphql index 995a899e..1526bd4b 100644 --- a/packages/graphql/src/gql/query.graphql +++ b/packages/graphql/src/gql/query.graphql @@ -648,19 +648,49 @@ query contributorsDetailList( totalPage } } -query contributorsOrganization( +query ecoContributorsOverview( $label: String! $level: String = "repo" + $filterOpts: [FilterOptionInput!] $beginDate: ISO8601DateTime $endDate: ISO8601DateTime ) { - contributorsDetailOverview( + ecoContributorsOverview( + label: $label + level: $level + filterOpts: $filterOpts + beginDate: $beginDate + endDate: $endDate + ) { + overviewName + subTypeName + subTypePercentage + topContributorDistribution { + subCount + subName + subRatio + totalCount + } + } +} +query orgContributorsOverview( + $label: String! + $level: String = "repo" + $filterOpts: [FilterOptionInput!] + $beginDate: ISO8601DateTime + $endDate: ISO8601DateTime +) { + orgContributorsOverview( label: $label level: $level + filterOpts: $filterOpts beginDate: $beginDate endDate: $endDate ) { - ecologicalDistribution { + overviewName + subTypeName + subTypePercentage + topContributorDistribution { subCount subName subRatio @@ -668,6 +698,26 @@ query contributorsOrganization( } } } +query contributorsOverview( + $label: String! + $level: String = "repo" + $filterOpts: [FilterOptionInput!] + $beginDate: ISO8601DateTime + $endDate: ISO8601DateTime +) { + ecoDistributionOverview( + label: $label + level: $level + filterOpts: $filterOpts + beginDate: $beginDate + endDate: $endDate + ) { + subCount + subName + subRatio + totalCount + } +} query issuesDetailList( $label: String! $level: String = "repo"