mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2026-01-07 13:07:22 +00:00
Fix: Max width layout alignment for Teams, Tags and Services page (#2083)
This commit is contained in:
parent
b866d8a73a
commit
dee7cd7717
@ -11,10 +11,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import classNames from 'classnames';
|
||||
import React, { ReactNode } from 'react';
|
||||
|
||||
const PageContainerV1 = ({ children }: { children: ReactNode }) => {
|
||||
return <div className="page-container-v1 tw-bg-body-main">{children}</div>;
|
||||
interface PageContainerV1Props {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const PageContainerV1 = ({
|
||||
children,
|
||||
className = '',
|
||||
}: PageContainerV1Props) => {
|
||||
return (
|
||||
<div className={classNames('page-container-v1 tw-bg-body-main', className)}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PageContainerV1;
|
||||
|
||||
@ -28,7 +28,8 @@ import { Button } from '../../components/buttons/Button/Button';
|
||||
import NextPrevious from '../../components/common/next-previous/NextPrevious';
|
||||
import NonAdminAction from '../../components/common/non-admin-action/NonAdminAction';
|
||||
import RichTextEditorPreviewer from '../../components/common/rich-text-editor/RichTextEditorPreviewer';
|
||||
import PageContainer from '../../components/containers/PageContainer';
|
||||
import PageContainerV1 from '../../components/containers/PageContainerV1';
|
||||
import PageLayout from '../../components/containers/PageLayout';
|
||||
import Loader from '../../components/Loader/Loader';
|
||||
import {
|
||||
AddServiceModal,
|
||||
@ -451,46 +452,47 @@ const ServicesPage = () => {
|
||||
return (
|
||||
<>
|
||||
{!isLoading ? (
|
||||
<PageContainer>
|
||||
<div className="container-fluid" data-testid="services-container">
|
||||
<div className="tw-bg-transparent tw-mb-4">
|
||||
<nav className="tw-flex tw-flex-row tw-gh-tabs-container tw-px-4">
|
||||
{getServiceTabs().map((tab, index) => (
|
||||
<button
|
||||
className={getTabClasses(tab.name, serviceName)}
|
||||
data-testid="tab"
|
||||
key={index}
|
||||
onClick={() => handleTabChange(tab.name)}>
|
||||
{tab.displayName}
|
||||
{getCountBadge(
|
||||
servicesCount[tab.name],
|
||||
'',
|
||||
tab.name === serviceName
|
||||
)}
|
||||
</button>
|
||||
))}
|
||||
<div className="tw-self-end tw-ml-auto">
|
||||
{serviceList.length > 0 ? (
|
||||
<NonAdminAction
|
||||
position="bottom"
|
||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||
<Button
|
||||
className={classNames('tw-h-8 tw-rounded tw-mb-2', {
|
||||
'tw-opacity-40': !isAdminUser && !isAuthDisabled,
|
||||
})}
|
||||
data-testid="add-new-user-button"
|
||||
size="small"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onClick={() => handleAddService()}>
|
||||
Add New Service
|
||||
</Button>
|
||||
</NonAdminAction>
|
||||
) : null}
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
{/* <div className="tw-flex">
|
||||
<PageContainerV1 className="tw-pt-1">
|
||||
<PageLayout>
|
||||
<div data-testid="services-container">
|
||||
<div className="tw-bg-transparent tw-mb-4">
|
||||
<nav className="tw-flex tw-flex-row tw-gh-tabs-container">
|
||||
{getServiceTabs().map((tab, index) => (
|
||||
<button
|
||||
className={getTabClasses(tab.name, serviceName)}
|
||||
data-testid="tab"
|
||||
key={index}
|
||||
onClick={() => handleTabChange(tab.name)}>
|
||||
{tab.displayName}
|
||||
{getCountBadge(
|
||||
servicesCount[tab.name],
|
||||
'',
|
||||
tab.name === serviceName
|
||||
)}
|
||||
</button>
|
||||
))}
|
||||
<div className="tw-self-end tw-ml-auto">
|
||||
{serviceList.length > 0 ? (
|
||||
<NonAdminAction
|
||||
position="bottom"
|
||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||
<Button
|
||||
className={classNames('tw-h-8 tw-rounded tw-mb-2', {
|
||||
'tw-opacity-40': !isAdminUser && !isAuthDisabled,
|
||||
})}
|
||||
data-testid="add-new-user-button"
|
||||
size="small"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onClick={() => handleAddService()}>
|
||||
Add New Service
|
||||
</Button>
|
||||
</NonAdminAction>
|
||||
) : null}
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
{/* <div className="tw-flex">
|
||||
<div className="tw-w-8/12 tw-flex tw-justify-end">
|
||||
{serviceList.length > 0 ? (
|
||||
<NonAdminAction
|
||||
@ -511,171 +513,174 @@ const ServicesPage = () => {
|
||||
) : null}
|
||||
</div>
|
||||
</div> */}
|
||||
{serviceList.length ? (
|
||||
<div
|
||||
className="tw-grid tw-grid-cols-4 tw-gap-4 tw-mb-4"
|
||||
data-testid="data-container">
|
||||
{serviceList.map((service, index) => (
|
||||
<div
|
||||
className="tw-card tw-flex tw-py-2 tw-px-3 tw-justify-between tw-text-grey-muted"
|
||||
key={index}>
|
||||
<div className="tw-flex-auto">
|
||||
<Link
|
||||
to={getServiceDetailsPath(
|
||||
service.name,
|
||||
service.serviceType || '',
|
||||
serviceName
|
||||
)}>
|
||||
<button>
|
||||
<h6
|
||||
className="tw-text-base tw-text-grey-body tw-font-medium"
|
||||
data-testid={`service-name-${service.name}`}>
|
||||
{service.name}
|
||||
</h6>
|
||||
</button>
|
||||
</Link>
|
||||
<div
|
||||
className="tw-text-grey-body tw-pb-1 tw-break-all description-text"
|
||||
data-testid="service-description">
|
||||
{service.description ? (
|
||||
<RichTextEditorPreviewer
|
||||
markdown={service.description}
|
||||
/>
|
||||
) : (
|
||||
<span className="tw-no-description">
|
||||
No description added
|
||||
{serviceList.length ? (
|
||||
<div
|
||||
className="tw-grid tw-grid-cols-4 tw-gap-4 tw-mb-4"
|
||||
data-testid="data-container">
|
||||
{serviceList.map((service, index) => (
|
||||
<div
|
||||
className="tw-card tw-flex tw-py-2 tw-px-3 tw-justify-between tw-text-grey-muted"
|
||||
key={index}>
|
||||
<div className="tw-flex-auto">
|
||||
<Link
|
||||
to={getServiceDetailsPath(
|
||||
service.name,
|
||||
service.serviceType || '',
|
||||
serviceName
|
||||
)}>
|
||||
<button>
|
||||
<h6
|
||||
className="tw-text-base tw-text-grey-body tw-font-medium"
|
||||
data-testid={`service-name-${service.name}`}>
|
||||
{service.name}
|
||||
</h6>
|
||||
</button>
|
||||
</Link>
|
||||
<div
|
||||
className="tw-text-grey-body tw-pb-1 tw-break-all description-text"
|
||||
data-testid="service-description">
|
||||
{service.description ? (
|
||||
<RichTextEditorPreviewer
|
||||
markdown={service.description}
|
||||
/>
|
||||
) : (
|
||||
<span className="tw-no-description">
|
||||
No description added
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{getOptionalFields(service)}
|
||||
<div
|
||||
className="tw-mb-1"
|
||||
data-testid="service-ingestion">
|
||||
<label className="tw-mb-0">Ingestion:</label>
|
||||
<span className=" tw-ml-1 tw-font-normal tw-text-grey-body">
|
||||
{service.ingestionSchedule?.repeatFrequency
|
||||
? getFrequencyTime(
|
||||
service.ingestionSchedule.repeatFrequency
|
||||
)
|
||||
: '--'}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="" data-testid="service-type">
|
||||
<label className="tw-mb-0">Type:</label>
|
||||
<span className=" tw-ml-1 tw-font-normal tw-text-grey-body">
|
||||
{service.serviceType}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{getOptionalFields(service)}
|
||||
<div className="tw-mb-1" data-testid="service-ingestion">
|
||||
<label className="tw-mb-0">Ingestion:</label>
|
||||
<span className=" tw-ml-1 tw-font-normal tw-text-grey-body">
|
||||
{service.ingestionSchedule?.repeatFrequency
|
||||
? getFrequencyTime(
|
||||
service.ingestionSchedule.repeatFrequency
|
||||
)
|
||||
: '--'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="" data-testid="service-type">
|
||||
<label className="tw-mb-0">Type:</label>
|
||||
<span className=" tw-ml-1 tw-font-normal tw-text-grey-body">
|
||||
{service.serviceType}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tw-flex tw-flex-col tw-justify-between tw-flex-none">
|
||||
<div className="tw-flex tw-justify-end">
|
||||
<NonAdminAction
|
||||
position="top"
|
||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||
<button
|
||||
className="tw-pr-3 focus:tw-outline-none"
|
||||
data-testid={`edit-service-${service.name}`}
|
||||
onClick={() => handleEdit(service)}>
|
||||
<SVGIcons
|
||||
alt="edit"
|
||||
icon="icon-edit"
|
||||
title="Edit"
|
||||
width="12px"
|
||||
/>
|
||||
</button>
|
||||
</NonAdminAction>
|
||||
<NonAdminAction
|
||||
position="top"
|
||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||
<button
|
||||
className="focus:tw-outline-none"
|
||||
data-testid={`delete-service-${service.name}`}
|
||||
onClick={() =>
|
||||
ConfirmDelete(service.id || '', service.name)
|
||||
}>
|
||||
<SVGIcons
|
||||
alt="delete"
|
||||
icon="icon-delete"
|
||||
title="Delete"
|
||||
width="12px"
|
||||
/>
|
||||
</button>
|
||||
</NonAdminAction>
|
||||
</div>
|
||||
<div
|
||||
className="tw-flex tw-justify-end"
|
||||
data-testid="service-icon">
|
||||
{/* {!isNull(serviceTypeLogo(service.serviceType)) && (
|
||||
<div className="tw-flex tw-flex-col tw-justify-between tw-flex-none">
|
||||
<div className="tw-flex tw-justify-end">
|
||||
<NonAdminAction
|
||||
position="top"
|
||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||
<button
|
||||
className="tw-pr-3 focus:tw-outline-none"
|
||||
data-testid={`edit-service-${service.name}`}
|
||||
onClick={() => handleEdit(service)}>
|
||||
<SVGIcons
|
||||
alt="edit"
|
||||
icon="icon-edit"
|
||||
title="Edit"
|
||||
width="12px"
|
||||
/>
|
||||
</button>
|
||||
</NonAdminAction>
|
||||
<NonAdminAction
|
||||
position="top"
|
||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||
<button
|
||||
className="focus:tw-outline-none"
|
||||
data-testid={`delete-service-${service.name}`}
|
||||
onClick={() =>
|
||||
ConfirmDelete(service.id || '', service.name)
|
||||
}>
|
||||
<SVGIcons
|
||||
alt="delete"
|
||||
icon="icon-delete"
|
||||
title="Delete"
|
||||
width="12px"
|
||||
/>
|
||||
</button>
|
||||
</NonAdminAction>
|
||||
</div>
|
||||
<div
|
||||
className="tw-flex tw-justify-end"
|
||||
data-testid="service-icon">
|
||||
{/* {!isNull(serviceTypeLogo(service.serviceType)) && (
|
||||
<img
|
||||
alt=""
|
||||
className="tw-h-10 tw-w-10"
|
||||
src={serviceTypeLogo(service.serviceType)}
|
||||
/>
|
||||
)} */}
|
||||
{getServiceLogo(service.serviceType || '')}
|
||||
{getServiceLogo(service.serviceType || '')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="tw-flex tw-items-center tw-flex-col">
|
||||
<div className="tw-mt-24">
|
||||
<img
|
||||
alt="No Service"
|
||||
src={NoDataFoundPlaceHolder}
|
||||
width={250}
|
||||
/>
|
||||
</div>
|
||||
<div className="tw-mt-11">
|
||||
<p className="tw-text-lg tw-text-center">
|
||||
{`No services found ${
|
||||
searchText ? `for "${searchText}"` : ''
|
||||
}`}
|
||||
</p>
|
||||
<p className="tw-text-lg tw-text-center">
|
||||
<button
|
||||
className="link-text tw-underline"
|
||||
data-testid="add-service-button"
|
||||
onClick={handleAddService}>
|
||||
Click here
|
||||
</button>{' '}
|
||||
to add new {servicesDisplayName[serviceName]}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="tw-flex tw-items-center tw-flex-col">
|
||||
<div className="tw-mt-24">
|
||||
<img
|
||||
alt="No Service"
|
||||
src={NoDataFoundPlaceHolder}
|
||||
width={250}
|
||||
/>
|
||||
</div>
|
||||
<div className="tw-mt-11">
|
||||
<p className="tw-text-lg tw-text-center">
|
||||
{`No services found ${
|
||||
searchText ? `for "${searchText}"` : ''
|
||||
}`}
|
||||
</p>
|
||||
<p className="tw-text-lg tw-text-center">
|
||||
<button
|
||||
className="link-text tw-underline"
|
||||
data-testid="add-service-button"
|
||||
onClick={handleAddService}>
|
||||
Click here
|
||||
</button>{' '}
|
||||
to add new {servicesDisplayName[serviceName]}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
|
||||
{(!isNil(paging[serviceName].after) ||
|
||||
!isNil(paging[serviceName].before)) && (
|
||||
<NextPrevious
|
||||
paging={paging[serviceName]}
|
||||
pagingHandler={pagingHandler}
|
||||
/>
|
||||
)}
|
||||
{(!isNil(paging[serviceName].after) ||
|
||||
!isNil(paging[serviceName].before)) && (
|
||||
<NextPrevious
|
||||
paging={paging[serviceName]}
|
||||
pagingHandler={pagingHandler}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isModalOpen && (
|
||||
<AddServiceModal
|
||||
data={editData}
|
||||
header={`${editData ? 'Edit' : 'Add new'} service`}
|
||||
serviceList={serviceList}
|
||||
serviceName={serviceName}
|
||||
onCancel={handleClose}
|
||||
onSave={handleSave}
|
||||
/>
|
||||
)}
|
||||
{isModalOpen && (
|
||||
<AddServiceModal
|
||||
data={editData}
|
||||
header={`${editData ? 'Edit' : 'Add new'} service`}
|
||||
serviceList={serviceList}
|
||||
serviceName={serviceName}
|
||||
onCancel={handleClose}
|
||||
onSave={handleSave}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isConfirmationModalOpen && (
|
||||
<ConfirmationModal
|
||||
bodyText={`You want to delete service ${deleteSelection.name} permanently? This action cannot be reverted.`}
|
||||
cancelText="Discard"
|
||||
confirmButtonCss="tw-bg-error hover:tw-bg-error focus:tw-bg-error"
|
||||
confirmText="Delete"
|
||||
header="Are you sure?"
|
||||
onCancel={handleCancelConfirmationModal}
|
||||
onConfirm={() => handleDelete(deleteSelection.id)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</PageContainer>
|
||||
{isConfirmationModalOpen && (
|
||||
<ConfirmationModal
|
||||
bodyText={`You want to delete service ${deleteSelection.name} permanently? This action cannot be reverted.`}
|
||||
cancelText="Discard"
|
||||
confirmButtonCss="tw-bg-error hover:tw-bg-error focus:tw-bg-error"
|
||||
confirmText="Delete"
|
||||
header="Are you sure?"
|
||||
onCancel={handleCancelConfirmationModal}
|
||||
onConfirm={() => handleDelete(deleteSelection.id)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</PageLayout>
|
||||
</PageContainerV1>
|
||||
) : (
|
||||
<Loader />
|
||||
)}
|
||||
|
||||
@ -27,7 +27,8 @@ import { Button } from '../../components/buttons/Button/Button';
|
||||
import Description from '../../components/common/description/Description';
|
||||
import NonAdminAction from '../../components/common/non-admin-action/NonAdminAction';
|
||||
import RichTextEditorPreviewer from '../../components/common/rich-text-editor/RichTextEditorPreviewer';
|
||||
import PageContainer from '../../components/containers/PageContainer';
|
||||
import PageContainerV1 from '../../components/containers/PageContainerV1';
|
||||
import PageLayout from '../../components/containers/PageLayout';
|
||||
import Loader from '../../components/Loader/Loader';
|
||||
import FormModal from '../../components/Modals/FormModal';
|
||||
import { ModalWithMarkdownEditor } from '../../components/Modals/ModalWithMarkdownEditor/ModalWithMarkdownEditor';
|
||||
@ -226,229 +227,235 @@ const TagsPage = () => {
|
||||
{error ? (
|
||||
<p className="tw-text-2xl tw-text-center tw-m-auto">{error}</p>
|
||||
) : (
|
||||
<PageContainer className="py-0" leftPanelContent={fetchLeftPanel()}>
|
||||
{isLoading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<div className="container-fluid py-3" data-testid="tags-container">
|
||||
{currentCategory && (
|
||||
<div
|
||||
className="tw-flex tw-justify-between tw-pl-1"
|
||||
data-testid="header">
|
||||
<PageContainerV1 className="tw-py-4">
|
||||
<PageLayout leftPanel={fetchLeftPanel()}>
|
||||
{isLoading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<div data-testid="tags-container">
|
||||
{currentCategory && (
|
||||
<div
|
||||
className="tw-heading tw-text-link tw-text-base"
|
||||
data-testid="category-name">
|
||||
{currentCategory.name}
|
||||
className="tw-flex tw-justify-between tw-pl-1"
|
||||
data-testid="header">
|
||||
<div
|
||||
className="tw-heading tw-text-link tw-text-base"
|
||||
data-testid="category-name">
|
||||
{currentCategory.name}
|
||||
</div>
|
||||
<NonAdminAction
|
||||
position="bottom"
|
||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||
<Button
|
||||
className={classNames('tw-h-8 tw-rounded tw-mb-2', {
|
||||
'tw-opacity-40': !isAdminUser && !isAuthDisabled,
|
||||
})}
|
||||
data-testid="add-new-tag-button"
|
||||
size="small"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onClick={() =>
|
||||
setIsAddingTag((prevState) => !prevState)
|
||||
}>
|
||||
Add new tag
|
||||
</Button>
|
||||
</NonAdminAction>
|
||||
</div>
|
||||
<NonAdminAction
|
||||
position="bottom"
|
||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||
<Button
|
||||
className={classNames('tw-h-8 tw-rounded tw-mb-2', {
|
||||
'tw-opacity-40': !isAdminUser && !isAuthDisabled,
|
||||
})}
|
||||
data-testid="add-new-tag-button"
|
||||
size="small"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onClick={() => setIsAddingTag((prevState) => !prevState)}>
|
||||
Add new tag
|
||||
</Button>
|
||||
</NonAdminAction>
|
||||
)}
|
||||
<div className="tw-mb-3" data-testid="description-container">
|
||||
<Description
|
||||
description={currentCategory?.description || ''}
|
||||
entityName={currentCategory?.displayName}
|
||||
isEdit={isEditCategory}
|
||||
onCancel={() => setIsEditCategory(false)}
|
||||
onDescriptionEdit={() => setIsEditCategory(true)}
|
||||
onDescriptionUpdate={UpdateCategory}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="tw-mb-3" data-testid="description-container">
|
||||
<Description
|
||||
description={currentCategory?.description || ''}
|
||||
entityName={currentCategory?.displayName}
|
||||
isEdit={isEditCategory}
|
||||
onCancel={() => setIsEditCategory(false)}
|
||||
onDescriptionEdit={() => setIsEditCategory(true)}
|
||||
onDescriptionUpdate={UpdateCategory}
|
||||
/>
|
||||
</div>
|
||||
<div className="tw-bg-white">
|
||||
<table
|
||||
className="tw-w-full tw-overflow-x-auto"
|
||||
data-testid="table">
|
||||
<thead>
|
||||
<tr className="tableHead-row">
|
||||
<th className="tableHead-cell" data-testid="heading-name">
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
className="tableHead-cell"
|
||||
data-testid="heading-description">
|
||||
Description
|
||||
</th>
|
||||
<th
|
||||
className="tableHead-cell tw-w-60"
|
||||
data-testid="heading-associated-tags">
|
||||
Associated tags
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="tw-text-sm" data-testid="table-body">
|
||||
{(currentCategory?.children as TagClass[])?.map(
|
||||
(tag: TagClass, index: number) => {
|
||||
return (
|
||||
<tr
|
||||
className={`tableBody-row ${
|
||||
!isEven(index + 1) && 'odd-row'
|
||||
}`}
|
||||
key={index}>
|
||||
<td className="tableBody-cell">
|
||||
<p>{tag.name}</p>
|
||||
</td>
|
||||
<td
|
||||
className="tw-group tableBody-cell"
|
||||
onClick={() => {
|
||||
setIsEditTag(true);
|
||||
setEditTag(tag);
|
||||
}}>
|
||||
<NonAdminAction
|
||||
position="left"
|
||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||
<div className="tw-cursor-pointer hover:tw-underline tw-flex">
|
||||
<div>
|
||||
{tag.description ? (
|
||||
<RichTextEditorPreviewer
|
||||
markdown={tag.description}
|
||||
/>
|
||||
) : (
|
||||
<span className="tw-no-description">
|
||||
No description added
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<button className="tw-self-start tw-w-8 tw-h-auto tw-opacity-0 tw-ml-1 group-hover:tw-opacity-100 focus:tw-outline-none">
|
||||
<SVGIcons
|
||||
alt="edit"
|
||||
data-testid="editTagDescription"
|
||||
icon="icon-edit"
|
||||
title="Edit"
|
||||
width="10px"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</NonAdminAction>
|
||||
<div className="tw-mt-1">
|
||||
<span className="tw-text-grey-muted tw-mr-1">
|
||||
Usage:
|
||||
</span>
|
||||
{tag.usageCount ? (
|
||||
<Link
|
||||
className="link-text tw-align-middle"
|
||||
data-testid="usage-count"
|
||||
to={getUsageCountLink(
|
||||
tag.fullyQualifiedName || ''
|
||||
)}>
|
||||
{tag.usageCount}
|
||||
</Link>
|
||||
) : (
|
||||
<span className="tw-no-description">
|
||||
Not used
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
className="tw-group tableBody-cell"
|
||||
onClick={() => {
|
||||
setEditTag(tag);
|
||||
}}>
|
||||
<NonAdminAction
|
||||
position="left"
|
||||
title={TITLE_FOR_NON_ADMIN_ACTION}
|
||||
trigger="click">
|
||||
<TagsContainer
|
||||
editable={
|
||||
editTag?.name === tag.name && !isEditTag
|
||||
}
|
||||
selectedTags={
|
||||
tag.associatedTags?.map((tag) => ({
|
||||
tagFQN: tag,
|
||||
})) || []
|
||||
}
|
||||
tagList={
|
||||
getTaglist(categories) as Array<string>
|
||||
}
|
||||
onCancel={() => {
|
||||
handleTagSelection();
|
||||
}}
|
||||
onSelectionChange={(tags) => {
|
||||
handleTagSelection(tags);
|
||||
}}>
|
||||
{tag.associatedTags?.length ? (
|
||||
<button className="tw-opacity-0 tw-ml-1 group-hover:tw-opacity-100 focus:tw-outline-none">
|
||||
<div className="tw-bg-white">
|
||||
<table
|
||||
className="tw-w-full tw-overflow-x-auto"
|
||||
data-testid="table">
|
||||
<thead>
|
||||
<tr className="tableHead-row">
|
||||
<th
|
||||
className="tableHead-cell"
|
||||
data-testid="heading-name">
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
className="tableHead-cell"
|
||||
data-testid="heading-description">
|
||||
Description
|
||||
</th>
|
||||
<th
|
||||
className="tableHead-cell tw-w-60"
|
||||
data-testid="heading-associated-tags">
|
||||
Associated tags
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="tw-text-sm" data-testid="table-body">
|
||||
{(currentCategory?.children as TagClass[])?.map(
|
||||
(tag: TagClass, index: number) => {
|
||||
return (
|
||||
<tr
|
||||
className={`tableBody-row ${
|
||||
!isEven(index + 1) && 'odd-row'
|
||||
}`}
|
||||
key={index}>
|
||||
<td className="tableBody-cell">
|
||||
<p>{tag.name}</p>
|
||||
</td>
|
||||
<td
|
||||
className="tw-group tableBody-cell"
|
||||
onClick={() => {
|
||||
setIsEditTag(true);
|
||||
setEditTag(tag);
|
||||
}}>
|
||||
<NonAdminAction
|
||||
position="left"
|
||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||
<div className="tw-cursor-pointer hover:tw-underline tw-flex">
|
||||
<div>
|
||||
{tag.description ? (
|
||||
<RichTextEditorPreviewer
|
||||
markdown={tag.description}
|
||||
/>
|
||||
) : (
|
||||
<span className="tw-no-description">
|
||||
No description added
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<button className="tw-self-start tw-w-8 tw-h-auto tw-opacity-0 tw-ml-1 group-hover:tw-opacity-100 focus:tw-outline-none">
|
||||
<SVGIcons
|
||||
alt="edit"
|
||||
data-testid="editTagDescription"
|
||||
icon="icon-edit"
|
||||
title="Edit"
|
||||
width="10px"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</NonAdminAction>
|
||||
<div className="tw-mt-1">
|
||||
<span className="tw-text-grey-muted tw-mr-1">
|
||||
Usage:
|
||||
</span>
|
||||
{tag.usageCount ? (
|
||||
<Link
|
||||
className="link-text tw-align-middle"
|
||||
data-testid="usage-count"
|
||||
to={getUsageCountLink(
|
||||
tag.fullyQualifiedName || ''
|
||||
)}>
|
||||
{tag.usageCount}
|
||||
</Link>
|
||||
) : (
|
||||
<span className="tw-opacity-0 group-hover:tw-opacity-100">
|
||||
<Tags
|
||||
className="tw-border-main"
|
||||
startWith="+ "
|
||||
tag="Add tag"
|
||||
type="outlined"
|
||||
/>
|
||||
<span className="tw-no-description">
|
||||
Not used
|
||||
</span>
|
||||
)}
|
||||
</TagsContainer>
|
||||
</NonAdminAction>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
className="tw-group tableBody-cell"
|
||||
onClick={() => {
|
||||
setEditTag(tag);
|
||||
}}>
|
||||
<NonAdminAction
|
||||
position="left"
|
||||
title={TITLE_FOR_NON_ADMIN_ACTION}
|
||||
trigger="click">
|
||||
<TagsContainer
|
||||
editable={
|
||||
editTag?.name === tag.name && !isEditTag
|
||||
}
|
||||
selectedTags={
|
||||
tag.associatedTags?.map((tag) => ({
|
||||
tagFQN: tag,
|
||||
})) || []
|
||||
}
|
||||
tagList={
|
||||
getTaglist(categories) as Array<string>
|
||||
}
|
||||
onCancel={() => {
|
||||
handleTagSelection();
|
||||
}}
|
||||
onSelectionChange={(tags) => {
|
||||
handleTagSelection(tags);
|
||||
}}>
|
||||
{tag.associatedTags?.length ? (
|
||||
<button className="tw-opacity-0 tw-ml-1 group-hover:tw-opacity-100 focus:tw-outline-none">
|
||||
<SVGIcons
|
||||
alt="edit"
|
||||
icon="icon-edit"
|
||||
title="Edit"
|
||||
width="10px"
|
||||
/>
|
||||
</button>
|
||||
) : (
|
||||
<span className="tw-opacity-0 group-hover:tw-opacity-100">
|
||||
<Tags
|
||||
className="tw-border-main"
|
||||
startWith="+ "
|
||||
tag="Add tag"
|
||||
type="outlined"
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</TagsContainer>
|
||||
</NonAdminAction>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{isEditTag && (
|
||||
<ModalWithMarkdownEditor
|
||||
header={`Edit description for ${editTag?.name}`}
|
||||
placeholder="Enter Description"
|
||||
value={editTag?.description as string}
|
||||
onCancel={() => {
|
||||
setIsEditTag(false);
|
||||
setEditTag(undefined);
|
||||
}}
|
||||
onSave={updatePrimaryTag}
|
||||
/>
|
||||
)}
|
||||
{isAddingCategory && (
|
||||
<FormModal
|
||||
form={Form}
|
||||
header="Adding new category"
|
||||
initialData={{
|
||||
name: '',
|
||||
description: '',
|
||||
categoryType: TagCategoryType.Descriptive,
|
||||
}}
|
||||
onCancel={() => setIsAddingCategory(false)}
|
||||
onSave={(data) => createCategory(data as TagCategory)}
|
||||
/>
|
||||
)}
|
||||
{isAddingTag && (
|
||||
<FormModal
|
||||
form={Form}
|
||||
header={`Adding new tag on ${currentCategory?.name}`}
|
||||
initialData={{
|
||||
name: '',
|
||||
description: '',
|
||||
categoryType: '',
|
||||
}}
|
||||
onCancel={() => setIsAddingTag(false)}
|
||||
onSave={(data) => createPrimaryTag(data as TagCategory)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{isEditTag && (
|
||||
<ModalWithMarkdownEditor
|
||||
header={`Edit description for ${editTag?.name}`}
|
||||
placeholder="Enter Description"
|
||||
value={editTag?.description as string}
|
||||
onCancel={() => {
|
||||
setIsEditTag(false);
|
||||
setEditTag(undefined);
|
||||
}}
|
||||
onSave={updatePrimaryTag}
|
||||
/>
|
||||
)}
|
||||
{isAddingCategory && (
|
||||
<FormModal
|
||||
form={Form}
|
||||
header="Adding new category"
|
||||
initialData={{
|
||||
name: '',
|
||||
description: '',
|
||||
categoryType: TagCategoryType.Descriptive,
|
||||
}}
|
||||
onCancel={() => setIsAddingCategory(false)}
|
||||
onSave={(data) => createCategory(data as TagCategory)}
|
||||
/>
|
||||
)}
|
||||
{isAddingTag && (
|
||||
<FormModal
|
||||
form={Form}
|
||||
header={`Adding new tag on ${currentCategory?.name}`}
|
||||
initialData={{
|
||||
name: '',
|
||||
description: '',
|
||||
categoryType: '',
|
||||
}}
|
||||
onCancel={() => setIsAddingTag(false)}
|
||||
onSave={(data) => createPrimaryTag(data as TagCategory)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</PageContainer>
|
||||
)}
|
||||
</PageLayout>
|
||||
</PageContainerV1>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@ -28,7 +28,8 @@ import { Button } from '../../components/buttons/Button/Button';
|
||||
import Description from '../../components/common/description/Description';
|
||||
import ErrorPlaceHolder from '../../components/common/error-with-placeholder/ErrorPlaceHolder';
|
||||
import NonAdminAction from '../../components/common/non-admin-action/NonAdminAction';
|
||||
import PageContainer from '../../components/containers/PageContainer';
|
||||
import PageContainerV1 from '../../components/containers/PageContainerV1';
|
||||
import PageLayout from '../../components/containers/PageLayout';
|
||||
import Loader from '../../components/Loader/Loader';
|
||||
import FormModal from '../../components/Modals/FormModal';
|
||||
import {
|
||||
@ -160,7 +161,7 @@ const TeamsPage = () => {
|
||||
return (
|
||||
<div className="tw-mb-3 ">
|
||||
<nav
|
||||
className="tw-flex tw-flex-row tw-gh-tabs-container tw-px-4"
|
||||
className="tw-flex tw-flex-row tw-gh-tabs-container"
|
||||
data-testid="tabs">
|
||||
<button
|
||||
className={`tw-pb-2 tw-px-4 tw-gh-tabs ${getActiveTabClass(1)}`}
|
||||
@ -372,92 +373,94 @@ const TeamsPage = () => {
|
||||
{error ? (
|
||||
<ErrorPlaceHolder />
|
||||
) : (
|
||||
<PageContainer leftPanelContent={fetchLeftPanel()}>
|
||||
{isLoading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<div
|
||||
className="container-fluid tw-pt-1 tw-pb-3"
|
||||
data-testid="team-container">
|
||||
{teams.length > 0 ? (
|
||||
<>
|
||||
<div
|
||||
className="tw-flex tw-justify-between tw-pl-1"
|
||||
data-testid="header">
|
||||
<div className="tw-heading tw-text-link tw-text-base">
|
||||
{currentTeam?.displayName}
|
||||
<PageContainerV1 className="tw-py-4">
|
||||
<PageLayout leftPanel={fetchLeftPanel()}>
|
||||
{isLoading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<div className="tw-pb-3" data-testid="team-container">
|
||||
{teams.length > 0 ? (
|
||||
<>
|
||||
<div
|
||||
className="tw-flex tw-justify-between tw-pl-1"
|
||||
data-testid="header">
|
||||
<div className="tw-heading tw-text-link tw-text-base">
|
||||
{currentTeam?.displayName}
|
||||
</div>
|
||||
<NonAdminAction
|
||||
position="bottom"
|
||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||
<Button
|
||||
className={classNames('tw-h-8 tw-rounded tw-mb-2', {
|
||||
'tw-opacity-40': !isAdminUser && !isAuthDisabled,
|
||||
})}
|
||||
data-testid="add-new-user-button"
|
||||
size="small"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onClick={() => setIsAddingUsers(true)}>
|
||||
Add new user
|
||||
</Button>
|
||||
</NonAdminAction>
|
||||
</div>
|
||||
<div
|
||||
className="tw-mb-3"
|
||||
data-testid="description-container">
|
||||
<Description
|
||||
description={currentTeam?.description || ''}
|
||||
entityName={currentTeam?.displayName}
|
||||
isEdit={isEditable}
|
||||
onCancel={onCancel}
|
||||
onDescriptionEdit={onDescriptionEdit}
|
||||
onDescriptionUpdate={onDescriptionUpdate}
|
||||
/>
|
||||
</div>
|
||||
<NonAdminAction
|
||||
position="bottom"
|
||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||
<Button
|
||||
className={classNames('tw-h-8 tw-rounded tw-mb-2', {
|
||||
'tw-opacity-40': !isAdminUser && !isAuthDisabled,
|
||||
})}
|
||||
data-testid="add-new-user-button"
|
||||
size="small"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
onClick={() => setIsAddingUsers(true)}>
|
||||
Add new user
|
||||
</Button>
|
||||
</NonAdminAction>
|
||||
</div>
|
||||
<div className="tw-mb-3" data-testid="description-container">
|
||||
<Description
|
||||
description={currentTeam?.description || ''}
|
||||
entityName={currentTeam?.displayName}
|
||||
isEdit={isEditable}
|
||||
onCancel={onCancel}
|
||||
onDescriptionEdit={onDescriptionEdit}
|
||||
onDescriptionUpdate={onDescriptionUpdate}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{getTabs()}
|
||||
{getTabs()}
|
||||
|
||||
{currentTab === 1 && getUserCards()}
|
||||
{currentTab === 1 && getUserCards()}
|
||||
|
||||
{currentTab === 2 && getDatasetCards()}
|
||||
{isAddingUsers && (
|
||||
<AddUsersModal
|
||||
header={`Adding new users to ${currentTeam?.name}`}
|
||||
list={getUniqueUserList()}
|
||||
onCancel={() => setIsAddingUsers(false)}
|
||||
onSave={(data) => createUsers(data)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<ErrorPlaceHolder>
|
||||
<p className="w-text-lg tw-text-center">No Teams Added.</p>
|
||||
<p className="w-text-lg tw-text-center">
|
||||
<button
|
||||
className="link-text tw-underline"
|
||||
onClick={() => setIsAddingTeam(true)}>
|
||||
Click here
|
||||
</button>
|
||||
{' to add new Team'}
|
||||
</p>
|
||||
</ErrorPlaceHolder>
|
||||
)}
|
||||
{currentTab === 2 && getDatasetCards()}
|
||||
{isAddingUsers && (
|
||||
<AddUsersModal
|
||||
header={`Adding new users to ${currentTeam?.name}`}
|
||||
list={getUniqueUserList()}
|
||||
onCancel={() => setIsAddingUsers(false)}
|
||||
onSave={(data) => createUsers(data)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<ErrorPlaceHolder>
|
||||
<p className="w-text-lg tw-text-center">No Teams Added.</p>
|
||||
<p className="w-text-lg tw-text-center">
|
||||
<button
|
||||
className="link-text tw-underline"
|
||||
onClick={() => setIsAddingTeam(true)}>
|
||||
Click here
|
||||
</button>
|
||||
{' to add new Team'}
|
||||
</p>
|
||||
</ErrorPlaceHolder>
|
||||
)}
|
||||
|
||||
{isAddingTeam && (
|
||||
<FormModal
|
||||
form={Form}
|
||||
header="Adding new team"
|
||||
initialData={{
|
||||
name: '',
|
||||
description: '',
|
||||
displayName: '',
|
||||
}}
|
||||
onCancel={() => setIsAddingTeam(false)}
|
||||
onSave={(data) => createNewTeam(data as Team)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</PageContainer>
|
||||
{isAddingTeam && (
|
||||
<FormModal
|
||||
form={Form}
|
||||
header="Adding new team"
|
||||
initialData={{
|
||||
name: '',
|
||||
description: '',
|
||||
displayName: '',
|
||||
}}
|
||||
onCancel={() => setIsAddingTeam(false)}
|
||||
onSave={(data) => createNewTeam(data as Team)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</PageLayout>
|
||||
</PageContainerV1>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user