Skip to content

Commit

Permalink
[apache#1429] improve(web): add form fields rules (apache#1633)
Browse files Browse the repository at this point in the history
### What changes were proposed in this pull request?

1. Add naming rules to the name field of the metalake
<img width="1036" alt="image"
src="https://github.com/datastrato/gravitino/assets/17310559/5affca7a-5994-4138-9153-18dd181a250b">

2. Optimize the display of the name field
<img width="1036" alt="image"
src="https://github.com/datastrato/gravitino/assets/17310559/0d29e959-2887-49b4-b4df-287aedfc3599">


### Why are the changes needed?

Fix: apache#1429
Fix: apache#1628 
Fix: apache#1629 

### Does this PR introduce _any_ user-facing change?

N/A

### How was this patch tested?

N/A
  • Loading branch information
ch3yne authored Jan 29, 2024
1 parent 3319394 commit 6988fe2
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 40 deletions.
24 changes: 22 additions & 2 deletions web/app/ui/CreateMetalakeDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,21 @@ import { useForm, Controller } from 'react-hook-form'
import { yupResolver } from '@hookform/resolvers/yup'

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

const defaultValues = {
name: '',
comment: ''
}

const schema = yup.object().shape({
name: yup.string().required()
name: yup
.string()
.required()
.matches(
nameRegex,
'This field must start with a letter or underscore, and can only contain letters, numbers, and underscores'
)
})

const Transition = forwardRef(function Transition(props, ref) {
Expand Down Expand Up @@ -75,6 +82,11 @@ const CreateMetalakeDialog = props => {

const duplicateKeys = nonEmptyKeys.some((item, i) => i !== index && item.key === event.target.value)
data[index].hasDuplicateKey = duplicateKeys

if (event.target.name === 'key') {
const invalidKey = !keyRegex.test(event.target.value)
data[index].invalid = invalidKey
}
}

const addFields = () => {
Expand Down Expand Up @@ -114,7 +126,9 @@ const CreateMetalakeDialog = props => {
filteredItems.findIndex(otherItem => otherItem !== item && otherItem.key.trim() === item.key.trim()) !== -1
)

if (duplicateKeys) {
const invalidKeys = innerProps.some(i => i.invalid)

if (duplicateKeys || invalidKeys) {
return
}

Expand Down Expand Up @@ -263,6 +277,12 @@ const CreateMetalakeDialog = props => {
{item.hasDuplicateKey && (
<FormHelperText className={'twc-text-error-main'}>Key already exists</FormHelperText>
)}
{item.invalid && (
<FormHelperText className={'twc-text-error-main'}>
Invalid key, matches strings starting with a letter/underscore, followed by alphanumeric
characters, underscores, hyphens, or dots.
</FormHelperText>
)}
</FormControl>
</Grid>
)
Expand Down
33 changes: 19 additions & 14 deletions web/app/ui/MetalakeList.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useEffect, useCallback, useState } from 'react'

import Link from 'next/link'

import { Box, Grid, Card, IconButton, Typography } from '@mui/material'
import { Box, Grid, Card, IconButton, Typography, Tooltip } from '@mui/material'
import { DataGrid } from '@mui/x-data-grid'

import Icon from '@/components/Icon'
Expand Down Expand Up @@ -88,19 +88,24 @@ const MetalakeList = () => {

return (
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Typography
noWrap
component={Link}
href={`/ui/metalakes?metalake=${name}`}
sx={{
fontWeight: 500,
color: 'primary.main',
textDecoration: 'none',
'&:hover': { color: 'primary.main', textDecoration: 'underline' }
}}
>
{name}
</Typography>
<Tooltip title={name} placement='top'>
<Typography
noWrap
component={Link}
href={`/ui/metalakes?metalake=${name}`}
sx={{
fontWeight: 500,
color: 'primary.main',
textDecoration: 'none',
maxWidth: 240,
overflow: 'hidden',
textOverflow: 'ellipsis',
'&:hover': { color: 'primary.main', textDecoration: 'underline' }
}}
>
{name}
</Typography>
</Tooltip>
</Box>
)
}
Expand Down
26 changes: 23 additions & 3 deletions web/app/ui/metalakes/CreateCatalogDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ import * as yup from 'yup'
import { useForm, Controller } from 'react-hook-form'
import { yupResolver } from '@hookform/resolvers/yup'

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

const defaultValues = {
name: '',
Expand All @@ -48,7 +49,13 @@ const defaultValues = {
const providerTypeValues = providers.map(i => i.value)

const schema = yup.object().shape({
name: yup.string().required(),
name: yup
.string()
.required()
.matches(
nameRegex,
'This field must start with a letter or underscore, and can only contain letters, numbers, and underscores'
),
type: yup.mixed().oneOf(['relational']).required(),
provider: yup.mixed().oneOf(providerTypeValues).required(),
propItems: yup.array().of(
Expand Down Expand Up @@ -106,6 +113,11 @@ const CreateCatalogDialog = props => {

const duplicateKeys = nonEmptyKeys.some((item, i) => i !== index && item.key === event.target.value)
data[index].hasDuplicateKey = duplicateKeys

if (event.target.name === 'key') {
const invalidKey = !keyRegex.test(event.target.value)
data[index].invalid = invalidKey
}
}

const addFields = () => {
Expand Down Expand Up @@ -179,7 +191,9 @@ const CreateCatalogDialog = props => {
filteredItems.findIndex(otherItem => otherItem !== item && otherItem.key.trim() === item.key.trim()) !== -1
)

if (duplicateKeys) {
const invalidKeys = innerProps.some(i => i.invalid)

if (duplicateKeys || invalidKeys) {
return
}

Expand Down Expand Up @@ -515,6 +529,12 @@ const CreateCatalogDialog = props => {
{item.hasDuplicateKey && (
<FormHelperText className={'twc-text-error-main'}>Key already exists</FormHelperText>
)}
{item.invalid && (
<FormHelperText className={'twc-text-error-main'}>
Invalid key, matches strings starting with a letter/underscore, followed by alphanumeric
characters, underscores, hyphens, or dots.
</FormHelperText>
)}
</FormControl>
</Grid>
</Fragment>
Expand Down
55 changes: 34 additions & 21 deletions web/app/ui/metalakes/MetalakePath.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Link from 'next/link'
import { useRouter, useSearchParams } from 'next/navigation'

import { Link as MUILink, Breadcrumbs, Typography, styled } from '@mui/material'
import { Link as MUILink, Breadcrumbs, Typography, Tooltip, styled } from '@mui/material'

import Icon from '@/components/Icon'

Expand Down Expand Up @@ -46,32 +46,45 @@ const MetalakePath = props => {
}}
>
{metalake && (
<MUILink
component={Link}
href={metalakeUrl}
onClick={event => handleClick(event, metalakeUrl)}
underline='hover'
>
{metalake}
</MUILink>
<Tooltip title={metalake} placement='top'>
<MUILink
component={Link}
href={metalakeUrl}
onClick={event => handleClick(event, metalakeUrl)}
underline='hover'
>
<Text>{metalake}</Text>
</MUILink>
</Tooltip>
)}
{catalog && (
<MUILink component={Link} href={catalogUrl} onClick={event => handleClick(event, catalogUrl)} underline='hover'>
<Icon icon='bx:book' fontSize={20} />
<Text title={catalog}>{catalog}</Text>
</MUILink>
<Tooltip title={catalog} placement='top'>
<MUILink
component={Link}
href={catalogUrl}
onClick={event => handleClick(event, catalogUrl)}
underline='hover'
>
<Icon icon='bx:book' fontSize={20} />
<Text>{catalog}</Text>
</MUILink>
</Tooltip>
)}
{schema && (
<MUILink component={Link} href={schemaUrl} onClick={event => handleClick(event, schemaUrl)} underline='hover'>
<Icon icon='bx:coin-stack' fontSize={20} />
<Text title={schema}>{schema}</Text>
</MUILink>
<Tooltip title={schema} placement='top'>
<MUILink component={Link} href={schemaUrl} onClick={event => handleClick(event, schemaUrl)} underline='hover'>
<Icon icon='bx:coin-stack' fontSize={20} />
<Text>{schema}</Text>
</MUILink>
</Tooltip>
)}
{table && (
<MUILink component={Link} href={tableUrl} onClick={event => handleClick(event, tableUrl)} underline='hover'>
<Icon icon='bx:table' fontSize={20} />
<Text title={table}>{table}</Text>
</MUILink>
<Tooltip title={table} placement='top'>
<MUILink component={Link} href={tableUrl} onClick={event => handleClick(event, tableUrl)} underline='hover'>
<Icon icon='bx:table' fontSize={20} />
<Text>{table}</Text>
</MUILink>
</Tooltip>
)}
</Breadcrumbs>
)
Expand Down
8 changes: 8 additions & 0 deletions web/lib/utils/regex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright 2024 Datastrato Pvt Ltd.
* This software is licensed under the Apache License version 2.
*/

export const nameRegex = /^[a-zA-Z_][a-zA-Z0-9_]*$/

export const propKeyRegex = /^[a-zA-Z_][a-zA-Z0-9-_.]*$/

0 comments on commit 6988fe2

Please sign in to comment.