issue-211: added addtional inforamtion related to driver class, frequ… (#235)

* issue-211: added addtional inforamtion related to driver class, frequency and service type

* added addtional info in services page, ui change for service page when there is no table data

* added same ui changes for all the pagination, if there is no info related to next prev page, pagination will be hidden

* added page count constant instead of fix value
This commit is contained in:
Shailesh Parmar 2021-08-23 10:33:26 +05:30 committed by GitHub
parent 95f650268b
commit f028c1d395
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 241 additions and 175 deletions

View File

@ -17,6 +17,7 @@
import classNames from 'classnames';
import React, { FunctionComponent, useRef, useState } from 'react';
import { fromISOString } from '../../../utils/ServiceUtils';
import { Button } from '../../buttons/Button/Button';
import MarkdownWithPreview from '../../common/editor/MarkdownWithPreview';
// import { serviceType } from '../../../constants/services.const';
@ -119,24 +120,6 @@ const seprateUrl = (url?: string) => {
return {};
};
const fromISOString = (isoValue = '') => {
if (isoValue) {
// 'P1DT 0H 0M'
const [d, hm] = isoValue.split('T');
const day = +d.replace('D', '').replace('P', '');
const [h, time] = hm.split('H');
const minute = +time.replace('M', '');
return { day, hour: +h, minute };
} else {
return {
day: 1,
hour: 0,
minute: 0,
};
}
};
const errorMsg = (value: string) => {
return (
<div className="tw-mt-1">

View File

@ -93,7 +93,7 @@ const SearchedData: React.FC<SearchedDataProp> = ({
</div>
))}
{totalValue > 0 && data.length > 0 && (
{totalValue > PAGE_SIZE && data.length > 0 && (
<Pagination
currentPage={currentPage}
paginate={paginate}

View File

@ -54,6 +54,10 @@ declare module 'Models' {
export type ServiceOption = {
id: string;
description: string;
ingestionSchedule?: {
repeatFrequency: string;
startDate: string;
};
jdbc: { connectionUrl: string; driverClass: string };
name: string;
serviceType: string;

View File

@ -18,6 +18,7 @@
import { AxiosResponse } from 'axios';
import classNames from 'classnames';
import { compare } from 'fast-json-patch';
import { isNull } from 'lodash';
import { observer } from 'mobx-react';
import { Database, Paging, TableDetail } from 'Models';
import React, { FunctionComponent, useEffect, useRef, useState } from 'react';
@ -265,102 +266,100 @@ const DatabaseDetails: FunctionComponent = () => {
</div>
</div>
</div>
{data.length ? (
<>
<table
className="tw-bg-white tw-w-full tw-mb-4"
data-testid="database-tables">
<thead>
<tr className="tableHead-row">
<th className="tableHead-cell">Table Name</th>
<th className="tableHead-cell">Description</th>
<th className="tableHead-cell">Owner</th>
<th className="tableHead-cell">Usage</th>
<th className="tableHead-cell tw-w-60">Tags</th>
</tr>
</thead>
<tbody className="tableBody">
{data.map((table, index) => (
<tr
className={classNames(
'tableBody-row',
!isEven(index + 1) ? 'odd-row' : null
<table
className="tw-bg-white tw-w-full tw-mb-4"
data-testid="database-tables">
<thead>
<tr className="tableHead-row">
<th className="tableHead-cell">Table Name</th>
<th className="tableHead-cell">Description</th>
<th className="tableHead-cell">Owner</th>
<th className="tableHead-cell">Usage</th>
<th className="tableHead-cell tw-w-60">Tags</th>
</tr>
</thead>
<tbody className="tableBody">
{data.length > 0 ? (
data.map((table, index) => (
<tr
className={classNames(
'tableBody-row',
!isEven(index + 1) ? 'odd-row' : null
)}
data-testid="column"
key={index}>
<td className="tableBody-cell">
<Link
to={getDatasetDetailsPath(table.fullyQualifiedName)}>
{table.name}
</Link>
</td>
<td className="tableBody-cell">
{table.description ? (
<RichTextEditorPreviewer
markdown={table.description}
/>
) : (
<span className="tw-no-description">
No description added
</span>
)}
data-testid="column"
key={index}>
<td className="tableBody-cell">
<Link
to={getDatasetDetailsPath(
table.fullyQualifiedName
)}>
{table.name}
</Link>
</td>
<td className="tableBody-cell">
{table.description ? (
<RichTextEditorPreviewer
markdown={table.description}
/>
) : (
<span className="tw-no-description">
No description added
</span>
</td>
<td className="tableBody-cell">
<p>{getOwnerFromId(table?.owner?.id)?.name || '--'}</p>
</td>
<td className="tableBody-cell">
<p>
{getUsagePercentile(
table.usageSummary.weeklyStats.percentileRank || 0
)}
</td>
<td className="tableBody-cell">
<p>
{getOwnerFromId(table?.owner?.id)?.name || '--'}
</p>
</td>
<td className="tableBody-cell">
<p>
{getUsagePercentile(
table.usageSummary.weeklyStats.percentileRank || 0
)}
</p>
</td>
<td className="tableBody-cell">
{table.tags.map((tag, tagIndex) => (
<PopOver
key={tagIndex}
position="top"
size="small"
title={tag.labelType}
trigger="mouseenter">
<Tags
className="tw-bg-gray-200"
tag={`#${
tag.tagFQN.startsWith('Tier.Tier')
? tag.tagFQN.split('.')[1]
: tag.tagFQN
}`}
/>
</PopOver>
))}
{getTableTags(table.columns).map((tag, tagIdx) => (
<PopOver
key={tagIdx}
position="top"
size="small"
title={tag.labelType}
trigger="mouseenter">
<Tags
className="tw-bg-gray-200"
tag={`#${tag.tagFQN}`}
/>
</PopOver>
))}
</td>
</tr>
))}
</tbody>
</table>
<NextPrevious paging={paging} pagingHandler={pagingHandler} />
</>
) : (
<h1 className="tw-text-center tw-mt-60 tw-text-grey-body tw-font-normal">
{databaseName} does not have any tables
</h1>
</p>
</td>
<td className="tableBody-cell">
{table.tags.map((tag, tagIndex) => (
<PopOver
key={tagIndex}
position="top"
size="small"
title={tag.labelType}
trigger="mouseenter">
<Tags
className="tw-bg-gray-200"
tag={`#${
tag.tagFQN.startsWith('Tier.Tier')
? tag.tagFQN.split('.')[1]
: tag.tagFQN
}`}
/>
</PopOver>
))}
{getTableTags(table.columns).map((tag, tagIdx) => (
<PopOver
key={tagIdx}
position="top"
size="small"
title={tag.labelType}
trigger="mouseenter">
<Tags
className="tw-bg-gray-200"
tag={`#${tag.tagFQN}`}
/>
</PopOver>
))}
</td>
</tr>
))
) : (
<tr className="tableBody-row">
<td className="tableBody-cell tw-text-center" colSpan={5}>
No records found.
</td>
</tr>
)}
</tbody>
</table>
{Boolean(!isNull(paging.after) || !isNull(paging.before)) && (
<NextPrevious paging={paging} pagingHandler={pagingHandler} />
)}
</div>
</PageContainer>

View File

@ -17,7 +17,7 @@
import { AxiosError, AxiosResponse } from 'axios';
import classNames from 'classnames';
import { isUndefined } from 'lodash';
import { isNull, isUndefined } from 'lodash';
import { Database, Paging, ServiceOption } from 'Models';
import React, { FunctionComponent, useEffect, useState } from 'react';
import { Link, useParams } from 'react-router-dom';
@ -33,7 +33,7 @@ import { ModalWithMarkdownEditor } from '../../components/Modals/ModalWithMarkdo
import { pagingObject } from '../../constants/constants';
import useToastContext from '../../hooks/useToastContext';
import { isEven } from '../../utils/CommonUtils';
import { serviceTypeLogo } from '../../utils/ServiceUtils';
import { getFrequencyTime, serviceTypeLogo } from '../../utils/ServiceUtils';
import SVGIcons from '../../utils/SvgUtils';
import { getUsagePercentile } from '../../utils/TableUtils';
@ -141,6 +141,44 @@ const ServicePage: FunctionComponent = () => {
<div className="tw-px-4">
<TitleBreadcrumb titleLinks={slashedTableName} />
<div className="tw-flex tw-gap-1 tw-mb-2 tw-mt-1">
<span>
<span className="tw-text-grey-muted tw-font-normal">
Driver Class :
</span>{' '}
<span className="tw-pl-1tw-font-normal ">
{serviceDetails?.jdbc.driverClass || '--'}
</span>
<span className="tw-mx-3 tw-inline-block tw-text-gray-400">
</span>
</span>
<span>
<span className="tw-text-grey-muted tw-font-normal">
Frequency :
</span>{' '}
<span className="tw-pl-1 tw-font-normal">
{' '}
{serviceDetails?.ingestionSchedule
? getFrequencyTime(
serviceDetails.ingestionSchedule.repeatFrequency
)
: 'N/A'}
</span>
<span className="tw-mx-3 tw-inline-block tw-text-gray-400">
</span>
</span>
<span>
<span className="tw-text-grey-muted tw-font-normal">
Service Type :
</span>{' '}
<span className="tw-pl-1 tw-font-normal">
{serviceDetails?.serviceType}
</span>
</span>
</div>
<div className="tw-bg-white tw-my-4">
<div className="tw-col-span-3">
<div className="schema-description tw-flex tw-flex-col tw-h-full tw-relative tw-border tw-border-main tw-rounded-md">
@ -179,67 +217,69 @@ const ServicePage: FunctionComponent = () => {
</div>
</div>
</div>
{data.length > 0 ? (
<>
<div className="tw-mt-4">
<table
className="tw-bg-white tw-w-full tw-mb-4"
data-testid="database-tables">
<thead>
<tr className="tableHead-row">
<th className="tableHead-cell">Database Name</th>
<th className="tableHead-cell">Description</th>
<th className="tableHead-cell">Owner</th>
<th className="tableHead-cell">Usage</th>
</tr>
</thead>
<tbody className="tableBody">
{data.map((database, index) => (
<tr
className={classNames(
'tableBody-row',
!isEven(index + 1) ? 'odd-row' : null
<div className="tw-mt-4">
<table
className="tw-bg-white tw-w-full tw-mb-4"
data-testid="database-tables">
<thead>
<tr className="tableHead-row">
<th className="tableHead-cell">Database Name</th>
<th className="tableHead-cell">Description</th>
<th className="tableHead-cell">Owner</th>
<th className="tableHead-cell">Usage</th>
</tr>
</thead>
<tbody className="tableBody">
{data.length > 0 ? (
data.map((database, index) => (
<tr
className={classNames(
'tableBody-row',
!isEven(index + 1) ? 'odd-row' : null
)}
data-testid="column"
key={index}>
<td className="tableBody-cell">
<Link to={`/database/${database.fullyQualifiedName}`}>
{database.name}
</Link>
</td>
<td className="tableBody-cell">
{database.description ? (
<RichTextEditorPreviewer
markdown={database.description}
/>
) : (
<span className="tw-no-description">
No description added
</span>
)}
data-testid="column"
key={index}>
<td className="tableBody-cell">
<Link
to={`/database/${database.fullyQualifiedName}`}>
{database.name}
</Link>
</td>
<td className="tableBody-cell">
{database.description ? (
<RichTextEditorPreviewer
markdown={database.description}
/>
) : (
<span className="tw-no-description">
No description added
</span>
</td>
<td className="tableBody-cell">
<p>{database?.owner?.name || '--'}</p>
</td>
<td className="tableBody-cell">
<p>
{getUsagePercentile(
database.usageSummary.weeklyStats.percentileRank
)}
</td>
<td className="tableBody-cell">
<p>{database?.owner?.name || '--'}</p>
</td>
<td className="tableBody-cell">
<p>
{getUsagePercentile(
database.usageSummary.weeklyStats.percentileRank
)}
</p>
</td>
</tr>
))}
</tbody>
</table>
</div>
<NextPrevious paging={paging} pagingHandler={pagingHandler} />
</>
) : (
<h1 className="tw-text-center tw-mt-60 tw-text-grey-body tw-font-normal">
{serviceFQN} does not have any databases
</h1>
</p>
</td>
</tr>
))
) : (
<tr className="tableBody-row">
<td className="tableBody-cell tw-text-center" colSpan={4}>
No records found.
</td>
</tr>
)}
</tbody>
</table>
</div>
{Boolean(!isNull(paging.after) || !isNull(paging.before)) && (
<NextPrevious paging={paging} pagingHandler={pagingHandler} />
)}
</div>
</PageContainer>

View File

@ -38,7 +38,7 @@ import {
} from '../../components/Modals/AddServiceModal/AddServiceModal';
import { getServiceDetailsPath } from '../../constants/constants';
import { NOSERVICE, PLUS } from '../../constants/services.const';
import { serviceTypeLogo } from '../../utils/ServiceUtils';
import { getFrequencyTime, serviceTypeLogo } from '../../utils/ServiceUtils';
import SVGIcons from '../../utils/SvgUtils';
export type ApiData = {
@ -218,6 +218,22 @@ const ServicesPage = () => {
<span className="tw-tag tw-ml-3">mysql</span>
<span className="tw-tag tw-ml-2">sales</span>
</div> */}
<div className="tw-mb-1">
<label className="tw-mb-0">Driver Class:</label>
<span className=" tw-ml-1 tw-font-normal tw-text-grey-body">
{service.driverClass}
</span>
</div>
<div className="tw-mb-1">
<label className="tw-mb-0">Frequency:</label>
<span className=" tw-ml-1 tw-font-normal tw-text-grey-body">
{service.ingestionSchedule
? getFrequencyTime(
service.ingestionSchedule.repeatFrequency
)
: 'N/A'}
</span>
</div>
<div className="">
<label className="tw-mb-0">Type:</label>
<span className=" tw-ml-1 tw-font-normal tw-text-grey-body">

View File

@ -47,6 +47,30 @@ export const serviceTypeLogo = (type: string) => {
}
};
export const fromISOString = (isoValue = '') => {
if (isoValue) {
// 'P1DT 0H 0M'
const [d, hm] = isoValue.split('T');
const day = +d.replace('D', '').replace('P', '');
const [h, time] = hm.split('H');
const minute = +time.replace('M', '');
return { day, hour: +h, minute };
} else {
return {
day: 1,
hour: 0,
minute: 0,
};
}
};
export const getFrequencyTime = (isoDate: string): string => {
const { day, hour, minute } = fromISOString(isoDate);
return `${day}D-${hour}H-${minute}M`;
};
const getAllServiceList = (
allServiceCollectionArr: Array<ServiceCollection>
): Promise<Array<ServiceDataObj>> => {