mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-31 04:14:34 +00:00
parent
0acf88e1ba
commit
4395cae6b7
@ -467,235 +467,241 @@ const DashboardDetails = ({
|
||||
tabs={tabs}
|
||||
/>
|
||||
|
||||
<div className="tw-bg-white tw-flex-grow tw--mx-6 tw-px-7 tw-py-4">
|
||||
{activeTab === 1 && (
|
||||
<>
|
||||
<div className="tw-grid tw-grid-cols-4 tw-gap-4 tw-w-full">
|
||||
<div className="tw-col-span-full">
|
||||
<Description
|
||||
description={description}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
'description',
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={dashboardFQN}
|
||||
entityName={entityName}
|
||||
entityType={EntityType.DASHBOARD}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
isEdit={isEdit}
|
||||
isReadOnly={deleted}
|
||||
owner={owner}
|
||||
onCancel={onCancel}
|
||||
onDescriptionEdit={onDescriptionEdit}
|
||||
onDescriptionUpdate={onDescriptionUpdate}
|
||||
onEntityFieldSelect={onEntityFieldSelect}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
<div className="tw-flex-grow tw-flex tw-flex-col tw--mx-6 tw-px-7 tw-py-4">
|
||||
<div className="tw-bg-white tw-flex-grow tw-p-4 tw-shadow tw-rounded-md">
|
||||
{activeTab === 1 && (
|
||||
<>
|
||||
<div className="tw-grid tw-grid-cols-4 tw-gap-4 tw-w-full">
|
||||
<div className="tw-col-span-full tw--ml-5">
|
||||
<Description
|
||||
description={description}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
'description',
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={dashboardFQN}
|
||||
entityName={entityName}
|
||||
entityType={EntityType.DASHBOARD}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
isEdit={isEdit}
|
||||
isReadOnly={deleted}
|
||||
owner={owner}
|
||||
onCancel={onCancel}
|
||||
onDescriptionEdit={onDescriptionEdit}
|
||||
onDescriptionUpdate={onDescriptionUpdate}
|
||||
onEntityFieldSelect={onEntityFieldSelect}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tw-table-responsive tw-my-6">
|
||||
<table className="tw-w-full" data-testid="charts-table">
|
||||
<thead>
|
||||
<tr className="tableHead-row">
|
||||
<th className="tableHead-cell">Chart Name</th>
|
||||
<th className="tableHead-cell">Chart Type</th>
|
||||
<th className="tableHead-cell">Description</th>
|
||||
<th className="tableHead-cell tw-w-60">Tags</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="tableBody">
|
||||
{charts.map((chart, index) => (
|
||||
<tr
|
||||
className={classNames(
|
||||
'tableBody-row',
|
||||
!isEven(index + 1) ? 'odd-row' : null
|
||||
)}
|
||||
key={index}>
|
||||
<td className="tableBody-cell">
|
||||
<Link
|
||||
target="_blank"
|
||||
to={{ pathname: chart.chartUrl }}>
|
||||
<span className="tw-flex">
|
||||
<span className="tw-mr-1">
|
||||
{chart.displayName}
|
||||
<div className="tw-table-responsive tw-my-6">
|
||||
<table className="tw-w-full" data-testid="charts-table">
|
||||
<thead>
|
||||
<tr className="tableHead-row">
|
||||
<th className="tableHead-cell">Chart Name</th>
|
||||
<th className="tableHead-cell">Chart Type</th>
|
||||
<th className="tableHead-cell">Description</th>
|
||||
<th className="tableHead-cell tw-w-60">Tags</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="tableBody">
|
||||
{charts.map((chart, index) => (
|
||||
<tr
|
||||
className={classNames(
|
||||
'tableBody-row',
|
||||
!isEven(index + 1) ? 'odd-row' : null
|
||||
)}
|
||||
key={index}>
|
||||
<td className="tableBody-cell">
|
||||
<Link
|
||||
target="_blank"
|
||||
to={{ pathname: chart.chartUrl }}>
|
||||
<span className="tw-flex">
|
||||
<span className="tw-mr-1">
|
||||
{chart.displayName}
|
||||
</span>
|
||||
<SVGIcons
|
||||
alt="external-link"
|
||||
className="tw-align-middle"
|
||||
icon="external-link"
|
||||
width="12px"
|
||||
/>
|
||||
</span>
|
||||
<SVGIcons
|
||||
alt="external-link"
|
||||
className="tw-align-middle"
|
||||
icon="external-link"
|
||||
width="12px"
|
||||
/>
|
||||
</span>
|
||||
</Link>
|
||||
</td>
|
||||
<td className="tableBody-cell">{chart.chartType}</td>
|
||||
<td className="tw-group tableBody-cell tw-relative">
|
||||
<div className="tw-inline-block">
|
||||
<div
|
||||
className="tw-cursor-pointer tw-flex"
|
||||
data-testid="description">
|
||||
<div>
|
||||
{chart.description ? (
|
||||
<RichTextEditorPreviewer
|
||||
markdown={chart.description}
|
||||
/>
|
||||
) : (
|
||||
<span className="tw-no-description">
|
||||
No description
|
||||
</span>
|
||||
</Link>
|
||||
</td>
|
||||
<td className="tableBody-cell">
|
||||
{chart.chartType}
|
||||
</td>
|
||||
<td className="tw-group tableBody-cell tw-relative">
|
||||
<div className="tw-inline-block">
|
||||
<div
|
||||
className="tw-cursor-pointer tw-flex"
|
||||
data-testid="description">
|
||||
<div>
|
||||
{chart.description ? (
|
||||
<RichTextEditorPreviewer
|
||||
markdown={chart.description}
|
||||
/>
|
||||
) : (
|
||||
<span className="tw-no-description">
|
||||
No description
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{!deleted && (
|
||||
<NonAdminAction
|
||||
html={getHtmlForNonAdminAction(
|
||||
Boolean(owner)
|
||||
)}
|
||||
isOwner={hasEditAccess()}
|
||||
permission={Operation.UpdateDescription}
|
||||
position="top">
|
||||
<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"
|
||||
onClick={() =>
|
||||
handleUpdateChart(chart, index)
|
||||
}>
|
||||
<SVGIcons
|
||||
alt="edit"
|
||||
icon="icon-edit"
|
||||
title="Edit"
|
||||
width="10px"
|
||||
/>
|
||||
</button>
|
||||
</NonAdminAction>
|
||||
)}
|
||||
</div>
|
||||
{!deleted && (
|
||||
<NonAdminAction
|
||||
html={getHtmlForNonAdminAction(
|
||||
Boolean(owner)
|
||||
)}
|
||||
isOwner={hasEditAccess()}
|
||||
permission={Operation.UpdateDescription}
|
||||
position="top">
|
||||
<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"
|
||||
onClick={() =>
|
||||
handleUpdateChart(chart, index)
|
||||
}>
|
||||
<SVGIcons
|
||||
alt="edit"
|
||||
icon="icon-edit"
|
||||
title="Edit"
|
||||
width="10px"
|
||||
/>
|
||||
</button>
|
||||
</NonAdminAction>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
className="tw-group tw-relative tableBody-cell"
|
||||
onClick={() => {
|
||||
if (!editChartTags) {
|
||||
// Fetch tags and terms only once
|
||||
if (tagList.length === 0 || tagFetchFailed) {
|
||||
fetchTagsAndGlossaryTerms();
|
||||
}
|
||||
handleEditChartTag(chart, index);
|
||||
}
|
||||
}}>
|
||||
{deleted ? (
|
||||
<div className="tw-flex tw-flex-wrap">
|
||||
<TagsViewer
|
||||
sizeCap={-1}
|
||||
tags={chart.tags || []}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<NonAdminAction
|
||||
html={getHtmlForNonAdminAction(Boolean(owner))}
|
||||
isOwner={hasEditAccess()}
|
||||
permission={Operation.UpdateTags}
|
||||
position="left"
|
||||
trigger="click">
|
||||
<TagsContainer
|
||||
editable={editChartTags?.index === index}
|
||||
isLoading={
|
||||
isTagLoading &&
|
||||
editChartTags?.index === index
|
||||
</td>
|
||||
<td
|
||||
className="tw-group tw-relative tableBody-cell"
|
||||
onClick={() => {
|
||||
if (!editChartTags) {
|
||||
// Fetch tags and terms only once
|
||||
if (tagList.length === 0 || tagFetchFailed) {
|
||||
fetchTagsAndGlossaryTerms();
|
||||
}
|
||||
selectedTags={chart.tags as EntityTags[]}
|
||||
size="small"
|
||||
tagList={tagList}
|
||||
type="label"
|
||||
onCancel={() => {
|
||||
handleChartTagSelection();
|
||||
}}
|
||||
onSelectionChange={(tags) => {
|
||||
handleChartTagSelection(tags);
|
||||
}}>
|
||||
{chart.tags?.length ? (
|
||||
<button
|
||||
className="tw-opacity-0 tw-ml-1 group-hover:tw-opacity-100 focus:tw-outline-none"
|
||||
data-testid="edit-tags">
|
||||
<SVGIcons
|
||||
alt="edit"
|
||||
icon="icon-edit"
|
||||
title="Edit"
|
||||
width="10px"
|
||||
/>
|
||||
</button>
|
||||
) : (
|
||||
<span className="tw-opacity-60 group-hover:tw-opacity-100 tw-text-grey-muted group-hover:tw-text-primary">
|
||||
<Tags
|
||||
startWith="+ "
|
||||
tag="Add tag"
|
||||
type="outlined"
|
||||
/>
|
||||
</span>
|
||||
handleEditChartTag(chart, index);
|
||||
}
|
||||
}}>
|
||||
{deleted ? (
|
||||
<div className="tw-flex tw-flex-wrap">
|
||||
<TagsViewer
|
||||
sizeCap={-1}
|
||||
tags={chart.tags || []}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<NonAdminAction
|
||||
html={getHtmlForNonAdminAction(
|
||||
Boolean(owner)
|
||||
)}
|
||||
</TagsContainer>
|
||||
</NonAdminAction>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
isOwner={hasEditAccess()}
|
||||
permission={Operation.UpdateTags}
|
||||
position="left"
|
||||
trigger="click">
|
||||
<TagsContainer
|
||||
editable={editChartTags?.index === index}
|
||||
isLoading={
|
||||
isTagLoading &&
|
||||
editChartTags?.index === index
|
||||
}
|
||||
selectedTags={chart.tags as EntityTags[]}
|
||||
size="small"
|
||||
tagList={tagList}
|
||||
type="label"
|
||||
onCancel={() => {
|
||||
handleChartTagSelection();
|
||||
}}
|
||||
onSelectionChange={(tags) => {
|
||||
handleChartTagSelection(tags);
|
||||
}}>
|
||||
{chart.tags?.length ? (
|
||||
<button
|
||||
className="tw-opacity-0 tw-ml-1 group-hover:tw-opacity-100 focus:tw-outline-none"
|
||||
data-testid="edit-tags">
|
||||
<SVGIcons
|
||||
alt="edit"
|
||||
icon="icon-edit"
|
||||
title="Edit"
|
||||
width="10px"
|
||||
/>
|
||||
</button>
|
||||
) : (
|
||||
<span className="tw-opacity-60 group-hover:tw-opacity-100 tw-text-grey-muted group-hover:tw-text-primary">
|
||||
<Tags
|
||||
startWith="+ "
|
||||
tag="Add tag"
|
||||
type="outlined"
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</TagsContainer>
|
||||
</NonAdminAction>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{activeTab === 2 && (
|
||||
<div
|
||||
className="tw-py-4 tw-px-7 tw-grid tw-grid-cols-3 entity-feed-list tw--mx-7 tw--my-4"
|
||||
id="activityfeed">
|
||||
<div />
|
||||
<ActivityFeedList
|
||||
isEntityFeed
|
||||
withSidePanel
|
||||
className=""
|
||||
deletePostHandler={deletePostHandler}
|
||||
entityName={entityName}
|
||||
feedList={entityThread}
|
||||
postFeedHandler={postFeedHandler}
|
||||
/>
|
||||
<div />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{activeTab === 2 && (
|
||||
)}
|
||||
{activeTab === 3 && (
|
||||
<div className="tw-h-full tw-px-3">
|
||||
<Entitylineage
|
||||
addLineageHandler={addLineageHandler}
|
||||
deleted={deleted}
|
||||
entityLineage={entityLineage}
|
||||
entityLineageHandler={entityLineageHandler}
|
||||
isLoading={isLineageLoading}
|
||||
isNodeLoading={isNodeLoading}
|
||||
isOwner={hasEditAccess()}
|
||||
lineageLeafNodes={lineageLeafNodes}
|
||||
loadNodeHandler={loadNodeHandler}
|
||||
removeLineageHandler={removeLineageHandler}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 4 && !deleted && (
|
||||
<div>
|
||||
<ManageTabComponent
|
||||
allowDelete
|
||||
currentTier={tier?.tagFQN}
|
||||
currentUser={owner}
|
||||
deletEntityMessage={getDeleteEntityMessage()}
|
||||
entityId={dashboardDetails.id}
|
||||
entityName={dashboardDetails.name}
|
||||
entityType={EntityType.DASHBOARD}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
manageSectionType={EntityType.DASHBOARD}
|
||||
onSave={onSettingsUpdate}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className="tw-py-4 tw-px-7 tw-grid tw-grid-cols-3 entity-feed-list tw--mx-7 tw--my-4"
|
||||
id="activityfeed">
|
||||
<div />
|
||||
<ActivityFeedList
|
||||
isEntityFeed
|
||||
withSidePanel
|
||||
className=""
|
||||
deletePostHandler={deletePostHandler}
|
||||
entityName={entityName}
|
||||
feedList={entityThread}
|
||||
postFeedHandler={postFeedHandler}
|
||||
/>
|
||||
<div />
|
||||
data-testid="observer-element"
|
||||
id="observer-element"
|
||||
ref={elementRef as RefObject<HTMLDivElement>}>
|
||||
{getLoader()}
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 3 && (
|
||||
<div className="tw-h-full">
|
||||
<Entitylineage
|
||||
addLineageHandler={addLineageHandler}
|
||||
deleted={deleted}
|
||||
entityLineage={entityLineage}
|
||||
entityLineageHandler={entityLineageHandler}
|
||||
isLoading={isLineageLoading}
|
||||
isNodeLoading={isNodeLoading}
|
||||
isOwner={hasEditAccess()}
|
||||
lineageLeafNodes={lineageLeafNodes}
|
||||
loadNodeHandler={loadNodeHandler}
|
||||
removeLineageHandler={removeLineageHandler}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 4 && !deleted && (
|
||||
<div>
|
||||
<ManageTabComponent
|
||||
allowDelete
|
||||
currentTier={tier?.tagFQN}
|
||||
currentUser={owner}
|
||||
deletEntityMessage={getDeleteEntityMessage()}
|
||||
entityId={dashboardDetails.id}
|
||||
entityName={dashboardDetails.name}
|
||||
entityType={EntityType.DASHBOARD}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
manageSectionType={EntityType.DASHBOARD}
|
||||
onSave={onSettingsUpdate}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
data-testid="observer-element"
|
||||
id="observer-element"
|
||||
ref={elementRef as RefObject<HTMLDivElement>}>
|
||||
{getLoader()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -579,187 +579,189 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
|
||||
setActiveTab={setActiveTabHandler}
|
||||
tabs={tabs}
|
||||
/>
|
||||
|
||||
<div className="tw-bg-white tw-flex-grow tw--mx-6 tw-px-7 tw-py-4">
|
||||
{activeTab === 1 && (
|
||||
<div
|
||||
className="tw-grid tw-grid-cols-4 tw-gap-4 tw-w-full"
|
||||
id="schemaDetails">
|
||||
<div className="tw-col-span-3">
|
||||
<Description
|
||||
description={description}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
'description',
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={datasetFQN}
|
||||
<div className="tw-flex-grow tw-flex tw-flex-col tw--mx-6 tw-px-7 tw-py-4">
|
||||
<div className="tw-bg-white tw-flex-grow tw-p-4 tw-shadow tw-rounded-md">
|
||||
{activeTab === 1 && (
|
||||
<div
|
||||
className="tw-grid tw-grid-cols-4 tw-gap-4 tw-w-full"
|
||||
id="schemaDetails">
|
||||
<div className="tw-col-span-3 tw--ml-5">
|
||||
<Description
|
||||
description={description}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
'description',
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={datasetFQN}
|
||||
entityName={entityName}
|
||||
entityType={EntityType.TABLE}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
isEdit={isEdit}
|
||||
isReadOnly={deleted}
|
||||
owner={owner}
|
||||
onCancel={onCancel}
|
||||
onDescriptionEdit={onDescriptionEdit}
|
||||
onDescriptionUpdate={onDescriptionUpdate}
|
||||
onEntityFieldSelect={onEntityFieldSelect}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
</div>
|
||||
<div className="tw-col-span-1 tw-border tw-border-main tw-rounded-md">
|
||||
<FrequentlyJoinedTables
|
||||
header="Frequently Joined Tables"
|
||||
tableList={getFrequentlyJoinedWithTables()}
|
||||
/>
|
||||
</div>
|
||||
<div className="tw-col-span-full">
|
||||
<SchemaTab
|
||||
columnName={getPartialNameFromTableFQN(
|
||||
datasetFQN,
|
||||
[FqnPart['Column']],
|
||||
FQN_SEPARATOR_CHAR
|
||||
)}
|
||||
columns={columns}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
'columns',
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={datasetFQN}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
isReadOnly={deleted}
|
||||
joins={tableJoinData.columnJoins as ColumnJoins[]}
|
||||
owner={owner}
|
||||
sampleData={sampleData}
|
||||
onEntityFieldSelect={onEntityFieldSelect}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
onUpdate={onColumnsUpdate}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 2 && (
|
||||
<div
|
||||
className="tw-py-4 tw-px-7 tw-grid tw-grid-cols-3 entity-feed-list tw--mx-7 tw--my-4"
|
||||
id="activityfeed">
|
||||
<div />
|
||||
<ActivityFeedList
|
||||
isEntityFeed
|
||||
withSidePanel
|
||||
className=""
|
||||
deletePostHandler={deletePostHandler}
|
||||
entityName={entityName}
|
||||
feedList={entityThread}
|
||||
postFeedHandler={postFeedHandler}
|
||||
/>
|
||||
<div />
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 3 && (
|
||||
<div id="sampleDataDetails">
|
||||
<SampleDataTable
|
||||
isLoading={isSampleDataLoading}
|
||||
sampleData={getSampleDataWithType()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 4 && (
|
||||
<div
|
||||
className="tw-py-4 tw-px-7 tw-grid tw-grid-cols-3 entity-feed-list"
|
||||
id="tablequeries">
|
||||
<div />
|
||||
<TableQueries
|
||||
isLoading={isQueriesLoading}
|
||||
queries={tableQueries}
|
||||
/>
|
||||
<div />
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 5 && (
|
||||
<div>
|
||||
<TableProfiler
|
||||
columns={columns.map((col) => ({
|
||||
constraint: col.constraint as string,
|
||||
colName: col.name,
|
||||
colType: col.dataTypeDisplay as string,
|
||||
dataType: col.dataType as string,
|
||||
colTests: col.columnTests,
|
||||
}))}
|
||||
isTableDeleted={deleted}
|
||||
qualityTestFormHandler={qualityTestFormHandler}
|
||||
tableProfiles={tableProfile}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === 6 && (
|
||||
<DataQualityTab
|
||||
columnOptions={columns}
|
||||
handleAddColumnTestCase={handleAddColumnTestCase}
|
||||
handleAddTableTestCase={handleAddTableTestCase}
|
||||
handleRemoveColumnTest={handleRemoveColumnTest}
|
||||
handleRemoveTableTest={handleRemoveTableTest}
|
||||
handleSelectedColumn={handleSelectedColumn}
|
||||
handleShowTestForm={handleShowTestForm}
|
||||
handleTestModeChange={handleTestModeChange}
|
||||
isTableDeleted={deleted}
|
||||
selectedColumn={selectedColumn}
|
||||
showTestForm={showTestForm}
|
||||
tableTestCase={tableTestCase}
|
||||
testMode={testMode}
|
||||
/>
|
||||
)}
|
||||
|
||||
{activeTab === 7 && (
|
||||
<div
|
||||
className={classNames(
|
||||
'tw-px-2',
|
||||
location.pathname.includes(ROUTES.TOUR)
|
||||
? 'tw-h-70vh'
|
||||
: 'tw-h-full'
|
||||
)}
|
||||
id="lineageDetails">
|
||||
<Entitylineage
|
||||
addLineageHandler={addLineageHandler}
|
||||
deleted={deleted}
|
||||
entityLineage={entityLineage}
|
||||
entityLineageHandler={entityLineageHandler}
|
||||
isLoading={isLineageLoading}
|
||||
isNodeLoading={isNodeLoading}
|
||||
isOwner={hasEditAccess()}
|
||||
lineageLeafNodes={lineageLeafNodes}
|
||||
loadNodeHandler={loadNodeHandler}
|
||||
removeLineageHandler={removeLineageHandler}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 8 && Boolean(dataModel?.sql) && (
|
||||
<div className="tw-border tw-border-main tw-rounded-md tw-py-4 tw-h-full cm-h-full">
|
||||
<SchemaEditor
|
||||
className="tw-h-full"
|
||||
mode={{ name: CSMode.SQL }}
|
||||
value={dataModel?.sql || ''}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 9 && !deleted && (
|
||||
<div>
|
||||
<ManageTab
|
||||
allowDelete
|
||||
currentTier={tier?.tagFQN}
|
||||
currentUser={owner}
|
||||
entityId={tableDetails.id}
|
||||
entityName={tableDetails.name}
|
||||
entityType={EntityType.TABLE}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
isEdit={isEdit}
|
||||
isReadOnly={deleted}
|
||||
owner={owner}
|
||||
onCancel={onCancel}
|
||||
onDescriptionEdit={onDescriptionEdit}
|
||||
onDescriptionUpdate={onDescriptionUpdate}
|
||||
onEntityFieldSelect={onEntityFieldSelect}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
manageSectionType={EntityType.TABLE}
|
||||
onSave={onSettingsUpdate}
|
||||
/>
|
||||
</div>
|
||||
<div className="tw-col-span-1 tw-border tw-border-main tw-rounded-md">
|
||||
<FrequentlyJoinedTables
|
||||
header="Frequently Joined Tables"
|
||||
tableList={getFrequentlyJoinedWithTables()}
|
||||
/>
|
||||
</div>
|
||||
<div className="tw-col-span-full">
|
||||
<SchemaTab
|
||||
columnName={getPartialNameFromTableFQN(
|
||||
datasetFQN,
|
||||
[FqnPart['Column']],
|
||||
FQN_SEPARATOR_CHAR
|
||||
)}
|
||||
columns={columns}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
'columns',
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={datasetFQN}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
isReadOnly={deleted}
|
||||
joins={tableJoinData.columnJoins as ColumnJoins[]}
|
||||
owner={owner}
|
||||
sampleData={sampleData}
|
||||
onEntityFieldSelect={onEntityFieldSelect}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
onUpdate={onColumnsUpdate}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 2 && (
|
||||
)}
|
||||
<div
|
||||
className="tw-py-4 tw-px-7 tw-grid tw-grid-cols-3 entity-feed-list tw--mx-7 tw--my-4"
|
||||
id="activityfeed">
|
||||
<div />
|
||||
<ActivityFeedList
|
||||
isEntityFeed
|
||||
withSidePanel
|
||||
className=""
|
||||
deletePostHandler={deletePostHandler}
|
||||
entityName={entityName}
|
||||
feedList={entityThread}
|
||||
postFeedHandler={postFeedHandler}
|
||||
/>
|
||||
<div />
|
||||
data-testid="observer-element"
|
||||
id="observer-element"
|
||||
ref={elementRef as RefObject<HTMLDivElement>}>
|
||||
{getLoader()}
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 3 && (
|
||||
<div id="sampleDataDetails">
|
||||
<SampleDataTable
|
||||
isLoading={isSampleDataLoading}
|
||||
sampleData={getSampleDataWithType()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 4 && (
|
||||
<div
|
||||
className="tw-py-4 tw-px-7 tw-grid tw-grid-cols-3 entity-feed-list"
|
||||
id="tablequeries">
|
||||
<div />
|
||||
<TableQueries
|
||||
isLoading={isQueriesLoading}
|
||||
queries={tableQueries}
|
||||
/>
|
||||
<div />
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 5 && (
|
||||
<div>
|
||||
<TableProfiler
|
||||
columns={columns.map((col) => ({
|
||||
constraint: col.constraint as string,
|
||||
colName: col.name,
|
||||
colType: col.dataTypeDisplay as string,
|
||||
dataType: col.dataType as string,
|
||||
colTests: col.columnTests,
|
||||
}))}
|
||||
isTableDeleted={deleted}
|
||||
qualityTestFormHandler={qualityTestFormHandler}
|
||||
tableProfiles={tableProfile}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === 6 && (
|
||||
<DataQualityTab
|
||||
columnOptions={columns}
|
||||
handleAddColumnTestCase={handleAddColumnTestCase}
|
||||
handleAddTableTestCase={handleAddTableTestCase}
|
||||
handleRemoveColumnTest={handleRemoveColumnTest}
|
||||
handleRemoveTableTest={handleRemoveTableTest}
|
||||
handleSelectedColumn={handleSelectedColumn}
|
||||
handleShowTestForm={handleShowTestForm}
|
||||
handleTestModeChange={handleTestModeChange}
|
||||
isTableDeleted={deleted}
|
||||
selectedColumn={selectedColumn}
|
||||
showTestForm={showTestForm}
|
||||
tableTestCase={tableTestCase}
|
||||
testMode={testMode}
|
||||
/>
|
||||
)}
|
||||
|
||||
{activeTab === 7 && (
|
||||
<div
|
||||
className={classNames(
|
||||
location.pathname.includes(ROUTES.TOUR)
|
||||
? 'tw-h-70vh'
|
||||
: 'tw-h-full'
|
||||
)}
|
||||
id="lineageDetails">
|
||||
<Entitylineage
|
||||
addLineageHandler={addLineageHandler}
|
||||
deleted={deleted}
|
||||
entityLineage={entityLineage}
|
||||
entityLineageHandler={entityLineageHandler}
|
||||
isLoading={isLineageLoading}
|
||||
isNodeLoading={isNodeLoading}
|
||||
isOwner={hasEditAccess()}
|
||||
lineageLeafNodes={lineageLeafNodes}
|
||||
loadNodeHandler={loadNodeHandler}
|
||||
removeLineageHandler={removeLineageHandler}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 8 && Boolean(dataModel?.sql) && (
|
||||
<div className="tw-border tw-border-main tw-rounded-md tw-py-4 tw-h-full cm-h-full">
|
||||
<SchemaEditor
|
||||
className="tw-h-full"
|
||||
mode={{ name: CSMode.SQL }}
|
||||
value={dataModel?.sql || ''}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 9 && !deleted && (
|
||||
<div>
|
||||
<ManageTab
|
||||
allowDelete
|
||||
currentTier={tier?.tagFQN}
|
||||
currentUser={owner}
|
||||
entityId={tableDetails.id}
|
||||
entityName={tableDetails.name}
|
||||
entityType={EntityType.TABLE}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
manageSectionType={EntityType.TABLE}
|
||||
onSave={onSettingsUpdate}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
data-testid="observer-element"
|
||||
id="observer-element"
|
||||
ref={elementRef as RefObject<HTMLDivElement>}>
|
||||
{getLoader()}
|
||||
</div>
|
||||
</div>
|
||||
{threadLink ? (
|
||||
|
@ -393,226 +393,230 @@ const PipelineDetails = ({
|
||||
tabs={tabs}
|
||||
/>
|
||||
|
||||
<div className="tw-bg-white tw-flex-grow tw--mx-6 tw-px-7 tw-py-4">
|
||||
{activeTab === 1 && (
|
||||
<>
|
||||
<div className="tw-grid tw-grid-cols-4 tw-gap-4 tw-w-full">
|
||||
<div className="tw-col-span-full">
|
||||
<Description
|
||||
description={description}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
'description',
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={pipelineFQN}
|
||||
entityName={entityName}
|
||||
entityType={EntityType.PIPELINE}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
isEdit={isEdit}
|
||||
isReadOnly={deleted}
|
||||
owner={owner}
|
||||
onCancel={onCancel}
|
||||
onDescriptionEdit={onDescriptionEdit}
|
||||
onDescriptionUpdate={onDescriptionUpdate}
|
||||
onEntityFieldSelect={onEntityFieldSelect}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
<div className="tw-flex-grow tw-flex tw-flex-col tw--mx-6 tw-px-7 tw-py-4">
|
||||
<div className="tw-bg-white tw-flex-grow tw-p-4 tw-shadow tw-rounded-md">
|
||||
{activeTab === 1 && (
|
||||
<>
|
||||
<div className="tw-grid tw-grid-cols-4 tw-gap-4 tw-w-full">
|
||||
<div className="tw-col-span-full tw--ml-5">
|
||||
<Description
|
||||
description={description}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
'description',
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={pipelineFQN}
|
||||
entityName={entityName}
|
||||
entityType={EntityType.PIPELINE}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
isEdit={isEdit}
|
||||
isReadOnly={deleted}
|
||||
owner={owner}
|
||||
onCancel={onCancel}
|
||||
onDescriptionEdit={onDescriptionEdit}
|
||||
onDescriptionUpdate={onDescriptionUpdate}
|
||||
onEntityFieldSelect={onEntityFieldSelect}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tw-table-responsive tw-my-6">
|
||||
{tasks ? (
|
||||
<table className="tw-w-full" data-testid="tasks-table">
|
||||
<thead>
|
||||
<tr className="tableHead-row">
|
||||
<th className="tableHead-cell">Task Name</th>
|
||||
<th className="tableHead-cell">Description</th>
|
||||
<th className="tableHead-cell">Task Type</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="tableBody">
|
||||
{tasks?.map((task, index) => (
|
||||
<tr
|
||||
className={classNames(
|
||||
'tableBody-row',
|
||||
!isEven(index + 1) ? 'odd-row' : null
|
||||
)}
|
||||
key={index}>
|
||||
<td className="tableBody-cell">
|
||||
<Link
|
||||
target="_blank"
|
||||
to={{ pathname: task.taskUrl }}>
|
||||
<span className="tw-flex">
|
||||
<span className="tw-mr-1">
|
||||
{task.displayName}
|
||||
</span>
|
||||
<SVGIcons
|
||||
alt="external-link"
|
||||
className="tw-align-middle"
|
||||
icon="external-link"
|
||||
width="12px"
|
||||
/>
|
||||
</span>
|
||||
</Link>
|
||||
</td>
|
||||
<td className="tw-group tableBody-cell tw-relative">
|
||||
<div
|
||||
className="tw-cursor-pointer tw-flex"
|
||||
data-testid="description">
|
||||
<div>
|
||||
{task.description ? (
|
||||
<RichTextEditorPreviewer
|
||||
markdown={task.description}
|
||||
/>
|
||||
) : (
|
||||
<span className="tw-no-description">
|
||||
No description{' '}
|
||||
<div className="tw-table-responsive tw-my-6">
|
||||
{tasks ? (
|
||||
<table className="tw-w-full" data-testid="tasks-table">
|
||||
<thead>
|
||||
<tr className="tableHead-row">
|
||||
<th className="tableHead-cell">Task Name</th>
|
||||
<th className="tableHead-cell">Description</th>
|
||||
<th className="tableHead-cell">Task Type</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="tableBody">
|
||||
{tasks?.map((task, index) => (
|
||||
<tr
|
||||
className={classNames(
|
||||
'tableBody-row',
|
||||
!isEven(index + 1) ? 'odd-row' : null
|
||||
)}
|
||||
key={index}>
|
||||
<td className="tableBody-cell">
|
||||
<Link
|
||||
target="_blank"
|
||||
to={{ pathname: task.taskUrl }}>
|
||||
<span className="tw-flex">
|
||||
<span className="tw-mr-1">
|
||||
{task.displayName}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{!deleted && (
|
||||
<Fragment>
|
||||
<NonAdminAction
|
||||
html={getHtmlForNonAdminAction(
|
||||
Boolean(owner)
|
||||
)}
|
||||
isOwner={hasEditAccess()}
|
||||
permission={Operation.UpdateDescription}
|
||||
position="top">
|
||||
<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"
|
||||
onClick={() =>
|
||||
handleUpdateTask(task, index)
|
||||
}>
|
||||
<SVGIcons
|
||||
alt="edit"
|
||||
icon="icon-edit"
|
||||
title="Edit"
|
||||
width="12px"
|
||||
/>
|
||||
</button>
|
||||
</NonAdminAction>
|
||||
{!isNil(
|
||||
getFieldThreadElement(
|
||||
<SVGIcons
|
||||
alt="external-link"
|
||||
className="tw-align-middle"
|
||||
icon="external-link"
|
||||
width="12px"
|
||||
/>
|
||||
</span>
|
||||
</Link>
|
||||
</td>
|
||||
<td className="tw-group tableBody-cell tw-relative">
|
||||
<div
|
||||
className="tw-cursor-pointer tw-flex"
|
||||
data-testid="description">
|
||||
<div>
|
||||
{task.description ? (
|
||||
<RichTextEditorPreviewer
|
||||
markdown={task.description}
|
||||
/>
|
||||
) : (
|
||||
<span className="tw-no-description">
|
||||
No description{' '}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{!deleted && (
|
||||
<Fragment>
|
||||
<NonAdminAction
|
||||
html={getHtmlForNonAdminAction(
|
||||
Boolean(owner)
|
||||
)}
|
||||
isOwner={hasEditAccess()}
|
||||
permission={Operation.UpdateDescription}
|
||||
position="top">
|
||||
<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"
|
||||
onClick={() =>
|
||||
handleUpdateTask(task, index)
|
||||
}>
|
||||
<SVGIcons
|
||||
alt="edit"
|
||||
icon="icon-edit"
|
||||
title="Edit"
|
||||
width="12px"
|
||||
/>
|
||||
</button>
|
||||
</NonAdminAction>
|
||||
{!isNil(
|
||||
getFieldThreadElement(
|
||||
task.name,
|
||||
'description',
|
||||
getEntityFieldThreadCounts(
|
||||
'tasks',
|
||||
entityFieldThreadCount
|
||||
) as EntityFieldThreads[],
|
||||
onThreadLinkSelect
|
||||
)
|
||||
) &&
|
||||
onEntityFieldSelect &&
|
||||
!task.description ? (
|
||||
<button
|
||||
className="focus:tw-outline-none tw-ml-1 tw-opacity-0 group-hover:tw-opacity-100 tw--mt-2"
|
||||
data-testid="request-description"
|
||||
onClick={() =>
|
||||
onEntityFieldSelect?.(
|
||||
`tasks/${task.name}/description`
|
||||
)
|
||||
}>
|
||||
<PopOver
|
||||
position="top"
|
||||
title="Request description"
|
||||
trigger="mouseenter">
|
||||
<SVGIcons
|
||||
alt="request-description"
|
||||
className="tw-mt-2.5"
|
||||
icon={Icons.REQUEST}
|
||||
/>
|
||||
</PopOver>
|
||||
</button>
|
||||
) : null}
|
||||
{getFieldThreadElement(
|
||||
task.name,
|
||||
'description',
|
||||
getEntityFieldThreadCounts(
|
||||
'tasks',
|
||||
entityFieldThreadCount
|
||||
) as EntityFieldThreads[],
|
||||
onThreadLinkSelect
|
||||
)
|
||||
) &&
|
||||
onEntityFieldSelect &&
|
||||
!task.description ? (
|
||||
<button
|
||||
className="focus:tw-outline-none tw-ml-1 tw-opacity-0 group-hover:tw-opacity-100 tw--mt-2"
|
||||
data-testid="request-description"
|
||||
onClick={() =>
|
||||
onEntityFieldSelect?.(
|
||||
`tasks/${task.name}/description`
|
||||
)
|
||||
}>
|
||||
<PopOver
|
||||
position="top"
|
||||
title="Request description"
|
||||
trigger="mouseenter">
|
||||
<SVGIcons
|
||||
alt="request-description"
|
||||
className="tw-mt-2.5"
|
||||
icon={Icons.REQUEST}
|
||||
/>
|
||||
</PopOver>
|
||||
</button>
|
||||
) : null}
|
||||
{getFieldThreadElement(
|
||||
task.name,
|
||||
'description',
|
||||
getEntityFieldThreadCounts(
|
||||
'tasks',
|
||||
entityFieldThreadCount
|
||||
) as EntityFieldThreads[],
|
||||
onThreadLinkSelect,
|
||||
EntityType.PIPELINE,
|
||||
pipelineFQN,
|
||||
`tasks/${task.name}/description`,
|
||||
Boolean(task.description)
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
<td className="tableBody-cell">{task.taskType}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
) : (
|
||||
<div className="tw-mt-4 tw-ml-4 tw-flex tw-justify-center tw-font-medium tw-items-center tw-border tw-border-main tw-rounded-md tw-p-8">
|
||||
<span>No task data is available</span>
|
||||
</div>
|
||||
)}
|
||||
onThreadLinkSelect,
|
||||
EntityType.PIPELINE,
|
||||
pipelineFQN,
|
||||
`tasks/${task.name}/description`,
|
||||
Boolean(task.description)
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
<td className="tableBody-cell">
|
||||
{task.taskType}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
) : (
|
||||
<div className="tw-mt-4 tw-ml-4 tw-flex tw-justify-center tw-font-medium tw-items-center tw-border tw-border-main tw-rounded-md tw-p-8">
|
||||
<span>No task data is available</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{activeTab === 2 && (
|
||||
<div
|
||||
className="tw-py-4 tw-px-7 tw-grid tw-grid-cols-3 entity-feed-list tw--mx-7 tw--my-4"
|
||||
id="activityfeed">
|
||||
<div />
|
||||
<ActivityFeedList
|
||||
isEntityFeed
|
||||
withSidePanel
|
||||
className=""
|
||||
deletePostHandler={deletePostHandler}
|
||||
entityName={entityName}
|
||||
feedList={entityThread}
|
||||
postFeedHandler={postFeedHandler}
|
||||
/>
|
||||
<div />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{activeTab === 2 && (
|
||||
)}
|
||||
{activeTab === 3 && (
|
||||
<PipelineStatusList
|
||||
isLoading={isPipelineStatusLoading}
|
||||
pipelineStatus={pipelineStatus}
|
||||
/>
|
||||
)}
|
||||
{activeTab === 4 && (
|
||||
<div className="tw-h-full tw-px-3">
|
||||
<Entitylineage
|
||||
addLineageHandler={addLineageHandler}
|
||||
deleted={deleted}
|
||||
entityLineage={entityLineage}
|
||||
entityLineageHandler={entityLineageHandler}
|
||||
isLoading={isLineageLoading}
|
||||
isNodeLoading={isNodeLoading}
|
||||
isOwner={hasEditAccess()}
|
||||
lineageLeafNodes={lineageLeafNodes}
|
||||
loadNodeHandler={loadNodeHandler}
|
||||
removeLineageHandler={removeLineageHandler}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 5 && !deleted && (
|
||||
<div>
|
||||
<ManageTabComponent
|
||||
allowDelete
|
||||
currentTier={tier?.tagFQN}
|
||||
currentUser={owner}
|
||||
entityId={pipelineDetails.id}
|
||||
entityName={pipelineDetails.name}
|
||||
entityType={EntityType.PIPELINE}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
manageSectionType={EntityType.PIPELINE}
|
||||
onSave={onSettingsUpdate}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className="tw-py-4 tw-px-7 tw-grid tw-grid-cols-3 entity-feed-list tw--mx-7 tw--my-4"
|
||||
id="activityfeed">
|
||||
<div />
|
||||
<ActivityFeedList
|
||||
isEntityFeed
|
||||
withSidePanel
|
||||
className=""
|
||||
deletePostHandler={deletePostHandler}
|
||||
entityName={entityName}
|
||||
feedList={entityThread}
|
||||
postFeedHandler={postFeedHandler}
|
||||
/>
|
||||
<div />
|
||||
data-testid="observer-element"
|
||||
id="observer-element"
|
||||
ref={elementRef as RefObject<HTMLDivElement>}>
|
||||
{getLoader()}
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 3 && (
|
||||
<PipelineStatusList
|
||||
isLoading={isPipelineStatusLoading}
|
||||
pipelineStatus={pipelineStatus}
|
||||
/>
|
||||
)}
|
||||
{activeTab === 4 && (
|
||||
<div className="tw-h-full">
|
||||
<Entitylineage
|
||||
addLineageHandler={addLineageHandler}
|
||||
deleted={deleted}
|
||||
entityLineage={entityLineage}
|
||||
entityLineageHandler={entityLineageHandler}
|
||||
isLoading={isLineageLoading}
|
||||
isNodeLoading={isNodeLoading}
|
||||
isOwner={hasEditAccess()}
|
||||
lineageLeafNodes={lineageLeafNodes}
|
||||
loadNodeHandler={loadNodeHandler}
|
||||
removeLineageHandler={removeLineageHandler}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 5 && !deleted && (
|
||||
<div>
|
||||
<ManageTabComponent
|
||||
allowDelete
|
||||
currentTier={tier?.tagFQN}
|
||||
currentUser={owner}
|
||||
entityId={pipelineDetails.id}
|
||||
entityName={pipelineDetails.name}
|
||||
entityType={EntityType.PIPELINE}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
manageSectionType={EntityType.PIPELINE}
|
||||
onSave={onSettingsUpdate}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
data-testid="observer-element"
|
||||
id="observer-element"
|
||||
ref={elementRef as RefObject<HTMLDivElement>}>
|
||||
{getLoader()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -387,99 +387,100 @@ const TopicDetails: React.FC<TopicDetailsProps> = ({
|
||||
setActiveTab={setActiveTabHandler}
|
||||
tabs={tabs}
|
||||
/>
|
||||
|
||||
<div className="tw-bg-white tw-flex-grow tw--mx-6 tw-px-7 tw-py-4">
|
||||
{activeTab === 1 && (
|
||||
<>
|
||||
<div className="tw-grid tw-grid-cols-4 tw-gap-4 tw-w-full">
|
||||
<div className="tw-col-span-full">
|
||||
<Description
|
||||
description={description}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
'description',
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={topicFQN}
|
||||
entityName={entityName}
|
||||
entityType={EntityType.TOPIC}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
isEdit={isEdit}
|
||||
isReadOnly={deleted}
|
||||
owner={owner}
|
||||
onCancel={onCancel}
|
||||
onDescriptionEdit={onDescriptionEdit}
|
||||
onDescriptionUpdate={onDescriptionUpdate}
|
||||
onEntityFieldSelect={onEntityFieldSelect}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{schemaText ? (
|
||||
<Fragment>
|
||||
{getInfoBadge([{ key: 'Schema', value: schemaType }])}
|
||||
<div
|
||||
className="tw-my-4 tw-border tw-border-main tw-rounded-md tw-py-4"
|
||||
data-testid="schema">
|
||||
<SchemaEditor value={schemaText} />
|
||||
<div className="tw-flex-grow tw-flex tw-flex-col tw--mx-6 tw-px-7 tw-py-4">
|
||||
<div className="tw-bg-white tw-flex-grow tw-p-4 tw-shadow tw-rounded-md">
|
||||
{activeTab === 1 && (
|
||||
<>
|
||||
<div className="tw-grid tw-grid-cols-4 tw-gap-4 tw-w-full">
|
||||
<div className="tw-col-span-full tw--ml-5">
|
||||
<Description
|
||||
description={description}
|
||||
entityFieldThreads={getEntityFieldThreadCounts(
|
||||
'description',
|
||||
entityFieldThreadCount
|
||||
)}
|
||||
entityFqn={topicFQN}
|
||||
entityName={entityName}
|
||||
entityType={EntityType.TOPIC}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
isEdit={isEdit}
|
||||
isReadOnly={deleted}
|
||||
owner={owner}
|
||||
onCancel={onCancel}
|
||||
onDescriptionEdit={onDescriptionEdit}
|
||||
onDescriptionUpdate={onDescriptionUpdate}
|
||||
onEntityFieldSelect={onEntityFieldSelect}
|
||||
onThreadLinkSelect={onThreadLinkSelect}
|
||||
/>
|
||||
</div>
|
||||
</Fragment>
|
||||
) : (
|
||||
<div className="tw-flex tw-justify-center tw-font-medium tw-items-center tw-border tw-border-main tw-rounded-md tw-p-8">
|
||||
No schema data available
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{activeTab === 2 && (
|
||||
{schemaText ? (
|
||||
<Fragment>
|
||||
{getInfoBadge([{ key: 'Schema', value: schemaType }])}
|
||||
<div
|
||||
className="tw-my-4 tw-border tw-border-main tw-rounded-md tw-py-4"
|
||||
data-testid="schema">
|
||||
<SchemaEditor value={schemaText} />
|
||||
</div>
|
||||
</Fragment>
|
||||
) : (
|
||||
<div className="tw-flex tw-justify-center tw-font-medium tw-items-center tw-border tw-border-main tw-rounded-md tw-p-8">
|
||||
No schema data available
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{activeTab === 2 && (
|
||||
<div
|
||||
className="tw-py-4 tw-px-7 tw-grid tw-grid-cols-3 entity-feed-list tw--mx-7 tw--my-4 "
|
||||
id="activityfeed">
|
||||
<div />
|
||||
<ActivityFeedList
|
||||
isEntityFeed
|
||||
withSidePanel
|
||||
className=""
|
||||
deletePostHandler={deletePostHandler}
|
||||
entityName={entityName}
|
||||
feedList={entityThread}
|
||||
postFeedHandler={postFeedHandler}
|
||||
/>
|
||||
<div />
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 3 && (
|
||||
<div data-testid="sample-data">
|
||||
<SampleDataTopic
|
||||
isLoading={isSampleDataLoading}
|
||||
sampleData={sampleData}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 4 && (
|
||||
<div data-testid="config">
|
||||
<SchemaEditor value={JSON.stringify(getConfigObject())} />
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 5 && !deleted && (
|
||||
<div>
|
||||
<ManageTabComponent
|
||||
allowDelete
|
||||
currentTier={tier?.tagFQN}
|
||||
currentUser={owner}
|
||||
entityId={topicDetails.id}
|
||||
entityName={topicDetails.name}
|
||||
entityType={EntityType.TOPIC}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
manageSectionType={EntityType.TOPIC}
|
||||
onSave={onSettingsUpdate}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className="tw-py-4 tw-px-7 tw-grid tw-grid-cols-3 entity-feed-list tw--mx-7 tw--my-4 "
|
||||
id="activityfeed">
|
||||
<div />
|
||||
<ActivityFeedList
|
||||
isEntityFeed
|
||||
withSidePanel
|
||||
className=""
|
||||
deletePostHandler={deletePostHandler}
|
||||
entityName={entityName}
|
||||
feedList={entityThread}
|
||||
postFeedHandler={postFeedHandler}
|
||||
/>
|
||||
<div />
|
||||
data-testid="observer-element"
|
||||
id="observer-element"
|
||||
ref={elementRef as RefObject<HTMLDivElement>}>
|
||||
{getLoader()}
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 3 && (
|
||||
<div data-testid="sample-data">
|
||||
<SampleDataTopic
|
||||
isLoading={isSampleDataLoading}
|
||||
sampleData={sampleData}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 4 && (
|
||||
<div data-testid="config">
|
||||
<SchemaEditor value={JSON.stringify(getConfigObject())} />
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 5 && !deleted && (
|
||||
<div>
|
||||
<ManageTabComponent
|
||||
allowDelete
|
||||
currentTier={tier?.tagFQN}
|
||||
currentUser={owner}
|
||||
entityId={topicDetails.id}
|
||||
entityName={topicDetails.name}
|
||||
entityType={EntityType.TOPIC}
|
||||
hasEditAccess={hasEditAccess()}
|
||||
manageSectionType={EntityType.TOPIC}
|
||||
onSave={onSettingsUpdate}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
data-testid="observer-element"
|
||||
id="observer-element"
|
||||
ref={elementRef as RefObject<HTMLDivElement>}>
|
||||
{getLoader()}
|
||||
</div>
|
||||
</div>
|
||||
{threadLink ? (
|
||||
|
@ -25,7 +25,7 @@ type Item = {
|
||||
email: string;
|
||||
isActiveUser?: boolean;
|
||||
profilePhoto?: string;
|
||||
teamCount?: string;
|
||||
teamCount?: string | JSX.Element;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
@ -73,7 +73,7 @@ const UserDataCard = ({ item, onClick, onDelete, showTeams = true }: Props) => {
|
||||
)}
|
||||
</div>
|
||||
<p className="tw-truncate">{item.email}</p>
|
||||
{showTeams && <p>Teams: {item.teamCount}</p>}
|
||||
{showTeams && <div>Teams: {item.teamCount}</div>}
|
||||
</div>
|
||||
</div>
|
||||
{!isNil(onDelete) && (
|
||||
|
@ -18,6 +18,7 @@ import { getUserPath } from '../../constants/constants';
|
||||
import { EntityReference, User } from '../../generated/entity/teams/user';
|
||||
import { getEntityName } from '../../utils/CommonUtils';
|
||||
import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder';
|
||||
import PopOver from '../common/popover/PopOver';
|
||||
import Searchbar from '../common/searchbar/Searchbar';
|
||||
import Loader from '../Loader/Loader';
|
||||
import ConfirmationModal from '../Modals/ConfirmationModal/ConfirmationModal';
|
||||
@ -66,6 +67,35 @@ const UserDetails = ({
|
||||
setDeletingUser(undefined);
|
||||
};
|
||||
|
||||
const getTeamsText = (teams: EntityReference[]) => {
|
||||
return teams.length > 1 ? (
|
||||
<span>
|
||||
{getEntityName(teams[0])}, &{' '}
|
||||
<PopOver
|
||||
html={
|
||||
<span>
|
||||
{teams.map((t, i) => {
|
||||
return i >= 1 ? (
|
||||
<span className="tw-block tw-text-left" key={i}>
|
||||
{getEntityName(t)}
|
||||
</span>
|
||||
) : null;
|
||||
})}
|
||||
</span>
|
||||
}
|
||||
position="bottom"
|
||||
theme="light"
|
||||
trigger="mouseenter">
|
||||
<span className="tw-underline tw-cursor-pointer">
|
||||
{teams.length - 1} more
|
||||
</span>
|
||||
</PopOver>
|
||||
</span>
|
||||
) : (
|
||||
`${getEntityName(teams[0])}`
|
||||
);
|
||||
};
|
||||
|
||||
const getUserCards = () => {
|
||||
return isUsersLoading ? (
|
||||
<Loader />
|
||||
@ -84,10 +114,8 @@ const UserDetails = ({
|
||||
isActiveUser: !user.deleted,
|
||||
profilePhoto: user.profile?.images?.image || '',
|
||||
teamCount:
|
||||
user.teams && user.teams?.length
|
||||
? user.teams
|
||||
?.map((team) => team.displayName ?? team.name)
|
||||
?.join(', ')
|
||||
user.teams && user.teams.length
|
||||
? getTeamsText(user.teams)
|
||||
: 'No teams',
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user