This is an automated email from the ASF dual-hosted git repository. yuqi4733 pushed a commit to branch internal-main in repository https://gitbox.apache.org/repos/asf/gravitino.git
commit b9486dbf8258ad9f44a048fa94198ef39ef944cc Author: Qian Xia <[email protected]> AuthorDate: Mon Jan 12 21:17:35 2026 +0800 [#95] web(UI): spport bigquery UI (#106) * [#95] web(UI): spport bigquery UI * Update web/web/src/app/metalakes/metalake/rightContent/MetalakePath.js Co-authored-by: Copilot <[email protected]> * Update web/web/src/app/metalakes/metalake/rightContent/MetalakePath.js Co-authored-by: Copilot <[email protected]> * improve checkCatalogIcon func --------- Co-authored-by: Copilot <[email protected]> --- web/web/src/app/metalakes/metalake/MetalakeTree.js | 39 +------------ .../metalake/rightContent/CreateCatalogDialog.js | 16 +++++- .../metalake/rightContent/MetalakePath.js | 10 +++- web/web/src/lib/utils/catalogIcons.js | 58 +++++++++++++++++++ web/web/src/lib/utils/initial.js | 66 ++++++++++++++++++++++ 5 files changed, 147 insertions(+), 42 deletions(-) diff --git a/web/web/src/app/metalakes/metalake/MetalakeTree.js b/web/web/src/app/metalakes/metalake/MetalakeTree.js index 661c04bf18..89f75000db 100644 --- a/web/web/src/app/metalakes/metalake/MetalakeTree.js +++ b/web/web/src/app/metalakes/metalake/MetalakeTree.js @@ -30,6 +30,7 @@ import Icon from '@/components/Icon' import clsx from 'clsx' import { useAppDispatch, useAppSelector } from '@/lib/hooks/useStore' +import { checkCatalogIcon } from '@/lib/utils/catalogIcons' import { setExpandedNodes, setIntoTreeNodeWithFetch, @@ -57,44 +58,6 @@ const MetalakeTree = props => { const dispatch = useAppDispatch() const store = useAppSelector(state => state.metalakes) - const checkCatalogIcon = ({ type, provider }) => { - switch (type) { - case 'relational': - switch (provider) { - case 'hive': - return 'custom-icons-hive' - case 'lakehouse-iceberg': - return 'openmoji:iceberg' - case 'jdbc-mysql': - return 'devicon:mysql-wordmark' - case 'jdbc-postgresql': - return 'devicon:postgresql-wordmark' - case 'jdbc-doris': - return 'custom-icons-doris' - case 'jdbc-starrocks': - return 'custom-icons-starrocks' - case 'lakehouse-paimon': - return 'custom-icons-paimon' - case 'lakehouse-hudi': - return 'custom-icons-hudi' - case 'lakehouse-generic': - return 'material-symbols:houseboat-outline' - case 'jdbc-oceanbase': - return 'custom-icons-oceanbase' - default: - return 'bx:book' - } - case 'messaging': - return 'skill-icons:kafka' - case 'fileset': - return 'twemoji:file-folder' - case 'model': - return 'carbon:machine-learning-model' - default: - return 'bx:book' - } - } - const handleClickIcon = (e, nodeProps) => { e.stopPropagation() if (nodeProps.data.inUse === 'false') return diff --git a/web/web/src/app/metalakes/metalake/rightContent/CreateCatalogDialog.js b/web/web/src/app/metalakes/metalake/rightContent/CreateCatalogDialog.js index b6a967b5a3..0a479a9198 100644 --- a/web/web/src/app/metalakes/metalake/rightContent/CreateCatalogDialog.js +++ b/web/web/src/app/metalakes/metalake/rightContent/CreateCatalogDialog.js @@ -257,7 +257,21 @@ const CreateCatalogDialog = props => { let properties = {} const prevProperties = innerProps - .filter(i => (typeSelect === 'fileset' && i.key === 'location' ? i.value.trim() !== '' : i.key.trim() !== '')) + .filter(item => { + const hasKey = item.key.trim() !== '' + + if (!hasKey) { + return false + } + + if (typeSelect === 'fileset' && item.key === 'location') { + return item.value.trim() !== '' + } + + const hasValue = item.value?.trim() !== '' + + return item.required || hasValue + }) .reduce((acc, item) => { acc[item.key] = item.value diff --git a/web/web/src/app/metalakes/metalake/rightContent/MetalakePath.js b/web/web/src/app/metalakes/metalake/rightContent/MetalakePath.js index 9deeff5375..f75e758b23 100644 --- a/web/web/src/app/metalakes/metalake/rightContent/MetalakePath.js +++ b/web/web/src/app/metalakes/metalake/rightContent/MetalakePath.js @@ -25,6 +25,8 @@ import { useSearchParams } from 'next/navigation' import { Link as MUILink, Breadcrumbs, Typography, Tooltip, styled, Box, IconButton } from '@mui/material' import Icon from '@/components/Icon' +import { useAppSelector } from '@/lib/hooks/useStore' +import { checkCatalogIcon } from '@/lib/utils/catalogIcons' const TextWrapper = styled(Typography)(({ theme }) => ({ maxWidth: '120px', @@ -36,10 +38,9 @@ const TextWrapper = styled(Typography)(({ theme }) => ({ const Text = props => { return <TextWrapper component='span' {...props} /> } - const MetalakePath = props => { const searchParams = useSearchParams() - + const store = useAppSelector(state => state.metalakes) const routeParams = { metalake: searchParams.get('metalake'), catalog: searchParams.get('catalog'), @@ -123,7 +124,10 @@ const MetalakePath = props => { onClick={event => handleClick(event, catalogUrl)} underline='hover' > - <Icon icon='bx:book' fontSize={20} /> + <Icon + icon={checkCatalogIcon({ type, provider: store.catalogs?.find(c => c.name === catalog)?.provider })} + fontSize={20} + /> <Text data-refer={`nav-to-catalog-${catalog}`}>{catalog}</Text> </MUILink> </Tooltip> diff --git a/web/web/src/lib/utils/catalogIcons.js b/web/web/src/lib/utils/catalogIcons.js new file mode 100644 index 0000000000..ffbb617511 --- /dev/null +++ b/web/web/src/lib/utils/catalogIcons.js @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const checkCatalogIcon = ({ type, provider }) => { + switch (type) { + case 'relational': + switch (provider) { + case 'hive': + return 'custom-icons-hive' + case 'lakehouse-iceberg': + return 'openmoji:iceberg' + case 'jdbc-mysql': + return 'devicon:mysql-wordmark' + case 'jdbc-bigquery': + return 'simple-icons:googlebigquery' + case 'jdbc-postgresql': + return 'devicon:postgresql-wordmark' + case 'jdbc-doris': + return 'custom-icons-doris' + case 'jdbc-starrocks': + return 'custom-icons-starrocks' + case 'lakehouse-paimon': + return 'custom-icons-paimon' + case 'lakehouse-hudi': + return 'custom-icons-hudi' + case 'lakehouse-generic': + return 'material-symbols:houseboat-outline' + case 'jdbc-oceanbase': + return 'custom-icons-oceanbase' + default: + return 'bx:book' + } + case 'messaging': + return 'skill-icons:kafka' + case 'fileset': + return 'twemoji:file-folder' + case 'model': + return 'carbon:machine-learning-model' + default: + return 'bx:book' + } +} diff --git a/web/web/src/lib/utils/initial.js b/web/web/src/lib/utils/initial.js index db6334b4be..edc760eb44 100644 --- a/web/web/src/lib/utils/initial.js +++ b/web/web/src/lib/utils/initial.js @@ -255,6 +255,54 @@ export const providers = [ } ] }, + { + label: 'Google BigQuery', + value: 'jdbc-bigquery', + defaultProps: [ + { + key: 'project-id', + value: '', + required: true, + description: 'Google Cloud Project ID' + }, + { + key: 'jdbc-driver', + value: '', + required: true, + description: 'e.g. com.simba.googlebigquery.jdbc42.Driver' + }, + { + key: 'jdbc-url', + value: '', + required: true, + description: 'e.g. jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443' + }, + { + key: 'jdbc-user', + value: '', + required: true, + description: 'Service account email' + }, + { + key: 'jdbc-password', + value: '', + required: true, + description: 'Path to service account key file' + }, + { + key: 'proxy-host', + value: '', + required: false, + description: 'Proxy server hostname or IP address (optional)' + }, + { + key: 'proxy-port', + value: '', + required: false, + description: 'Proxy server port number (required if proxy-host is set)' + } + ] + }, { label: 'Lakehouse Generic', value: 'lakehouse-generic', @@ -525,6 +573,24 @@ const relationalColumnTypeMap = { 'timestamp', 'varchar' ], + 'jdbc-bigquery': [ + 'binary', + 'boolean', + 'byte', + 'char', + 'date', + 'decimal', + 'double', + 'float', + 'integer', + 'long', + 'short', + 'string', + 'time', + 'timestamp', + 'timestamp_tz', + 'varchar' + ], 'jdbc-mysql': [ 'binary', 'byte',
