This is an automated email from the ASF dual-hosted git repository.
jshao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new 79c69b7251 [#7106] subtask(web): support update model/model version
for UI (#7107)
79c69b7251 is described below
commit 79c69b72514f9fa1d802285ba8e4c4163b3808a9
Author: Qian Xia <[email protected]>
AuthorDate: Wed Apr 30 12:01:25 2025 +0800
[#7106] subtask(web): support update model/model version for UI (#7107)
### What changes were proposed in this pull request?
update model for UI
update model version for UI
<img width="883" alt="image"
src="https://github.com/user-attachments/assets/1c41a1fe-e991-4d1a-b0b3-ac35ca973304"
/>
<img width="835" alt="image"
src="https://github.com/user-attachments/assets/ea089f22-c39a-4abe-9b28-4db898303946"
/>
### Why are the changes needed?
Fix: #7106
### Does this PR introduce _any_ user-facing change?
N/A
### How was this patch tested?
manually
---
.../metalake/rightContent/LinkVersionDialog.js | 47 +++++++++++++++++++---
.../metalake/rightContent/RegisterModelDialog.js | 24 +++++++++--
.../tabsContent/tableView/TableView.js | 43 +++++++++++++++++++-
web/web/src/lib/api/models/index.js | 12 ++++++
web/web/src/lib/store/metalakes/index.js | 26 +++++++++++-
web/web/src/lib/utils/index.js | 4 ++
6 files changed, 146 insertions(+), 10 deletions(-)
diff --git
a/web/web/src/app/metalakes/metalake/rightContent/LinkVersionDialog.js
b/web/web/src/app/metalakes/metalake/rightContent/LinkVersionDialog.js
index dadb464c4b..83c3127947 100644
--- a/web/web/src/app/metalakes/metalake/rightContent/LinkVersionDialog.js
+++ b/web/web/src/app/metalakes/metalake/rightContent/LinkVersionDialog.js
@@ -40,12 +40,12 @@ import {
import Icon from '@/components/Icon'
import { useAppDispatch } from '@/lib/hooks/useStore'
-import { linkVersion } from '@/lib/store/metalakes'
+import { linkVersion, updateVersion } from '@/lib/store/metalakes'
import * as yup from 'yup'
import { useForm, Controller, useFieldArray } from 'react-hook-form'
import { yupResolver } from '@hookform/resolvers/yup'
-
+import { genUpdates } from '@/lib/utils'
import { groupBy } from 'lodash-es'
import { keyRegex } from '@/lib/utils/regex'
import { useSearchParams } from 'next/navigation'
@@ -224,6 +224,27 @@ const LinkVersionDialog = props => {
handleClose()
}
})
+ } else {
+ const reqData = { updates: genUpdates(cacheData, schemaData) }
+ console.log('reqData', reqData)
+
+ if (reqData.updates.length !== 0) {
+ dispatch(
+ updateVersion({
+ metalake,
+ catalog,
+ type: catalogType,
+ schema: schemaName,
+ model,
+ version: cacheData.version,
+ data: reqData
+ })
+ ).then(res => {
+ if (!res.payload?.err) {
+ handleClose()
+ }
+ })
+ }
}
})
.catch(err => {
@@ -243,6 +264,10 @@ const LinkVersionDialog = props => {
setValue('uri', data.uri)
setValue('comment', data.comment)
+ data.aliases.forEach((alias, index) => {
+ setValue(`aliases.${index}.name`, alias)
+ })
+
const propsItems = Object.entries(properties).map(([key, value]) => {
return {
key,
@@ -292,7 +317,6 @@ const LinkVersionDialog = props => {
label='URI'
onChange={onChange}
placeholder=''
- disabled={type === 'update'}
error={Boolean(errors.uri)}
data-refer='link-uri-field'
/>
@@ -323,6 +347,7 @@ const LinkVersionDialog = props => {
field.onChange(event)
trigger('aliases')
}}
+ disabled={type === 'update'}
label={`Alias ${index + 1}`}
error={!!errors.aliases?.[index]?.name ||
!!errors.aliases?.message}
helperText={errors.aliases?.[index]?.name?.message || errors.aliases?.message}
@@ -334,13 +359,25 @@ const LinkVersionDialog = props => {
<Box>
{index === 0 ? (
<Box sx={{ minWidth: 40 }}>
- <IconButton onClick={() => append({ name: '' })}>
+ <IconButton
+ sx={{ cursor: type === 'update' ?
'not-allowed' : 'pointer' }}
+ onClick={() => {
+ if (type === 'update') return
+ append({ name: '' })
+ }}
+ >
<Icon icon='mdi:plus-circle-outline' />
</IconButton>
</Box>
) : (
<Box sx={{ minWidth: 40 }}>
- <IconButton onClick={() => remove(index)}>
+ <IconButton
+ sx={{ cursor: type === 'update' ?
'not-allowed' : 'pointer' }}
+ onClick={() => {
+ if (type === 'update') return
+ remove(index)
+ }}
+ >
<Icon icon='mdi:minus-circle-outline' />
</IconButton>
</Box>
diff --git
a/web/web/src/app/metalakes/metalake/rightContent/RegisterModelDialog.js
b/web/web/src/app/metalakes/metalake/rightContent/RegisterModelDialog.js
index 68661fa9ba..b9b2800dc7 100644
--- a/web/web/src/app/metalakes/metalake/rightContent/RegisterModelDialog.js
+++ b/web/web/src/app/metalakes/metalake/rightContent/RegisterModelDialog.js
@@ -40,12 +40,12 @@ import {
import Icon from '@/components/Icon'
import { useAppDispatch } from '@/lib/hooks/useStore'
-import { registerModel } from '@/lib/store/metalakes'
+import { registerModel, updateModel } 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 { groupBy } from 'lodash-es'
import { nameRegex, nameRegexDesc, keyRegex } from '@/lib/utils/regex'
import { useSearchParams } from 'next/navigation'
@@ -190,6 +190,25 @@ const RegisterModelDialog = props => {
}
}
)
+ } else {
+ const reqData = { updates: genUpdates(cacheData, schemaData) }
+
+ if (reqData.updates.length !== 0) {
+ dispatch(
+ updateModel({
+ metalake,
+ catalog,
+ type: catalogType,
+ schema: schemaName,
+ model: cacheData.name,
+ data: reqData
+ })
+ ).then(res => {
+ if (!res.payload?.err) {
+ handleClose()
+ }
+ })
+ }
}
})
.catch(err => {
@@ -258,7 +277,6 @@ const RegisterModelDialog = props => {
label='Name'
onChange={onChange}
placeholder=''
- disabled={type === 'update'}
error={Boolean(errors.name)}
data-refer='model-name-field'
/>
diff --git
a/web/web/src/app/metalakes/metalake/rightContent/tabsContent/tableView/TableView.js
b/web/web/src/app/metalakes/metalake/rightContent/tabsContent/tableView/TableView.js
index aca7960b23..bdf8318f3b 100644
---
a/web/web/src/app/metalakes/metalake/rightContent/tabsContent/tableView/TableView.js
+++
b/web/web/src/app/metalakes/metalake/rightContent/tabsContent/tableView/TableView.js
@@ -44,6 +44,8 @@ import CreateSchemaDialog from '../../CreateSchemaDialog'
import CreateFilesetDialog from '../../CreateFilesetDialog'
import CreateTopicDialog from '../../CreateTopicDialog'
import CreateTableDialog from '../../CreateTableDialog'
+import RegisterModelDialog from '../../RegisterModelDialog'
+import LinkVersionDialog from '../../LinkVersionDialog'
import { useAppSelector, useAppDispatch } from '@/lib/hooks/useStore'
import {
@@ -120,6 +122,8 @@ const TableView = () => {
const [openFilesetDialog, setOpenFilesetDialog] = useState(false)
const [openTopicDialog, setOpenTopicDialog] = useState(false)
const [openTableDialog, setOpenTableDialog] = useState(false)
+ const [openModelDialog, setOpenModelDialog] = useState(false)
+ const [openModelVersionDialog, setOpenModelVersionDialog] = useState(false)
const [dialogData, setDialogData] = useState({})
const [dialogType, setDialogType] = useState('create')
const [isHideEdit, setIsHideEdit] = useState(true)
@@ -132,7 +136,7 @@ const TableView = () => {
const isHideAction =
(['lakehouse-hudi', 'kafka'].includes(currentCatalog?.provider) &&
paramsSize == 3) ||
(currentCatalog?.provider === 'lakehouse-hudi' && paramsSize == 4)
- setIsHideEdit(isHideAction || type === 'model')
+ setIsHideEdit(isHideAction)
setIsHideDrop(isHideAction)
}
}, [store.catalogs, store.catalogs.length, paramsSize, catalog, type])
@@ -637,6 +641,34 @@ const TableView = () => {
}
break
}
+ case 'model': {
+ if (metalake && catalog && schema) {
+ const [err, res] = await to(getModelDetailsApi({ metalake, catalog,
schema, model: data.row?.name }))
+ if (err || !res) {
+ throw new Error(err)
+ }
+
+ setDialogType('update')
+ setDialogData(res.model)
+ setOpenModelDialog(true)
+ }
+ break
+ }
+ case 'version': {
+ if (metalake && catalog && schema && model) {
+ const [err, res] = await to(
+ getVersionDetailsApi({ metalake, catalog, schema, model, version:
data.row?.name })
+ )
+ if (err || !res) {
+ throw new Error(err)
+ }
+
+ setDialogType('update')
+ setDialogData(res.modelVersion)
+ setOpenModelVersionDialog(true)
+ }
+ break
+ }
default:
return
}
@@ -779,6 +811,15 @@ const TableView = () => {
<CreateTopicDialog open={openTopicDialog} setOpen={setOpenTopicDialog}
data={dialogData} type={dialogType} />
<CreateTableDialog open={openTableDialog} setOpen={setOpenTableDialog}
data={dialogData} type={dialogType} />
+
+ <RegisterModelDialog open={openModelDialog} setOpen={setOpenModelDialog}
data={dialogData} type={dialogType} />
+
+ <LinkVersionDialog
+ open={openModelVersionDialog}
+ setOpen={setOpenModelVersionDialog}
+ data={dialogData}
+ type={dialogType}
+ />
</Box>
)
}
diff --git a/web/web/src/lib/api/models/index.js
b/web/web/src/lib/api/models/index.js
index 74d2e0d368..435e4806d4 100644
--- a/web/web/src/lib/api/models/index.js
+++ b/web/web/src/lib/api/models/index.js
@@ -46,6 +46,11 @@ const Apis = {
`/api/metalakes/${encodeURIComponent(metalake)}/catalogs/${encodeURIComponent(
catalog
)}/schemas/${encodeURIComponent(schema)}/models/${encodeURIComponent(model)}/versions`,
+ UPDATE_VERSION: ({ metalake, catalog, schema, model, version }) => {
+ return
`/api/metalakes/${encodeURIComponent(metalake)}/catalogs/${encodeURIComponent(
+ catalog
+
)}/schemas/${encodeURIComponent(schema)}/models/${encodeURIComponent(model)}/versions/${version}`
+ },
DELETE_VERSION: ({ metalake, catalog, schema, model, version }) => {
return
`/api/metalakes/${encodeURIComponent(metalake)}/catalogs/${encodeURIComponent(
catalog
@@ -87,6 +92,13 @@ export const linkVersionApi = ({ metalake, catalog, schema,
model, data }) => {
return defHttp.post({ url: `${Apis.LINK_VERSION({ metalake, catalog, schema,
model })}`, data })
}
+export const updateVersionApi = ({ metalake, catalog, schema, model, version,
data }) => {
+ return defHttp.put({
+ url: `${Apis.UPDATE_VERSION({ metalake, catalog, schema, model, version
})}`,
+ data
+ })
+}
+
export const getVersionDetailsApi = ({ metalake, catalog, schema, model,
version }) => {
return defHttp.get({
url: `${Apis.GET_VERSION_DETAIL({ metalake, catalog, schema, model,
version })}`
diff --git a/web/web/src/lib/store/metalakes/index.js
b/web/web/src/lib/store/metalakes/index.js
index 9d4eebc3c9..2862ca96d5 100644
--- a/web/web/src/lib/store/metalakes/index.js
+++ b/web/web/src/lib/store/metalakes/index.js
@@ -64,6 +64,7 @@ import {
getModelVersionsApi,
getVersionDetailsApi,
linkVersionApi,
+ updateVersionApi,
deleteVersionApi
} from '@/lib/api/models'
@@ -1304,7 +1305,7 @@ export const registerModel = createAsyncThunk(
export const updateModel = createAsyncThunk(
'appMetalakes/updateModel',
async ({ metalake, catalog, type, schema, model, data }, { dispatch }) => {
- const [err, res] = await to(updateTopicApi({ metalake, catalog, schema,
model, data }))
+ const [err, res] = await to(updateModelApi({ metalake, catalog, schema,
model, data }))
if (err || !res) {
return { err: true }
}
@@ -1422,6 +1423,19 @@ export const linkVersion = createAsyncThunk(
}
)
+export const updateVersion = createAsyncThunk(
+ 'appMetalakes/updateVersion',
+ async ({ metalake, catalog, type, schema, model, version, data }, { dispatch
}) => {
+ const [err, res] = await to(updateVersionApi({ metalake, catalog, schema,
model, version, data }))
+ if (err || !res) {
+ return { err: true }
+ }
+ dispatch(fetchModelVersions({ metalake, catalog, type, schema, model,
init: true }))
+
+ return res.modelVersion
+ }
+)
+
export const deleteVersion = createAsyncThunk(
'appMetalakes/deleteVersion',
async ({ metalake, catalog, type, schema, model, version }, { dispatch }) =>
{
@@ -1828,6 +1842,16 @@ export const appMetalakesSlice = createSlice({
toast.error(action.error.message)
}
})
+ builder.addCase(updateVersion.rejected, (state, action) => {
+ if (!action.error.message.includes('CanceledError')) {
+ toast.error(action.error.message)
+ }
+ })
+ builder.addCase(deleteVersion.rejected, (state, action) => {
+ if (!action.error.message.includes('CanceledError')) {
+ toast.error(action.error.message)
+ }
+ })
}
})
diff --git a/web/web/src/lib/utils/index.js b/web/web/src/lib/utils/index.js
index 8b41db98a6..2755a8346c 100644
--- a/web/web/src/lib/utils/index.js
+++ b/web/web/src/lib/utils/index.js
@@ -59,6 +59,10 @@ export const genUpdates = (originalData, newData) => {
updates.push({ '@type': 'rename', newName: newData.name })
}
+ if (originalData.uri !== newData.uri) {
+ updates.push({ '@type': 'updateUri', newUri: newData.uri })
+ }
+
if (originalData.comment !== newData.comment) {
updates.push({ '@type': 'updateComment', newComment: newData.comment })
}