mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-13 16:46:59 +00:00
added sample data support to show sample data on dataset details page. (#274)
* added sample data support to show sample data on dataset details page. * addressing review comment * minor fix * minor fix
This commit is contained in:
parent
6ba87a5297
commit
a049ec9a4f
@ -15,52 +15,36 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { lowerCase } from 'lodash';
|
||||||
import React, { FunctionComponent } from 'react';
|
import React, { FunctionComponent } from 'react';
|
||||||
import { isEven } from '../../utils/CommonUtils';
|
import { isEven } from '../../utils/CommonUtils';
|
||||||
|
type Columns = { name: string; dataType: string };
|
||||||
// type Column = {
|
|
||||||
// columnConstraint?: string;
|
|
||||||
// columnDataType: string;
|
|
||||||
// description: string;
|
|
||||||
// name: string;
|
|
||||||
// ordinalPosition: number;
|
|
||||||
// piiTags?: Array<string>;
|
|
||||||
// };
|
|
||||||
|
|
||||||
type MockColumn = {
|
|
||||||
columnId: number;
|
|
||||||
name: string;
|
|
||||||
columnDataType: string;
|
|
||||||
description?: string;
|
|
||||||
selected?: boolean;
|
|
||||||
piiTags?: Array<string>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
columns: Array<MockColumn>;
|
sampleData: {
|
||||||
data: Array<Record<string, string>>;
|
columns: Array<Columns>;
|
||||||
|
rows: Array<Array<string>>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const SampleDataTable: FunctionComponent<Props> = ({
|
const SampleDataTable: FunctionComponent<Props> = ({ sampleData }: Props) => {
|
||||||
columns,
|
|
||||||
data,
|
|
||||||
}: Props) => {
|
|
||||||
return (
|
return (
|
||||||
<div className="tw-table-responsive">
|
<div className="tw-table-responsive">
|
||||||
<table
|
<table
|
||||||
className="tw-min-w-max tw-w-full tw-table-auto"
|
className="tw-min-w-max tw-w-full tw-table-auto"
|
||||||
data-testid="sample-data-table">
|
data-testid="sample-data-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr className="tw-border tw-border-main tw-bg-gray-200 tw-text-gray-600 tw-text-sm tw-leading-normal">
|
<tr className="tableHead-row">
|
||||||
{columns.map((column) => {
|
{sampleData.columns.map((column) => {
|
||||||
return (
|
return (
|
||||||
<th
|
<th
|
||||||
className="tw-py-3 tw-px-6 tw-text-left tw-whitespace-nowrap"
|
className="tableHead-cell"
|
||||||
data-testid="column-name"
|
data-testid="column-name"
|
||||||
key={column.columnId}>
|
key={column.name}>
|
||||||
<p className="tw-mb-2">{column.name}</p>
|
{column.name}
|
||||||
<span className={'sl-label ' + column.columnDataType}>
|
<span className="tw-py-0.5 tw-px-1 tw-ml-1 tw-rounded tw-text-grey-muted">
|
||||||
{column.columnDataType}
|
({lowerCase(column.dataType)})
|
||||||
</span>
|
</span>
|
||||||
</th>
|
</th>
|
||||||
);
|
);
|
||||||
@ -68,21 +52,22 @@ const SampleDataTable: FunctionComponent<Props> = ({
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="tw-text-gray-600 tw-text-sm">
|
<tbody className="tw-text-gray-600 tw-text-sm">
|
||||||
{data.map((row, rowIndex) => {
|
{sampleData.rows.map((row, rowIndex) => {
|
||||||
return (
|
return (
|
||||||
<tr
|
<tr
|
||||||
className={`tw-border tw-border-main tableBody-row ${
|
className={classNames(
|
||||||
!isEven(rowIndex + 1) && 'odd-row'
|
'tableBody-row',
|
||||||
}`}
|
!isEven(rowIndex + 1) ? 'odd-row' : null
|
||||||
|
)}
|
||||||
data-testid="row"
|
data-testid="row"
|
||||||
key={rowIndex}>
|
key={rowIndex}>
|
||||||
{columns.map((column) => {
|
{row.map((data) => {
|
||||||
return (
|
return (
|
||||||
<td
|
<td
|
||||||
className="tw-py-3 tw-px-6 tw-text-left"
|
className="tableBody-cell"
|
||||||
data-testid="cell"
|
data-testid="cell"
|
||||||
key={column.columnId}>
|
key={data}>
|
||||||
{row[column.name]}
|
{data}
|
||||||
</td>
|
</td>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@ -16,9 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { lowerCase } from 'lodash';
|
import { lowerCase } from 'lodash';
|
||||||
import { ColumnJoins, MockColumn, TableColumn } from 'Models';
|
import { ColumnJoins, SampleData, TableColumn } from 'Models';
|
||||||
import React, { FunctionComponent, useEffect, useState } from 'react';
|
import React, { FunctionComponent, useState } from 'react';
|
||||||
import { fetchData } from '../../pages/my-data-details/index.mock';
|
|
||||||
import Searchbar from '../common/searchbar/Searchbar';
|
import Searchbar from '../common/searchbar/Searchbar';
|
||||||
import SampleDataTable from './SampleDataTable';
|
import SampleDataTable from './SampleDataTable';
|
||||||
import SchemaTable from './SchemaTable';
|
import SchemaTable from './SchemaTable';
|
||||||
@ -27,55 +26,69 @@ type Props = {
|
|||||||
columns: Array<TableColumn>;
|
columns: Array<TableColumn>;
|
||||||
joins: Array<ColumnJoins>;
|
joins: Array<ColumnJoins>;
|
||||||
onUpdate: (columns: Array<TableColumn>) => void;
|
onUpdate: (columns: Array<TableColumn>) => void;
|
||||||
|
sampleData: SampleData;
|
||||||
};
|
};
|
||||||
|
|
||||||
const SchemaTab: FunctionComponent<Props> = ({
|
const SchemaTab: FunctionComponent<Props> = ({
|
||||||
columns,
|
columns,
|
||||||
joins,
|
joins,
|
||||||
onUpdate,
|
onUpdate,
|
||||||
|
sampleData,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const [data, setData] = useState<Array<Record<string, string>>>([]);
|
|
||||||
const [searchText, setSearchText] = useState('');
|
const [searchText, setSearchText] = useState('');
|
||||||
const [checkedValue] = useState('schema');
|
const [checkedValue, setCheckedValue] = useState('schema');
|
||||||
const [mockColumns, setMockColumns] = useState<Array<MockColumn>>([]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const schemaDetails = fetchData();
|
|
||||||
setData(schemaDetails.data);
|
|
||||||
// TODO remove this to show actual columns from tables api
|
|
||||||
setMockColumns(schemaDetails.columns);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleSearchAction = (searchValue: string) => {
|
const handleSearchAction = (searchValue: string) => {
|
||||||
setSearchText(searchValue);
|
setSearchText(searchValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
// const handleToggleChange = (value: string) => {
|
const handleToggleChange = (value: string) => {
|
||||||
// setCheckedValue(value);
|
setCheckedValue(value);
|
||||||
// };
|
};
|
||||||
|
|
||||||
// const getToggleButtonClasses = (type: string): string => {
|
const getToggleButtonClasses = (type: string): string => {
|
||||||
// return (
|
return (
|
||||||
// 'tw-flex-1 tw-text-primary tw-font-medium tw-border tw-border-transparent
|
'tw-flex-1 tw-text-primary tw-font-medium tw-border tw-border-transparent tw-rounded tw-py-1 tw-px-2 focus:tw-outline-none' +
|
||||||
// tw-rounded-md tw-py-1 tw-px-2 focus:tw-outline-none' +
|
(type === checkedValue ? ' tw-bg-primary-hover-lite tw-border-main' : '')
|
||||||
// (type === checkedValue ? ' tw-bg-blue-100 tw-border-blue-100' : '')
|
);
|
||||||
// );
|
};
|
||||||
// };
|
|
||||||
|
const getSampleDataWithType = () => {
|
||||||
|
const updatedColumns = sampleData.columns.map((column) => {
|
||||||
|
const matchedColumn = columns.find((col) => col.name === column);
|
||||||
|
|
||||||
|
if (matchedColumn) {
|
||||||
|
return {
|
||||||
|
name: matchedColumn.name,
|
||||||
|
dataType: matchedColumn.columnDataType,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
name: column,
|
||||||
|
dataType: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return { columns: updatedColumns, rows: sampleData.rows };
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="tw-grid tw-grid-cols-3 tw-gap-x-2">
|
<div className="tw-grid tw-grid-cols-3 tw-gap-x-2">
|
||||||
<div>
|
<div>
|
||||||
<Searchbar
|
{checkedValue === 'schema' && (
|
||||||
placeholder="Find in table..."
|
<Searchbar
|
||||||
searchValue={searchText}
|
placeholder="Find in table..."
|
||||||
typingInterval={1500}
|
searchValue={searchText}
|
||||||
onSearch={handleSearchAction}
|
typingInterval={1500}
|
||||||
/>
|
onSearch={handleSearchAction}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{/* <div className="tw-col-span-2 tw-text-right">
|
<div className="tw-col-span-2 tw-text-right tw-mb-4">
|
||||||
<div
|
<div
|
||||||
className="tw-w-60 tw-inline-flex tw-border tw-border-blue-100
|
className="tw-w-60 tw-inline-flex tw-border tw-border-main
|
||||||
tw-text-sm tw-rounded-md tw-h-8 tw-bg-white">
|
tw-text-sm tw-rounded-md tw-h-8 tw-bg-white">
|
||||||
<button
|
<button
|
||||||
className={getToggleButtonClasses('schema')}
|
className={getToggleButtonClasses('schema')}
|
||||||
@ -86,11 +99,13 @@ const SchemaTab: FunctionComponent<Props> = ({
|
|||||||
<button
|
<button
|
||||||
className={getToggleButtonClasses('sample-data')}
|
className={getToggleButtonClasses('sample-data')}
|
||||||
data-testid="sample-data-button"
|
data-testid="sample-data-button"
|
||||||
onClick={() => handleToggleChange('sample-data')}>
|
onClick={() => {
|
||||||
|
handleToggleChange('sample-data');
|
||||||
|
}}>
|
||||||
Sample Data
|
Sample Data
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div> */}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-sm-12">
|
<div className="col-sm-12">
|
||||||
@ -102,20 +117,7 @@ const SchemaTab: FunctionComponent<Props> = ({
|
|||||||
onUpdate={onUpdate}
|
onUpdate={onUpdate}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<SampleDataTable
|
<SampleDataTable sampleData={getSampleDataWithType()} />
|
||||||
columns={mockColumns
|
|
||||||
.filter((column) => {
|
|
||||||
return column;
|
|
||||||
})
|
|
||||||
.map((column) => {
|
|
||||||
return {
|
|
||||||
columnId: column.columnId,
|
|
||||||
name: column.name,
|
|
||||||
columnDataType: column.columnDataType,
|
|
||||||
};
|
|
||||||
})}
|
|
||||||
data={data}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -231,177 +231,182 @@ const SchemaTable: FunctionComponent<Props> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<table className="tw-w-full" data-testid="schema-table">
|
<div className="tw-table-responsive">
|
||||||
<thead>
|
<table className="tw-w-full" data-testid="schema-table">
|
||||||
<tr className="tableHead-row">
|
<thead>
|
||||||
<th className="tableHead-cell">Column Name</th>
|
<tr className="tableHead-row">
|
||||||
<th className="tableHead-cell">Data Type</th>
|
<th className="tableHead-cell">Column Name</th>
|
||||||
<th className="tableHead-cell">Description</th>
|
<th className="tableHead-cell">Data Type</th>
|
||||||
<th className="tableHead-cell tw-w-60">Tags</th>
|
<th className="tableHead-cell">Description</th>
|
||||||
</tr>
|
<th className="tableHead-cell tw-w-60">Tags</th>
|
||||||
</thead>
|
</tr>
|
||||||
<tbody className="tableBody">
|
</thead>
|
||||||
{searchedColumns.map((column, index) => {
|
<tbody className="tableBody">
|
||||||
return (
|
{searchedColumns.map((column, index) => {
|
||||||
<tr
|
return (
|
||||||
className={classNames(
|
<tr
|
||||||
'tableBody-row',
|
className={classNames(
|
||||||
!isEven(index + 1) ? 'odd-row' : null
|
'tableBody-row',
|
||||||
)}
|
!isEven(index + 1) ? 'odd-row' : null
|
||||||
data-testid="column"
|
)}
|
||||||
id={column.name}
|
data-testid="column"
|
||||||
key={index}
|
id={column.name}
|
||||||
ref={rowRef}>
|
key={index}
|
||||||
<td className="tw-relative tableBody-cell">
|
ref={rowRef}>
|
||||||
{getConstraintIcon(column.columnConstraint)}
|
<td className="tw-relative tableBody-cell">
|
||||||
<span>{column.name}</span>
|
{getConstraintIcon(column.columnConstraint)}
|
||||||
</td>
|
<span>{column.name}</span>
|
||||||
|
</td>
|
||||||
|
|
||||||
<td className="tableBody-cell">
|
<td className="tableBody-cell">
|
||||||
<span>
|
<span>
|
||||||
{column.columnDataType
|
{column.columnDataType
|
||||||
? lowerCase(getDataTypeString(column.columnDataType))
|
? lowerCase(getDataTypeString(column.columnDataType))
|
||||||
: ''}
|
: ''}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className="tw-group tableBody-cell tw-relative">
|
<td className="tw-group tableBody-cell tw-relative">
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
className="tw-cursor-pointer hover:tw-underline tw-flex"
|
className="tw-cursor-pointer hover:tw-underline tw-flex"
|
||||||
data-testid="description"
|
data-testid="description"
|
||||||
id={`column-description-${index}`}
|
id={`column-description-${index}`}
|
||||||
onClick={() => handleEditColumn(column, index)}>
|
onClick={() => handleEditColumn(column, index)}>
|
||||||
<div>
|
<div>
|
||||||
{column.description ? (
|
{column.description ? (
|
||||||
<RichTextEditorPreviewer
|
<RichTextEditorPreviewer
|
||||||
markdown={column.description}
|
markdown={column.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"
|
||||||
|
icon="icon-edit"
|
||||||
|
title="edit"
|
||||||
|
width="10px"
|
||||||
/>
|
/>
|
||||||
) : (
|
</button>
|
||||||
<span className="tw-no-description">
|
</div>
|
||||||
No description added
|
|
||||||
|
{checkIfJoinsAvailable(column.name) && (
|
||||||
|
<div className="tw-mt-3">
|
||||||
|
<span className="tw-text-gray-400 tw-mr-1">
|
||||||
|
Frequently joined columns:
|
||||||
</span>
|
</span>
|
||||||
)}
|
{getFrequentlyJoinedWithColumns(column.name)
|
||||||
</div>
|
.slice(0, 3)
|
||||||
<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">
|
.map((columnJoin, index) => (
|
||||||
<SVGIcons
|
<Fragment key={index}>
|
||||||
alt="edit"
|
{index > 0 && (
|
||||||
icon="icon-edit"
|
<span className="tw-mr-1">,</span>
|
||||||
title="edit"
|
)}
|
||||||
width="10px"
|
<Link
|
||||||
/>
|
className="link-text"
|
||||||
</button>
|
to={getDatasetDetailsPath(
|
||||||
</div>
|
getTableFQNFromColumnFQN(
|
||||||
{checkIfJoinsAvailable(column.name) && (
|
columnJoin.fullyQualifiedName
|
||||||
<div className="tw-mt-3">
|
),
|
||||||
<span className="tw-text-gray-400 tw-mr-1">
|
getPartialNameFromFQN(
|
||||||
Frequently joined columns:
|
columnJoin.fullyQualifiedName,
|
||||||
</span>
|
['column']
|
||||||
{getFrequentlyJoinedWithColumns(column.name)
|
)
|
||||||
.slice(0, 3)
|
)}
|
||||||
.map((columnJoin, index) => (
|
onClick={handleClick}>
|
||||||
<Fragment key={index}>
|
{getPartialNameFromFQN(
|
||||||
{index > 0 && <span className="tw-mr-1">,</span>}
|
|
||||||
<Link
|
|
||||||
className="link-text"
|
|
||||||
to={getDatasetDetailsPath(
|
|
||||||
getTableFQNFromColumnFQN(
|
|
||||||
columnJoin.fullyQualifiedName
|
|
||||||
),
|
|
||||||
getPartialNameFromFQN(
|
|
||||||
columnJoin.fullyQualifiedName,
|
columnJoin.fullyQualifiedName,
|
||||||
['column']
|
['database', 'table', 'column']
|
||||||
)
|
)}
|
||||||
)}
|
</Link>
|
||||||
onClick={handleClick}>
|
</Fragment>
|
||||||
{getPartialNameFromFQN(
|
))}
|
||||||
columnJoin.fullyQualifiedName,
|
{getFrequentlyJoinedWithColumns(column.name).length >
|
||||||
['database', 'table', 'column']
|
3 && (
|
||||||
)}
|
<PopOver
|
||||||
</Link>
|
html={
|
||||||
</Fragment>
|
<div className="tw-text-left">
|
||||||
))}
|
{getFrequentlyJoinedWithColumns(column.name)
|
||||||
{getFrequentlyJoinedWithColumns(column.name).length >
|
?.slice(3)
|
||||||
3 && (
|
.map((columnJoin, index) => (
|
||||||
<PopOver
|
<Fragment key={index}>
|
||||||
html={
|
<a
|
||||||
<div className="tw-text-left">
|
className="link-text tw-block tw-py-1"
|
||||||
{getFrequentlyJoinedWithColumns(column.name)
|
href={getDatasetDetailsPath(
|
||||||
?.slice(3)
|
getTableFQNFromColumnFQN(
|
||||||
.map((columnJoin, index) => (
|
columnJoin.fullyQualifiedName
|
||||||
<Fragment key={index}>
|
),
|
||||||
<a
|
getPartialNameFromFQN(
|
||||||
className="link-text tw-block tw-py-1"
|
columnJoin.fullyQualifiedName,
|
||||||
href={getDatasetDetailsPath(
|
['column']
|
||||||
getTableFQNFromColumnFQN(
|
)
|
||||||
columnJoin.fullyQualifiedName
|
)}
|
||||||
),
|
onClick={handleClick}>
|
||||||
getPartialNameFromFQN(
|
{getPartialNameFromFQN(
|
||||||
columnJoin.fullyQualifiedName,
|
columnJoin.fullyQualifiedName,
|
||||||
['column']
|
['database', 'table', 'column']
|
||||||
)
|
)}
|
||||||
)}
|
</a>
|
||||||
onClick={handleClick}>
|
</Fragment>
|
||||||
{getPartialNameFromFQN(
|
))}
|
||||||
columnJoin.fullyQualifiedName,
|
</div>
|
||||||
['database', 'table', 'column']
|
}
|
||||||
)}
|
position="bottom"
|
||||||
</a>
|
theme="light"
|
||||||
</Fragment>
|
trigger="click">
|
||||||
))}
|
<span className="show-more tw-ml-1">...</span>
|
||||||
</div>
|
</PopOver>
|
||||||
}
|
)}
|
||||||
position="bottom"
|
</div>
|
||||||
theme="light"
|
)}
|
||||||
trigger="click">
|
</div>
|
||||||
<span className="show-more tw-ml-1">...</span>
|
</td>
|
||||||
</PopOver>
|
<td
|
||||||
)}
|
className="tw-group tw-relative tableBody-cell"
|
||||||
</div>
|
onClick={() => {
|
||||||
)}
|
if (!editColumnTag) {
|
||||||
</div>
|
handleEditColumnTag(column, index);
|
||||||
</td>
|
}
|
||||||
<td
|
|
||||||
className="tw-group tw-relative tableBody-cell"
|
|
||||||
onClick={() => {
|
|
||||||
if (!editColumnTag) {
|
|
||||||
handleEditColumnTag(column, index);
|
|
||||||
}
|
|
||||||
}}>
|
|
||||||
<TagsContainer
|
|
||||||
editable={editColumnTag?.index === index}
|
|
||||||
selectedTags={column.tags}
|
|
||||||
tagList={allTags}
|
|
||||||
onCancel={() => {
|
|
||||||
handleTagSelection();
|
|
||||||
}}
|
|
||||||
onSelectionChange={(tags) => {
|
|
||||||
handleTagSelection(tags);
|
|
||||||
}}>
|
}}>
|
||||||
{column.tags.length ? (
|
<TagsContainer
|
||||||
<button className="tw-opacity-0 tw-ml-1 group-hover:tw-opacity-100 focus:tw-outline-none">
|
editable={editColumnTag?.index === index}
|
||||||
<SVGIcons
|
selectedTags={column.tags}
|
||||||
alt="edit"
|
tagList={allTags}
|
||||||
icon="icon-edit"
|
onCancel={() => {
|
||||||
title="edit"
|
handleTagSelection();
|
||||||
width="10px"
|
}}
|
||||||
/>
|
onSelectionChange={(tags) => {
|
||||||
</button>
|
handleTagSelection(tags);
|
||||||
) : (
|
}}>
|
||||||
<span className="tw-opacity-0 group-hover:tw-opacity-100">
|
{column.tags.length ? (
|
||||||
<Tags
|
<button className="tw-opacity-0 tw-ml-1 group-hover:tw-opacity-100 focus:tw-outline-none">
|
||||||
className="tw-border-main"
|
<SVGIcons
|
||||||
tag="+ Add new tag"
|
alt="edit"
|
||||||
type="outlined"
|
icon="icon-edit"
|
||||||
/>
|
title="edit"
|
||||||
</span>
|
width="10px"
|
||||||
)}
|
/>
|
||||||
</TagsContainer>
|
</button>
|
||||||
</td>
|
) : (
|
||||||
</tr>
|
<span className="tw-opacity-0 group-hover:tw-opacity-100">
|
||||||
);
|
<Tags
|
||||||
})}
|
className="tw-border-main"
|
||||||
</tbody>
|
tag="+ Add new tag"
|
||||||
</table>
|
type="outlined"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</TagsContainer>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
{editColumn && (
|
{editColumn && (
|
||||||
<ModalWithMarkdownEditor
|
<ModalWithMarkdownEditor
|
||||||
header={`Edit column: "${editColumn.column.name}"`}
|
header={`Edit column: "${editColumn.column.name}"`}
|
||||||
|
|||||||
@ -311,4 +311,9 @@ declare module 'Models' {
|
|||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type SampleData = {
|
||||||
|
columns: Array<string>;
|
||||||
|
rows: Array<Array<string>>;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,13 @@ import classNames from 'classnames';
|
|||||||
import { compare } from 'fast-json-patch';
|
import { compare } from 'fast-json-patch';
|
||||||
import { isEqual, isNil } from 'lodash';
|
import { isEqual, isNil } from 'lodash';
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import { ColumnTags, TableColumn, TableDetail, TableJoinsData } from 'Models';
|
import {
|
||||||
|
ColumnTags,
|
||||||
|
SampleData,
|
||||||
|
TableColumn,
|
||||||
|
TableDetail,
|
||||||
|
TableJoinsData,
|
||||||
|
} from 'Models';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { getDatabase } from '../../axiosAPIs/databaseAPI';
|
import { getDatabase } from '../../axiosAPIs/databaseAPI';
|
||||||
@ -89,6 +95,10 @@ const MyDataDetailsPage = () => {
|
|||||||
const [usage, setUsage] = useState('');
|
const [usage, setUsage] = useState('');
|
||||||
const [weeklyUsageCount, setWeeklyUsageCount] = useState('');
|
const [weeklyUsageCount, setWeeklyUsageCount] = useState('');
|
||||||
const [columns, setColumns] = useState<Array<TableColumn>>([]);
|
const [columns, setColumns] = useState<Array<TableColumn>>([]);
|
||||||
|
const [sampleData, setSampleData] = useState<SampleData>({
|
||||||
|
columns: [],
|
||||||
|
rows: [],
|
||||||
|
});
|
||||||
const [tableTags, setTableTags] = useState<Array<ColumnTags>>([]);
|
const [tableTags, setTableTags] = useState<Array<ColumnTags>>([]);
|
||||||
const [isEdit, setIsEdit] = useState(false);
|
const [isEdit, setIsEdit] = useState(false);
|
||||||
const [owner, setOwner] = useState<TableDetail['owner']>();
|
const [owner, setOwner] = useState<TableDetail['owner']>();
|
||||||
@ -108,7 +118,7 @@ const MyDataDetailsPage = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getTableDetailsByFQN(
|
getTableDetailsByFQN(
|
||||||
tableFQN,
|
tableFQN,
|
||||||
'columns, database, usageSummary, followers, joins, tags, owner'
|
'columns, database, usageSummary, followers, joins, tags, owner,sampleData'
|
||||||
).then((res: AxiosResponse) => {
|
).then((res: AxiosResponse) => {
|
||||||
const {
|
const {
|
||||||
description,
|
description,
|
||||||
@ -122,6 +132,7 @@ const MyDataDetailsPage = () => {
|
|||||||
followers,
|
followers,
|
||||||
joins,
|
joins,
|
||||||
tags,
|
tags,
|
||||||
|
sampleData,
|
||||||
} = res.data;
|
} = res.data;
|
||||||
setTableDetails(res.data);
|
setTableDetails(res.data);
|
||||||
setTableId(id);
|
setTableId(id);
|
||||||
@ -162,6 +173,7 @@ const MyDataDetailsPage = () => {
|
|||||||
|
|
||||||
setDescription(description);
|
setDescription(description);
|
||||||
setColumns(columns || []);
|
setColumns(columns || []);
|
||||||
|
setSampleData(sampleData);
|
||||||
setTableTags(getTableTags(columns || []));
|
setTableTags(getTableTags(columns || []));
|
||||||
if (!isNil(usageSummary?.weeklyStats.percentileRank)) {
|
if (!isNil(usageSummary?.weeklyStats.percentileRank)) {
|
||||||
const percentile = getUsagePercentile(
|
const percentile = getUsagePercentile(
|
||||||
@ -529,6 +541,7 @@ const MyDataDetailsPage = () => {
|
|||||||
<SchemaTab
|
<SchemaTab
|
||||||
columns={columns}
|
columns={columns}
|
||||||
joins={tableJoinData.columnJoins}
|
joins={tableJoinData.columnJoins}
|
||||||
|
sampleData={sampleData}
|
||||||
onUpdate={onColumnsUpdate}
|
onUpdate={onColumnsUpdate}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user