diff --git a/apps/web/i18n b/apps/web/i18n index 1754fbe3..ec6f692e 160000 --- a/apps/web/i18n +++ b/apps/web/i18n @@ -1 +1 @@ -Subproject commit 1754fbe3465ea5ee3cc1433d9137a3f810d4da5c +Subproject commit ec6f692eb0e40fff1d28cda19f946a234c95dff8 diff --git a/apps/web/src/common/components/OrgEdit/DateRangePicker.tsx b/apps/web/src/common/components/OrgEdit/DateRangePicker.tsx new file mode 100644 index 00000000..35092594 --- /dev/null +++ b/apps/web/src/common/components/OrgEdit/DateRangePicker.tsx @@ -0,0 +1,88 @@ +import React, { useState, useRef, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; +import { DatePicker, ConfigProvider } from 'antd'; +import classnames from 'classnames'; +import zhCN from 'antd/locale/zh_CN'; +import enUS from 'antd/locale/en_US'; +import 'dayjs/locale/zh-cn'; +import dayjs from 'dayjs'; +import type { Dayjs } from 'dayjs'; +import type { DatePickerProps } from 'antd'; + +type RangeValue = [Dayjs | null, Dayjs | null] | null; +const FORMAT_YMD = 'YYYY-MM-DD'; + +const DateRangePicker = ({ + value, + onChange, + inputClass, + disabledDate, +}: { + value?: RangeValue; + onChange?: (value: RangeValue) => void; + disabledDate?: (value: Dayjs) => boolean; + inputClass?: string; +}) => { + const { t, i18n } = useTranslation(); + const inputRef = useRef(null); + const { RangePicker } = DatePicker; + const [local, setLocale] = useState(zhCN); + useEffect(() => { + setLocale(i18n.language === 'zh' ? zhCN : enUS); + }, [i18n]); + + const [dates, setDates] = useState(null); + const [datesValue, setDatesValue] = useState(value || null); + + const onOpenChange = (open: boolean) => { + if (!open) { + setDates(null); + } + }; + const setToNow = () => { + setDates([dates[0], dayjs('2099/01/01', FORMAT_YMD)]); + setDatesValue([dates[0], dayjs('2099/01/01', FORMAT_YMD)]); + onChange([dates[0], dayjs('2099/01/01', FORMAT_YMD)]); + inputRef.current!.blur(); + }; + const customFormat: DatePickerProps['format'] = (value) => { + const date = value.format(FORMAT_YMD); + if (date.startsWith('2099')) { + return t('common:up_to_now'); + } + return date; + }; + + return ( + + { + setDates(val); + }} + disabledDate={disabledDate} + onChange={(val) => { + setDatesValue(val); + onChange(val); + }} + format={customFormat} + renderExtraFooter={() => ( +
+ + {t('common:up_to_now')} + +
+ )} + /> +
+ ); +}; +export default DateRangePicker; diff --git a/apps/web/src/common/components/OrgEdit/ManageOrgEdit.tsx b/apps/web/src/common/components/OrgEdit/ManageOrgEdit.tsx new file mode 100644 index 00000000..0c8d253a --- /dev/null +++ b/apps/web/src/common/components/OrgEdit/ManageOrgEdit.tsx @@ -0,0 +1,143 @@ +import React, { useState } from 'react'; +import { Button } from '@oss-compass/ui'; +import { useTranslation } from 'react-i18next'; +import OrgInput from './OrgInput'; +import DateRangePicker from './DateRangePicker'; +import { Form } from 'antd'; +import { useManageUserOrgsMutation } from '@oss-compass/graphql'; +import client from '@common/gqlClient'; +import { toast } from 'react-hot-toast'; +import type { Dayjs } from 'dayjs'; +const FORMAT_YMD = 'YYYY-MM-DD'; + +type RangeValue = [Dayjs | null, Dayjs | null] | null; + +const ManageOrgEdit = ({ + label, + level, + contributor, + name, + setShowEdit, +}: { + label?: string; + level?: string; + contributor?: string; + name?: string; + setShowEdit: (b: boolean) => void; +}) => { + const { t } = useTranslation(); + const [orgName, setOrgName] = useState(name || ''); + const [date, setDate] = useState(null); + const [form] = Form.useForm(); + const onCheck = async () => { + try { + const values = await form.validateFields(); + const firstDate = values['date'][0].format(FORMAT_YMD); + const lastDate = values['date'][1].format(FORMAT_YMD); + const orgName = values['orgName']; + mutation.mutate({ + label, + level, + contributor, + platform: 'github', + organizations: [{ orgName, firstDate, lastDate }], + }); + } catch (errorInfo) { + console.log('Failed:', errorInfo); + } + }; + const mutation = useManageUserOrgsMutation(client, { + onSuccess(res) { + if (res.manageUserOrgs?.status === 'true') { + setShowEdit(false); + if (res.manageUserOrgs?.prUrl) { + let message = ( +
+ {t('common:toast.modification_successful')} + + {res.manageUserOrgs?.prUrl} + +
+ ); + toast.success(message, { + duration: 5000, + className: '!max-w-[500px]', + }); + } else { + toast.success(t('common:toast.modification_successful')); + } + } + if (res.manageUserOrgs?.status === 'false') { + toast.error( + res.manageUserOrgs?.message || t('common:toast.modification_failed') + ); + } + }, + }); + return ( +
+
+
+ + { + setOrgName(e); + }} + placeholder={''} + /> + + + { + setDate(e); + }} + /> + + + + +
+
+
+ ); +}; +export default ManageOrgEdit; diff --git a/apps/web/src/common/components/OrgEdit/OrgInput.tsx b/apps/web/src/common/components/OrgEdit/OrgInput.tsx new file mode 100644 index 00000000..9b650eb6 --- /dev/null +++ b/apps/web/src/common/components/OrgEdit/OrgInput.tsx @@ -0,0 +1,97 @@ +import React, { PropsWithChildren, useState } from 'react'; +import classnames from 'classnames'; +import { Input } from 'antd'; +import { useThrottle } from 'ahooks'; +import { useOrgSearchQuery } from '@oss-compass/graphql'; +import client from '@common/gqlClient'; +import { AiOutlineLoading } from 'react-icons/ai'; + +const Select: React.FC< + PropsWithChildren<{ + value?: string; + onChange?: (value: string) => void; + className?: string; + inputClass?: string; + dropClass?: string; + placeholder?: string; + onClick?: () => void; + }> +> = ({ value, onChange, className, inputClass, dropClass, placeholder }) => { + const [showList, setShowlist] = useState(false); + + const [keyword, setKeyword] = useState(value); + const throttledKeyword = useThrottle(keyword, { wait: 300 }); + const { isLoading, data, fetchStatus } = useOrgSearchQuery( + client, + { + keyword: throttledKeyword, + }, + { + enabled: Boolean(throttledKeyword), + onSuccess(res) { + if (res?.orgFuzzySearch?.length === 0) { + onChange(throttledKeyword); + } + }, + } + ); + const showLoading = isLoading && fetchStatus === 'fetching'; + + return ( +
+ { + setKeyword(e.target.value); + }} + onFocus={() => { + setShowlist(true); + }} + onBlur={() => { + setTimeout(() => { + setShowlist(false); + }, 200); + }} + placeholder={placeholder} + className={classnames(inputClass ? inputClass : 'ant-org-input')} + autoComplete={'off'} + /> + {data?.orgFuzzySearch?.length > 0 && ( +
+ {data?.orgFuzzySearch?.map(({ orgName }) => { + return ( +
{ + setKeyword(orgName); + onChange(orgName); + }} + > + {orgName} +
+ ); + })} +
+ )} +
+ {showLoading ? ( + + ) : null} +
+
+ ); +}; + +export default Select; diff --git a/apps/web/src/common/components/OrgEdit/index.tsx b/apps/web/src/common/components/OrgEdit/index.tsx new file mode 100644 index 00000000..fa5dc0d1 --- /dev/null +++ b/apps/web/src/common/components/OrgEdit/index.tsx @@ -0,0 +1,170 @@ +import React, { useState } from 'react'; +import { Button } from '@oss-compass/ui'; +import { useTranslation } from 'react-i18next'; +import OrgInput from './OrgInput'; +import DateRangePicker from './DateRangePicker'; +import { Form } from 'antd'; +import { + ContributorOrgInput, + useModifyUserOrgsMutation, +} from '@oss-compass/graphql'; +import client from '@common/gqlClient'; +import { toast } from 'react-hot-toast'; +import dayjs from 'dayjs'; +import type { Dayjs } from 'dayjs'; +const FORMAT_YMD = 'YYYY-MM-DD'; + +type RangeValue = [Dayjs | null, Dayjs | null] | null; + +const OrgEdit = ({ + organizations = [], + type = 'add', + index, + setShowEdit, + onSuccess, +}: { + organizations?: ContributorOrgInput[]; + type?: 'add' | 'edit'; + index?: number; + setShowEdit: (b: boolean) => void; + onSuccess?: () => void; +}) => { + const { t } = useTranslation(); + const [orgName, setOrgName] = useState( + type === 'edit' ? organizations[index]['orgName'] : '' + ); + const [date, setDate] = useState( + type === 'edit' + ? [ + dayjs(organizations[index]['firstDate'], FORMAT_YMD), + dayjs(organizations[index]['lastDate'], FORMAT_YMD), + ] + : null + ); + const [form] = Form.useForm(); + const onCheck = async () => { + try { + const values = await form.validateFields(); + const firstDate = values['date'][0].format(FORMAT_YMD); + const lastDate = values['date'][1].format(FORMAT_YMD); + const orgName = values['orgName']; + if (type === 'edit') { + organizations[index] = { orgName, firstDate, lastDate }; + mutation.mutate({ + platform: 'github', + organizations: [...organizations], + }); + } else { + mutation.mutate({ + platform: 'github', + organizations: [{ orgName, firstDate, lastDate }, ...organizations], + }); + } + } catch (errorInfo) { + console.log('Failed:', errorInfo); + } + }; + const disabledDate = (current: Dayjs) => { + if (!organizations) { + return false; + } + const result = organizations.some(({ firstDate, lastDate }, i) => { + if (index === i) { + return false; + } + return ( + firstDate && current > dayjs(firstDate) && current < dayjs(lastDate) + ); + }); + return result; + }; + const mutation = useModifyUserOrgsMutation(client, { + onSuccess(res) { + if (res.modifyUserOrgs?.status === 'true') { + setShowEdit(false); + toast.success( + res.modifyUserOrgs?.message || type === 'add' + ? t('common:toast.add_successful') + : t('common:toast.modification_successful') + ); + onSuccess(); + } + + if (res.modifyUserOrgs?.status === 'false') { + toast.error( + res.modifyUserOrgs?.message || type === 'add' + ? t('common:toast.add_failed') + : t('common:toast.modification_failed') + ); + } + }, + }); + return ( +
+
+
+ + { + setOrgName(e); + }} + placeholder={''} + /> + + + { + setDate(e); + }} + /> + +
+
+ + +
+
+
+ ); +}; +export default OrgEdit; diff --git a/apps/web/src/common/components/SelectAndInput/index.tsx b/apps/web/src/common/components/SelectAndInput/index.tsx index 4facfedc..323a577c 100644 --- a/apps/web/src/common/components/SelectAndInput/index.tsx +++ b/apps/web/src/common/components/SelectAndInput/index.tsx @@ -46,7 +46,7 @@ const Select: React.FC< }} placeholder={placeholder} className={classnames( - 'daisy-select h-12 w-full flex-1 border-2 border-black text-base outline-none' + 'daisy-select !h-full w-full flex-1 border-2 border-black text-base outline-none' )} autoComplete={'off'} /> diff --git a/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/ContributorContribution.tsx b/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/ContributorContribution.tsx index a3fca750..29c75474 100644 --- a/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/ContributorContribution.tsx +++ b/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/ContributorContribution.tsx @@ -138,6 +138,7 @@ const getSeriesFun = (data, onlyIdentity, onlyOrg, getEcologicalText) => { itemStyle: { color: colorList[0] }, }); legend.push({ + index: index, name: name, itemStyle: { color: colorList[0] }, }); @@ -167,6 +168,7 @@ const getSeriesFun = (data, onlyIdentity, onlyOrg, getEcologicalText) => { }); }); legend.push({ + index: index, name: name, itemStyle: { color: colorList[0] }, }); @@ -179,7 +181,7 @@ const getSeriesFun = (data, onlyIdentity, onlyOrg, getEcologicalText) => { }); } } - + legend.sort((a, b) => a?.index - b?.index); return { legend, allCount, @@ -334,6 +336,7 @@ const OrgContributorContribution: React.FC<{ }); }); legend.push({ + index: index, name: name, itemStyle: { color: colorList[0] }, }); @@ -345,6 +348,7 @@ const OrgContributorContribution: React.FC<{ }); }); } + legend.sort((a, b) => a?.index - b?.index); return { legend, allCount, diff --git a/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/ContributorOrganizations.tsx b/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/ContributorOrganizations.tsx index ed9078f5..c2070c42 100644 --- a/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/ContributorOrganizations.tsx +++ b/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/ContributorOrganizations.tsx @@ -71,6 +71,7 @@ const ContributorContribution: React.FC<{ formatter: formatter, }, legend: { + type: 'scroll', top: 40, left: 'center', data: getSeries.legend, diff --git a/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/ContributorTable.tsx b/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/ContributorTable.tsx index 7465d97a..e3faeb94 100644 --- a/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/ContributorTable.tsx +++ b/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/ContributorTable.tsx @@ -7,6 +7,7 @@ import { } from '@oss-compass/graphql'; import client from '@common/gqlClient'; import MyTable from '@common/components/Table'; +import classnames from 'classnames'; import { useContributionTypeLsit, useGetContributionTypeI18n, @@ -17,11 +18,16 @@ import { Tag } from 'antd'; 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 { getContributorPolling, getContributorExport } from '../tableDownload'; import { useRouter } from 'next/router'; import { useHandleQueryParams } from '@modules/analyze/hooks/useHandleQueryParams'; +import Dialog from '@common/components/Dialog'; +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'; + interface TableParams { pagination?: TablePaginationConfig; filterOpts?: FilterOptionInput[]; @@ -37,6 +43,11 @@ const MetricTable: React.FC<{ mileage: string[]; }> = ({ label, level, beginDate, endDate, mileage }) => { const { t } = useTranslation(); + const [openConfirm, setOpenConfirm] = useState(false); + const [currentName, setCurrentName] = useState(''); + const [currentOrgName, setCurrentOrgName] = useState(''); + const { data } = useVerifyDetailRange(); + const ecologicalOptions = useEcologicalType(); const mileageOptions = useMileageOptions(); const filterMap = { @@ -106,7 +117,6 @@ const MetricTable: React.FC<{ ); }); } - setData(items); setTableParams({ ...tableParams, pagination: { @@ -114,6 +124,7 @@ const MetricTable: React.FC<{ total: data.contributorsDetailList.count, }, }); + setData(items); }, // keepPreviousData: true, // onError(res: any) { @@ -162,7 +173,10 @@ const MetricTable: React.FC<{ }); setFilterOpts(filterOpts); setTableParams({ - pagination, + pagination: { + showTotal: tableParams.pagination.showTotal, + ...pagination, + }, sortOpts, filterOpts, }); @@ -239,6 +253,25 @@ const MetricTable: React.FC<{ dataIndex: 'organization', align: 'left', width: '160px', + render: (text, col) => { + return ( +
+ {text || '-'} + + {data?.verifyDetailDataRange?.labelAdmin && ( + { + setCurrentName(col.contributor); + col.organization && setCurrentOrgName(col.organization); + setOpenConfirm(true); + }} + /> + )} + +
+ ); + }, }, { title: t('analyze:metric_detail:contribution'), @@ -279,6 +312,48 @@ const MetricTable: React.FC<{ rowKey={'contributor'} scroll={{ x: 'max-content' }} /> + +

+ {currentName + + ' ' + + t('analyze:organization_information_modification')} +

+
{ + setOpenConfirm(false); + }} + > + +
+ + } + dialogContent={ +
+ { + setOpenConfirm(false); + }} + /> +
+ } + handleClose={() => { + setOpenConfirm(false); + }} + /> ); }; diff --git a/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/Contributors.tsx b/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/Contributors.tsx index edd9eb60..72a8f934 100644 --- a/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/Contributors.tsx +++ b/apps/web/src/modules/analyze/DataView/MetricDetail/MetricContributor/Contributors.tsx @@ -69,6 +69,7 @@ const getSeriesFun = (data, onlyIdentity, onlyOrg, getEcologicalText) => { itemStyle: { color: colorList[0] }, }); legend.push({ + index: index, name: name, itemStyle: { color: colorList[0] }, }); @@ -99,6 +100,7 @@ const getSeriesFun = (data, onlyIdentity, onlyOrg, getEcologicalText) => { }); legend.push({ name: name, + index: index, itemStyle: { color: colorList[0] }, }); allCount += count; @@ -110,7 +112,7 @@ const getSeriesFun = (data, onlyIdentity, onlyOrg, getEcologicalText) => { }); } } - + legend.sort((a, b) => a?.index - b?.index); return { legend, allCount, diff --git a/apps/web/src/modules/analyze/DataView/MetricDetail/MetricIssue/IssueTable.tsx b/apps/web/src/modules/analyze/DataView/MetricDetail/MetricIssue/IssueTable.tsx index c57ac6d1..fec11021 100644 --- a/apps/web/src/modules/analyze/DataView/MetricDetail/MetricIssue/IssueTable.tsx +++ b/apps/web/src/modules/analyze/DataView/MetricDetail/MetricIssue/IssueTable.tsx @@ -93,7 +93,10 @@ const MetricTable: React.FC<{ } } setTableParams({ - pagination, + pagination: { + showTotal: tableParams.pagination.showTotal, + ...pagination, + }, sortOpts, filterOpts, }); diff --git a/apps/web/src/modules/analyze/DataView/MetricDetail/MetricPr/PrTable.tsx b/apps/web/src/modules/analyze/DataView/MetricDetail/MetricPr/PrTable.tsx index 34c4f5de..6c6c492a 100644 --- a/apps/web/src/modules/analyze/DataView/MetricDetail/MetricPr/PrTable.tsx +++ b/apps/web/src/modules/analyze/DataView/MetricDetail/MetricPr/PrTable.tsx @@ -93,7 +93,10 @@ const MetricTable: React.FC<{ } } setTableParams({ - pagination, + pagination: { + showTotal: tableParams.pagination.showTotal, + ...pagination, + }, sortOpts, filterOpts, }); diff --git a/apps/web/src/modules/settings/profile/Organizations.tsx b/apps/web/src/modules/settings/profile/Organizations.tsx new file mode 100644 index 00000000..a19784fb --- /dev/null +++ b/apps/web/src/modules/settings/profile/Organizations.tsx @@ -0,0 +1,146 @@ +import React, { useRef, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import classNames from 'classnames'; +import { RiDeleteBinLine } from 'react-icons/ri'; +import { FiEdit } from 'react-icons/fi'; +import OrgEdit from '@common/components/OrgEdit'; +import client from '@common/gqlClient'; +import { toast } from 'react-hot-toast'; +import { useSnapshot } from 'valtio'; +import { userInfoStore, userEvent } from '@modules/auth/UserInfoStore'; +import { + useModifyUserOrgsMutation, + ContributorOrgInput, +} from '@oss-compass/graphql'; + +const OrgItem = ({ provider, index, organizations, onSuccess }) => { + const customFormat = (date) => { + if (date.startsWith('2099')) { + return t('common:up_to_now'); + } + return date; + }; + const { t } = useTranslation(); + const [showEdit, setShowEdit] = useState(false); + const mutation = useModifyUserOrgsMutation(client, { + onSuccess(res) { + if (res.modifyUserOrgs?.status === 'true') { + onSuccess(); + toast.success( + res.modifyUserOrgs?.message || t('common:toast.delete_successful') + ); + } + if (res.modifyUserOrgs?.status === 'false') { + toast.error( + res.modifyUserOrgs?.message || t('common:toast.delete_successful') + ); + } + }, + }); + const onDelete = () => { + const arr = [...organizations]; + arr.splice(index, 1); + mutation.mutate({ + platform: 'github', + organizations: [...arr], + }); + }; + return ( +
+ {showEdit ? ( + + ) : ( +
+
+
+ + {provider.orgName} + +
+
+
{customFormat(provider?.firstDate)}
+ {'-'}{' '} +
{customFormat(provider?.lastDate)}
+
+
+
+ + setShowEdit(true)} + /> +
+
+ )} +
+ ); +}; + +const Organizations = () => { + const { t } = useTranslation(); + const { currentUser } = useSnapshot(userInfoStore); + const contributingOrgs = currentUser.contributingOrgs.map((item) => { + return { + orgName: item.orgName, + firstDate: item.firstDate?.slice(0, 10), + lastDate: item.lastDate?.slice(0, 10), + }; + }); + const [showEdit, setShowEdit] = useState(false); + const onSuccess = () => { + setTimeout(() => { + userInfoStore.event$?.emit(userEvent.REFRESH); + }, 1000); + }; + return ( +
+
+ {t('setting:profile.organizations')} +
+
{t('setting:profile.organizations_desc')}
+
+ {contributingOrgs.map((item, index) => { + return ( + + ); + })} +
+ {showEdit && ( + + )} +
+ { + !showEdit && setShowEdit(true); + }} + > + {t('setting:profile.add_a_new_organization')} + +
+
+ ); +}; + +export default Organizations; diff --git a/apps/web/src/modules/settings/profile/index.tsx b/apps/web/src/modules/settings/profile/index.tsx index d1363315..d08ea6ed 100644 --- a/apps/web/src/modules/settings/profile/index.tsx +++ b/apps/web/src/modules/settings/profile/index.tsx @@ -2,6 +2,7 @@ import React, { useEffect } from 'react'; import Center from '@common/components/Layout/Center'; import ProfileForm from './ProfileForm'; import OAuthList from './OAuthList'; +import Organizations from './Organizations'; import DeleteAccount from './DeleteAccount'; const ProfileSetting = () => { @@ -9,6 +10,7 @@ const ProfileSetting = () => {
+
); diff --git a/apps/web/src/styles/antd.scss b/apps/web/src/styles/antd.scss index b991547f..f2a0ff45 100644 --- a/apps/web/src/styles/antd.scss +++ b/apps/web/src/styles/antd.scss @@ -14,6 +14,42 @@ .ant-progress-inner { border-radius: 0px !important; } +.ant-range-picker { + border-radius: 0px !important; + height: 26px; + width: 250px; +} +.ant-org-input { + border-radius: 0px !important; + height: 26px; + // width: 160px; +} +.ant-form-item-control-input { + min-height: 24px !important; +} +.ant-form-item-required { + font-size: 16px !important; +} +.ant-picker-dropdown { + z-index: 99999; +} +.ant-input:focus-within { + border-color: unset; + box-shadow: none; +} +.ant-input:hover { + border-color: unset; +} +.ant-picker-focused.ant-picker { + border-color: unset; + box-shadow: none; +} +.ant-picker:hover { + border-color: unset; +} +.ant-picker-clear { + // inset-inline-end: 16px !important; +} // .ant-spin-nested-loading { // height: 100%; // .ant-spin-container { diff --git a/packages/graphql/src/generated.ts b/packages/graphql/src/generated.ts index 148c11cd..bd6ddc3a 100644 --- a/packages/graphql/src/generated.ts +++ b/packages/graphql/src/generated.ts @@ -39,6 +39,7 @@ export type Scalars = { Boolean: boolean; Int: number; Float: number; + ISO8601Date: any; ISO8601DateTime: any; }; @@ -482,6 +483,27 @@ export type ContributorDetailPage = { totalPage?: Maybe; }; +export type ContributorOrg = { + __typename?: 'ContributorOrg'; + /** time of begin of service by the organization */ + firstDate?: Maybe; + /** time of end of service by the organization */ + lastDate?: Maybe; + /** organization's name */ + orgName?: Maybe; + /** platform type of the organization */ + platformType?: Maybe; +}; + +export type ContributorOrgInput = { + /** time of begin of service by the organization */ + firstDate: Scalars['ISO8601Date']; + /** time of end of service by the organization */ + lastDate: Scalars['ISO8601Date']; + /** organization's name */ + orgName: Scalars['String']; +}; + export type ContributorTopOverview = { __typename?: 'ContributorTopOverview'; overviewName?: Maybe; @@ -1011,6 +1033,34 @@ export type LoginBind = { provider?: Maybe; }; +/** Autogenerated input type of ManageUserOrgs */ +export type ManageUserOrgsInput = { + /** A unique identifier for the client performing the mutation. */ + clientMutationId?: InputMaybe; + /** name of the contributor */ + contributor: Scalars['String']; + /** repo or community label */ + label: Scalars['String']; + /** repo or community level */ + level?: InputMaybe; + /** contributor organizations */ + organizations: Array; + /** platform of the organization */ + platform: Scalars['String']; +}; + +/** Autogenerated return type of ManageUserOrgs */ +export type ManageUserOrgsPayload = { + __typename?: 'ManageUserOrgsPayload'; + /** A unique identifier for the client performing the mutation. */ + clientMutationId?: Maybe; + /** Errors encountered during execution of the mutation. */ + errors?: Maybe>; + message?: Maybe; + prUrl?: Maybe; + status: Scalars['String']; +}; + export type MemberPage = { __typename?: 'MemberPage'; count?: Maybe; @@ -1177,6 +1227,27 @@ export type ModifyUserInput = { name: Scalars['String']; }; +/** Autogenerated input type of ModifyUserOrgs */ +export type ModifyUserOrgsInput = { + /** A unique identifier for the client performing the mutation. */ + clientMutationId?: InputMaybe; + /** contributor organizations */ + organizations: Array; + /** platform of the organization */ + platform: Scalars['String']; +}; + +/** Autogenerated return type of ModifyUserOrgs */ +export type ModifyUserOrgsPayload = { + __typename?: 'ModifyUserOrgsPayload'; + /** A unique identifier for the client performing the mutation. */ + clientMutationId?: Maybe; + /** Errors encountered during execution of the mutation. */ + errors?: Maybe>; + message?: Maybe; + status: Scalars['String']; +}; + /** Autogenerated return type of ModifyUser */ export type ModifyUserPayload = { __typename?: 'ModifyUserPayload'; @@ -1218,8 +1289,12 @@ export type Mutation = { deleteLabModelVersion?: Maybe; /** Destroy user */ destroyUser?: Maybe; + /** Manage user organizations */ + manageUserOrgs?: Maybe; /** Modify user */ modifyUser?: Maybe; + /** Modify user organizations */ + modifyUserOrgs?: Maybe; /** Send email verify */ sendEmailVerify?: Maybe; /** Send member invitation */ @@ -1292,10 +1367,18 @@ export type MutationDeleteLabModelVersionArgs = { input: DeleteLabModelVersionInput; }; +export type MutationManageUserOrgsArgs = { + input: ManageUserOrgsInput; +}; + export type MutationModifyUserArgs = { input: ModifyUserInput; }; +export type MutationModifyUserOrgsArgs = { + input: ModifyUserOrgsInput; +}; + export type MutationSendEmailVerifyArgs = { input: SendEmailVerifyInput; }; @@ -1336,6 +1419,12 @@ export type MyModels = { totalPage?: Maybe; }; +export type OrgCompletionRow = { + __typename?: 'OrgCompletionRow'; + /** organization name */ + orgName?: Maybe; +}; + export type Panel = { __typename?: 'Panel'; /** specific fields and chart types for metric data */ @@ -1502,6 +1591,8 @@ export type Query = { orgContributorsDistribution: Array; /** Get organization contributors overview */ orgContributorsOverview: Array; + /** Fuzzy search organization by keyword */ + orgFuzzySearch: Array; /** Get overview data of a repo */ pullsDetailList: PullDetailPage; /** Get overview data of a pull detail */ @@ -1799,6 +1890,10 @@ export type QueryOrgContributorsOverviewArgs = { level?: InputMaybe; }; +export type QueryOrgFuzzySearchArgs = { + keyword: Scalars['String']; +}; + export type QueryPullsDetailListArgs = { beginDate?: InputMaybe; endDate?: InputMaybe; @@ -2167,6 +2262,7 @@ export type UpdateMemberPermissionPayload = { export type User = { __typename?: 'User'; + contributingOrgs?: Maybe>; email: Scalars['String']; emailVerified: Scalars['Boolean']; id: Scalars['Int']; @@ -2206,6 +2302,8 @@ export type ValidDataRange = { __typename?: 'ValidDataRange'; /** metric model object identification */ label?: Maybe; + /** whether current is a repo admin for this label */ + labelAdmin?: Maybe; /** metric model object level (project or repo) */ level?: Maybe; /** max valid date */ @@ -3651,6 +3749,50 @@ export type CancelSubscriptionMutation = { } | null; }; +export type ModifyUserOrgsMutationVariables = Exact<{ + platform: Scalars['String']; + organizations: Array | ContributorOrgInput; +}>; + +export type ModifyUserOrgsMutation = { + __typename?: 'Mutation'; + modifyUserOrgs?: { + __typename?: 'ModifyUserOrgsPayload'; + clientMutationId?: string | null; + message?: string | null; + status: string; + errors?: Array<{ + __typename?: 'Error'; + message?: string | null; + path?: Array | null; + }> | null; + } | null; +}; + +export type ManageUserOrgsMutationVariables = Exact<{ + platform: Scalars['String']; + organizations: Array | ContributorOrgInput; + contributor: Scalars['String']; + label: Scalars['String']; + level: Scalars['String']; +}>; + +export type ManageUserOrgsMutation = { + __typename?: 'Mutation'; + manageUserOrgs?: { + __typename?: 'ManageUserOrgsPayload'; + clientMutationId?: string | null; + message?: string | null; + prUrl?: string | null; + status: string; + errors?: Array<{ + __typename?: 'Error'; + message?: string | null; + path?: Array | null; + }> | null; + } | null; +}; + export type UserinfoQueryVariables = Exact<{ [key: string]: never }>; export type UserinfoQuery = { @@ -3669,6 +3811,13 @@ export type UserinfoQuery = { nickname?: string | null; provider?: string | null; }> | null; + contributingOrgs?: Array<{ + __typename?: 'ContributorOrg'; + firstDate?: any | null; + lastDate?: any | null; + orgName?: string | null; + platformType?: string | null; + }> | null; } | null; }; @@ -4201,6 +4350,18 @@ export type SummaryQuery = { }>; }; +export type OrgSearchQueryVariables = Exact<{ + keyword: Scalars['String']; +}>; + +export type OrgSearchQuery = { + __typename?: 'Query'; + orgFuzzySearch: Array<{ + __typename?: 'OrgCompletionRow'; + orgName?: string | null; + }>; +}; + export type MetricStatFragment = { __typename?: 'MetricStat'; mean?: number | null; @@ -4717,6 +4878,7 @@ export type VerifyDetailDataRangeQuery = { status?: boolean | null; max?: any | null; min?: any | null; + labelAdmin?: boolean | null; }; }; @@ -6878,6 +7040,109 @@ useCancelSubscriptionMutation.fetcher = ( variables, headers ); +export const ModifyUserOrgsDocument = /*#__PURE__*/ ` + mutation modifyUserOrgs($platform: String!, $organizations: [ContributorOrgInput!]!) { + modifyUserOrgs(input: {platform: $platform, organizations: $organizations}) { + clientMutationId + errors { + message + path + } + message + status + } +} + `; +export const useModifyUserOrgsMutation = ( + client: GraphQLClient, + options?: UseMutationOptions< + ModifyUserOrgsMutation, + TError, + ModifyUserOrgsMutationVariables, + TContext + >, + headers?: RequestInit['headers'] +) => + useMutation< + ModifyUserOrgsMutation, + TError, + ModifyUserOrgsMutationVariables, + TContext + >( + ['modifyUserOrgs'], + (variables?: ModifyUserOrgsMutationVariables) => + fetcher( + client, + ModifyUserOrgsDocument, + variables, + headers + )(), + options + ); +useModifyUserOrgsMutation.fetcher = ( + client: GraphQLClient, + variables: ModifyUserOrgsMutationVariables, + headers?: RequestInit['headers'] +) => + fetcher( + client, + ModifyUserOrgsDocument, + variables, + headers + ); +export const ManageUserOrgsDocument = /*#__PURE__*/ ` + mutation manageUserOrgs($platform: String!, $organizations: [ContributorOrgInput!]!, $contributor: String!, $label: String!, $level: String!) { + manageUserOrgs( + input: {platform: $platform, contributor: $contributor, label: $label, level: $level, organizations: $organizations} + ) { + clientMutationId + errors { + message + path + } + message + prUrl + status + } +} + `; +export const useManageUserOrgsMutation = ( + client: GraphQLClient, + options?: UseMutationOptions< + ManageUserOrgsMutation, + TError, + ManageUserOrgsMutationVariables, + TContext + >, + headers?: RequestInit['headers'] +) => + useMutation< + ManageUserOrgsMutation, + TError, + ManageUserOrgsMutationVariables, + TContext + >( + ['manageUserOrgs'], + (variables?: ManageUserOrgsMutationVariables) => + fetcher( + client, + ManageUserOrgsDocument, + variables, + headers + )(), + options + ); +useManageUserOrgsMutation.fetcher = ( + client: GraphQLClient, + variables: ManageUserOrgsMutationVariables, + headers?: RequestInit['headers'] +) => + fetcher( + client, + ManageUserOrgsDocument, + variables, + headers + ); export const UserinfoDocument = /*#__PURE__*/ ` query userinfo { currentUser { @@ -6892,6 +7157,12 @@ export const UserinfoDocument = /*#__PURE__*/ ` nickname provider } + contributingOrgs { + firstDate + lastDate + orgName + platformType + } } } `; @@ -7604,6 +7875,45 @@ useSummaryQuery.fetcher = ( variables, headers ); +export const OrgSearchDocument = /*#__PURE__*/ ` + query orgSearch($keyword: String!) { + orgFuzzySearch(keyword: $keyword) { + orgName + } +} + `; +export const useOrgSearchQuery = ( + client: GraphQLClient, + variables: OrgSearchQueryVariables, + options?: UseQueryOptions, + headers?: RequestInit['headers'] +) => + useQuery( + ['orgSearch', variables], + fetcher( + client, + OrgSearchDocument, + variables, + headers + ), + options + ); + +useOrgSearchQuery.getKey = (variables: OrgSearchQueryVariables) => [ + 'orgSearch', + variables, +]; +useOrgSearchQuery.fetcher = ( + client: GraphQLClient, + variables: OrgSearchQueryVariables, + headers?: RequestInit['headers'] +) => + fetcher( + client, + OrgSearchDocument, + variables, + headers + ); export const CollectionHottestDocument = /*#__PURE__*/ ` query collectionHottest($ident: String!, $limit: Int) { collectionHottest(ident: $ident, limit: $limit) { @@ -8670,6 +8980,7 @@ export const VerifyDetailDataRangeDocument = /*#__PURE__*/ ` status max min + labelAdmin } } `; diff --git a/packages/graphql/src/gql/mutation.graphql b/packages/graphql/src/gql/mutation.graphql index 52d0db22..3e91f297 100644 --- a/packages/graphql/src/gql/mutation.graphql +++ b/packages/graphql/src/gql/mutation.graphql @@ -79,3 +79,45 @@ mutation cancelSubscription($label: String!, $level: String!) { status } } +mutation modifyUserOrgs( + $platform: String! + $organizations: [ContributorOrgInput!]! +) { + modifyUserOrgs( + input: { platform: $platform, organizations: $organizations } + ) { + clientMutationId + errors { + message + path + } + message + status + } +} +mutation manageUserOrgs( + $platform: String! + $organizations: [ContributorOrgInput!]! + $contributor: String! + $label: String! + $level: String! +) { + manageUserOrgs( + input: { + platform: $platform + contributor: $contributor + label: $label + level: $level + organizations: $organizations + } + ) { + clientMutationId + errors { + message + path + } + message + prUrl + status + } +} diff --git a/packages/graphql/src/gql/query.graphql b/packages/graphql/src/gql/query.graphql index a72ff960..095e0377 100644 --- a/packages/graphql/src/gql/query.graphql +++ b/packages/graphql/src/gql/query.graphql @@ -11,6 +11,12 @@ query userinfo { nickname provider } + contributingOrgs { + firstDate + lastDate + orgName + platformType + } } } @@ -423,6 +429,11 @@ query summary($start: ISO8601DateTime, $end: ISO8601DateTime) { # } } +query orgSearch($keyword: String!) { + orgFuzzySearch(keyword: $keyword) { + orgName + } +} # query labMetric( # $label: String! # $level: String = "repo" @@ -930,6 +941,7 @@ query verifyDetailDataRange( status max min + labelAdmin } }