Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add table download #302

Merged
merged 3 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/web/i18n
31 changes: 31 additions & 0 deletions apps/web/src/common/components/Table/Download.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React, { useState } from 'react';
import { useTranslation } from 'next-i18next';
import { BsDownload } from 'react-icons/bs';
import { AiOutlineLoading } from 'react-icons/ai';

const Download = ({ downloadFun }: { downloadFun: () => void }) => {
const { t } = useTranslation();
const [loadingDownLoad, setLoadingDownLoad] = useState(false);

return (
<>
<div className="flex h-7 w-10 cursor-pointer items-center justify-center rounded-sm border border-[#3f60ef] text-xs text-[#3f60ef]">
{loadingDownLoad ? (
<AiOutlineLoading className="t animate-spin" />
) : (
<div
className="flex h-full w-full items-center justify-center"
onClick={async () => {
setLoadingDownLoad(true);
await downloadFun();
setLoadingDownLoad(false);
}}
>
<BsDownload />
</div>
)}
</div>
</>
);
};
export default Download;
1 change: 1 addition & 0 deletions apps/web/src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const config = {
matcher: [
'/api/graphql',
'/api/beta/predict',
'/api/v1/:path*',
'/badge/:path*',
'/files/:path*',
'/users/:path*',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import type { ColumnsType, TablePaginationConfig } from 'antd/es/table';
import type { FilterValue, SorterResult } from 'antd/es/table/interface';
import { useTranslation } from 'next-i18next';
import Tooltip from '@common/components/Tooltip';

import Download from '@common/components/Table/Download';
import { contributorDownload } from '../tableDownload';
import { useRouter } from 'next/router';
import { useHandleQueryParams } from '@modules/analyze/hooks/useHandleQueryParams';
interface TableParams {
pagination?: TablePaginationConfig;
filterOpts?: FilterOptionInput[];
Expand All @@ -32,14 +35,17 @@ const MetricTable: React.FC<{
endDate: Date;
mileage: string[];
}> = ({ label, level, beginDate, endDate, mileage }) => {
const { t, i18n } = useTranslation();
const { t } = useTranslation();
const ecologicalOptions = useEcologicalType();
const mileageOptions = useMileageOptions();
const filterMap = {
ecologicalType: 'ecological_type',
contributionTypeList: 'contribution_type',
};
const contributionTypeMap = useGetContributionTypeI18n();
const router = useRouter();
const { handleQueryParams } = useHandleQueryParams();

const mileageFilter = useMemo(() => {
if (mileage.length > 0) {
return { type: 'mileage_type', values: mileage };
Expand All @@ -48,7 +54,16 @@ const MetricTable: React.FC<{
}
}, [mileage]);

const [filterContributionType, setFilterContributionType] = useState(false);
const queryFilterOpts = router.query?.filterOpts as string;
const defaultFilterOpts = queryFilterOpts ? JSON.parse(queryFilterOpts) : [];
const defaultSortOpts = router.query?.sortOpts
? JSON.parse(router.query?.sortOpts as string)
: [];
console.log(1);
const [filterOpts, setFilterOpts] = useState(defaultFilterOpts || []);
const filterContributionType = useMemo(() => {
return filterOpts.find((i) => i.type === 'contribution_type');
}, [filterOpts]);
const [tableData, setData] = useState<ContributorDetail[]>();
const [tableParams, setTableParams] = useState<TableParams>({
pagination: {
Expand All @@ -60,7 +75,8 @@ const MetricTable: React.FC<{
return `${t('analyze:total_people', { total })} `;
},
},
filterOpts: [],
filterOpts: filterOpts,
sortOpts: defaultSortOpts,
});
const query = {
page: tableParams.pagination.current,
Expand Down Expand Up @@ -117,7 +133,7 @@ const MetricTable: React.FC<{
) => {
let sortOpts = null;
let filterOpts = [];

console.log(filters);
for (const key in filters) {
if (filters.hasOwnProperty(key)) {
const transformedObj = {
Expand All @@ -128,7 +144,6 @@ const MetricTable: React.FC<{
}
}
if (filterOpts.find((i) => i.type === 'contribution_type')) {
setFilterContributionType(true);
sortOpts = sorter.field && {
type:
sorter.field === 'contribution'
Expand All @@ -137,12 +152,16 @@ const MetricTable: React.FC<{
direction: sorter.order === 'ascend' ? 'asc' : 'desc',
};
} else {
setFilterContributionType(false);
sortOpts = sorter.field && {
type: sorter.field,
direction: sorter.order === 'ascend' ? 'asc' : 'desc',
};
}
handleQueryParams({
filterOpts: JSON.stringify(filterOpts),
sortOpts: JSON.stringify(sortOpts),
});
setFilterOpts(filterOpts);
setTableParams({
pagination,
sortOpts,
Expand All @@ -165,6 +184,9 @@ const MetricTable: React.FC<{
align: 'left',
width: '200px',
filters: ecologicalOptions,
defaultFilteredValue:
defaultFilterOpts.find((i) => i.type === 'ecological_type')?.values ||
null,
render: (text) => {
return ecologicalOptions.find((i) => i.value === text)?.text || text;
},
Expand All @@ -186,16 +208,24 @@ const MetricTable: React.FC<{
let arr = list.map(
(item) => contributionTypeMap[item.contributionType]
);
const str = arr.join(', ');
const length = arr.join(', ')?.length;
const str = arr.map((obj, index) => (
<span key={index} style={{ color: obj.color }}>
{arr.length - 1 == index ? obj.text : obj.text + ', '}
</span>
));
return (
<Tooltip arrow title={str.length > 20 ? str : ''} placement="right">
<div className="line-clamp-1 w-[200px] !whitespace-normal">
<Tooltip arrow title={length > 27 ? str : ''} placement="right">
<div className="line-clamp-1 w-[218px] !whitespace-normal">
{str}
</div>
</Tooltip>
);
},
filters: useContributionTypeLsit(),
defaultFilteredValue:
defaultFilterOpts.find((i) => i.type === 'contribution_type')?.values ||
null,
filterMode: 'tree',
ellipsis: true,
align: 'left',
Expand Down Expand Up @@ -228,15 +258,27 @@ const MetricTable: React.FC<{
},
];
return (
<MyTable
columns={columns}
dataSource={tableData}
loading={isLoading || isFetching}
onChange={handleTableChange}
pagination={tableParams.pagination}
rowKey={'contributor'}
scroll={{ x: 'max-content' }}
/>
<>
<div className="absolute right-0 top-2">
<Download
downloadFun={() =>
contributorDownload(
query,
t('analyze:metric_detail:contributor_data_table')
)
}
/>
</div>
<MyTable
columns={columns}
dataSource={tableData}
loading={isLoading || isFetching}
onChange={handleTableChange}
pagination={tableParams.pagination}
rowKey={'contributor'}
scroll={{ x: 'max-content' }}
/>
</>
);
};
export default MetricTable;
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useTranslation } from 'next-i18next';

// 领域画像 option
const useContributionTypeMap = () => {
const { t } = useTranslation();
return {
Expand Down Expand Up @@ -113,6 +114,7 @@ const useContributionTypeMap = () => {
},
};
};
// 领域画像 filter
export const useContributionTypeLsit = () => {
const obj = useContributionTypeMap();
const result = [];
Expand All @@ -133,23 +135,32 @@ export const useContributionTypeLsit = () => {
}
return result;
};
// 领域画像 i18n(表格字段翻译)
export const useGetContributionTypeI18n = () => {
const obj = useContributionTypeMap();
const result = {};

function traverseObject(obj) {
const colors = [
'#007ACC', // 蓝色
'#008000', // 绿色
'#FFA500', // 橙色
'#FF1493', // 粉红
'#800080', // 紫色
];
function traverseObject(obj, color) {
for (const key in obj) {
if (typeof obj[key] === 'object') {
traverseObject(obj[key]);
const c = colors.shift() || '#ccc';
traverseObject(obj[key], c);
} else {
result[key] = obj[key];
result[key] = { text: obj[key], color };
}
}
}

traverseObject(obj);
traverseObject(obj, '#ccc');
return result;
};

// 里程画像 i18n(表格字段翻译)
export const useMileageOptions = () => {
const { t } = useTranslation();

Expand All @@ -159,6 +170,8 @@ export const useMileageOptions = () => {
{ label: t('analyze:metric_detail:guest'), value: 'guest' },
];
};

//角色画像 option
export const useEcologicalType = () => {
const { t } = useTranslation();

Expand All @@ -181,7 +194,7 @@ export const useEcologicalType = () => {
},
];
};

//角色画像 i18n
export const useGetEcologicalText = () => {
const { t } = useTranslation();
const ecologicalOptions = useEcologicalType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,27 @@ import { AiOutlineQuestionCircle } from 'react-icons/ai';
import Tooltip from '@common/components/Tooltip';
import useLabelStatus from '@modules/analyze/hooks/useLabelStatus';
import BaseCard from '@common/components/BaseCard';
import { useRouter } from 'next/router';
import { useHandleQueryParams } from '@modules/analyze/hooks/useHandleQueryParams';

const MetricContributor = () => {
const { t } = useTranslation();
const router = useRouter();
const { handleQueryParams } = useHandleQueryParams();
const { verifiedItems } = useLabelStatus();
const { label, level } = verifiedItems[0];
const [tab, setTab] = useState('1');
const queryCard = router.query?.card as string;
const [tab, setTab] = useState(queryCard || '1');
const { timeStart, timeEnd } = useVerifyDateRange();
const options = useMileageOptions();
const [mileage, setMileage] = useState<string[]>(['core', 'regular']);
const queryMileage = router.query?.mileage as string;
const defaultMileage = queryMileage
? JSON.parse(queryMileage)
: ['core', 'regular'];
const [mileage, setMileage] = useState<string[]>(defaultMileage);
const onChange = (checkedValues: string[]) => {
setMileage(checkedValues);
handleQueryParams({ mileage: JSON.stringify(checkedValues) });
};
let source;
switch (tab) {
Expand Down Expand Up @@ -63,6 +73,15 @@ const MetricContributor = () => {
break;
}
default: {
source = (
<MetricTable
label={label}
level={level}
beginDate={timeStart}
endDate={timeEnd}
mileage={mileage}
/>
);
break;
}
}
Expand All @@ -79,6 +98,7 @@ const MetricContributor = () => {
value={tab}
onChange={(e, v) => {
setTab(v);
handleQueryParams({ card: v });
}}
aria-label="Tabs where selection follows focus"
selectionFollowsFocus
Expand Down Expand Up @@ -110,7 +130,7 @@ const MetricContributor = () => {
</Tabs>
</div>

<div className="absolute right-1 top-2.5 flex md:hidden xl:-top-2.5">
<div className="absolute right-14 top-2.5 flex md:hidden xl:right-0 xl:-top-4">
<span className="mr-2 flex cursor-pointer items-center font-medium">
{t('analyze:metric_detail:milestone_persona_filter')}
<Tooltip
Expand Down Expand Up @@ -147,7 +167,7 @@ const MetricContributor = () => {
<span className="mr-2">:</span>
<Checkbox.Group
options={options}
defaultValue={['core', 'regular']}
defaultValue={defaultMileage}
onChange={onChange}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useIssueCommentQuery } from '@oss-compass/graphql';
import client from '@common/gqlClient';
import { useTranslation } from 'next-i18next';
import MetricChart from '@modules/analyze/DataView/MetricDetail/MetricChart';
import type { EChartsOption } from 'echarts';
import { getPieOption } from '@modules/analyze/DataView/MetricDetail/metricChartOption';

const IssueCompletion: React.FC<{
Expand Down Expand Up @@ -39,7 +38,7 @@ const IssueCompletion: React.FC<{
const option = getPieOption({ seriesData: getSeries });

return (
<div className="h-[600px] pt-4" ref={chartRef}>
<div className="relative flex h-full pt-4" ref={chartRef}>
<MetricChart
loading={isLoading}
option={option}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const IssueCompletion: React.FC<{
const option = getPieOption({ seriesData: getSeries });

return (
<div className="h-[600px] pt-4" ref={chartRef}>
<div className="relative flex h-full pt-4" ref={chartRef}>
<MetricChart
loading={isLoading}
option={option}
Expand Down
Loading