Skip to content

Commit

Permalink
[apache#1208] feat(web): add catalog management via api (apache#1718)
Browse files Browse the repository at this point in the history
  • Loading branch information
ch3yne and jerryshao committed Jan 29, 2024
1 parent fac45b6 commit 652a567
Show file tree
Hide file tree
Showing 7 changed files with 492 additions and 39 deletions.
77 changes: 65 additions & 12 deletions web/app/ui/metalakes/CreateCatalogDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ import {
import Icon from '@/components/Icon'

import { useAppDispatch } from '@/lib/hooks/useStore'
import { createCatalog } from '@/lib/store/metalakes'
import { createCatalog, updateCatalog } from '@/lib/store/metalakes'

import * as yup from 'yup'
import { useForm, Controller } from 'react-hook-form'
import { yupResolver } from '@hookform/resolvers/yup'

import { genUpdates } from '@/lib/utils'
import { providers } from '@/lib/utils/initial'
import { nameRegex, keyRegex } from '@/lib/utils/regex'

Expand Down Expand Up @@ -120,6 +121,17 @@ const CreateCatalogDialog = props => {
}

const addFields = () => {
const duplicateKeys = innerProps
.filter(item => item.key.trim() !== '')
.some(
(item, index, filteredItems) =>
filteredItems.findIndex(otherItem => otherItem !== item && otherItem.key.trim() === item.key.trim()) !== -1
)

if (duplicateKeys) {
return
}

let newField = { key: '', value: '', required: false }

setInnerProps([...innerProps, newField])
Expand Down Expand Up @@ -236,6 +248,12 @@ const CreateCatalogDialog = props => {

if (type === 'create') {
dispatch(createCatalog({ data: catalogData, metalake }))
} else {
const reqData = { updates: genUpdates(cacheData, catalogData) }

if (reqData.updates.length !== 0) {
dispatch(updateCatalog({ metalake, catalog: cacheData.name, data: reqData }))
}
}

handleClose()
Expand All @@ -258,27 +276,58 @@ const CreateCatalogDialog = props => {
defaultProps = providers[providerItemIndex].defaultProps

resetPropsFields(providers, providerItemIndex)
setInnerProps(defaultProps)
setValue('propItems', providers[providerItemIndex].defaultProps)

if (type === 'create') {
setInnerProps(defaultProps)
setValue('propItems', providers[providerItemIndex].defaultProps)
}
}
}, [providerSelect, setInnerProps, setValue])

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

useEffect(() => {
if (open && JSON.stringify(data) !== '{}') {
setCacheData(data)
const { properties = {} } = data

const propsArr = Object.keys(properties).map(item => {
return {
key: item,
value: properties[item]
setCacheData(data)
setValue('name', data.name)
setValue('comment', data.comment)
setValue('type', data.type)
setValue('provider', data.provider)

const providerItem = providers.find(i => i.value === data.provider)
let propsItems = [...providerItem.defaultProps]

propsItems = propsItems.map((it, idx) => {
let propItem = {
...it,
disabled: true
}

const findProp = Object.keys(properties).find(i => i === it.key)

if (findProp) {
propItem.value = properties[findProp]
}

return propItem
})

setInnerProps(propsArr)
for (let item of Object.keys(properties)) {
const findPropIndex = propsItems.findIndex(i => i.key === item)

setValue('name', data.name)
setValue('comment', data.comment)
if (findPropIndex === -1) {
let propItem = {
key: item,
value: properties[item]
}
propsItems.push(propItem)
}
}

setInnerProps(propsItems)
setValue('propItems', propsItems)
}
}, [open, data, setValue])

Expand Down Expand Up @@ -344,6 +393,7 @@ const CreateCatalogDialog = props => {
onChange={onChange}
error={Boolean(errors.type)}
labelId='select-catalog-type'
disabled={type === 'update'}
>
<MenuItem value={'relational'}>relational</MenuItem>
</Select>
Expand All @@ -370,6 +420,7 @@ const CreateCatalogDialog = props => {
onChange={e => handleChangeProvider(onChange, e)}
error={Boolean(errors.provider)}
labelId='select-catalog-provider'
disabled={type === 'update'}
>
<MenuItem value={'hive'}>hive</MenuItem>
<MenuItem value={'lakehouse-iceberg'}>iceberg</MenuItem>
Expand Down Expand Up @@ -425,6 +476,7 @@ const CreateCatalogDialog = props => {
value={item.key}
disabled={item.required}
onChange={event => handleFormChange({ index, event })}
error={item.hasDuplicateKey}
/>
</Box>
<Box>
Expand All @@ -449,6 +501,7 @@ const CreateCatalogDialog = props => {
label='Value'
error={item.required && item.value === ''}
value={item.value}
disabled={item.disabled}
onChange={event => handleFormChange({ index, event })}
/>
)}
Expand Down
176 changes: 176 additions & 0 deletions web/app/ui/metalakes/DetailsDrawer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/*
* Copyright 2024 Datastrato Pvt Ltd.
* This software is licensed under the Apache License version 2.
*/

import { useEffect, useState } from 'react'

import {
Box,
Grid,
Drawer,
IconButton,
Typography,
Table,
TableHead,
TableBody,
TableRow,
TableCell,
TableContainer
} from '@mui/material'

import Icon from '@/components/Icon'

import EmptyText from '@/components/EmptyText'

import { formatToDateTime, isValidDate } from '@/lib/utils/date'

const DetailsDrawer = props => {
const { openDrawer, setOpenDrawer, drawerData = {} } = props

const { audit = {} } = drawerData

const [properties, setProperties] = useState([])

const handleClose = () => {
setOpenDrawer(false)
}

const renderFieldText = (value, linkBreak = false) => {
if (!value) {
return <EmptyText />
}

return (
<Typography sx={{ fontWeight: 500, whiteSpace: linkBreak ? 'pre-wrap' : 'normal' }}>
{isValidDate(value) ? formatToDateTime(value) : value}
</Typography>
)
}

useEffect(() => {
if (drawerData.properties) {
const propsData = Object.keys(drawerData.properties).map(item => {
return {
key: item,
value: drawerData.properties[item]
}
})

setProperties(propsData)
}
}, [drawerData])

return (
<Drawer
open={openDrawer}
anchor='right'
variant='temporary'
onClose={handleClose}
ModalProps={{ keepMounted: true }}
PaperProps={{
sx: {
width: {
xs: 300,
sm: 400
}
}
}}
>
<Box
className={'drawer-header twc-flex twc-items-center twc-justify-between'}
sx={{
p: theme => theme.spacing(3, 4),
borderBottom: theme => `1px solid ${theme.palette.divider}`,
backgroundColor: theme => theme.palette.background.default
}}
>
<Typography variant='h6'>Details</Typography>
<IconButton size='small' onClick={handleClose} sx={{ color: 'text.primary' }}>
<Icon icon='bx:x' fontSize={20} />
</IconButton>
</Box>
<Box sx={{ p: 4 }}>
<Grid item xs={12} sx={{ mb: [0, 5] }}>
<Typography
variant='subtitle1'
className={'twc-py-2 twc-font-semibold twc-text-[1.2rem]'}
sx={{
borderBottom: theme => `1px solid ${theme.palette.divider}`
}}
>
{drawerData.name}
</Typography>
</Grid>

<Grid item xs={12} sx={{ mb: [0, 5] }}>
<Typography variant='body2' sx={{ mb: 2 }}>
Comment
</Typography>
{renderFieldText(drawerData.comment, true)}
</Grid>

<Grid item xs={12} sx={{ mb: [0, 5] }}>
<Typography variant='body2' sx={{ mb: 2 }}>
Created by
</Typography>
{renderFieldText(audit.creator)}
</Grid>

<Grid item xs={12} sx={{ mb: [0, 5] }}>
<Typography variant='body2' sx={{ mb: 2 }}>
Created at
</Typography>
{renderFieldText(audit.createTime)}
</Grid>

<Grid item xs={12} sx={{ mb: [0, 5] }}>
<Typography variant='body2' sx={{ mb: 2 }}>
Last modified by
</Typography>
{renderFieldText(audit.lastModifier)}
</Grid>

<Grid item xs={12} sx={{ mb: [0, 5] }}>
<Typography variant='body2' sx={{ mb: 2 }}>
Last modified at
</Typography>
{renderFieldText(audit.lastModifiedTime)}
</Grid>

<Grid item xs={12} sx={{ mb: [0, 5] }}>
<Typography variant='body2' sx={{ mb: 2 }}>
Properties
</Typography>

<TableContainer>
<Table>
<TableHead
sx={{
backgroundColor: theme => theme.palette.action.hover
}}
>
<TableRow>
<TableCell sx={{ py: 2 }}>Key</TableCell>
<TableCell sx={{ py: 2 }}>Value</TableCell>
</TableRow>
</TableHead>
<TableBody>
{properties.map((item, index) => {
return (
<TableRow key={index}>
<TableCell className={'twc-py-[0.7rem]'}>{item.key}</TableCell>
<TableCell className={'twc-py-[0.7rem]'}>{item.value}</TableCell>
</TableRow>
)
})}
</TableBody>
</Table>
</TableContainer>
</Grid>
</Box>
</Drawer>
)
}

export default DetailsDrawer
2 changes: 1 addition & 1 deletion web/app/ui/metalakes/RightContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const RightContent = props => {
</Box>

<Box sx={{ height: 'calc(100% - 4rem)' }}>
<TabsContent tableTitle={tableTitle} store={store} page={page} />
<TabsContent tableTitle={tableTitle} store={store} page={page} routeParams={routeParams} />
</Box>
</Box>
)
Expand Down
Loading

0 comments on commit 652a567

Please sign in to comment.