Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#2292]feat(fileset): add web ui support for fileset catalog #2721

Merged
merged 4 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class CatalogsPageTest extends AbstractWebIT {

private static final String metalakeName = "metalake_name";
String catalogName = "catalog_name";
String catalogType = "relational";
String modifiedCatalogName = catalogName + "_edited";
String schemaName = "default";
String tableName = "employee";
Expand Down Expand Up @@ -124,21 +125,22 @@ public void testEditCatalog() throws InterruptedException {
@Test
@Order(6)
public void testClickCatalogLink() {
catalogsPage.clickCatalogLink(metalakeName, modifiedCatalogName);
catalogsPage.clickCatalogLink(metalakeName, modifiedCatalogName, catalogType);
Assertions.assertTrue(catalogsPage.verifyShowTableTitle("Schemas"));
}

@Test
@Order(7)
public void testClickSchemaLink() {
catalogsPage.clickSchemaLink(metalakeName, modifiedCatalogName, schemaName);
catalogsPage.clickSchemaLink(metalakeName, modifiedCatalogName, catalogType, schemaName);
Assertions.assertTrue(catalogsPage.verifyShowTableTitle("Tables"));
}

@Test
@Order(8)
public void testClickTableLink() {
catalogsPage.clickTableLink(metalakeName, modifiedCatalogName, schemaName, tableName);
catalogsPage.clickTableLink(
metalakeName, modifiedCatalogName, catalogType, schemaName, tableName);
Assertions.assertTrue(catalogsPage.verifyShowTableTitle("Columns"));
Assertions.assertTrue(catalogsPage.verifyTableColumns());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,16 @@ public void clickDeleteCatalogBtn(String name) {
}
}

public void clickCatalogLink(String metalakeName, String catalogName) {
public void clickCatalogLink(String metalakeName, String catalogName, String catalogType) {
try {
String xpath = "//a[@href='?metalake=" + metalakeName + "&catalog=" + catalogName + "']";
String xpath =
"//a[@href='?metalake="
+ metalakeName
+ "&catalog="
+ catalogName
+ "&type="
+ catalogType
+ "']";
WebElement link = tableGrid.findElement(By.xpath(xpath));
WebDriverWait wait = new WebDriverWait(driver, MAX_TIMEOUT);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath(xpath)));
Expand All @@ -186,13 +193,16 @@ public void clickCatalogLink(String metalakeName, String catalogName) {
}
}

public void clickSchemaLink(String metalakeName, String catalogName, String schemaName) {
public void clickSchemaLink(
String metalakeName, String catalogName, String catalogType, String schemaName) {
try {
String xpath =
"//a[@href='?metalake="
+ metalakeName
+ "&catalog="
+ catalogName
+ "&type="
+ catalogType
+ "&schema="
+ schemaName
+ "']";
Expand All @@ -206,13 +216,19 @@ public void clickSchemaLink(String metalakeName, String catalogName, String sche
}

public void clickTableLink(
String metalakeName, String catalogName, String schemaName, String tableName) {
String metalakeName,
String catalogName,
String catalogType,
String schemaName,
String tableName) {
try {
String xpath =
"//a[@href='?metalake="
+ metalakeName
+ "&catalog="
+ catalogName
+ "&type="
+ catalogType
+ "&schema="
+ schemaName
+ "&table="
Expand Down
22 changes: 21 additions & 1 deletion web/src/app/metalakes/metalake/MetalakeTree.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ import {
removeExpandedNode,
setSelectedNodes,
setLoadedNodes,
getTableDetails
getTableDetails,
getFilesetDetails
} from '@/lib/store/metalakes'

import { extractPlaceholder } from '@/lib/utils'
Expand All @@ -47,6 +48,12 @@ const MetalakeTree = props => {
const [metalake, catalog, schema, table] = pathArr
dispatch(getTableDetails({ init: true, metalake, catalog, schema, table }))
}
} else if (nodeProps.data.node === 'fileset') {
if (store.selectedNodes.includes(nodeProps.data.key)) {
const pathArr = extractPlaceholder(nodeProps.data.key)
const [metalake, catalog, schema, fileset] = pathArr
dispatch(getFilesetDetails({ init: true, metalake, catalog, schema, fileset }))
}
} else {
dispatch(setIntoTreeNodeWithFetch({ key: nodeProps.data.key }))
}
Expand Down Expand Up @@ -143,6 +150,19 @@ const MetalakeTree = props => {
<Icon icon={isHover !== nodeProps.data.key ? 'bx:table' : 'mdi:reload'} fontSize='inherit' />
</IconButton>
)
case 'fileset':
return (
<IconButton
disableRipple={!store.selectedNodes.includes(nodeProps.data.key)}
size='small'
sx={{ color: '#666' }}
onClick={e => handleClickIcon(e, nodeProps)}
onMouseEnter={e => onMouseEnter(e, nodeProps)}
onMouseLeave={e => onMouseLeave(e, nodeProps)}
>
<Icon icon={isHover !== nodeProps.data.key ? 'bx:file' : 'mdi:reload'} fontSize='inherit' />
</IconButton>
)

default:
return <></>
Expand Down
34 changes: 24 additions & 10 deletions web/src/app/metalakes/metalake/MetalakeView.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ import {
fetchCatalogs,
fetchSchemas,
fetchTables,
fetchFilesets,
getMetalakeDetails,
getCatalogDetails,
getSchemaDetails,
getTableDetails,
getFilesetDetails,
setSelectedNodes
} from '@/lib/store/metalakes'

Expand All @@ -35,39 +37,51 @@ const MetalakeView = () => {
const routeParams = {
metalake: searchParams.get('metalake'),
catalog: searchParams.get('catalog'),
type: searchParams.get('type'),
schema: searchParams.get('schema'),
table: searchParams.get('table')
table: searchParams.get('table'),
fileset: searchParams.get('fileset')
}
if ([...searchParams.keys()].length) {
const { metalake, catalog, schema, table } = routeParams
const { metalake, catalog, type, schema, table, fileset } = routeParams

if (paramsSize === 1 && metalake) {
dispatch(fetchCatalogs({ init: true, page: 'metalakes', metalake }))
dispatch(getMetalakeDetails({ metalake }))
}

if (paramsSize === 2 && catalog) {
dispatch(fetchSchemas({ init: true, page: 'catalogs', metalake, catalog }))
dispatch(getCatalogDetails({ metalake, catalog }))
if (paramsSize === 3 && catalog) {
dispatch(fetchSchemas({ init: true, page: 'catalogs', metalake, catalog, type }))
dispatch(getCatalogDetails({ metalake, catalog, type }))
}

if (paramsSize === 3 && catalog && schema) {
dispatch(fetchTables({ init: true, page: 'schemas', metalake, catalog, schema }))
if (paramsSize === 4 && catalog && type && schema) {
if (type === 'fileset') {
dispatch(fetchFilesets({ init: true, page: 'schemas', metalake, catalog, schema }))
} else {
dispatch(fetchTables({ init: true, page: 'schemas', metalake, catalog, schema }))
}
dispatch(getSchemaDetails({ metalake, catalog, schema }))
}

if (paramsSize === 4 && catalog && schema && table) {
if (paramsSize === 5 && catalog && schema && table) {
dispatch(getTableDetails({ init: true, metalake, catalog, schema, table }))
}

if (paramsSize === 5 && catalog && schema && fileset) {
dispatch(getFilesetDetails({ init: true, metalake, catalog, schema, fileset }))
}
}

dispatch(
setSelectedNodes(
routeParams.catalog
? [
`{{${routeParams.metalake}}}{{${routeParams.catalog}}}${
`{{${routeParams.metalake}}}{{${routeParams.catalog}}}{{${routeParams.type}}}${
routeParams.schema ? `{{${routeParams.schema}}}` : ''
}${routeParams.table ? `{{${routeParams.table}}}` : ''}`
}${routeParams.table ? `{{${routeParams.table}}}` : ''}${
routeParams.fileset ? `{{${routeParams.fileset}}}` : ''
}`
]
: []
)
Expand Down
31 changes: 25 additions & 6 deletions web/src/app/metalakes/metalake/rightContent/CreateCatalogDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import { useSearchParams } from 'next/navigation'
const defaultValues = {
name: '',
type: 'relational',
provider: 'hive',
provider: '',
comment: '',
propItems: providers[0].defaultProps
}
Expand All @@ -58,7 +58,7 @@ const schema = yup.object().shape({
nameRegex,
'This field must start with a letter or underscore, and can only contain letters, numbers, and underscores'
),
type: yup.mixed().oneOf(['relational']).required(),
type: yup.mixed().oneOf(['relational', 'fileset']).required(),
provider: yup.mixed().oneOf(providerTypeValues).required(),
propItems: yup.array().of(
yup.object().shape({
Expand Down Expand Up @@ -87,6 +87,8 @@ const CreateCatalogDialog = props => {

const [cacheData, setCacheData] = useState()

const [providerTypes, setProviderTypes] = useState(providers)

const {
control,
reset,
Expand All @@ -103,6 +105,7 @@ const CreateCatalogDialog = props => {
})

const providerSelect = watch('provider')
const typeSelect = watch('type')

const handleFormChange = ({ index, event }) => {
let data = [...innerProps]
Expand Down Expand Up @@ -280,6 +283,18 @@ const CreateCatalogDialog = props => {
console.error('fields error', errors)
}

useEffect(() => {
if (typeSelect === 'fileset') {
setProviderTypes(providers.filter(p => p.value === 'hadoop'))
setValue('provider', 'hadoop')
} else {
setProviderTypes(providers.filter(p => p.value !== 'hadoop'))
setValue('provider', 'hive')
}

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [typeSelect, open])

useEffect(() => {
let defaultProps = []

Expand Down Expand Up @@ -410,6 +425,7 @@ const CreateCatalogDialog = props => {
disabled={type === 'update'}
>
<MenuItem value={'relational'}>relational</MenuItem>
<MenuItem value={'fileset'}>fileset</MenuItem>
</Select>
)}
/>
Expand All @@ -436,10 +452,13 @@ const CreateCatalogDialog = props => {
labelId='select-catalog-provider'
disabled={type === 'update'}
>
<MenuItem value={'hive'}>hive</MenuItem>
<MenuItem value={'lakehouse-iceberg'}>iceberg</MenuItem>
<MenuItem value={'jdbc-mysql'}>mysql</MenuItem>
<MenuItem value={'jdbc-postgresql'}>postgresql</MenuItem>
{providerTypes.map(item => {
return (
<MenuItem key={item.label} value={item.value}>
{item.label}
</MenuItem>
)
})}
</Select>
)}
/>
Expand Down
26 changes: 21 additions & 5 deletions web/src/app/metalakes/metalake/rightContent/MetalakePath.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,19 @@ const MetalakePath = props => {
const routeParams = {
metalake: searchParams.get('metalake'),
catalog: searchParams.get('catalog'),
type: searchParams.get('type'),
schema: searchParams.get('schema'),
table: searchParams.get('table')
table: searchParams.get('table'),
fileset: searchParams.get('fileset')
}

const { metalake, catalog, schema, table } = routeParams
const { metalake, catalog, type, schema, table, fileset } = routeParams

const metalakeUrl = `?metalake=${metalake}`
const catalogUrl = `?metalake=${metalake}&catalog=${catalog}`
const schemaUrl = `?metalake=${metalake}&catalog=${catalog}&schema=${schema}`
const tableUrl = `?metalake=${metalake}&catalog=${catalog}&schema=${schema}&table=${table}`
const catalogUrl = `?metalake=${metalake}&catalog=${catalog}&type=${type}`
const schemaUrl = `?metalake=${metalake}&catalog=${catalog}&type=${type}&schema=${schema}`
const tableUrl = `?metalake=${metalake}&catalog=${catalog}&type=${type}&schema=${schema}&table=${table}`
const filesetUrl = `?metalake=${metalake}&catalog=${catalog}&type=${type}&schema=${schema}&fileset=${fileset}`

const handleClick = (event, path) => {
path === `?${searchParams.toString()}` && event.preventDefault()
Expand Down Expand Up @@ -91,6 +94,19 @@ const MetalakePath = props => {
</MUILink>
</Tooltip>
)}
{fileset && (
<Tooltip title={fileset} placement='top'>
<MUILink
component={Link}
href={filesetUrl}
onClick={event => handleClick(event, filesetUrl)}
underline='hover'
>
<Icon icon='bx:file' fontSize={20} />
<Text>{fileset}</Text>
</MUILink>
</Tooltip>
)}
</Breadcrumbs>
)
}
Expand Down
Loading
Loading