Skip to content

Commit

Permalink
feat: domain persona optimize (#306)
Browse files Browse the repository at this point in the history
Signed-off-by: laixingyou <[email protected]>
  • Loading branch information
coder-sett authored Jan 27, 2024
1 parent c12c016 commit 0c181e6
Show file tree
Hide file tree
Showing 8 changed files with 272 additions and 85 deletions.
2 changes: 1 addition & 1 deletion apps/web/i18n
2 changes: 1 addition & 1 deletion apps/web/src/common/components/OrgEdit/ManageOrgEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ const ManageOrgEdit = ({
<OrgInput
className="h-full w-full"
inputClass="daisy-input-bordered daisy-input h-12 w-full flex-1 border-2 px-4 text-base outline-none border-black"
dropClass="top-[50px] border-2"
dropClass="top-[50px] border-2"
value={orgName}
onChange={(e) => {
setOrgName(e);
Expand Down
3 changes: 2 additions & 1 deletion apps/web/src/common/components/OrgEdit/OrgInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ const Select: React.FC<
)}
<div
className={classnames(
'absolute top-1.5 right-2 cursor-pointer text-[#CCCCCC]'
'absolute top-1.5 right-2 cursor-pointer text-[#CCCCCC]',
inputClass ? 'top-5' : ''
)}
>
{showLoading ? (
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/common/components/OrgEdit/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ const OrgEdit = ({
onChange={(e) => {
setOrgName(e);
}}
placeholder={''}
placeholder={t('common:org_name')}
/>
</Form.Item>
<Form.Item
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import MyTable from '@common/components/Table';
import classnames from 'classnames';
import {
useContributionTypeLsit,
useGetContributionTypeI18n,
useEcologicalType,
useMileageOptions,
} from './contribution';
import { Tag } from 'antd';
import { getMaxDomain } from './utils';
import DomainPersona from './DomainPersona';
import type { ColumnsType, TablePaginationConfig } from 'antd/es/table';
import type { FilterValue, SorterResult } from 'antd/es/table/interface';
import { useTranslation } from 'next-i18next';
Expand Down Expand Up @@ -54,7 +54,6 @@ const MetricTable: React.FC<{
ecologicalType: 'ecological_type',
contributionTypeList: 'contribution_type',
};
const contributionTypeMap = useGetContributionTypeI18n();
const router = useRouter();
const { handleQueryParams } = useHandleQueryParams();

Expand Down Expand Up @@ -99,6 +98,10 @@ const MetricTable: React.FC<{
beginDate,
endDate,
};

const maxDomain = useMemo(() => {
return getMaxDomain(tableData);
}, [tableData]);
const { isLoading, isFetching } = useContributorsDetailListQuery(
client,
query,
Expand All @@ -112,9 +115,11 @@ const MetricTable: React.FC<{
let value = hasTypeFilter.values;
items.map((item) => {
let list = item.contributionTypeList;
item.contributionTypeList = list.filter((i) =>
value.includes(i.contributionType)
);
item.contributionTypeList = list.filter((i) => {
if (value.includes(i.contributionType)) {
return true;
}
});
});
}
setTableParams({
Expand Down Expand Up @@ -217,27 +222,14 @@ const MetricTable: React.FC<{
{
title: t('analyze:metric_detail:domain_persona'),
dataIndex: 'contributionTypeList',
render: (list) => {
let arr = list.map(
(item) => contributionTypeMap[item.contributionType]
render: (dataList, col) => {
return (
<DomainPersona
maxDomain={maxDomain}
dataList={dataList}
name={col.contributor}
/>
);
let sortObj = arr.reduce((result, item) => {
(result[item.color] = result[item.color] || []).push(item);
return result;
}, {});
let newArr = Object.keys(sortObj).sort();
const str = newArr.map((item) => {
return (
<div key={item} className="line-clamp-1 my-1">
{sortObj[item]?.map((obj, index) => (
<Tag key={index} color={obj.color}>
{obj.text}
</Tag>
))}
</div>
);
});
return str;
},
filters: useContributionTypeLsit(),
defaultFilteredValue:
Expand All @@ -246,7 +238,7 @@ const MetricTable: React.FC<{
filterMode: 'tree',
// ellipsis: { showTitle: true },
align: 'left',
width: '590px',
width: '300px',
},
{
title: t('analyze:metric_detail:organization'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import React, { useState, useMemo } from 'react';
import { useTranslation } from 'next-i18next';
import { useGetContributionTypeI18n } from '../contribution';
import { getDomainData } from '../utils';
import { toFixed } from '@common/utils';
import classnames from 'classnames';
import Popper from '@mui/material/Popper';
import { ClickAwayListener } from '@mui/base/ClickAwayListener';

const PopperContent = ({ dataList, name, active, setActive }) => {
const activeItem = dataList
.find((item) => item.type === active)
?.childern.sort((a, b) => b.contribution - a.contribution);

// const allType = ['Code', 'Code Admin', 'Issue', 'Issue Admin', 'Observe'];
return (
<div className="right-0 rounded bg-[#fcfcfc] text-xs drop-shadow-md">
<div className="flex h-10 items-center pl-3 text-sm font-semibold">
{name}
</div>
<div className="flex h-[300px]">
<div className="flex h-full w-40 flex-shrink-0 flex-col border-t">
{dataList.map(({ type, color, contribution }) => {
return (
<div
key={type}
onClick={() => {
setActive(type);
}}
className={classnames(
'flex h-9 w-full cursor-pointer items-center justify-between border-b border-r bg-[#F6F6F6] last:border-b-0',
{ '!border-r-0 !bg-[#FFFFFF]': active === type }
)}
>
<div
style={{ backgroundColor: color }}
className="ml-3 h-2 w-2"
></div>
<div className="ml-2 text-xs font-bold">{type}</div>
<div className="ml-auto mr-3 text-[#868690]">
{contribution}
</div>
</div>
);
})}
<div className="flex-1 border-r bg-[#F6F6F6]"></div>
</div>
<div className="h-full w-[216px] flex-shrink-0 overflow-auto border-t px-4 py-2 text-xs">
{activeItem.map(({ text, contribution }) => {
return (
<div
key={text}
className="flex h-7 w-full items-center justify-between"
>
<div className="text-[#2C3542]">{text}</div>
<div className="text-[#868690]">{contribution}</div>
</div>
);
})}
</div>
</div>
</div>
);
};

const DomainPersona = ({ maxDomain, dataList, name }) => {
const { t } = useTranslation();
const contributionTypeMap = useGetContributionTypeI18n();
const domainData = useMemo(() => {
return getDomainData(dataList, contributionTypeMap);
}, [dataList]);
const [active, setActive] = useState('');
const [popperOpen, togglePopperOpen] = React.useState(false);
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const handleClick = (event: React.MouseEvent<HTMLElement>, type) => {
setActive(type);
setAnchorEl(event.currentTarget);
togglePopperOpen(() => true);
};

return (
<ClickAwayListener
onClickAway={() => {
setActive('');
popperOpen && togglePopperOpen(() => false);
}}
>
<div>
<div className="flex items-center">
{domainData.map(({ type, color, contribution }) => {
const width = toFixed((contribution / maxDomain) * 100, 2);
const bg = {
backgroundColor: color,
width: `${width}%`,
};
return active === type ? (
<div
key={type}
className="cursor-pointer border"
style={{
width: `${width}%`,
borderColor: color,
padding: '1px',
}}
>
<div className="h-2" style={{ backgroundColor: color }}></div>
</div>
) : (
<div
onClick={(e) => {
handleClick(e, type);
}}
key={type}
style={{ backgroundColor: color, width: `${width}%` }}
className="h-2 cursor-pointer"
></div>
);
})}
</div>
<Popper
open={popperOpen}
style={{
zIndex: 1000,
}}
placement={'bottom'}
anchorEl={anchorEl}
modifiers={[
{
name: 'offset',
options: {
offset: [0, 5],
},
},
]}
>
<PopperContent
dataList={domainData}
name={name}
active={active}
setActive={setActive}
/>
</Popper>
</div>
</ClickAwayListener>
);
};

export default DomainPersona;
Loading

1 comment on commit 0c181e6

@vercel
Copy link

@vercel vercel bot commented on 0c181e6 Jan 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.