Fix #8481 (UI): Changed how team assets are shown similar to explore page (#8526)

* Changed how entity details are shown in 'My Data' and 'Following' tabs on user details page

* Changed how team assets are shown similar to explore page

* removed isUndefined as isEmpty will cover that

* - Renamed 'GlossaryTermAssets' interface to 'AssetsDataType' to use it commonly and made the required changes for where it was used
- Code optimisation to reuse repeated code blocks
- Localization changes for 'UserPage'

* - Code optimisation by using common util functions
- Localization changes for 'TeamsPage' and 'TeamDetailsV1'
- Fixed spelling mistakes
This commit is contained in:
Aniket Katkar 2022-11-08 16:42:00 +05:30 committed by GitHub
parent 710e3d785f
commit 00bac5c929
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 146 additions and 64 deletions

View File

@ -38,6 +38,7 @@ import { reactivateTeam } from '../../axiosAPIs/teamsAPI';
import { import {
getTeamAndUserDetailsPath, getTeamAndUserDetailsPath,
getUserPath, getUserPath,
LIST_SIZE,
PAGE_SIZE_MEDIUM, PAGE_SIZE_MEDIUM,
} from '../../constants/constants'; } from '../../constants/constants';
import { TEAMS_DOCS } from '../../constants/docs.constants'; import { TEAMS_DOCS } from '../../constants/docs.constants';
@ -54,13 +55,13 @@ import {
User, User,
} from '../../generated/entity/teams/user'; } from '../../generated/entity/teams/user';
import { EntityReference } from '../../generated/type/entityReference'; import { EntityReference } from '../../generated/type/entityReference';
import { Paging } from '../../generated/type/paging';
import { TeamDetailsProp } from '../../interface/teamsAndUsers.interface'; import { TeamDetailsProp } from '../../interface/teamsAndUsers.interface';
import jsonData from '../../jsons/en';
import AddAttributeModal from '../../pages/RolesPage/AddAttributeModal/AddAttributeModal'; import AddAttributeModal from '../../pages/RolesPage/AddAttributeModal/AddAttributeModal';
import UserCard from '../../pages/teams/UserCard';
import { import {
commonUserDetailColumns, commonUserDetailColumns,
getEntityName, getEntityName,
getTierFromEntityInfo,
hasEditAccess, hasEditAccess,
} from '../../utils/CommonUtils'; } from '../../utils/CommonUtils';
import { filterEntityAssets } from '../../utils/EntityUtils'; import { filterEntityAssets } from '../../utils/EntityUtils';
@ -83,6 +84,7 @@ import EntitySummaryDetails from '../common/EntitySummaryDetails/EntitySummaryDe
import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder'; import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder';
import NextPrevious from '../common/next-previous/NextPrevious'; import NextPrevious from '../common/next-previous/NextPrevious';
import Searchbar from '../common/searchbar/Searchbar'; import Searchbar from '../common/searchbar/Searchbar';
import TableDataCard from '../common/table-data-card/TableDataCard';
import TabsPane from '../common/TabsPane/TabsPane'; import TabsPane from '../common/TabsPane/TabsPane';
import TitleBreadcrumb from '../common/title-breadcrumb/title-breadcrumb.component'; import TitleBreadcrumb from '../common/title-breadcrumb/title-breadcrumb.component';
import { TitleBreadcrumbProps } from '../common/title-breadcrumb/title-breadcrumb.interface'; import { TitleBreadcrumbProps } from '../common/title-breadcrumb/title-breadcrumb.interface';
@ -115,6 +117,7 @@ interface PlaceholderProps {
} }
const TeamDetailsV1 = ({ const TeamDetailsV1 = ({
assets,
hasAccess, hasAccess,
currentTeam, currentTeam,
currentTeamUsers, currentTeamUsers,
@ -139,6 +142,7 @@ const TeamDetailsV1 = ({
handleAddUser, handleAddUser,
removeUserFromTeam, removeUserFromTeam,
afterDeleteAction, afterDeleteAction,
onAssetsPaginate,
}: TeamDetailsProp) => { }: TeamDetailsProp) => {
const { t } = useTranslation(); const { t } = useTranslation();
const isOrganization = currentTeam.name === TeamType.Organization; const isOrganization = currentTeam.name === TeamType.Organization;
@ -550,7 +554,9 @@ const TeamDetailsV1 = ({
} catch (error) { } catch (error) {
showErrorToast( showErrorToast(
error as AxiosError, error as AxiosError,
jsonData['api-error-messages']['fetch-user-permission-error'] t('message.entity-fetch-error', {
entity: 'User Permissions',
})
); );
} finally { } finally {
setLoading(false); setLoading(false);
@ -801,7 +807,7 @@ const TeamDetailsV1 = ({
* Check for current team datasets and return the dataset cards * Check for current team datasets and return the dataset cards
* @returns - dataset cards * @returns - dataset cards
*/ */
const getDatasetCards = () => { const getAssetDetailCards = () => {
const ownData = filterEntityAssets(currentTeam?.owns || []); const ownData = filterEntityAssets(currentTeam?.owns || []);
if (ownData.length <= 0) { if (ownData.length <= 0) {
@ -823,26 +829,38 @@ const TeamDetailsV1 = ({
} }
return ( return (
<> <div data-testid="table-container">
<div {assets.data.map((entity, index) => (
className="tw-grid xxl:tw-grid-cols-4 md:tw-grid-cols-3 tw-gap-4" <div className="m-b-sm" key={`${entity.name}${index}`}>
data-testid="dataset-card"> <TableDataCard
{' '} database={entity.database}
{ownData.map((dataset, index) => { databaseSchema={entity.databaseSchema}
const Dataset = { deleted={entity.deleted}
displayName: dataset.displayName || dataset.name || '', description={entity.description}
type: dataset.type, fullyQualifiedName={entity.fullyQualifiedName}
fqn: dataset.fullyQualifiedName || '', id={`tabledatacard${index}`}
id: dataset.id, indexType={entity.index}
name: dataset.name, name={entity.name}
}; owner={entity.owner}
service={entity.service}
return ( serviceType={entity.serviceType || '--'}
<UserCard isDataset isIconVisible item={Dataset} key={index} /> tags={entity.tags}
); tier={getTierFromEntityInfo(entity)}
})} usage={entity.weeklyPercentileRank}
</div> />
</> </div>
))}
{assets.total > LIST_SIZE && assets.data.length > 0 && (
<NextPrevious
isNumberBased
currentPage={assets.currPage}
pageSize={LIST_SIZE}
paging={{} as Paging}
pagingHandler={onAssetsPaginate}
totalCount={assets.total}
/>
)}
</div>
); );
}; };
@ -1116,7 +1134,7 @@ const TeamDetailsV1 = ({
{currentTab === 2 && getUserCards()} {currentTab === 2 && getUserCards()}
{currentTab === 3 && getDatasetCards()} {currentTab === 3 && getAssetDetailCards()}
{currentTab === 4 && {currentTab === 4 &&
(isEmpty(currentTeam.defaultRoles || []) ? ( (isEmpty(currentTeam.defaultRoles || []) ? (

View File

@ -12,7 +12,7 @@
*/ */
import { Operation } from 'fast-json-patch'; import { Operation } from 'fast-json-patch';
import { FormErrorData } from 'Models'; import { AssetsDataType, FormErrorData } from 'Models';
import { UserType } from '../enums/user.enum'; import { UserType } from '../enums/user.enum';
import { Team } from '../generated/entity/teams/team'; import { Team } from '../generated/entity/teams/team';
import { import {
@ -90,6 +90,7 @@ export interface TeamsAndUsersProps {
export interface TeamDetailsProp { export interface TeamDetailsProp {
currentTeam: Team; currentTeam: Team;
teams?: Team[]; teams?: Team[];
assets: AssetsDataType;
currentTeamUsers: User[]; currentTeamUsers: User[];
teamUserPagin: Paging; teamUserPagin: Paging;
currentTeamUserPage: number; currentTeamUserPage: number;
@ -114,6 +115,7 @@ export interface TeamDetailsProp {
handleLeaveTeamClick: (id: string, data: Operation[]) => Promise<void>; handleLeaveTeamClick: (id: string, data: Operation[]) => Promise<void>;
childTeams: Team[]; childTeams: Team[];
showDeletedTeam: boolean; showDeletedTeam: boolean;
onAssetsPaginate: (page: string | number) => void;
onShowDeletedTeamChange: (checked: boolean) => void; onShowDeletedTeamChange: (checked: boolean) => void;
onTeamExpand: ( onTeamExpand: (
loading?: boolean, loading?: boolean,

View File

@ -198,7 +198,6 @@
"start-date": "Start Date", "start-date": "Start Date",
"view-dag": "View Dag", "view-dag": "View Dag",
"search-team": "Search Team", "search-team": "Search Team",
"end-date": "End Date",
"show-deleted": "Show deleted", "show-deleted": "Show deleted",
"add-bot": "Add Bot", "add-bot": "Add Bot",
"search-for-bots": "Search for bots...", "search-for-bots": "Search for bots...",
@ -233,7 +232,13 @@
"no-owned-entities": "You have not owned anything yet.", "no-owned-entities": "You have not owned anything yet.",
"entity-fetch-error": "Error while fetching {{entity}}", "entity-fetch-error": "Error while fetching {{entity}}",
"feed-post-error": "Error while posting the message!", "feed-post-error": "Error while posting the message!",
"unexpected-error": "An unexpected error occurred." "unexpected-error": "An unexpected error occurred.",
"entity-creation-error": "Error while creating {{entity}}",
"entity-updation-error": "Error while updating {{entity}}",
"join-team-success": "Team joined successfully!",
"leave-team-success": "Left the team successfully!",
"join-team-error": "Error while joining the team!",
"leave-team-error": "Error while leaving the team!"
}, },
"server": { "server": {
"unexpected-response": "Unexpected response from server!" "unexpected-response": "Unexpected response from server!"

View File

@ -13,9 +13,10 @@
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import { compare, Operation } from 'fast-json-patch'; import { compare, Operation } from 'fast-json-patch';
import { cloneDeep, isUndefined } from 'lodash'; import { cloneDeep, isEmpty, isUndefined } from 'lodash';
import { SearchResponse } from 'Models'; import { AssetsDataType, FormattedTableData, SearchResponse } from 'Models';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useHistory, useParams } from 'react-router-dom'; import { useHistory, useParams } from 'react-router-dom';
import AppState from '../../AppState'; import AppState from '../../AppState';
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider'; import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
@ -38,10 +39,12 @@ import TeamDetailsV1 from '../../components/TeamDetails/TeamDetailsV1';
import Teams from '../../components/TeamDetails/Teams'; import Teams from '../../components/TeamDetails/Teams';
import { import {
INITIAL_PAGING_VALUE, INITIAL_PAGING_VALUE,
LIST_SIZE,
PAGE_SIZE_MEDIUM, PAGE_SIZE_MEDIUM,
pagingObject, pagingObject,
} from '../../constants/constants'; } from '../../constants/constants';
import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil'; import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil';
import { myDataSearchIndex } from '../../constants/Mydata.constants';
import { SearchIndex } from '../../enums/search.enum'; import { SearchIndex } from '../../enums/search.enum';
import { CreateTeam, TeamType } from '../../generated/api/teams/createTeam'; import { CreateTeam, TeamType } from '../../generated/api/teams/createTeam';
import { EntityReference } from '../../generated/entity/data/table'; import { EntityReference } from '../../generated/entity/data/table';
@ -49,8 +52,7 @@ import { Team } from '../../generated/entity/teams/team';
import { User } from '../../generated/entity/teams/user'; import { User } from '../../generated/entity/teams/user';
import { Paging } from '../../generated/type/paging'; import { Paging } from '../../generated/type/paging';
import { useAuth } from '../../hooks/authHooks'; import { useAuth } from '../../hooks/authHooks';
import jsonData from '../../jsons/en'; import { formatDataResponse, formatUsersResponse } from '../../utils/APIUtils';
import { formatUsersResponse } from '../../utils/APIUtils';
import { getEntityName } from '../../utils/CommonUtils'; import { getEntityName } from '../../utils/CommonUtils';
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils'; import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
import { getSettingPath, getTeamsWithFqnPath } from '../../utils/RouterUtils'; import { getSettingPath, getTeamsWithFqnPath } from '../../utils/RouterUtils';
@ -60,6 +62,7 @@ import AddUsersModalV1 from './AddUsersModalV1';
const TeamsPage = () => { const TeamsPage = () => {
const history = useHistory(); const history = useHistory();
const { t } = useTranslation();
const { getEntityPermissionByFqn } = usePermissionProvider(); const { getEntityPermissionByFqn } = usePermissionProvider();
const { isAdminUser } = useAuth(); const { isAdminUser } = useAuth();
const { isAuthDisabled } = useAuthContext(); const { isAuthDisabled } = useAuthContext();
@ -79,6 +82,11 @@ const TeamsPage = () => {
const [isAddingTeam, setIsAddingTeam] = useState<boolean>(false); const [isAddingTeam, setIsAddingTeam] = useState<boolean>(false);
const [isAddingUsers, setIsAddingUsers] = useState<boolean>(false); const [isAddingUsers, setIsAddingUsers] = useState<boolean>(false);
const [isLoading, setIsLoading] = useState<boolean>(false); const [isLoading, setIsLoading] = useState<boolean>(false);
const [assets, setAssets] = useState<AssetsDataType>({
data: [],
total: 0,
currPage: 1,
});
const [entityPermissions, setEntityPermissions] = const [entityPermissions, setEntityPermissions] =
useState<OperationPermission>(DEFAULT_ENTITY_PERMISSION); useState<OperationPermission>(DEFAULT_ENTITY_PERMISSION);
@ -156,10 +164,7 @@ const TeamsPage = () => {
setAllTeam(modifiedTeams); setAllTeam(modifiedTeams);
} }
} catch (error) { } catch (error) {
showErrorToast( showErrorToast(error as AxiosError, t('server.unexpected-response'));
error as AxiosError,
jsonData['api-error-messages']['unexpected-server-response']
);
} }
loading && setIsDataLoading((isDataLoading) => --isDataLoading); loading && setIsDataLoading((isDataLoading) => --isDataLoading);
}; };
@ -207,13 +212,10 @@ const TeamsPage = () => {
getCurrentTeamUsers(data.name); getCurrentTeamUsers(data.name);
setSelectedTeam(data); setSelectedTeam(data);
} else { } else {
throw jsonData['api-error-messages']['unexpected-server-response']; throw t('server.unexpected-response');
} }
} catch (error) { } catch (error) {
showErrorToast( showErrorToast(error as AxiosError, t('server.unexpected-response'));
error as AxiosError,
jsonData['api-error-messages']['unexpected-server-response']
);
} }
setIsPageLoading(false); setIsPageLoading(false);
}; };
@ -242,7 +244,9 @@ const TeamsPage = () => {
} catch (error) { } catch (error) {
showErrorToast( showErrorToast(
error as AxiosError, error as AxiosError,
jsonData['api-error-messages']['create-team-error'] t('message.entity-creation-error', {
entity: 'Team',
})
); );
} finally { } finally {
setIsLoading(false); setIsLoading(false);
@ -287,13 +291,15 @@ const TeamsPage = () => {
} }
resolve(); resolve();
} else { } else {
throw jsonData['api-error-messages']['unexpected-server-response']; throw t('server.unexpected-response');
} }
}) })
.catch((error: AxiosError) => { .catch((error: AxiosError) => {
showErrorToast( showErrorToast(
error, error,
jsonData['api-error-messages']['update-team-error'] t('message.entity-updation-error', {
entity: 'Team',
})
); );
reject(); reject();
}); });
@ -322,16 +328,13 @@ const TeamsPage = () => {
if (res) { if (res) {
AppState.updateUserDetails(res); AppState.updateUserDetails(res);
fetchTeamByFqn(selectedTeam.name); fetchTeamByFqn(selectedTeam.name);
showSuccessToast( showSuccessToast(t('message.join-team-success'), 2000);
jsonData['api-success-messages']['join-team-success'],
2000
);
} else { } else {
throw jsonData['api-error-messages']['join-team-error']; throw t('message.join-team-error');
} }
}) })
.catch((err: AxiosError) => { .catch((err: AxiosError) => {
showErrorToast(err, jsonData['api-error-messages']['join-team-error']); showErrorToast(err, t('message.join-team-error'));
// setIsRightPanelLoading(false); // setIsRightPanelLoading(false);
}); });
}; };
@ -345,20 +348,14 @@ const TeamsPage = () => {
if (res) { if (res) {
AppState.updateUserDetails(res); AppState.updateUserDetails(res);
fetchTeamByFqn(selectedTeam.name); fetchTeamByFqn(selectedTeam.name);
showSuccessToast( showSuccessToast(t('message.leave-team-success'), 2000);
jsonData['api-success-messages']['leave-team-success'],
2000
);
resolve(); resolve();
} else { } else {
throw jsonData['api-error-messages']['leave-team-error']; throw t('message.leave-team-error');
} }
}) })
.catch((err: AxiosError) => { .catch((err: AxiosError) => {
showErrorToast( showErrorToast(err, t('message.leave-team-error'));
err,
jsonData['api-error-messages']['leave-team-error']
);
// setIsRightPanelLoading(false); // setIsRightPanelLoading(false);
}); });
}); });
@ -380,13 +377,15 @@ const TeamsPage = () => {
if (res) { if (res) {
fetchTeamByFqn(res.name); fetchTeamByFqn(res.name);
} else { } else {
throw jsonData['api-error-messages']['unexpected-server-response']; throw t('server.unexpected-response');
} }
}) })
.catch((error: AxiosError) => { .catch((error: AxiosError) => {
showErrorToast( showErrorToast(
error, error,
jsonData['api-error-messages']['update-team-error'] t('message.entity-updation-error', {
entity: 'Team',
})
); );
}) })
.finally(() => { .finally(() => {
@ -416,13 +415,15 @@ const TeamsPage = () => {
if (res) { if (res) {
fetchTeamByFqn(res.name); fetchTeamByFqn(res.name);
} else { } else {
throw jsonData['api-error-messages']['unexpected-server-response']; throw t('server.unexpected-response');
} }
}) })
.catch((error: AxiosError) => { .catch((error: AxiosError) => {
showErrorToast( showErrorToast(
error, error,
jsonData['api-error-messages']['update-team-error'] t('message.entity-updation-error', {
entity: 'Team',
})
); );
}) })
.finally(() => { .finally(() => {
@ -454,7 +455,7 @@ const TeamsPage = () => {
if (response) { if (response) {
fetchTeamByFqn(response.name); fetchTeamByFqn(response.name);
} else { } else {
throw jsonData['api-error-messages']['unexpected-server-response']; throw t('server.unexpected-response');
} }
} catch (error) { } catch (error) {
showErrorToast(error as AxiosError); showErrorToast(error as AxiosError);
@ -474,6 +475,60 @@ const TeamsPage = () => {
setShowDeletedTeam(checked); setShowDeletedTeam(checked);
}; };
const fetchAssets = () => {
searchData(
`owner.id:${selectedTeam.id}`,
assets.currPage,
LIST_SIZE,
``,
'',
'',
myDataSearchIndex
)
.then((res: SearchResponse) => {
const hits = res?.data?.hits?.hits;
if (hits?.length > 0) {
const data = formatDataResponse(hits);
const total = res.data.hits.total.value;
setAssets({
data,
total,
currPage: assets.currPage,
});
} else {
const data = [] as FormattedTableData[];
const total = 0;
setAssets({
data,
total,
currPage: assets.currPage,
});
}
})
.catch((err: AxiosError) => {
showErrorToast(
err,
t('message.entity-fetch-error', {
entity: 'Team Assets',
})
);
});
};
const handleAssetsPaginate = (page: string | number) => {
setAssets((pre) => ({ ...pre, currPage: page as number }));
};
useEffect(() => {
if (!isEmpty(selectedTeam) && !isUndefined(selectedTeam)) {
fetchAssets();
}
}, [selectedTeam]);
useEffect(() => {
fetchAssets();
}, [assets.currPage]);
useEffect(() => { useEffect(() => {
if ( if (
(entityPermissions.ViewAll || entityPermissions.ViewBasic) && (entityPermissions.ViewAll || entityPermissions.ViewBasic) &&
@ -510,6 +565,7 @@ const TeamsPage = () => {
) : ( ) : (
<TeamDetailsV1 <TeamDetailsV1
afterDeleteAction={afterDeleteAction} afterDeleteAction={afterDeleteAction}
assets={assets}
childTeams={allTeam} childTeams={allTeam}
currentTeam={selectedTeam} currentTeam={selectedTeam}
currentTeamUserPage={currentUserPage} currentTeamUserPage={currentUserPage}
@ -530,6 +586,7 @@ const TeamsPage = () => {
teamUserPaginHandler={userPagingHandler} teamUserPaginHandler={userPagingHandler}
teamUsersSearchText={userSearchValue} teamUsersSearchText={userSearchValue}
updateTeamHandler={updateTeamHandler} updateTeamHandler={updateTeamHandler}
onAssetsPaginate={handleAssetsPaginate}
onDescriptionUpdate={onDescriptionUpdate} onDescriptionUpdate={onDescriptionUpdate}
onShowDeletedTeamChange={handleShowDeletedTeam} onShowDeletedTeamChange={handleShowDeletedTeam}
onTeamExpand={fetchAllTeams} onTeamExpand={fetchAllTeams}