mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-07-23 17:30:35 +00:00
Work on UI Feedback 0.10 (#4382)
This commit is contained in:
parent
b5b42e1ca9
commit
bca22514f3
@ -17,10 +17,11 @@ import { compare } from 'fast-json-patch';
|
||||
import { cloneDeep, orderBy } from 'lodash';
|
||||
import { ExtraInfo, TableDetail } from 'Models';
|
||||
import React, { Fragment, useEffect, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Link, useHistory } from 'react-router-dom';
|
||||
import AppState from '../../AppState';
|
||||
import {
|
||||
getTeamAndUserDetailsPath,
|
||||
getUserPath,
|
||||
PAGE_SIZE_MEDIUM,
|
||||
TITLE_FOR_NON_ADMIN_ACTION,
|
||||
} from '../../constants/constants';
|
||||
@ -45,6 +46,7 @@ import NextPrevious from '../common/next-previous/NextPrevious';
|
||||
import NonAdminAction from '../common/non-admin-action/NonAdminAction';
|
||||
import Searchbar from '../common/searchbar/Searchbar';
|
||||
import TabsPane from '../common/TabsPane/TabsPane';
|
||||
import Loader from '../Loader/Loader';
|
||||
import ManageTab from '../ManageTab/ManageTab.component';
|
||||
import ConfirmationModal from '../Modals/ConfirmationModal/ConfirmationModal';
|
||||
import FormModal from '../Modals/FormModal';
|
||||
@ -61,6 +63,7 @@ const TeamDetails = ({
|
||||
isDescriptionEditable,
|
||||
errorNewTeamData,
|
||||
isAddingTeam,
|
||||
isTeamMemberLoading,
|
||||
handleAddTeam,
|
||||
createNewTeam,
|
||||
onNewTeamDataChange,
|
||||
@ -76,6 +79,7 @@ const TeamDetails = ({
|
||||
handleAddUser,
|
||||
removeUserFromTeam,
|
||||
}: TeamDetailsProp) => {
|
||||
const history = useHistory();
|
||||
const DELETE_USER_INITIAL_STATE = {
|
||||
user: undefined,
|
||||
state: false,
|
||||
@ -127,7 +131,11 @@ const TeamDetails = ({
|
||||
{
|
||||
name: 'Manage',
|
||||
isProtected: false,
|
||||
isHidden: isOwner() || userPermissions[Operation.UpdateOwner],
|
||||
isHidden: !(
|
||||
hasAccess ||
|
||||
isOwner() ||
|
||||
userPermissions[Operation.UpdateOwner]
|
||||
),
|
||||
position: 4,
|
||||
},
|
||||
];
|
||||
@ -218,6 +226,14 @@ const TeamDetails = ({
|
||||
return Promise.reject();
|
||||
};
|
||||
|
||||
/**
|
||||
* Redirects user to profile page.
|
||||
* @param name user name
|
||||
*/
|
||||
const handleUserRedirection = (name: string) => {
|
||||
history.push(getUserPath(name));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (currentTeam) {
|
||||
setHeading(currentTeam.displayName);
|
||||
@ -284,64 +300,71 @@ const TeamDetails = ({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{currentTeamUsers.length <= 0 ? (
|
||||
<div className="tw-flex tw-flex-col tw-items-center tw-place-content-center tw-mt-40 tw-gap-1">
|
||||
<p>
|
||||
There are no users{' '}
|
||||
{teamUsersSearchText
|
||||
? `as ${teamUsersSearchText}.`
|
||||
: `added yet.`}
|
||||
</p>
|
||||
{isActionAllowed(userPermissions[Operation.UpdateTeam]) ? (
|
||||
<>
|
||||
<p>Would like to start adding some?</p>
|
||||
<Button
|
||||
className="tw-h-8 tw-rounded tw-my-2"
|
||||
size="small"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onClick={() => handleAddUser(true)}>
|
||||
Add new user
|
||||
</Button>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
{isTeamMemberLoading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<Fragment>
|
||||
<div
|
||||
className="tw-grid xxl:tw-grid-cols-4 lg:tw-grid-cols-3 md:tw-grid-cols-2 tw-gap-4"
|
||||
data-testid="user-card-container">
|
||||
{sortedUser.map((user, index) => {
|
||||
const User = {
|
||||
displayName: user.displayName || user.name,
|
||||
fqn: user.name || '',
|
||||
type: 'user',
|
||||
id: user.id,
|
||||
name: user.name,
|
||||
};
|
||||
<div>
|
||||
{currentTeamUsers.length <= 0 ? (
|
||||
<div className="tw-flex tw-flex-col tw-items-center tw-place-content-center tw-mt-40 tw-gap-1">
|
||||
<p>
|
||||
There are no users{' '}
|
||||
{teamUsersSearchText
|
||||
? `as ${teamUsersSearchText}.`
|
||||
: `added yet.`}
|
||||
</p>
|
||||
{isActionAllowed(userPermissions[Operation.UpdateTeam]) ? (
|
||||
<>
|
||||
<p>Would like to start adding some?</p>
|
||||
<Button
|
||||
className="tw-h-8 tw-rounded tw-my-2"
|
||||
size="small"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onClick={() => handleAddUser(true)}>
|
||||
Add new user
|
||||
</Button>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
) : (
|
||||
<Fragment>
|
||||
<div
|
||||
className="tw-grid xxl:tw-grid-cols-4 lg:tw-grid-cols-3 md:tw-grid-cols-2 tw-gap-4"
|
||||
data-testid="user-card-container">
|
||||
{sortedUser.map((user, index) => {
|
||||
const User = {
|
||||
displayName: user.displayName || user.name,
|
||||
fqn: user.name || '',
|
||||
type: 'user',
|
||||
id: user.id,
|
||||
name: user.name,
|
||||
};
|
||||
|
||||
return (
|
||||
<UserCard
|
||||
isActionVisible
|
||||
isIconVisible
|
||||
item={User}
|
||||
key={index}
|
||||
onRemove={deleteUserHandler}
|
||||
return (
|
||||
<UserCard
|
||||
isActionVisible
|
||||
isIconVisible
|
||||
item={User}
|
||||
key={index}
|
||||
onRemove={deleteUserHandler}
|
||||
onTitleClick={handleUserRedirection}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{teamUserPagin.total > PAGE_SIZE_MEDIUM && (
|
||||
<NextPrevious
|
||||
currentPage={currentTeamUserPage}
|
||||
isNumberBased={Boolean(teamUsersSearchText)}
|
||||
pageSize={PAGE_SIZE_MEDIUM}
|
||||
paging={teamUserPagin}
|
||||
pagingHandler={teamUserPaginHandler}
|
||||
totalCount={teamUserPagin.total}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{teamUserPagin.total > PAGE_SIZE_MEDIUM && (
|
||||
<NextPrevious
|
||||
currentPage={currentTeamUserPage}
|
||||
isNumberBased={Boolean(teamUsersSearchText)}
|
||||
pageSize={PAGE_SIZE_MEDIUM}
|
||||
paging={teamUserPagin}
|
||||
pagingHandler={teamUserPaginHandler}
|
||||
totalCount={teamUserPagin.total}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
@ -18,20 +18,22 @@ import { TeamsAndUsersProps } from '../../interface/teamsAndUsers.interface';
|
||||
import { getActiveCatClass, getCountBadge } from '../../utils/CommonUtils';
|
||||
import { getActiveUsers } from '../../utils/TeamUtils';
|
||||
import PageLayout from '../containers/PageLayout';
|
||||
import Loader from '../Loader/Loader';
|
||||
import TeamDetails from '../TeamDetails/TeamDetails';
|
||||
import UserDetails from '../UserDetails/UserDetails';
|
||||
|
||||
const TeamsAndUsers = ({
|
||||
users,
|
||||
isUsersLoading,
|
||||
admins,
|
||||
bots,
|
||||
activeUserTab,
|
||||
userSearchTerm,
|
||||
selectedUserList,
|
||||
updateUser,
|
||||
handleUserSearchTerm,
|
||||
handleDeleteUser,
|
||||
handleJoinTeamClick,
|
||||
isRightPannelLoading,
|
||||
hasAccess,
|
||||
isTeamVisible,
|
||||
teams,
|
||||
@ -54,6 +56,7 @@ const TeamsAndUsers = ({
|
||||
teamUserPaginHandler,
|
||||
changeCurrentTeam,
|
||||
isAddingUsers,
|
||||
isTeamMemberLoading,
|
||||
getUniqueUserList,
|
||||
addUsersToTeam,
|
||||
handleAddUser,
|
||||
@ -145,47 +148,52 @@ const TeamsAndUsers = ({
|
||||
|
||||
return (
|
||||
<PageLayout classes="tw-h-full tw-p-4" leftPanel={fetchLeftPanel()}>
|
||||
<div
|
||||
className="tw-pb-3 tw-w-full tw-h-full tw-flex tw-flex-col"
|
||||
data-testid="team-and-user-container">
|
||||
{!isTeamVisible ? (
|
||||
<UserDetails
|
||||
handleAddNewUser={handleAddNewUser}
|
||||
handleDeleteUser={handleDeleteUser}
|
||||
handleUserSearchTerm={handleUserSearchTerm}
|
||||
selectedUserList={selectedUserList}
|
||||
updateUser={updateUser}
|
||||
userSearchTerm={userSearchTerm}
|
||||
/>
|
||||
) : (
|
||||
<TeamDetails
|
||||
addUsersToTeam={addUsersToTeam}
|
||||
createNewTeam={createNewTeam}
|
||||
currentTeam={currentTeam}
|
||||
currentTeamUserPage={currentTeamUserPage}
|
||||
currentTeamUsers={currentTeamUsers}
|
||||
descriptionHandler={descriptionHandler}
|
||||
errorNewTeamData={errorNewTeamData}
|
||||
getUniqueUserList={getUniqueUserList}
|
||||
handleAddTeam={handleAddTeam}
|
||||
handleAddUser={handleAddUser}
|
||||
handleJoinTeamClick={handleJoinTeamClick}
|
||||
handleTeamUsersSearchAction={handleTeamUsersSearchAction}
|
||||
hasAccess={hasAccess}
|
||||
isAddingTeam={isAddingTeam}
|
||||
isAddingUsers={isAddingUsers}
|
||||
isDescriptionEditable={isDescriptionEditable}
|
||||
removeUserFromTeam={removeUserFromTeam}
|
||||
teamUserPagin={teamUserPagin}
|
||||
teamUserPaginHandler={teamUserPaginHandler}
|
||||
teamUsersSearchText={teamUsersSearchText}
|
||||
teams={teams}
|
||||
updateTeamHandler={updateTeamHandler}
|
||||
onDescriptionUpdate={onDescriptionUpdate}
|
||||
onNewTeamDataChange={onNewTeamDataChange}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{isRightPannelLoading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<div
|
||||
className="tw-pb-3 tw-w-full tw-h-full tw-flex tw-flex-col"
|
||||
data-testid="team-and-user-container">
|
||||
{!isTeamVisible ? (
|
||||
<UserDetails
|
||||
handleAddNewUser={handleAddNewUser}
|
||||
handleDeleteUser={handleDeleteUser}
|
||||
handleUserSearchTerm={handleUserSearchTerm}
|
||||
isUsersLoading={isUsersLoading}
|
||||
selectedUserList={selectedUserList}
|
||||
userSearchTerm={userSearchTerm}
|
||||
/>
|
||||
) : (
|
||||
<TeamDetails
|
||||
addUsersToTeam={addUsersToTeam}
|
||||
createNewTeam={createNewTeam}
|
||||
currentTeam={currentTeam}
|
||||
currentTeamUserPage={currentTeamUserPage}
|
||||
currentTeamUsers={currentTeamUsers}
|
||||
descriptionHandler={descriptionHandler}
|
||||
errorNewTeamData={errorNewTeamData}
|
||||
getUniqueUserList={getUniqueUserList}
|
||||
handleAddTeam={handleAddTeam}
|
||||
handleAddUser={handleAddUser}
|
||||
handleJoinTeamClick={handleJoinTeamClick}
|
||||
handleTeamUsersSearchAction={handleTeamUsersSearchAction}
|
||||
hasAccess={hasAccess}
|
||||
isAddingTeam={isAddingTeam}
|
||||
isAddingUsers={isAddingUsers}
|
||||
isDescriptionEditable={isDescriptionEditable}
|
||||
isTeamMemberLoading={isTeamMemberLoading}
|
||||
removeUserFromTeam={removeUserFromTeam}
|
||||
teamUserPagin={teamUserPagin}
|
||||
teamUserPaginHandler={teamUserPaginHandler}
|
||||
teamUsersSearchText={teamUsersSearchText}
|
||||
teams={teams}
|
||||
updateTeamHandler={updateTeamHandler}
|
||||
onDescriptionUpdate={onDescriptionUpdate}
|
||||
onNewTeamDataChange={onNewTeamDataChange}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</PageLayout>
|
||||
);
|
||||
};
|
||||
|
@ -23,18 +23,19 @@ type Item = {
|
||||
name: string;
|
||||
id?: string;
|
||||
email: string;
|
||||
isActiveUser: boolean;
|
||||
profilePhoto: string;
|
||||
teamCount: string;
|
||||
isActiveUser?: boolean;
|
||||
profilePhoto?: string;
|
||||
teamCount?: string;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
item: Item;
|
||||
onClick: (value: string) => void;
|
||||
showTeams?: boolean;
|
||||
onClick?: (value: string) => void;
|
||||
onDelete?: (id: string, name: string) => void;
|
||||
};
|
||||
|
||||
const UserDataCard = ({ item, onClick, onDelete }: Props) => {
|
||||
const UserDataCard = ({ item, onClick, onDelete, showTeams = true }: Props) => {
|
||||
return (
|
||||
<div
|
||||
className="tw-card tw-flex tw-justify-between tw-py-2 tw-px-3 tw-group"
|
||||
@ -58,21 +59,21 @@ const UserDataCard = ({ item, onClick, onDelete }: Props) => {
|
||||
<div className="tw-flex tw-justify-between">
|
||||
<p
|
||||
className={classNames('tw-font-normal', {
|
||||
'tw-cursor-pointer': Boolean(onClick),
|
||||
'tw-cursor-pointer hover:tw-underline': Boolean(onClick),
|
||||
})}
|
||||
onClick={() => {
|
||||
onClick(item.id as string);
|
||||
onClick?.(item.name);
|
||||
}}>
|
||||
{item.description}
|
||||
</p>
|
||||
{!item.isActiveUser && (
|
||||
{!item?.isActiveUser && (
|
||||
<span className="tw-text-xs tw-bg-badge tw-border tw-px-2 tw-py-0.5 tw-rounded">
|
||||
Inactive
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="tw-truncate">{item.email}</p>
|
||||
<p>Teams: {item.teamCount}</p>
|
||||
{showTeams && <p>Teams: {item.teamCount}</p>}
|
||||
</div>
|
||||
</div>
|
||||
{!isNil(onDelete) && (
|
||||
|
@ -11,27 +11,28 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { compare, Operation } from 'fast-json-patch';
|
||||
import { isUndefined } from 'lodash';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import AppState from '../../AppState';
|
||||
import { TITLE_FOR_NON_ADMIN_ACTION } from '../../constants/constants';
|
||||
import { Role } from '../../generated/entity/teams/role';
|
||||
import React, { useState } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import {
|
||||
getUserPath,
|
||||
TITLE_FOR_NON_ADMIN_ACTION,
|
||||
} from '../../constants/constants';
|
||||
import { EntityReference, User } from '../../generated/entity/teams/user';
|
||||
import { getEntityName } from '../../utils/CommonUtils';
|
||||
import { Button } from '../buttons/Button/Button';
|
||||
import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder';
|
||||
import NonAdminAction from '../common/non-admin-action/NonAdminAction';
|
||||
import Searchbar from '../common/searchbar/Searchbar';
|
||||
import Loader from '../Loader/Loader';
|
||||
import ConfirmationModal from '../Modals/ConfirmationModal/ConfirmationModal';
|
||||
import UserDetailsModal from '../Modals/UserDetailsModal/UserDetailsModal';
|
||||
import UserDataCard from '../UserDataCard/UserDataCard';
|
||||
|
||||
type UserDetailsProps = {
|
||||
selectedUserList: User[];
|
||||
handleUserSearchTerm: (value: string) => void;
|
||||
userSearchTerm: string;
|
||||
updateUser: (id: string, data: Operation[], updatedUser: User) => void;
|
||||
isUsersLoading: boolean;
|
||||
handleDeleteUser: (id: string) => void;
|
||||
handleAddNewUser: () => void;
|
||||
};
|
||||
@ -44,45 +45,14 @@ interface DeleteUserInfo {
|
||||
const UserDetails = ({
|
||||
selectedUserList,
|
||||
userSearchTerm,
|
||||
isUsersLoading,
|
||||
handleDeleteUser,
|
||||
handleUserSearchTerm,
|
||||
updateUser,
|
||||
handleAddNewUser,
|
||||
}: UserDetailsProps) => {
|
||||
const [selectedUser, setSelectedUser] = useState<User>();
|
||||
const [roles, setRoles] = useState<Role[]>([]);
|
||||
const history = useHistory();
|
||||
const [deletingUser, setDeletingUser] = useState<DeleteUserInfo>();
|
||||
|
||||
const selectUser = (id: string) => {
|
||||
const user = selectedUserList.find((user) => user.id === id);
|
||||
if (user) {
|
||||
setSelectedUser(user);
|
||||
} else {
|
||||
setSelectedUser(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSave = (rolesData: Array<string>) => {
|
||||
if (selectedUser) {
|
||||
const updatedData: User = {
|
||||
...selectedUser,
|
||||
isAdmin: Boolean(rolesData.find((role) => role === 'admin')),
|
||||
roles: roles
|
||||
.filter((role) => rolesData.includes(role.id))
|
||||
.map((role) => ({
|
||||
id: role.id,
|
||||
type: 'role',
|
||||
href: role.href,
|
||||
displayName: role.displayName,
|
||||
})),
|
||||
};
|
||||
const jsonPatch = compare(selectedUser, updatedData);
|
||||
updateUser(selectedUser.id, jsonPatch, updatedData);
|
||||
|
||||
setSelectedUser(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteUserModal = (id: string, name: string) => {
|
||||
setDeletingUser({
|
||||
name,
|
||||
@ -90,18 +60,24 @@ const UserDetails = ({
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Redirects user to profile page.
|
||||
* @param name user name
|
||||
*/
|
||||
const handleUserRedirection = (name: string) => {
|
||||
history.push(getUserPath(name));
|
||||
};
|
||||
|
||||
const onConfirmDeleteUser = (id: string) => {
|
||||
handleDeleteUser(id);
|
||||
setDeletingUser(undefined);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setRoles(AppState.userRoles);
|
||||
}, [AppState.userRoles]);
|
||||
|
||||
const getUserCards = () => {
|
||||
return (
|
||||
<>
|
||||
return isUsersLoading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<div>
|
||||
{selectedUserList.length > 0 ? (
|
||||
<div
|
||||
className="tw-grid xxl:tw-grid-cols-3 lg:tw-grid-cols-2 tw-gap-4"
|
||||
@ -123,13 +99,10 @@ const UserDetails = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className="tw-cursor-pointer"
|
||||
key={index}
|
||||
onClick={() => selectUser(User.id)}>
|
||||
<div key={index}>
|
||||
<UserDataCard
|
||||
item={User}
|
||||
onClick={selectUser}
|
||||
onClick={handleUserRedirection}
|
||||
onDelete={handleDeleteUserModal}
|
||||
/>
|
||||
</div>
|
||||
@ -141,7 +114,7 @@ const UserDetails = ({
|
||||
<p>No user available</p>
|
||||
</ErrorPlaceHolder>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -173,16 +146,6 @@ const UserDetails = ({
|
||||
</div>
|
||||
{getUserCards()}
|
||||
|
||||
{!isUndefined(selectedUser) && (
|
||||
<UserDetailsModal
|
||||
header="Update user"
|
||||
roles={roles}
|
||||
userData={selectedUser}
|
||||
onCancel={() => setSelectedUser(undefined)}
|
||||
onSave={handleSave}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!isUndefined(deletingUser) && (
|
||||
<ConfirmationModal
|
||||
bodyText={`Are you sure you want to delete ${deletingUser.name}?`}
|
||||
|
@ -28,6 +28,8 @@ export type TeamDeleteType = {
|
||||
|
||||
export interface TeamsAndUsersProps {
|
||||
hasAccess: boolean;
|
||||
isUsersLoading: boolean;
|
||||
isTeamMemberLoading: boolean;
|
||||
isTeamVisible: boolean;
|
||||
activeUserTab: UserType | undefined;
|
||||
activeUserTabHandler: (value: UserType | undefined) => void;
|
||||
@ -42,9 +44,9 @@ export interface TeamsAndUsersProps {
|
||||
currentTeamUserPage: number;
|
||||
teamUsersSearchText: string;
|
||||
isDescriptionEditable: boolean;
|
||||
isRightPannelLoading: boolean;
|
||||
errorNewTeamData: FormErrorData | undefined;
|
||||
isAddingTeam: boolean;
|
||||
updateUser: (id: string, data: Operation[], updatedUser: User) => void;
|
||||
createNewTeam: (data: Team) => void;
|
||||
handleAddTeam: (value: boolean) => void;
|
||||
onNewTeamDataChange: (
|
||||
@ -82,6 +84,7 @@ export interface TeamDetailsProp {
|
||||
currentTeamUserPage: number;
|
||||
teamUsersSearchText: string;
|
||||
isDescriptionEditable: boolean;
|
||||
isTeamMemberLoading: boolean;
|
||||
hasAccess: boolean;
|
||||
errorNewTeamData: FormErrorData | undefined;
|
||||
isAddingTeam: boolean;
|
||||
|
@ -61,7 +61,10 @@ const TeamsAndUsersPage = () => {
|
||||
const { isAuthDisabled } = useAuthContext();
|
||||
const history = useHistory();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isRightPannelLoading, setIsRightPannelLoading] = useState(true);
|
||||
const [isTeamMemberLoading, setIsTeamMemberLoading] = useState(true);
|
||||
const [isTeamVisible, setIsTeamVisible] = useState(true);
|
||||
const [isUsersLoading, setIsUsersLoading] = useState(true);
|
||||
const [teams, setTeams] = useState<Team[]>([]);
|
||||
const [currentTeam, setCurrentTeam] = useState<Team>();
|
||||
const [currentTeamUsers, setCurrentTeamUsers] = useState<User[]>([]);
|
||||
@ -84,6 +87,10 @@ const TeamsAndUsersPage = () => {
|
||||
setIsDescriptionEditable(value);
|
||||
};
|
||||
|
||||
const handleRightPannelLoading = (value: boolean) => {
|
||||
setIsRightPannelLoading(value);
|
||||
};
|
||||
|
||||
const handleAddTeam = (value: boolean) => {
|
||||
setIsAddingTeam(value);
|
||||
};
|
||||
@ -101,6 +108,7 @@ const TeamsAndUsersPage = () => {
|
||||
};
|
||||
|
||||
const setAllTabList = (users: User[], type = '') => {
|
||||
setIsUsersLoading(true);
|
||||
const dBots = users.filter((user) => user.isBot);
|
||||
const dUsers = users.filter((user) => !user.isBot);
|
||||
const dAdmins = users.filter((user) => user.isAdmin);
|
||||
@ -126,9 +134,11 @@ const TeamsAndUsersPage = () => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
setIsUsersLoading(false);
|
||||
};
|
||||
|
||||
const handleUserSearchTerm = (value: string) => {
|
||||
setIsUsersLoading(true);
|
||||
setUserSearchTerm(value);
|
||||
if (value) {
|
||||
let updatedList: User[] = [];
|
||||
@ -160,42 +170,15 @@ const TeamsAndUsersPage = () => {
|
||||
} else {
|
||||
setAllTabList(userList, activeUserTab);
|
||||
}
|
||||
setIsUsersLoading(false);
|
||||
};
|
||||
|
||||
const handleAddNewUser = () => {
|
||||
history.push(ROUTES.CREATE_USER);
|
||||
};
|
||||
|
||||
const updateUser = (id: string, data: Operation[], updatedUser: User) => {
|
||||
setIsLoading(true);
|
||||
updateUserDetail(id, data)
|
||||
.then((res) => {
|
||||
if (res.data) {
|
||||
const updatedData = (userList || []).map((user) => {
|
||||
if (user.id === id) {
|
||||
return updatedUser;
|
||||
}
|
||||
|
||||
return user;
|
||||
});
|
||||
setAllTabList(updatedData, activeUserTab);
|
||||
setUserList(updatedData);
|
||||
} else {
|
||||
throw jsonData['api-error-messages']['unexpected-server-response'];
|
||||
}
|
||||
})
|
||||
.catch((err: AxiosError) => {
|
||||
showErrorToast(
|
||||
err,
|
||||
jsonData['api-error-messages']['update-user-error']
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
});
|
||||
};
|
||||
const handleDeleteUser = (id: string) => {
|
||||
setIsLoading(true);
|
||||
setIsUsersLoading(true);
|
||||
deleteUser(id)
|
||||
.then(() => {
|
||||
AppState.updateUsers((userList || []).filter((item) => item.id !== id));
|
||||
@ -208,6 +191,7 @@ const TeamsAndUsersPage = () => {
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
setIsUsersLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
@ -218,21 +202,25 @@ const TeamsAndUsersPage = () => {
|
||||
team: string,
|
||||
pagin = {} as { [key: string]: string }
|
||||
) => {
|
||||
getUsers('', PAGE_SIZE_MEDIUM, { team, ...pagin }).then(
|
||||
(res: AxiosResponse) => {
|
||||
setIsTeamMemberLoading(true);
|
||||
getUsers('', PAGE_SIZE_MEDIUM, { team, ...pagin })
|
||||
.then((res: AxiosResponse) => {
|
||||
if (res.data) {
|
||||
setCurrentTeamUsers(res.data.data);
|
||||
setTeamUserPagin(res.data.paging);
|
||||
}
|
||||
}
|
||||
);
|
||||
})
|
||||
.catch(() => {
|
||||
setCurrentTeamUsers([]);
|
||||
setTeamUserPagin({ total: 0 });
|
||||
})
|
||||
.finally(() => setIsTeamMemberLoading(false));
|
||||
};
|
||||
|
||||
/**
|
||||
* Make API call to fetch all the teams
|
||||
*/
|
||||
const fetchTeams = () => {
|
||||
setIsLoading(true);
|
||||
getTeams(['users', 'owns', 'defaultRoles', 'owner'])
|
||||
.then((res: AxiosResponse) => {
|
||||
if (res.data) {
|
||||
@ -255,6 +243,7 @@ const TeamsAndUsersPage = () => {
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
handleRightPannelLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
@ -263,7 +252,6 @@ const TeamsAndUsersPage = () => {
|
||||
*/
|
||||
const fetchCurrentTeam = (name: string, update = false) => {
|
||||
if (currentTeam?.name !== name || update) {
|
||||
// setIsLoading(true);
|
||||
getTeamByName(name, ['users', 'owns', 'defaultRoles', 'owner'])
|
||||
.then((res: AxiosResponse) => {
|
||||
if (res.data) {
|
||||
@ -299,6 +287,7 @@ const TeamsAndUsersPage = () => {
|
||||
};
|
||||
|
||||
const searchUsers = (text: string, currentPage: number) => {
|
||||
setIsTeamMemberLoading(true);
|
||||
searchData(
|
||||
text,
|
||||
currentPage,
|
||||
@ -317,7 +306,8 @@ const TeamsAndUsersPage = () => {
|
||||
})
|
||||
.catch(() => {
|
||||
setCurrentTeamUsers([]);
|
||||
});
|
||||
})
|
||||
.finally(() => setIsTeamMemberLoading(false));
|
||||
};
|
||||
|
||||
const teamUserPaginHandler = (cursorValue: string | number) => {
|
||||
@ -418,6 +408,7 @@ const TeamsAndUsersPage = () => {
|
||||
* @param name - team name
|
||||
*/
|
||||
const changeCurrentTeam = (name: string, isUsersCategory: boolean) => {
|
||||
handleRightPannelLoading(true);
|
||||
history.push(getTeamAndUserDetailsPath(name));
|
||||
if (isUsersCategory) {
|
||||
setIsTeamVisible(false);
|
||||
@ -635,7 +626,10 @@ const TeamsAndUsersPage = () => {
|
||||
isAddingTeam={isAddingTeam}
|
||||
isAddingUsers={isAddingUsers}
|
||||
isDescriptionEditable={isDescriptionEditable}
|
||||
isRightPannelLoading={isRightPannelLoading}
|
||||
isTeamMemberLoading={isTeamMemberLoading}
|
||||
isTeamVisible={isTeamVisible}
|
||||
isUsersLoading={isUsersLoading}
|
||||
removeUserFromTeam={removeUserFromTeam}
|
||||
selectedUserList={selectedUserList}
|
||||
teamUserPagin={teamUserPagin}
|
||||
@ -643,7 +637,6 @@ const TeamsAndUsersPage = () => {
|
||||
teamUsersSearchText={teamUsersSearchText}
|
||||
teams={teams}
|
||||
updateTeamHandler={updateTeamHandler}
|
||||
updateUser={updateUser}
|
||||
userSearchTerm={userSearchTerm}
|
||||
users={users}
|
||||
onDescriptionUpdate={onDescriptionUpdate}
|
||||
|
@ -43,6 +43,7 @@ interface Props {
|
||||
isDataset?: boolean;
|
||||
isCheckBoxes?: boolean;
|
||||
isOwner?: boolean;
|
||||
onTitleClick?: (value: string) => void;
|
||||
onSelect?: (value: string) => void;
|
||||
onRemove?: (value: string) => void;
|
||||
}
|
||||
@ -54,6 +55,7 @@ const UserCard = ({
|
||||
isDataset = false,
|
||||
isCheckBoxes = false,
|
||||
isOwner = false,
|
||||
onTitleClick,
|
||||
onSelect,
|
||||
onRemove,
|
||||
}: Props) => {
|
||||
@ -172,9 +174,16 @@ const UserCard = ({
|
||||
<p
|
||||
className={classNames(
|
||||
'tw-font-normal',
|
||||
isActionVisible ? 'tw-truncate tw-w-32' : null
|
||||
isActionVisible ? 'tw-truncate tw-w-32' : null,
|
||||
{
|
||||
'tw-cursor-pointer hover:tw-underline':
|
||||
Boolean(onTitleClick),
|
||||
}
|
||||
)}
|
||||
title={item.displayName}>
|
||||
title={item.displayName}
|
||||
onClick={() => {
|
||||
onTitleClick?.(item.fqn);
|
||||
}}>
|
||||
{item.displayName}
|
||||
</p>
|
||||
{item.name && (
|
||||
|
Loading…
x
Reference in New Issue
Block a user