Skip to content

Commit

Permalink
feat: add contributor hub url contributor search (#321)
Browse files Browse the repository at this point in the history
Signed-off-by: laixingyou <[email protected]>
  • Loading branch information
coder-sett authored Feb 26, 2024
1 parent 0b7f788 commit a9378af
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 64 deletions.
2 changes: 1 addition & 1 deletion apps/web/i18n
Submodule i18n updated 2 files
+8 −2 en/analyze.json
+4 −1 zh/analyze.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { useState } from 'react';
// import { AiOutlineSearch } from 'react-icons/ai';
import { Button, Input } from 'antd';
import { useTranslation } from 'next-i18next';

const ContributorDropdown = ({ selectedKeys, setSelectedKeys, confirm }) => {
const { t } = useTranslation();
const [contributor, setContributor] = useState(selectedKeys);

const handleSearch = () => {
setSelectedKeys(contributor);
confirm();
};
const handleReset = () => {
setContributor([]);
};
return (
<div style={{ padding: 8 }} onKeyDown={(e) => e.stopPropagation()}>
<Input
placeholder={t('analyze:metric_detail:search_contributor')}
value={contributor[0]}
onChange={(e) => setContributor([e.target.value])}
onPressEnter={() => handleSearch()}
style={{ marginBottom: 8, display: 'block' }}
/>
<div className="flex justify-between">
<Button
type="link"
disabled={contributor[0] ? false : true}
onClick={() => handleReset()}
size="small"
>
{t('analyze:metric_detail:reset')}
</Button>
<Button
type="primary"
className="flex items-center"
onClick={() => handleSearch()}
size="small"
>
{t('analyze:metric_detail:search')}
</Button>
</div>
</div>
);
};

export default ContributorDropdown;
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,37 @@ import Image from 'next/image';

const DomainPersona = ({ name, origin }) => {
let icon = getIcons(origin, name);

let url = getHubUrl(origin, name);
return (
<div className="flex">
<div>{icon}</div>
{name}
{url ? (
<a
className="whitespace-nowrap hover:text-[black] hover:underline"
href={url}
target="_blank"
rel={'noreferrer'}
>
{name}
</a>
) : (
name
)}
</div>
);
};

const getHubUrl = (origin, name) => {
switch (origin) {
case 'github':
return 'https://github.com/' + name;
case 'gitee':
return 'https://gitee.com/' + name;
// return <SiGitee color="#c71c27" className="mr-0" />;
default:
return null;
}
};
const getIcons = (origin, name) => {
switch (origin) {
case 'github':
Expand Down Expand Up @@ -51,7 +73,6 @@ const getIcons = (origin, name) => {
/>
</div>
);
// return <SiGitee color="#c71c27" className="mr-0" />;
default:
return <IoPeopleCircle />;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@ import { getMaxDomain } from '../utils';
import { getContributorPolling, getContributorExport } from './tableDownload';
import DomainPersona from './DomainPersona';
import ContributorName from './ContributorName';
import ContributorDropdown from './ContributorDropdown';
import { useTranslation } from 'next-i18next';
import Download from '@common/components/Table/Download';
import { useRouter } from 'next/router';
import { useHandleQueryParams } from '@modules/analyze/hooks/useHandleQueryParams';
import Dialog from '@common/components/Dialog';
import Tooltip from '@common/components/Tooltip';
import { FiEdit } from 'react-icons/fi';
import { GrClose } from 'react-icons/gr';
import ManageOrgEdit from '@common/components/OrgEdit/ManageOrgEdit';
import useVerifyDetailRange from '@modules/analyze/hooks/useVerifyDetailRange';
import { useIsCurrentUser } from '@modules/analyze/hooks/useIsCurrentUser';
import { FiEdit } from 'react-icons/fi';
import { GrClose } from 'react-icons/gr';
import { AiOutlineSearch } from 'react-icons/ai';

import type { ColumnsType, TablePaginationConfig } from 'antd/es/table';
import type { FilterValue, SorterResult } from 'antd/es/table/interface';
Expand Down Expand Up @@ -90,13 +92,12 @@ const MetricTable: React.FC<{
return `${t('analyze:total_people', { total })} `;
},
},
filterOpts: filterOpts,
sortOpts: defaultSortOpts,
});
const query = {
page: tableParams.pagination.current,
per: tableParams.pagination.pageSize,
filterOpts: [...tableParams.filterOpts, mileageFilter],
filterOpts: [...filterOpts, mileageFilter],
sortOpts: tableParams.sortOpts,
label,
level,
Expand All @@ -113,7 +114,7 @@ const MetricTable: React.FC<{
{
onSuccess: (data) => {
const items = data.contributorsDetailList.items;
const hasTypeFilter = tableParams.filterOpts.find(
const hasTypeFilter = filterOpts.find(
(i) => i.type === 'contribution_type'
);
if (hasTypeFilter) {
Expand Down Expand Up @@ -149,29 +150,29 @@ const MetricTable: React.FC<{
for (const key in filters) {
if (filters.hasOwnProperty(key)) {
const transformedObj = {
type: filterMap[key],
type: filterMap[key] || key,
values: filters[key] as string[],
};
filters[key] && filterOpts.push(transformedObj);
}
}
if (filterOpts.find((i) => i.type === 'contribution_type')) {
sortOpts = sorter.field && {
sortOpts = sorter.order && {
type:
sorter.field === 'contribution'
? 'contribution_filterd'
: sorter.field,
direction: sorter.order === 'ascend' ? 'asc' : 'desc',
};
} else {
sortOpts = sorter.field && {
sortOpts = sorter.order && {
type: sorter.field,
direction: sorter.order === 'ascend' ? 'asc' : 'desc',
};
}
handleQueryParams({
filterOpts: JSON.stringify(filterOpts),
sortOpts: JSON.stringify(sortOpts),
filterOpts: filterOpts.length > 0 ? JSON.stringify(filterOpts) : null,
sortOpts: sortOpts && JSON.stringify(sortOpts),
});
setFilterOpts(filterOpts);
setTableParams({
Expand All @@ -180,7 +181,6 @@ const MetricTable: React.FC<{
...pagination,
},
sortOpts,
filterOpts,
});
};

Expand All @@ -190,11 +190,27 @@ const MetricTable: React.FC<{
dataIndex: 'contributor',
align: 'left',
width: '200px',
sorter: true,
fixed: 'left',
render: (name) => {
return <ContributorName name={name} origin={origin} />;
},
filterIcon: (filtered: boolean) => (
<AiOutlineSearch
className="text-lg"
style={{ color: filtered ? '#1677ff' : undefined }}
/>
),
defaultFilteredValue:
defaultFilterOpts.find((i) => i.type === 'contributor')?.values || null,
filterDropdown: ({ selectedKeys, setSelectedKeys, confirm }) => {
return (
<ContributorDropdown
selectedKeys={selectedKeys}
setSelectedKeys={setSelectedKeys}
confirm={confirm}
/>
);
},
},
{
title: t('analyze:metric_detail:role_persona'),
Expand Down
119 changes: 72 additions & 47 deletions apps/web/src/modules/analyze/DataView/MetricDetail/MetricDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,10 @@ const MetricBoxContributors: React.FC<{
</div>
<div>
<div className="flex text-xl font-medium">
<div className="mt-1 mr-2 text-[#ccc]">
{getUserIcons(
data.highestContributionContributor.origin,
data.highestContributionContributor.name
)}
</div>
<div className="line-clamp-1">
{data.highestContributionContributor.name || '/'}
</div>
{getTopUser(
data.highestContributionContributor.origin,
data.highestContributionContributor.name
)}
</div>
<div className="line-clamp-1 pl-7 text-sm text-[#585858]">
{t('analyze:metric_detail:top_contributor')}
Expand Down Expand Up @@ -328,44 +323,74 @@ const getIcons = (type: string) => {
return <IoPeopleCircle />;
}
};
const getUserIcons = (type, name) => {
switch (type) {
case 'github':
return (
<div className="relative h-[22px] w-[22px] overflow-hidden rounded-full border border-gray-100 p-0">
<Image
src={'https://github.com/' + name + '.png'}
onError={(e) => (e.currentTarget.src = '/images/github.png')}
unoptimized
fill={true}
style={{
objectFit: 'cover',
}}
alt="icon"
placeholder="blur"
blurDataURL="/images/github.png"
/>
</div>
);
case 'gitee':
return (
<div className="relative h-[22px] w-[22px] overflow-hidden rounded-full border border-gray-100">
<Image
src={'https://gitee.com/' + name + '.png'}
onError={(e) =>
(e.currentTarget.src = '/images/logos/gitee-red.svg')
}
unoptimized
fill={true}
alt="icon"
placeholder="blur"
blurDataURL="/images/logos/gitee-red.svg"
/>
</div>
);
// return <SiGitee color="#c71c27" className="mr-0" />;
default:
return <IoPersonCircle />;
const getTopUser = (type, name) => {
let url = null;
let userIcon = null;
if (!name) {
userIcon = <IoPersonCircle />;
} else {
switch (type) {
case 'github':
url = 'https://github.com/' + name;
userIcon = (
<div className="relative h-[22px] w-[22px] overflow-hidden rounded-full border border-gray-100 p-0">
<Image
src={'https://github.com/' + name + '.png'}
onError={(e) => (e.currentTarget.src = '/images/github.png')}
unoptimized
fill={true}
style={{
objectFit: 'cover',
}}
alt="icon"
placeholder="blur"
blurDataURL="/images/github.png"
/>
</div>
);
break;
case 'gitee':
url = 'https://gitee.com/' + name;
userIcon = (
<div className="relative h-[22px] w-[22px] overflow-hidden rounded-full border border-gray-100">
<Image
src={'https://gitee.com/' + name + '.png'}
onError={(e) =>
(e.currentTarget.src = '/images/logos/gitee-red.svg')
}
unoptimized
fill={true}
alt="icon"
placeholder="blur"
blurDataURL="/images/logos/gitee-red.svg"
/>
</div>
);
break;
default:
userIcon = <IoPersonCircle />;
break;
}
}

return (
<>
<div className="mt-1 mr-2 text-[#ccc]">{userIcon}</div>
<div className="line-clamp-1">
{url ? (
<a
className="whitespace-nowrap hover:text-[black] hover:underline"
href={url}
target="_blank"
rel={'noreferrer'}
>
{name}
</a>
) : (
name || '/'
)}
</div>
</>
);
};
export default MetricDashboard;
8 changes: 8 additions & 0 deletions apps/web/src/modules/analyze/hooks/useHandleQueryParams.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import { useRouter } from 'next/router';

// 修改或新增查询参数
const clearEmptyProperties = (obj) => {
Object.keys(obj).forEach(function (key) {
if (obj[key] === null || obj[key] === undefined || obj[key] === '') {
delete obj[key];
}
});
};
export const useHandleQueryParams = () => {
const router = useRouter();
const handleQueryParams = (newParams) => {
const { pathname, query } = router;
const newQueryParams = { ...query, ...newParams };
clearEmptyProperties(newQueryParams);
router.push({
pathname,
query: newQueryParams,
Expand Down
5 changes: 4 additions & 1 deletion apps/web/src/styles/antd.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
.ant-table-filter-dropdown-btns {
.ant-table-filter-dropdown {
.ant-btn-primary {
background-color: #1677ff !important;
// :hover {
// background-color: #4096ff !important;
// }
}
}
.ant-progress-bg {
Expand Down

0 comments on commit a9378af

Please sign in to comment.