mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-06 13:31:28 +00:00
ui: feedback 1.0.1 part 2 (#11482)
* ui: feedback 1.0.1 part 2 * miner fix * fixed code smell bug
This commit is contained in:
parent
9945974fac
commit
8607d30b1e
@ -13,13 +13,12 @@
|
|||||||
import { Button, Popover, Space, Tabs, Tooltip, Typography } from 'antd';
|
import { Button, Popover, Space, Tabs, Tooltip, Typography } from 'antd';
|
||||||
import { ReactComponent as EditIcon } from 'assets/svg/edit-new.svg';
|
import { ReactComponent as EditIcon } from 'assets/svg/edit-new.svg';
|
||||||
import { WILD_CARD_CHAR } from 'constants/char.constants';
|
import { WILD_CARD_CHAR } from 'constants/char.constants';
|
||||||
import { PAGE_SIZE_MEDIUM, pagingObject } from 'constants/constants';
|
import { PAGE_SIZE_MEDIUM } from 'constants/constants';
|
||||||
import { NO_PERMISSION_FOR_ACTION } from 'constants/HelperTextUtil';
|
import { NO_PERMISSION_FOR_ACTION } from 'constants/HelperTextUtil';
|
||||||
import { EntityType } from 'enums/entity.enum';
|
import { EntityType } from 'enums/entity.enum';
|
||||||
import { SearchIndex } from 'enums/search.enum';
|
import { SearchIndex } from 'enums/search.enum';
|
||||||
import { EntityReference } from 'generated/entity/data/table';
|
import { EntityReference } from 'generated/entity/data/table';
|
||||||
import { Paging } from 'generated/type/paging';
|
import { isEmpty, noop, toString } from 'lodash';
|
||||||
import { isEmpty, isEqual, noop, toString } from 'lodash';
|
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { searchData } from 'rest/miscAPI';
|
import { searchData } from 'rest/miscAPI';
|
||||||
@ -35,6 +34,15 @@ import { SelectableList } from '../SelectableList/SelectableList.component';
|
|||||||
import './user-team-selectable-list.less';
|
import './user-team-selectable-list.less';
|
||||||
import { UserSelectDropdownProps } from './UserTeamSelectableList.interface';
|
import { UserSelectDropdownProps } from './UserTeamSelectableList.interface';
|
||||||
|
|
||||||
|
export const TeamListItemRenderer = (props: EntityReference) => {
|
||||||
|
return (
|
||||||
|
<Space>
|
||||||
|
<SVGIcons icon={Icons.TEAMS_GREY} />
|
||||||
|
<Typography.Text>{getEntityName(props)}</Typography.Text>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const UserTeamSelectableList = ({
|
export const UserTeamSelectableList = ({
|
||||||
hasPermission,
|
hasPermission,
|
||||||
owner,
|
owner,
|
||||||
@ -43,9 +51,8 @@ export const UserTeamSelectableList = ({
|
|||||||
}: UserSelectDropdownProps) => {
|
}: UserSelectDropdownProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [popupVisible, setPopupVisible] = useState(false);
|
const [popupVisible, setPopupVisible] = useState(false);
|
||||||
const [userPaging, setUserPaging] = useState<Paging>(pagingObject);
|
|
||||||
const [teamPaging, setTeamPaging] = useState<Paging>(pagingObject);
|
|
||||||
const [activeTab, setActiveTab] = useState<'teams' | 'users'>('teams');
|
const [activeTab, setActiveTab] = useState<'teams' | 'users'>('teams');
|
||||||
|
const [count, setCount] = useState({ team: 0, user: 0 });
|
||||||
|
|
||||||
const fetchUserOptions = async (searchText: string, after?: string) => {
|
const fetchUserOptions = async (searchText: string, after?: string) => {
|
||||||
if (searchText) {
|
if (searchText) {
|
||||||
@ -64,7 +71,7 @@ export const UserTeamSelectableList = ({
|
|||||||
formatUsersResponse(res.data.hits.hits),
|
formatUsersResponse(res.data.hits.hits),
|
||||||
EntityType.USER
|
EntityType.USER
|
||||||
);
|
);
|
||||||
setUserPaging({ total: res.data.hits.total.value });
|
setCount((pre) => ({ ...pre, user: res.data.hits.total.value }));
|
||||||
|
|
||||||
return { data, paging: { total: res.data.hits.total.value } };
|
return { data, paging: { total: res.data.hits.total.value } };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -87,7 +94,8 @@ export const UserTeamSelectableList = ({
|
|||||||
data,
|
data,
|
||||||
EntityType.USER
|
EntityType.USER
|
||||||
);
|
);
|
||||||
setUserPaging(paging);
|
|
||||||
|
setCount((pre) => ({ ...pre, user: paging.total }));
|
||||||
|
|
||||||
return { data: filterData, paging };
|
return { data: filterData, paging };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -116,7 +124,7 @@ export const UserTeamSelectableList = ({
|
|||||||
EntityType.TEAM
|
EntityType.TEAM
|
||||||
);
|
);
|
||||||
|
|
||||||
setTeamPaging({ total: res.data.hits.total.value });
|
setCount((pre) => ({ ...pre, team: res.data.hits.total.value }));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data,
|
data,
|
||||||
@ -145,10 +153,7 @@ export const UserTeamSelectableList = ({
|
|||||||
EntityType.TEAM
|
EntityType.TEAM
|
||||||
);
|
);
|
||||||
|
|
||||||
setTeamPaging({
|
setCount((pre) => ({ ...pre, team: data.hits.total.value }));
|
||||||
total: data.hits.total.value,
|
|
||||||
after: toString(afterPage + 1),
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: filterData,
|
data: filterData,
|
||||||
@ -189,14 +194,34 @@ export const UserTeamSelectableList = ({
|
|||||||
SearchIndex.USER
|
SearchIndex.USER
|
||||||
);
|
);
|
||||||
|
|
||||||
setUserPaging({ total: res.data.hits.total.value });
|
setCount((pre) => ({ ...pre, user: res.data.hits.total.value }));
|
||||||
|
};
|
||||||
|
const getTeamCount = async () => {
|
||||||
|
const res = await searchData(
|
||||||
|
'',
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
'teamType:Group',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
SearchIndex.TEAM
|
||||||
|
);
|
||||||
|
|
||||||
|
setCount((pre) => ({ ...pre, team: res.data.hits.total.value }));
|
||||||
};
|
};
|
||||||
|
|
||||||
// To pre-cache user total count
|
const fetchCount = async () => {
|
||||||
useEffect(() => {
|
if (popupVisible) {
|
||||||
if (popupVisible && isEqual(userPaging, pagingObject)) {
|
if (owner?.type === EntityType.USER) {
|
||||||
getUserCount();
|
await getTeamCount();
|
||||||
|
} else {
|
||||||
|
await getUserCount();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchCount();
|
||||||
}, [popupVisible]);
|
}, [popupVisible]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -221,7 +246,7 @@ export const UserTeamSelectableList = ({
|
|||||||
label: (
|
label: (
|
||||||
<>
|
<>
|
||||||
{t('label.team-plural')}{' '}
|
{t('label.team-plural')}{' '}
|
||||||
{getCountBadge(teamPaging.total, '', activeTab === 'teams')}
|
{getCountBadge(count.team, '', activeTab === 'teams')}
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
key: 'teams',
|
key: 'teams',
|
||||||
@ -242,7 +267,7 @@ export const UserTeamSelectableList = ({
|
|||||||
label: (
|
label: (
|
||||||
<>
|
<>
|
||||||
{t('label.user-plural')}
|
{t('label.user-plural')}
|
||||||
{getCountBadge(userPaging.total, '', activeTab === 'users')}
|
{getCountBadge(count.user, '', activeTab === 'users')}
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
key: 'users',
|
key: 'users',
|
||||||
@ -289,12 +314,3 @@ export const UserTeamSelectableList = ({
|
|||||||
</Popover>
|
</Popover>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TeamListItemRenderer = (props: EntityReference) => {
|
|
||||||
return (
|
|
||||||
<Space>
|
|
||||||
<SVGIcons icon={Icons.TEAMS_GREY} />
|
|
||||||
<Typography.Text>{getEntityName(props)}</Typography.Text>
|
|
||||||
</Space>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|||||||
@ -11,10 +11,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Select } from 'antd';
|
import { Select, Space, Typography } from 'antd';
|
||||||
|
import { ReactComponent as TeamIcon } from 'assets/svg/teams-grey.svg';
|
||||||
import { UserTag } from 'components/common/UserTag/UserTag.component';
|
import { UserTag } from 'components/common/UserTag/UserTag.component';
|
||||||
|
import { OwnerType } from 'enums/user.enum';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import React, { FC } from 'react';
|
import { groupBy, isUndefined } from 'lodash';
|
||||||
|
import React, { FC, useMemo } from 'react';
|
||||||
import { Option } from '../TasksPage.interface';
|
import { Option } from '../TasksPage.interface';
|
||||||
import './Assignee.less';
|
import './Assignee.less';
|
||||||
|
|
||||||
@ -31,18 +34,54 @@ const Assignees: FC<Props> = ({
|
|||||||
onChange,
|
onChange,
|
||||||
options,
|
options,
|
||||||
}) => {
|
}) => {
|
||||||
const { Option } = Select;
|
|
||||||
|
|
||||||
const handleOnChange = (_values: Option[], newOptions: Option | Option[]) => {
|
const handleOnChange = (_values: Option[], newOptions: Option | Option[]) => {
|
||||||
const newValues = (newOptions as Option[]).map((option) => ({
|
const newValues = (newOptions as Option[]).map((option) => ({
|
||||||
label: option['data-label'],
|
label: option['data-label'],
|
||||||
value: option.value,
|
value: option.value,
|
||||||
type: option['data-usertype'],
|
type: option.type,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
onChange(newValues as Option[]);
|
onChange(newValues as Option[]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updatedOption = useMemo(() => {
|
||||||
|
const groupByType = groupBy(options, (d) => d.type);
|
||||||
|
const groupOptions = [];
|
||||||
|
if (!isUndefined(groupByType.team)) {
|
||||||
|
groupOptions.push({
|
||||||
|
type: 'group',
|
||||||
|
label: 'Teams',
|
||||||
|
value: OwnerType.TEAM,
|
||||||
|
options: groupByType.team.map((team) => ({
|
||||||
|
...team,
|
||||||
|
label: (
|
||||||
|
<Space data-testid="assignee-option" key={team.value}>
|
||||||
|
<TeamIcon height={16} width={16} />
|
||||||
|
<Typography.Text>{team.label}</Typography.Text>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!isUndefined(groupByType.user)) {
|
||||||
|
groupOptions.push({
|
||||||
|
type: 'group',
|
||||||
|
label: 'Users',
|
||||||
|
value: OwnerType.USER,
|
||||||
|
options: groupByType.user.map((user) => ({
|
||||||
|
...user,
|
||||||
|
label: (
|
||||||
|
<div data-testid="assignee-option">
|
||||||
|
<UserTag id={user.value} name={user.label} />
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return groupOptions;
|
||||||
|
}, [options]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
showSearch
|
showSearch
|
||||||
@ -52,21 +91,13 @@ const Assignees: FC<Props> = ({
|
|||||||
filterOption={false}
|
filterOption={false}
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
notFoundContent={null}
|
notFoundContent={null}
|
||||||
|
options={updatedOption}
|
||||||
placeholder={t('label.select-to-search')}
|
placeholder={t('label.select-to-search')}
|
||||||
showArrow={false}
|
showArrow={false}
|
||||||
value={assignees.length ? assignees : undefined}
|
value={assignees.length ? assignees : undefined}
|
||||||
onChange={handleOnChange}
|
onChange={handleOnChange}
|
||||||
onSearch={onSearch}>
|
onSearch={onSearch}
|
||||||
{options.map((option) => (
|
/>
|
||||||
<Option
|
|
||||||
data-label={option.label}
|
|
||||||
data-testid="assignee-option"
|
|
||||||
data-usertype={option.type}
|
|
||||||
key={option.value}>
|
|
||||||
<UserTag id={option.value} name={option.label} />
|
|
||||||
</Option>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user