From 34f657457ce094292714fdecba6aaedba8fba6a4 Mon Sep 17 00:00:00 2001 From: s7monk <“15512826113@163.com”> Date: Fri, 11 Aug 2023 19:00:42 +0800 Subject: [PATCH 1/6] add meta data --- README.md | 2 +- paimon-web-api/pom.xml | 1 + paimon-web-server/pom.xml | 17 +++ .../web/server/configrue/CorsConfig.java | 47 ++++++++ .../web/server/configrue/JacksonConfig.java | 51 +++++++++ .../server/configrue/SaTokenConfigure.java | 4 +- .../server/controller/CatalogController.java | 98 +++++++++++++++++ .../src/main/resources/application-dev.yml | 3 + .../src/main/resources/application.yml | 2 +- paimon-web-ui/index.html | 2 +- paimon-web-ui/package.json | 7 +- paimon-web-ui/src/api/api.ts | 42 +++++++ paimon-web-ui/src/api/data.d.ts | 41 +++++++ paimon-web-ui/src/api/endpoints.ts | 22 ++++ paimon-web-ui/src/api/http.ts | 89 +++++++++++++++ paimon-web-ui/src/app/App.less | 7 +- .../components/Dropdown/CatalogDropdown.tsx | 2 +- .../src/pages/Layout/Header/index.tsx | 2 +- .../CatalogModalForm/CatalogForm/index.tsx | 104 ++++++++++++++++++ .../components/CatalogModalForm/index.tsx | 58 ++++++++++ .../CatalogTree/catalog-tree.module.less | 2 +- .../Metadata/components/LeftContent/index.tsx | 47 +++++++- .../LeftContent/left-content.module.less | 8 ++ .../components/TopPanel/Tab/index.tsx | 2 +- .../TreeComponent/tree-component.module.less | 4 + paimon-web-ui/tsconfig.json | 3 +- paimon-web-ui/vite.config.ts | 15 ++- 27 files changed, 665 insertions(+), 17 deletions(-) create mode 100644 paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/CorsConfig.java create mode 100644 paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/JacksonConfig.java create mode 100644 paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/CatalogController.java create mode 100644 paimon-web-ui/src/api/api.ts create mode 100644 paimon-web-ui/src/api/data.d.ts create mode 100644 paimon-web-ui/src/api/endpoints.ts create mode 100644 paimon-web-ui/src/api/http.ts create mode 100644 paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogModalForm/CatalogForm/index.tsx create mode 100644 paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogModalForm/index.tsx diff --git a/README.md b/README.md index 9249cd896..3744ba36b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Apache Paimon (incubating) Manager +# Apache Paimon (incubating) Web UI This repository is web ui for the [Apache Paimon](https://paimon.apache.org/) project. diff --git a/paimon-web-api/pom.xml b/paimon-web-api/pom.xml index 6d6886d80..24f8c1ce2 100644 --- a/paimon-web-api/pom.xml +++ b/paimon-web-api/pom.xml @@ -49,6 +49,7 @@ under the License. paimon-web-common ${project.version} + org.junit.jupiter junit-jupiter diff --git a/paimon-web-server/pom.xml b/paimon-web-server/pom.xml index 78d43f4cf..993f48ecc 100644 --- a/paimon-web-server/pom.xml +++ b/paimon-web-server/pom.xml @@ -34,6 +34,10 @@ under the License. Paimon Web Server is a server for the [Apache Paimon](https://paimon.apache.org/) project. + + 2.8.5 + + org.apache.paimon @@ -41,6 +45,12 @@ under the License. ${project.version} + + org.apache.paimon + paimon-web-api + ${project.version} + + org.springframework.boot spring-boot-configuration-processor @@ -136,6 +146,13 @@ under the License. h2 runtime + + + org.apache.hadoop + hadoop-client + ${hadoop.version} + provided + diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/CorsConfig.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/CorsConfig.java new file mode 100644 index 000000000..60a4aed9a --- /dev/null +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/CorsConfig.java @@ -0,0 +1,47 @@ +/* + * + * 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. + * + */ + +package org.apache.paimon.web.server.configrue; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +@Slf4j +//@Configuration +public class CorsConfig { + + @Bean + public CorsFilter corsFilter() { + CorsConfiguration corsConfiguration = new CorsConfiguration(); + corsConfiguration.setAllowCredentials(true); + corsConfiguration.addAllowedHeader("*"); + corsConfiguration.addAllowedMethod("*"); + corsConfiguration.addExposedHeader("*"); + corsConfiguration.addAllowedOrigin("http://127.0.0.1:5173"); + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", corsConfiguration); + return new CorsFilter(source); + } + + +} diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/JacksonConfig.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/JacksonConfig.java new file mode 100644 index 000000000..f592c66a1 --- /dev/null +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/JacksonConfig.java @@ -0,0 +1,51 @@ +/* + * + * 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. + * + */ + +package org.apache.paimon.web.server.configrue; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +import java.text.SimpleDateFormat; + +@Configuration +public class JacksonConfig { + @Bean + public ObjectMapper getJacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { + ObjectMapper objectMapper = builder.createXmlMapper(false).build(); + // When the sequence is changed to json, all longs will be changed to strings. + // Because the numeric type in js cannot contain all java long values, precision will be lost after more than 16 digits. + SimpleModule simpleModule = new SimpleModule(); + simpleModule.addSerializer(Long.class, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance); + simpleModule.addSerializer(Long.TYPE, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance); + objectMapper.registerModule(simpleModule); + // If there are more attributes during deserialization, no exception will be thrown. + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + // Date format handling. + objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); + objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); + return objectMapper; + } +} diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/SaTokenConfigure.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/SaTokenConfigure.java index 11bf30564..05a6de82b 100644 --- a/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/SaTokenConfigure.java +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/SaTokenConfigure.java @@ -26,12 +26,12 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** Sa-Token path config. */ -@Configuration +//@Configuration public class SaTokenConfigure implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin())) .addPathPatterns("/**") - .excludePathPatterns("/api/login"); + .excludePathPatterns("/***"); } } diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/CatalogController.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/CatalogController.java new file mode 100644 index 000000000..b9be43230 --- /dev/null +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/CatalogController.java @@ -0,0 +1,98 @@ +/* + * 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. + */ + +package org.apache.paimon.web.server.controller; + +import lombok.extern.slf4j.Slf4j; +import org.apache.paimon.catalog.Catalog; +import org.apache.paimon.web.api.catalog.CatalogCreator; +import org.apache.paimon.web.server.data.result.R; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Slf4j +@RestController +@RequestMapping("/api/catalog") +public class CatalogController { + + /** + * Create a filesystem catalog. + * + * @param fileSystemCatalogInfo The fileSystemCatalogInfo for the filesystem catalog. + * @return The created catalog. + */ + @PostMapping("/createFilesystemCatalog") + public R createFilesystemCatalog(@RequestBody FileSystemCatalogInfo fileSystemCatalogInfo) { + return R.succeed(CatalogCreator.createFilesystemCatalog(fileSystemCatalogInfo.path)); + } + + /** + * Create a hive catalog. + * + * @param catalogInfo The information for the hive catalog. + * @return The created catalog. + */ + @PostMapping("/createHiveCatalog") + public Catalog createHiveCatalog(@RequestBody HiveCatalogInfo catalogInfo) { + return CatalogCreator.createHiveCatalog(catalogInfo.getWarehouse(), catalogInfo.getUri(), catalogInfo.getHiveConfDir()); + } + + /** + * A class to hold the information for the filesystem catalog. + */ + public static class FileSystemCatalogInfo { + private String catalogName; + private String catalogType; + private String path; + } + + /** + * A class to hold the information for the hive catalog. + */ + public static class HiveCatalogInfo { + private String warehouse; + private String uri; + private String hiveConfDir; + + public String getWarehouse() { + return warehouse; + } + + public void setWarehouse(String warehouse) { + this.warehouse = warehouse; + } + + public String getUri() { + return uri; + } + + public void setUri(String uri) { + this.uri = uri; + } + + public String getHiveConfDir() { + return hiveConfDir; + } + + public void setHiveConfDir(String hiveConfDir) { + this.hiveConfDir = hiveConfDir; + } + } +} diff --git a/paimon-web-server/src/main/resources/application-dev.yml b/paimon-web-server/src/main/resources/application-dev.yml index 252158bce..70756dd12 100644 --- a/paimon-web-server/src/main/resources/application-dev.yml +++ b/paimon-web-server/src/main/resources/application-dev.yml @@ -14,6 +14,9 @@ # limitations under the License. spring: + h2: #http://localhost:10088/h2-console + console: + enabled: true datasource: driver-class-name: org.h2.Driver url: jdbc:h2:mem:paimon;MODE=MySQL;DB_CLOSE_DELAY=-1;DATABASE_TO_LOWER=true;;NON_KEYWORDS=USER;INIT=runscript from 'classpath:db/ddl-h2.sql' diff --git a/paimon-web-server/src/main/resources/application.yml b/paimon-web-server/src/main/resources/application.yml index 4e702ad67..8bd64dc37 100644 --- a/paimon-web-server/src/main/resources/application.yml +++ b/paimon-web-server/src/main/resources/application.yml @@ -20,7 +20,7 @@ server: spring: # Paimon Web Service Name application: - name: PaimonManager + name: Paimon Web UI profiles: active: dev messages: diff --git a/paimon-web-ui/index.html b/paimon-web-ui/index.html index 85d1141eb..49b9c5575 100644 --- a/paimon-web-ui/index.html +++ b/paimon-web-ui/index.html @@ -23,7 +23,7 @@ - Paimon Manager + 巴别实时计算平台
diff --git a/paimon-web-ui/package.json b/paimon-web-ui/package.json index e9ef6174a..ba4009341 100644 --- a/paimon-web-ui/package.json +++ b/paimon-web-ui/package.json @@ -13,14 +13,19 @@ "@douyinfe/semi-icons": "^2.38.1", "@douyinfe/semi-ui": "^2.38.1", "@monaco-editor/react": "^4.5.1", + "@reduxjs/toolkit": "^1.9.5", "@semi-bot/semi-theme-doucreator": "^1.0.18", "@semi-bot/semi-theme-figma": "^0.1.6", + "axios": "^1.4.0", + "http-proxy-middleware": "^2.0.6", "less": "^4.1.3", "monaco-editor": "^0.40.0", "react": "^18.2.0", "react-bootstrap": "^2.8.0", "react-dom": "^18.2.0", - "react-icons": "^4.10.1" + "react-icons": "^4.10.1", + "react-redux": "^8.1.2", + "redux": "^4.2.1" }, "devDependencies": { "@types/node": "^20.3.2", diff --git a/paimon-web-ui/src/api/api.ts b/paimon-web-ui/src/api/api.ts new file mode 100644 index 000000000..d6d9a1934 --- /dev/null +++ b/paimon-web-ui/src/api/api.ts @@ -0,0 +1,42 @@ +/* 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. */ + +import http from '@api/http' +import { API_ENDPOINTS } from '@api/endpoints'; + +export const createFileSystemCatalog = async (catalogProp: Prop.FileSystemCatalogProp) => { + try { + const response: API.Result = + await http.httpPost, Prop.FileSystemCatalogProp>(API_ENDPOINTS.CREATE_FILE_SYSTEM_CATALOG, catalogProp); + console.log(response) + if (response.code === 200) { + console.log('Catalog was successfully created'); + return response.data; + } else { + console.log('There was a problem creating the catalog:', response.msg); + } + } catch (error) { + console.error('Failed to create catalog:', error); + } +}; + +const Api = { + createFileSystemCatalog +} + +export default Api; + diff --git a/paimon-web-ui/src/api/data.d.ts b/paimon-web-ui/src/api/data.d.ts new file mode 100644 index 000000000..10ae56141 --- /dev/null +++ b/paimon-web-ui/src/api/data.d.ts @@ -0,0 +1,41 @@ +/* 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. */ + +declare namespace API { + export interface Result { + code: number; + msg: string; + data: T; + } + + export interface PageData { + records: T[]; + page: number; + size: number; + total: number; + } + + export type PageResult = Result> +} + +declare namespace Prop { + export interface FileSystemCatalogProp { + catalogName: string, + catalogType: string, + path: string + } +} \ No newline at end of file diff --git a/paimon-web-ui/src/api/endpoints.ts b/paimon-web-ui/src/api/endpoints.ts new file mode 100644 index 000000000..bf1df5655 --- /dev/null +++ b/paimon-web-ui/src/api/endpoints.ts @@ -0,0 +1,22 @@ +/* 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 API_ENDPOINTS = { + // catalog + CREATE_FILE_SYSTEM_CATALOG: '/catalog/createFilesystemCatalog', + CREATE_HIVE_CATALOG: '/catalog/createHiveCatalog', +}; \ No newline at end of file diff --git a/paimon-web-ui/src/api/http.ts b/paimon-web-ui/src/api/http.ts new file mode 100644 index 000000000..e1364c6e2 --- /dev/null +++ b/paimon-web-ui/src/api/http.ts @@ -0,0 +1,89 @@ +/* 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. */ + +import axios, { AxiosResponse, AxiosError } from 'axios'; + +const httpClient = axios.create({ + baseURL: '/api', + timeout: 30 * 1000, + withCredentials: false, + headers: { + 'Content-Type': 'application/json' + } +}); + +// request interceptor. +httpClient.interceptors.request.use( + (config: any) => { + // Here you can set request headers like:config.headers['Token'] = localStorage.getItem('Token'). + /* config.headers = { + "Authorization": store.getState().user.token + }*/ + return config; + }, + (error: AxiosError) => { + // Handle request errors + console.log('request:', error); + return Promise.reject(error); + } +); + +// response interceptor. +httpClient.interceptors.response.use( + (response: AxiosResponse) => { + // Here you can process the response data. + return response; + }, + (error: AxiosError) => { + // Handle response errors. + console.log('response:', error); + return Promise.reject(error); + } +); + +const httpGet = async (url: string, param?: E): Promise => { + const {data} = await httpClient.get(url, {params: param}) + return data +} + +const httpPost = async (url: string, param: E): Promise => { + const {data} = await httpClient.post(url, param) + return data +} + +const httpDelete = async (url: string, param: E): Promise => { + const {data} = await httpClient.delete(url, {params: param}) + return data +} + +const httpFormPost = async (url: string, params?: E): Promise => { + const {data} = await httpClient.post(url, params, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }) + return data +} + +const http = { + httpGet, + httpPost, + httpDelete, + httpFormPost +} + +export default http; \ No newline at end of file diff --git a/paimon-web-ui/src/app/App.less b/paimon-web-ui/src/app/App.less index aa5443cf7..e14bbbd67 100644 --- a/paimon-web-ui/src/app/App.less +++ b/paimon-web-ui/src/app/App.less @@ -24,7 +24,10 @@ body, padding: 0; color: rgba(0, 0, 0, 0.65) !important; //--semi-color-primary: rgba(var(--semi-violet-6), 1); - --semi-color-primary: rgba(var(--semi-grey-6), 1); - --semi-color-primary-hover: rgba(var(--semi-violet-3), 1); + //--semi-color-primary: rgba(var(--semi-grey-6), 1); + //--semi-color-primary: rgba(var(--semi-blue-5), 1); + //--semi-color-primary-hover: rgba(var(--semi-violet-3), 1); + //--semi-color-primary-hover: rgba(var(--semi-blue-6), 1); + //--semi-color-primary-active: rgba(var(--semi-blue-7), 1); --semi-color-primary-light-default: rgba(var(--semi-color-bg-0), 1); } diff --git a/paimon-web-ui/src/components/Dropdown/CatalogDropdown.tsx b/paimon-web-ui/src/components/Dropdown/CatalogDropdown.tsx index 722c20659..f533505d0 100644 --- a/paimon-web-ui/src/components/Dropdown/CatalogDropdown.tsx +++ b/paimon-web-ui/src/components/Dropdown/CatalogDropdown.tsx @@ -65,7 +65,7 @@ const CatalogDropdown: React.FC = (props) => { placeholder="Select Catalog" optionList={renderCatalogList()} showClear - style={{display: "flex", flexGrow: 1, backgroundColor: "var(--semi-color-bg-0)"}} + style={{display: "flex", flexGrow: 1}} /> } diff --git a/paimon-web-ui/src/pages/Layout/Header/index.tsx b/paimon-web-ui/src/pages/Layout/Header/index.tsx index 34910088b..e4d033f13 100644 --- a/paimon-web-ui/src/pages/Layout/Header/index.tsx +++ b/paimon-web-ui/src/pages/Layout/Header/index.tsx @@ -64,7 +64,7 @@ const HeaderRoot = ()=> { header={{ logo: Apache Paimon, - text: 'Apache Paimon' + text: '巴别实时计算平台' }} mode={"horizontal"} defaultSelectedKeys={['Home']} diff --git a/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogModalForm/CatalogForm/index.tsx b/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogModalForm/CatalogForm/index.tsx new file mode 100644 index 000000000..ebcf2a310 --- /dev/null +++ b/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogModalForm/CatalogForm/index.tsx @@ -0,0 +1,104 @@ +/* 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. */ + +import { Form } from '@douyinfe/semi-ui'; + +// @ts-ignore +const CatalogForm = ({ getFormApi }) => { + let message = 'This item is required.'; + return( + <> +
+ { + ({ formState }) => ( + <> + + + + FileSystem + Hive + + + {formState.values.catalog === 'filesystem' ? ( + + ) + : + <> + + + + + + + } + + ) + } + + + ); +} + +export default CatalogForm; \ No newline at end of file diff --git a/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogModalForm/index.tsx b/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogModalForm/index.tsx new file mode 100644 index 000000000..05780b1b4 --- /dev/null +++ b/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogModalForm/index.tsx @@ -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. */ + +import React, {useState} from "react"; +import { Modal } from '@douyinfe/semi-ui'; +import CatalogForm from "@pages/Metadata/components/LeftContent/components/CatalogModalForm/CatalogForm"; + +type CatalogModalFormProps = { + visible: boolean; + onClose: () => void; + onOk: (formApi: any) => void; +}; + + +const CatalogModalForm: React.FC = ({ visible , onClose, onOk }) => { + const [formApi, setFormApi] = useState(null); + + const getFormApi = (api: any) => { + setFormApi(api); + }; + + const handleOkClick = async () => { + await onOk(formApi); + onClose(); + }; + + return( + handleOkClick()} + > + + + ); +} + +export default CatalogModalForm; \ No newline at end of file diff --git a/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogTree/catalog-tree.module.less b/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogTree/catalog-tree.module.less index 9f178b65b..4f3f8474d 100644 --- a/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogTree/catalog-tree.module.less +++ b/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogTree/catalog-tree.module.less @@ -16,7 +16,7 @@ specific language governing permissions and limitations under the License. */ .catalog-tree-input { - background-color: var(--semi-color-bg-0); + //background-color: var(--semi-color-bg-0); width: 347px; margin-left: -12px; } \ No newline at end of file diff --git a/paimon-web-ui/src/pages/Metadata/components/LeftContent/index.tsx b/paimon-web-ui/src/pages/Metadata/components/LeftContent/index.tsx index b2a016c39..f0a5cdcce 100644 --- a/paimon-web-ui/src/pages/Metadata/components/LeftContent/index.tsx +++ b/paimon-web-ui/src/pages/Metadata/components/LeftContent/index.tsx @@ -17,16 +17,61 @@ under the License. */ import { IconPlus } from "@douyinfe/semi-icons"; import CatalogTree from "@pages/Metadata/components/LeftContent/components/CatalogTree"; +import {useState} from "react"; +import CatalogModalForm from "@pages/Metadata/components/LeftContent/components/CatalogModalForm"; +import Api from "@api/api.ts"; import styles from "./left-content.module.less"; const MetadataSidebar = () => { + + const [showModal, setShowModal] = useState(false); + + const handleOpenModal = () => { + setShowModal(true); + }; + + const handleCloseModal = () => { + setShowModal(false); + }; + + const handleOk = (formApi: any) => { + return new Promise((resolve, reject) => { + formApi + .validate() + .then((values: any) => { + // Assuming values contains the form data + const formData = values; + + if (formData.catalog === 'filesystem') { + const catalogProp: Prop.FileSystemCatalogProp = { + catalogName: formData.catalog, + catalogType: 'filesystem', + path: formData.path + }; + let catalog = Api.createFileSystemCatalog(catalogProp); + console.log(catalog); + } else { + + } + resolve(); // Resolve the promise when done + }) + .catch((errors: any) => { + console.log(errors); + reject(errors); // Reject the promise on error + }); + }); + }; + return(
Catalog - +
+ {showModal && ( + + )}
) } diff --git a/paimon-web-ui/src/pages/Metadata/components/LeftContent/left-content.module.less b/paimon-web-ui/src/pages/Metadata/components/LeftContent/left-content.module.less index bcee82511..862b5c58f 100644 --- a/paimon-web-ui/src/pages/Metadata/components/LeftContent/left-content.module.less +++ b/paimon-web-ui/src/pages/Metadata/components/LeftContent/left-content.module.less @@ -28,4 +28,12 @@ under the License. */ flex-direction: row; justify-content: space-between; align-items: center; +} + +.iconPlus { + transition: box-shadow 0.1s ease-in-out; +} + +.iconPlus:hover { + box-shadow: 0px 0px 30px rgba(var(--semi-light-blue-5), 1); } \ No newline at end of file diff --git a/paimon-web-ui/src/pages/Playground/components/RightContent/components/TopPanel/Tab/index.tsx b/paimon-web-ui/src/pages/Playground/components/RightContent/components/TopPanel/Tab/index.tsx index 0eb87108b..3397ad3af 100644 --- a/paimon-web-ui/src/pages/Playground/components/RightContent/components/TopPanel/Tab/index.tsx +++ b/paimon-web-ui/src/pages/Playground/components/RightContent/components/TopPanel/Tab/index.tsx @@ -40,7 +40,7 @@ const Index = () => { return ( {tabList.map((t) => ( - {t.tab}} itemKey={t.itemKey} key={t.itemKey}> + {t.tab}} itemKey={t.itemKey} key={t.itemKey}> {t.content} ))} diff --git a/paimon-web-ui/src/pages/Playground/components/TabMenuSidebar/components/TreeComponent/tree-component.module.less b/paimon-web-ui/src/pages/Playground/components/TabMenuSidebar/components/TreeComponent/tree-component.module.less index 9c77a32be..892457f63 100644 --- a/paimon-web-ui/src/pages/Playground/components/TabMenuSidebar/components/TreeComponent/tree-component.module.less +++ b/paimon-web-ui/src/pages/Playground/components/TabMenuSidebar/components/TreeComponent/tree-component.module.less @@ -22,3 +22,7 @@ under the License. */ .catalog-tree-input { background-color: var(--semi-color-bg-0); } + +.selected-node { + background-color: #ff0000; +} diff --git a/paimon-web-ui/tsconfig.json b/paimon-web-ui/tsconfig.json index dc41217c2..eb79bd42e 100644 --- a/paimon-web-ui/tsconfig.json +++ b/paimon-web-ui/tsconfig.json @@ -27,9 +27,10 @@ "@config/*": ["src/config/*"], "@utils/*": ["src/utils/*"], "@pages/*": ["src/pages/*"], + "@api/*": ["src/api/*"], "@mock/*": ["mock/*"] } }, - "include": ["src"], + "include": ["src","./**/*.d.ts", "./**/*.ts", "./**/*.tsx"], "references": [{ "path": "./tsconfig.node.json" }] } diff --git a/paimon-web-ui/vite.config.ts b/paimon-web-ui/vite.config.ts index 812d23e44..1a9f90174 100644 --- a/paimon-web-ui/vite.config.ts +++ b/paimon-web-ui/vite.config.ts @@ -22,9 +22,9 @@ import { resolve } from 'path' export default defineConfig({ plugins: [ - SemiPlugin({ + /*SemiPlugin({ theme: "@semi-bot/semi-theme-figma" - }), + }),*/ react() ], resolve: { @@ -35,7 +35,16 @@ export default defineConfig({ '@pages': resolve(__dirname, './src/pages'), '@utils': resolve(__dirname, './src/utils'), '@config': resolve(__dirname, './src/config'), - '@mock': resolve(__dirname, './mock') + '@mock': resolve(__dirname, './mock'), + '@api': resolve(__dirname, './src/api') + } + }, + server: { + proxy: { + '/api': { + target: 'http://localhost:10088', + changeOrigin: true + } } } }) From 794773407c51406fc0b3b16fee57da051e71c104 Mon Sep 17 00:00:00 2001 From: s7monk <“15512826113@163.com”> Date: Mon, 14 Aug 2023 19:14:23 +0800 Subject: [PATCH 2/6] add meta data --- .../web/api/catalog/CatalogCreatorTest.java | 3 +- .../server/controller/CatalogController.java | 89 ++++++++++--------- .../web/server/data/model/CatalogInfo.java | 50 +++++++++++ .../web/server/data/result/enums/Status.java | 4 + .../web/server/mapper/CatalogMapper.java | 28 ++++++ .../web/server/service/CatalogService.java | 34 +++++++ .../service/impl/CatalogServiceImpl.java | 37 ++++++++ .../src/main/resources/db/ddl-h2.sql | 13 +++ .../main/resources/i18n/messages.properties | 2 + paimon-web-ui/package.json | 3 +- paimon-web-ui/src/api/api.ts | 36 +++++--- paimon-web-ui/src/api/data.d.ts | 8 +- paimon-web-ui/src/api/endpoints.ts | 1 + .../CatalogModalForm/CatalogForm/index.tsx | 6 +- .../components/CatalogTree/index.tsx | 1 - .../Metadata/components/LeftContent/index.tsx | 56 +++++++++--- paimon-web-ui/src/store/createStore.ts | 43 +++++++++ paimon-web-ui/src/store/index.ts | 20 +++++ paimon-web-ui/src/store/initialState.ts | 39 ++++++++ paimon-web-ui/src/store/useState.ts | 21 +++++ paimon-web-ui/src/types/Catalog/data.d.ts | 30 +++++++ 21 files changed, 450 insertions(+), 74 deletions(-) create mode 100644 paimon-web-server/src/main/java/org/apache/paimon/web/server/data/model/CatalogInfo.java create mode 100644 paimon-web-server/src/main/java/org/apache/paimon/web/server/mapper/CatalogMapper.java create mode 100644 paimon-web-server/src/main/java/org/apache/paimon/web/server/service/CatalogService.java create mode 100644 paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/CatalogServiceImpl.java create mode 100644 paimon-web-ui/src/store/createStore.ts create mode 100644 paimon-web-ui/src/store/index.ts create mode 100644 paimon-web-ui/src/store/initialState.ts create mode 100644 paimon-web-ui/src/store/useState.ts create mode 100644 paimon-web-ui/src/types/Catalog/data.d.ts diff --git a/paimon-web-api/src/test/java/org/apache/paimon/web/api/catalog/CatalogCreatorTest.java b/paimon-web-api/src/test/java/org/apache/paimon/web/api/catalog/CatalogCreatorTest.java index a472ade28..e3e4047ba 100644 --- a/paimon-web-api/src/test/java/org/apache/paimon/web/api/catalog/CatalogCreatorTest.java +++ b/paimon-web-api/src/test/java/org/apache/paimon/web/api/catalog/CatalogCreatorTest.java @@ -33,7 +33,8 @@ public class CatalogCreatorTest { @Test public void testCreateFileSystemCatalog() { - String warehouse = tempFile.toUri().toString(); + //String warehouse = tempFile.toUri().toString(); + String warehouse = "file://D:/path/"; Catalog catalog = CatalogCreator.createFilesystemCatalog(warehouse); assertThat(catalog).isInstanceOf(FileSystemCatalog.class); } diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/CatalogController.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/CatalogController.java index b9be43230..2014fb279 100644 --- a/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/CatalogController.java +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/CatalogController.java @@ -19,28 +19,48 @@ package org.apache.paimon.web.server.controller; import lombok.extern.slf4j.Slf4j; -import org.apache.paimon.catalog.Catalog; import org.apache.paimon.web.api.catalog.CatalogCreator; +import org.apache.paimon.web.server.data.model.CatalogInfo; import org.apache.paimon.web.server.data.result.R; +import org.apache.paimon.web.server.data.result.enums.Status; +import org.apache.paimon.web.server.service.CatalogService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + +/** Catalog api controller. */ @Slf4j @RestController @RequestMapping("/api/catalog") public class CatalogController { + @Autowired + private CatalogService catalogService; + /** * Create a filesystem catalog. * - * @param fileSystemCatalogInfo The fileSystemCatalogInfo for the filesystem catalog. + * @param catalogInfo The catalogInfo for the filesystem catalog. * @return The created catalog. */ @PostMapping("/createFilesystemCatalog") - public R createFilesystemCatalog(@RequestBody FileSystemCatalogInfo fileSystemCatalogInfo) { - return R.succeed(CatalogCreator.createFilesystemCatalog(fileSystemCatalogInfo.path)); + public R createFilesystemCatalog(@RequestBody CatalogInfo catalogInfo) { + if (!catalogService.checkCatalogNameUnique(catalogInfo)) { + return R.failed(Status.CATALOG_NAME_IS_EXIST, catalogInfo.getCatalogName()); + } + + try { + CatalogCreator.createFilesystemCatalog(catalogInfo.getWarehouse()); + return catalogService.save(catalogInfo) ? R.succeed() : R.failed(); + } catch (Exception e) { + e.printStackTrace(); + return R.failed(Status.CATALOG_CREATE_ERROR); + } } /** @@ -50,49 +70,32 @@ public R createFilesystemCatalog(@RequestBody FileSystemCatalogInfo fil * @return The created catalog. */ @PostMapping("/createHiveCatalog") - public Catalog createHiveCatalog(@RequestBody HiveCatalogInfo catalogInfo) { - return CatalogCreator.createHiveCatalog(catalogInfo.getWarehouse(), catalogInfo.getUri(), catalogInfo.getHiveConfDir()); - } + public R createHiveCatalog(@RequestBody CatalogInfo catalogInfo) { + if (!catalogService.checkCatalogNameUnique(catalogInfo)) { + return R.failed(Status.CATALOG_NAME_IS_EXIST, catalogInfo.getCatalogName()); + } - /** - * A class to hold the information for the filesystem catalog. - */ - public static class FileSystemCatalogInfo { - private String catalogName; - private String catalogType; - private String path; + try { + CatalogCreator.createHiveCatalog( + catalogInfo.getWarehouse(), + catalogInfo.getHiveUri(), + catalogInfo.getHiveConfDir()); + return catalogService.save(catalogInfo) ? R.succeed() : R.failed(); + } catch (Exception e) { + e.printStackTrace(); + return R.failed(Status.CATALOG_CREATE_ERROR); + } } /** - * A class to hold the information for the hive catalog. + * Get all catalog information. + * + * @return The list of all catalogs. */ - public static class HiveCatalogInfo { - private String warehouse; - private String uri; - private String hiveConfDir; - - public String getWarehouse() { - return warehouse; - } - - public void setWarehouse(String warehouse) { - this.warehouse = warehouse; - } - - public String getUri() { - return uri; - } - - public void setUri(String uri) { - this.uri = uri; - } - - public String getHiveConfDir() { - return hiveConfDir; - } - - public void setHiveConfDir(String hiveConfDir) { - this.hiveConfDir = hiveConfDir; - } + @GetMapping("/getAllCatalogs") + public R> getCatalog() { + List catalogs = catalogService.list(); + return R.succeed(catalogs); } + } diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/model/CatalogInfo.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/model/CatalogInfo.java new file mode 100644 index 000000000..12ab8757d --- /dev/null +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/model/CatalogInfo.java @@ -0,0 +1,50 @@ +/* + * 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. + */ + +package org.apache.paimon.web.server.data.model; + +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** Catalog table model. */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@TableName("catalog") +public class CatalogInfo extends BaseModel{ + + private String catalogType; + + private String catalogName; + + private String warehouse; + + private String hiveUri; + + private String hiveConfDir; + + @TableLogic + private boolean isDelete; +} diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java index e20edcaf6..c8dc0d3c2 100644 --- a/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/result/enums/Status.java @@ -49,6 +49,10 @@ public enum Status { MENU_IN_USED(10201, "menu.in.used"), MENU_NAME_IS_EXIST(10202, "menu.name.exist"), MENU_PATH_INVALID(10203, "menu.path.invalid"), + + /** ------------catalog-----------------. */ + CATALOG_NAME_IS_EXIST(10301, "catalog.name.exist"), + CATALOG_CREATE_ERROR(10302, "catalog.create.error"), ; private final int code; diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/mapper/CatalogMapper.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/mapper/CatalogMapper.java new file mode 100644 index 000000000..87753d3b5 --- /dev/null +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/mapper/CatalogMapper.java @@ -0,0 +1,28 @@ +/* + * 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. + */ + +package org.apache.paimon.web.server.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.paimon.web.server.data.model.CatalogInfo; + +/** Catalog table mapper. */ +@Mapper +public interface CatalogMapper extends BaseMapper { +} diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/CatalogService.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/CatalogService.java new file mode 100644 index 000000000..b29ccbc06 --- /dev/null +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/CatalogService.java @@ -0,0 +1,34 @@ +/* + * 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. + */ + +package org.apache.paimon.web.server.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import org.apache.paimon.web.server.data.model.CatalogInfo; + +/** Catalog Service. */ +public interface CatalogService extends IService { + + /** + * Verify if the catalog name is unique. + * + * @param catalog catalog info + * @return result + */ + boolean checkCatalogNameUnique(CatalogInfo catalog); +} diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/CatalogServiceImpl.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/CatalogServiceImpl.java new file mode 100644 index 000000000..ba9af0357 --- /dev/null +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/CatalogServiceImpl.java @@ -0,0 +1,37 @@ +/* + * 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. + */ + +package org.apache.paimon.web.server.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.paimon.web.server.data.model.CatalogInfo; +import org.apache.paimon.web.server.mapper.CatalogMapper; +import org.apache.paimon.web.server.service.CatalogService; +import org.springframework.stereotype.Service; + +/** CatalogServiceImpl. */ +@Service +public class CatalogServiceImpl extends ServiceImpl implements CatalogService { + + @Override + public boolean checkCatalogNameUnique(CatalogInfo catalog) { + int catalogId = catalog.getId() == null ? -1 : catalog.getId(); + CatalogInfo info = this.lambdaQuery().eq(CatalogInfo::getCatalogName, catalog.getCatalogName()).one(); + return info == null || info.getId() == catalogId; + } +} diff --git a/paimon-web-server/src/main/resources/db/ddl-h2.sql b/paimon-web-server/src/main/resources/db/ddl-h2.sql index 4f406e1c0..fc6936fda 100644 --- a/paimon-web-server/src/main/resources/db/ddl-h2.sql +++ b/paimon-web-server/src/main/resources/db/ddl-h2.sql @@ -101,4 +101,17 @@ CREATE TABLE if not exists `role_menu` `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'create time', `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'update time', unique key `idx_role_menu` (`role_id`, `menu_id`) +) engine = innodb; + +CREATE TABLE if not exists `catalog` +( + `id` int(11) not null auto_increment primary key comment 'id', + `catalog_type` varchar(50) not null comment 'catalog type', + `catalog_name` varchar(100) not null comment 'catalog name', + `warehouse` varchar(200) not null comment 'warehouse', + `hive_uri` varchar(200) comment 'hive uri', + `hive_conf_dir` varchar(100) comment 'catalog name', + `is_delete` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'is delete', + `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'create time', + `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'update time' ) engine = innodb; \ No newline at end of file diff --git a/paimon-web-server/src/main/resources/i18n/messages.properties b/paimon-web-server/src/main/resources/i18n/messages.properties index ed0836100..a96af9fdd 100644 --- a/paimon-web-server/src/main/resources/i18n/messages.properties +++ b/paimon-web-server/src/main/resources/i18n/messages.properties @@ -30,3 +30,5 @@ role.key.exist=This role key {0} is exist menu.in.used=This menu is in used menu.name.exist=This menu name is exist:{0} menu.path.invalid=This menu path is invalid:{0} +catalog.name.exist=This catalog name {0} is exist +catalog.create.error=An exception is returned when calling the Paimon API to create a Catalog. diff --git a/paimon-web-ui/package.json b/paimon-web-ui/package.json index ba4009341..fa6b4180d 100644 --- a/paimon-web-ui/package.json +++ b/paimon-web-ui/package.json @@ -25,7 +25,8 @@ "react-dom": "^18.2.0", "react-icons": "^4.10.1", "react-redux": "^8.1.2", - "redux": "^4.2.1" + "redux": "^4.2.1", + "zustand": "^4.4.1" }, "devDependencies": { "@types/node": "^20.3.2", diff --git a/paimon-web-ui/src/api/api.ts b/paimon-web-ui/src/api/api.ts index d6d9a1934..d34cf718e 100644 --- a/paimon-web-ui/src/api/api.ts +++ b/paimon-web-ui/src/api/api.ts @@ -16,26 +16,38 @@ specific language governing permissions and limitations under the License. */ import http from '@api/http' -import { API_ENDPOINTS } from '@api/endpoints'; +import {API_ENDPOINTS} from '@api/endpoints'; +import Result = API.Result; +import {CatalogItemList} from "@src/types/Catalog/data"; -export const createFileSystemCatalog = async (catalogProp: Prop.FileSystemCatalogProp) => { +export const createFileSystemCatalog = async (catalogProp: Prop.CatalogProp) => { try { - const response: API.Result = - await http.httpPost, Prop.FileSystemCatalogProp>(API_ENDPOINTS.CREATE_FILE_SYSTEM_CATALOG, catalogProp); - console.log(response) - if (response.code === 200) { - console.log('Catalog was successfully created'); - return response.data; - } else { - console.log('There was a problem creating the catalog:', response.msg); - } + return await http.httpPost, Prop.CatalogProp>(API_ENDPOINTS.CREATE_FILE_SYSTEM_CATALOG, catalogProp); } catch (error) { console.error('Failed to create catalog:', error); } }; +export const createHiveCatalog = async (catalogProp: Prop.CatalogProp) => { + try { + return await http.httpPost, Prop.CatalogProp>(API_ENDPOINTS.CREATE_HIVE_CATALOG, catalogProp); + } catch (error) { + console.error('Failed to create catalog:', error); + } +}; + +export const getAllCatalogs = async () => { + try { + return await http.httpGet, null>(API_ENDPOINTS.GET_ALL_CATALOGS) + } catch (error) { + console.error('Failed to get catalogs:', error); + } +} + const Api = { - createFileSystemCatalog + createFileSystemCatalog, + createHiveCatalog, + getAllCatalogs } export default Api; diff --git a/paimon-web-ui/src/api/data.d.ts b/paimon-web-ui/src/api/data.d.ts index 10ae56141..2381a787d 100644 --- a/paimon-web-ui/src/api/data.d.ts +++ b/paimon-web-ui/src/api/data.d.ts @@ -33,9 +33,13 @@ declare namespace API { } declare namespace Prop { - export interface FileSystemCatalogProp { + // Catalog + export interface CatalogProp { catalogName: string, catalogType: string, - path: string + warehouse: string, + hiveUri: string, + hiveConfDir: string, + isDelete: boolean } } \ No newline at end of file diff --git a/paimon-web-ui/src/api/endpoints.ts b/paimon-web-ui/src/api/endpoints.ts index bf1df5655..dc7a79f3c 100644 --- a/paimon-web-ui/src/api/endpoints.ts +++ b/paimon-web-ui/src/api/endpoints.ts @@ -19,4 +19,5 @@ export const API_ENDPOINTS = { // catalog CREATE_FILE_SYSTEM_CATALOG: '/catalog/createFilesystemCatalog', CREATE_HIVE_CATALOG: '/catalog/createHiveCatalog', + GET_ALL_CATALOGS: '/catalog/getAllCatalogs', }; \ No newline at end of file diff --git a/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogModalForm/CatalogForm/index.tsx b/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogModalForm/CatalogForm/index.tsx index ebcf2a310..55cd745bb 100644 --- a/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogModalForm/CatalogForm/index.tsx +++ b/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogModalForm/CatalogForm/index.tsx @@ -42,7 +42,7 @@ const CatalogForm = ({ getFormApi }) => { style={{ width: "100%" }}/> { Hive - {formState.values.catalog === 'filesystem' ? ( + {formState.values.catalogType === 'filesystem' ? ( { ); }; - return( { // Assuming values contains the form data const formData = values; - if (formData.catalog === 'filesystem') { - const catalogProp: Prop.FileSystemCatalogProp = { - catalogName: formData.catalog, - catalogType: 'filesystem', - path: formData.path - }; - let catalog = Api.createFileSystemCatalog(catalogProp); - console.log(catalog); - } else { + const catalogProp: Prop.CatalogProp = { + catalogName: formData.catalogName, + catalogType: formData.catalogType, + warehouse: formData.warehouse, + hiveUri: formData.hiveUri, + hiveConfDir: formData.hiveConfDir, + isDelete: false + }; + if (formData.catalogType === 'filesystem') { + Api.createFileSystemCatalog(catalogProp) + .then((response: any) => { + if (response.code === 200) { + Toast.success('Catalog created successfully!'); + resolve(); // Resolve the promise when done + } else { + console.error('Failed to create catalog:', response.msg); + Toast.error('Failed to create catalog:' + response.msg); + reject(response.message); // Reject the promise on error + } + }) + .catch((error: any) => { + console.error('Failed to create catalog:', error); + Toast.error('Failed to create catalog:' + error); + reject(error); // Reject the promise on error + }) + } else { + Api.createHiveCatalog(catalogProp) + .then((response: any) => { + if (response.code === 200) { + Toast.success('Catalog created successfully!'); + resolve(); // Resolve the promise when done + } else { + console.error('Failed to create catalog:', response.msg); + Toast.error('Failed to create catalog:' + response.msg); + reject(response.message); // Reject the promise on error + } + }) + .catch((error: any) => { + console.error('Failed to create catalog:', error); + Toast.error('Failed to create catalog:' + error); + reject(error); // Reject the promise on error + }) } - resolve(); // Resolve the promise when done + resolve(); }) .catch((errors: any) => { console.log(errors); - reject(errors); // Reject the promise on error + reject(errors); }); }); }; diff --git a/paimon-web-ui/src/store/createStore.ts b/paimon-web-ui/src/store/createStore.ts new file mode 100644 index 000000000..8d9466928 --- /dev/null +++ b/paimon-web-ui/src/store/createStore.ts @@ -0,0 +1,43 @@ +/* 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. */ + +/** + * Responsible for creating Store method and Action method + */ +import {create} from 'zustand'; +import {persist} from "zustand/middleware"; +import type {State} from './initialState'; +import {initialState} from './initialState'; + +interface Action { + resetUser: () => void; +} + +export type Store = State & Action; + +export const useStore = create()(persist( + (set) => ({ + ...initialState, + + resetUser: () => { + set({}); + }, + + }), { + name: 'app-storage' + } +)) \ No newline at end of file diff --git a/paimon-web-ui/src/store/index.ts b/paimon-web-ui/src/store/index.ts new file mode 100644 index 000000000..a6019f6a7 --- /dev/null +++ b/paimon-web-ui/src/store/index.ts @@ -0,0 +1,20 @@ +/* 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 {useStore} from './createStore'; +export type {Store} from './createStore'; +export type {State} from './initialState'; \ No newline at end of file diff --git a/paimon-web-ui/src/store/initialState.ts b/paimon-web-ui/src/store/initialState.ts new file mode 100644 index 000000000..3d0bcd0a5 --- /dev/null +++ b/paimon-web-ui/src/store/initialState.ts @@ -0,0 +1,39 @@ +/* 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. */ + +/** + * Responsible for State - adding state types and initializing state values. + */ +import {CatalogItem} from "@src/types/Catalog/data"; + +export const initCatalogItem: CatalogItem = { + id: 0, + catalogName: '', + catalogType: '', + warehouse: '', + hiveUri: '', + hiveConfDir: '', + isDelete: false, + createTime: new Date(), + updateTime: new Date(), +} + +export type State = CatalogItem + +export const initialState: State = { + ...initCatalogItem +} \ No newline at end of file diff --git a/paimon-web-ui/src/store/useState.ts b/paimon-web-ui/src/store/useState.ts new file mode 100644 index 000000000..409d53b47 --- /dev/null +++ b/paimon-web-ui/src/store/useState.ts @@ -0,0 +1,21 @@ +/* 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. */ + +/** + * Custom state hooks + */ + diff --git a/paimon-web-ui/src/types/Catalog/data.d.ts b/paimon-web-ui/src/types/Catalog/data.d.ts new file mode 100644 index 000000000..2bf4e516c --- /dev/null +++ b/paimon-web-ui/src/types/Catalog/data.d.ts @@ -0,0 +1,30 @@ +/* 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 type CatalogItem = { + id: number, + catalogName: string, + catalogType: string, + warehouse: string, + hiveUri: string, + hiveConfDir: string, + isDelete: boolean, + createTime: Date, + updateTime: Date +} + +export type CatalogItemList = CatalogItem[]; \ No newline at end of file From 9098bf520f3edfebf83554255ed211812c6a8794 Mon Sep 17 00:00:00 2001 From: s7monk <“15512826113@163.com”> Date: Tue, 15 Aug 2023 11:08:05 +0800 Subject: [PATCH 3/6] add meta data --- .../web/api/catalog/CatalogCreatorTest.java | 2 +- .../web/server/configrue/CorsConfig.java | 6 +- .../web/server/configrue/JacksonConfig.java | 10 +- .../server/configrue/SaTokenConfigure.java | 3 +- .../server/controller/CatalogController.java | 7 +- .../web/server/data/model/CatalogInfo.java | 5 +- .../web/server/mapper/CatalogMapper.java | 6 +- .../web/server/service/CatalogService.java | 3 +- .../service/impl/CatalogServiceImpl.java | 9 +- .../src/main/resources/db/dml-h2.sql | 7 +- paimon-web-ui/src/api/api.ts | 2 +- .../components/CatalogTree/index.tsx | 139 ++++-------------- paimon-web-ui/src/store/catalogStore.ts | 72 +++++++++ paimon-web-ui/src/store/createStore.ts | 42 +++++- paimon-web-ui/src/store/initialState.ts | 16 +- 15 files changed, 180 insertions(+), 149 deletions(-) create mode 100644 paimon-web-ui/src/store/catalogStore.ts diff --git a/paimon-web-api/src/test/java/org/apache/paimon/web/api/catalog/CatalogCreatorTest.java b/paimon-web-api/src/test/java/org/apache/paimon/web/api/catalog/CatalogCreatorTest.java index e3e4047ba..5d1d42a4c 100644 --- a/paimon-web-api/src/test/java/org/apache/paimon/web/api/catalog/CatalogCreatorTest.java +++ b/paimon-web-api/src/test/java/org/apache/paimon/web/api/catalog/CatalogCreatorTest.java @@ -33,7 +33,7 @@ public class CatalogCreatorTest { @Test public void testCreateFileSystemCatalog() { - //String warehouse = tempFile.toUri().toString(); + // String warehouse = tempFile.toUri().toString(); String warehouse = "file://D:/path/"; Catalog catalog = CatalogCreator.createFilesystemCatalog(warehouse); assertThat(catalog).isInstanceOf(FileSystemCatalog.class); diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/CorsConfig.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/CorsConfig.java index 60a4aed9a..7fff0b23f 100644 --- a/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/CorsConfig.java +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/CorsConfig.java @@ -21,13 +21,13 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; +/** CorsConfig. */ @Slf4j -//@Configuration +// @Configuration public class CorsConfig { @Bean @@ -42,6 +42,4 @@ public CorsFilter corsFilter() { source.registerCorsConfiguration("/**", corsConfiguration); return new CorsFilter(source); } - - } diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/JacksonConfig.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/JacksonConfig.java index f592c66a1..2f7b2fbce 100644 --- a/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/JacksonConfig.java +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/JacksonConfig.java @@ -30,16 +30,20 @@ import java.text.SimpleDateFormat; +/** JacksonConfig. */ @Configuration public class JacksonConfig { @Bean public ObjectMapper getJacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { ObjectMapper objectMapper = builder.createXmlMapper(false).build(); // When the sequence is changed to json, all longs will be changed to strings. - // Because the numeric type in js cannot contain all java long values, precision will be lost after more than 16 digits. + // Because the numeric type in js cannot contain all java long values, precision will be + // lost after more than 16 digits. SimpleModule simpleModule = new SimpleModule(); - simpleModule.addSerializer(Long.class, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance); - simpleModule.addSerializer(Long.TYPE, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance); + simpleModule.addSerializer( + Long.class, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance); + simpleModule.addSerializer( + Long.TYPE, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance); objectMapper.registerModule(simpleModule); // If there are more attributes during deserialization, no exception will be thrown. objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/SaTokenConfigure.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/SaTokenConfigure.java index 05a6de82b..24970377c 100644 --- a/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/SaTokenConfigure.java +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/configrue/SaTokenConfigure.java @@ -21,12 +21,11 @@ import cn.dev33.satoken.interceptor.SaInterceptor; import cn.dev33.satoken.stp.StpUtil; -import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** Sa-Token path config. */ -//@Configuration +// @Configuration public class SaTokenConfigure implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/CatalogController.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/CatalogController.java index 2014fb279..ef954b45f 100644 --- a/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/CatalogController.java +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/CatalogController.java @@ -18,12 +18,13 @@ package org.apache.paimon.web.server.controller; -import lombok.extern.slf4j.Slf4j; import org.apache.paimon.web.api.catalog.CatalogCreator; import org.apache.paimon.web.server.data.model.CatalogInfo; import org.apache.paimon.web.server.data.result.R; import org.apache.paimon.web.server.data.result.enums.Status; import org.apache.paimon.web.server.service.CatalogService; + +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -39,8 +40,7 @@ @RequestMapping("/api/catalog") public class CatalogController { - @Autowired - private CatalogService catalogService; + @Autowired private CatalogService catalogService; /** * Create a filesystem catalog. @@ -97,5 +97,4 @@ public R> getCatalog() { List catalogs = catalogService.list(); return R.succeed(catalogs); } - } diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/model/CatalogInfo.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/model/CatalogInfo.java index 12ab8757d..a90885a3f 100644 --- a/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/model/CatalogInfo.java +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/data/model/CatalogInfo.java @@ -33,7 +33,7 @@ @AllArgsConstructor @EqualsAndHashCode(callSuper = true) @TableName("catalog") -public class CatalogInfo extends BaseModel{ +public class CatalogInfo extends BaseModel { private String catalogType; @@ -45,6 +45,5 @@ public class CatalogInfo extends BaseModel{ private String hiveConfDir; - @TableLogic - private boolean isDelete; + @TableLogic private boolean isDelete; } diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/mapper/CatalogMapper.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/mapper/CatalogMapper.java index 87753d3b5..6d4c922a3 100644 --- a/paimon-web-server/src/main/java/org/apache/paimon/web/server/mapper/CatalogMapper.java +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/mapper/CatalogMapper.java @@ -18,11 +18,11 @@ package org.apache.paimon.web.server.mapper; +import org.apache.paimon.web.server.data.model.CatalogInfo; + import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; -import org.apache.paimon.web.server.data.model.CatalogInfo; /** Catalog table mapper. */ @Mapper -public interface CatalogMapper extends BaseMapper { -} +public interface CatalogMapper extends BaseMapper {} diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/CatalogService.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/CatalogService.java index b29ccbc06..ecba5a12d 100644 --- a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/CatalogService.java +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/CatalogService.java @@ -18,9 +18,10 @@ package org.apache.paimon.web.server.service; -import com.baomidou.mybatisplus.extension.service.IService; import org.apache.paimon.web.server.data.model.CatalogInfo; +import com.baomidou.mybatisplus.extension.service.IService; + /** Catalog Service. */ public interface CatalogService extends IService { diff --git a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/CatalogServiceImpl.java b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/CatalogServiceImpl.java index ba9af0357..316459abe 100644 --- a/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/CatalogServiceImpl.java +++ b/paimon-web-server/src/main/java/org/apache/paimon/web/server/service/impl/CatalogServiceImpl.java @@ -18,20 +18,23 @@ package org.apache.paimon.web.server.service.impl; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.apache.paimon.web.server.data.model.CatalogInfo; import org.apache.paimon.web.server.mapper.CatalogMapper; import org.apache.paimon.web.server.service.CatalogService; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; /** CatalogServiceImpl. */ @Service -public class CatalogServiceImpl extends ServiceImpl implements CatalogService { +public class CatalogServiceImpl extends ServiceImpl + implements CatalogService { @Override public boolean checkCatalogNameUnique(CatalogInfo catalog) { int catalogId = catalog.getId() == null ? -1 : catalog.getId(); - CatalogInfo info = this.lambdaQuery().eq(CatalogInfo::getCatalogName, catalog.getCatalogName()).one(); + CatalogInfo info = + this.lambdaQuery().eq(CatalogInfo::getCatalogName, catalog.getCatalogName()).one(); return info == null || info.getId() == catalogId; } } diff --git a/paimon-web-server/src/main/resources/db/dml-h2.sql b/paimon-web-server/src/main/resources/db/dml-h2.sql index a8b0c5492..6b0cfa65d 100644 --- a/paimon-web-server/src/main/resources/db/dml-h2.sql +++ b/paimon-web-server/src/main/resources/db/dml-h2.sql @@ -59,4 +59,9 @@ values (1, 1), (1, 1001), (1, 1002), (1, 1003), - (1, 1004); \ No newline at end of file + (1, 1004); + +insert into `catalog` (catalog_type, catalog_name, warehouse) +values ('filesystem', 'paimon', 'file:///D:/path/'), + ('filesystem', 'fts', 'file:///D:/path/'), + ('filesystem', 'streaming_warehouse', 'file:///D:/path/') diff --git a/paimon-web-ui/src/api/api.ts b/paimon-web-ui/src/api/api.ts index d34cf718e..679728c33 100644 --- a/paimon-web-ui/src/api/api.ts +++ b/paimon-web-ui/src/api/api.ts @@ -39,7 +39,7 @@ export const createHiveCatalog = async (catalogProp: Prop.CatalogProp) => { export const getAllCatalogs = async () => { try { return await http.httpGet, null>(API_ENDPOINTS.GET_ALL_CATALOGS) - } catch (error) { + } catch (error: any) { console.error('Failed to get catalogs:', error); } } diff --git a/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogTree/index.tsx b/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogTree/index.tsx index 0c1e1c284..709d82be6 100644 --- a/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogTree/index.tsx +++ b/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogTree/index.tsx @@ -16,116 +16,41 @@ specific language governing permissions and limitations under the License. */ import {Input, Tree} from '@douyinfe/semi-ui'; -import { IconSearch } from "@douyinfe/semi-icons"; +import { IconSearch, IconFile } from "@douyinfe/semi-icons"; +import Api from "@api/api.ts"; +import {useEffect, useState} from "react"; import styles from "./catalog-tree.module.less" const CatalogTree = () => { - const treeData = [ - { - label: 'paimon_catalog_01', - value: 'catalog01', - key: '0', - children: [ - { - label: 'paimon_db_01', - value: 'db01', - key: '0-0', - children: [ - { - label: 'paimon_table_01', - value: 'paimon_table_01', - key: '0-0-0', - }, - { - label: 'paimon_table_02', - value: 'paimon_table_02', - key: '0-1-0', - }, - { - label: 'paimon_table_03', - value: 'paimon_table_03', - key: '0-2-0', - }, - { - label: 'paimon_table_04', - value: 'paimon_table_04', - key: '0-3-0', - }, - { - label: 'paimon_table_05', - value: 'paimon_table_05', - key: '0-4-0', - }, - ], - }, - { - label: 'paimon_db_02', - value: 'paimon_db_02', - key: '0-1', - children: [ - { - label: 'Osaka', - value: 'Osaka', - key: '0-1-0' - } - ] - }, - { - label: 'paimon_db_03', - value: 'paimon_db_03', - key: '0-2', - children: [ - { - label: 'Beijing', - value: 'Beijing', - key: '0-2-0', - }, - ], - }, - { - label: 'paimon_db_04', - value: 'paimon_db_04', - key: '0-3', - children: [ - { - label: 'Beijing', - value: 'Beijing', - key: '0-3-0', - }, - ], - }, - { - label: 'paimon_db_05', - value: 'paimon_db_05', - key: '0-4', - children: [ - { - label: 'Beijing', - value: 'Beijing', - key: '0-4-0', - }, - ], - }, - ], - }, - { - label: 'paimon_catalog_02', - value: 'paimon_catalog_02', - key: '1', - children: [ - { - label: 'United States', - value: 'United States', - key: '1-0' - }, - { - label: 'Canada', - value: 'Canada', - key: '1-1' + + type TreeDataItem = { + label: string; + value: string; + key: string; + children?: TreeDataItem[]; + }; + + const [treeData, setTreeData] = useState([]); + + useEffect(() => { + const fetchData = async () => { + try { + const result = await Api.getAllCatalogs(); + if (result && result.data) { + const transformedData = result.data.map(item => ({ + label: item.catalogName, + value: item.catalogName, + key: item.id.toString(), + })); + setTreeData(transformedData); } - ] - } - ]; + } catch (error) { + console.error('Failed to get catalogs:', error); + } + }; + + fetchData(); + }, []); const renderLabel = (x: any) => { const className = x.className; @@ -141,7 +66,7 @@ const CatalogTree = () => { role="treeitem" onClick={isLeaf ? onClick : onExpand} > - {isLeaf ? null : expandIcon} + {isLeaf ? : expandIcon} {label} ); diff --git a/paimon-web-ui/src/store/catalogStore.ts b/paimon-web-ui/src/store/catalogStore.ts new file mode 100644 index 000000000..84ab2d0d4 --- /dev/null +++ b/paimon-web-ui/src/store/catalogStore.ts @@ -0,0 +1,72 @@ +/* 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. */ + +import {create} from 'zustand'; +import {persist} from "zustand/middleware"; +import Result = API.Result; +import {CatalogItemList} from "@src/types/Catalog/data"; +import Api from "@api/api.ts"; +import {Toast} from "@douyinfe/semi-ui"; + +type Store = { + catalogItemList: CatalogItemList[]; + createFileSystemCatalog: (catalogProp: Prop.CatalogProp) => Promise; + createHiveCatalog: (catalogProp: Prop.CatalogProp) => Promise; +}; + +export const useCatalogStore = create()(persist( + (set) => ({ + catalogItemList: [], + createFileSystemCatalog: async (catalogProp) => { + try { + const response = await Api.createFileSystemCatalog(catalogProp); + if (!response) { + throw new Error('No response from createFileSystemCatalog'); + } + if (response.code === 200) { + Toast.success('Catalog created successfully!'); + } else { + console.error('Failed to create catalog:', response.msg); + Toast.error('Failed to create catalog:' + response.msg); + } + } catch (error) { + console.error('Failed to create catalog:', error); + Toast.error('Failed to create catalog:' + error); + } + }, + createHiveCatalog: async (catalogProp) => { + try { + const response = await Api.createHiveCatalog(catalogProp); + if (!response) { + throw new Error('No response from createFileSystemCatalog'); + } + if (response.code === 200) { + Toast.success('Catalog created successfully!'); + //set((state) => state.fetchTreeData()); + } else { + console.error('Failed to create catalog:', response.msg); + Toast.error('Failed to create catalog:' + response.msg); + } + } catch (error) { + console.error('Failed to create catalog:', error); + Toast.error('Failed to create catalog:' + error); + } + }, + }),{ + name: 'catalog-storage' + } +)) \ No newline at end of file diff --git a/paimon-web-ui/src/store/createStore.ts b/paimon-web-ui/src/store/createStore.ts index 8d9466928..7944c04c4 100644 --- a/paimon-web-ui/src/store/createStore.ts +++ b/paimon-web-ui/src/store/createStore.ts @@ -22,9 +22,12 @@ import {create} from 'zustand'; import {persist} from "zustand/middleware"; import type {State} from './initialState'; import {initialState} from './initialState'; +import Api from "@api/api.ts"; +import {Toast} from "@douyinfe/semi-ui"; interface Action { - resetUser: () => void; + createFileSystemCatalog: (catalogProp: Prop.CatalogProp) => Promise; + createHiveCatalog: (catalogProp: Prop.CatalogProp) => Promise; } export type Store = State & Action; @@ -33,8 +36,41 @@ export const useStore = create()(persist( (set) => ({ ...initialState, - resetUser: () => { - set({}); + createFileSystemCatalog: async (catalogProp) => { + try { + const response = await Api.createFileSystemCatalog(catalogProp); + if (!response) { + throw new Error('No response from createFileSystemCatalog'); + } + if (response.code === 200) { + Toast.success('Catalog created successfully!'); + //set((state) => state.fetchTreeData()); + } else { + console.error('Failed to create catalog:', response.msg); + Toast.error('Failed to create catalog:' + response.msg); + } + } catch (error) { + console.error('Failed to create catalog:', error); + Toast.error('Failed to create catalog:' + error); + } + }, + createHiveCatalog: async (catalogProp) => { + try { + const response = await Api.createHiveCatalog(catalogProp); + if (!response) { + throw new Error('No response from createFileSystemCatalog'); + } + if (response.code === 200) { + Toast.success('Catalog created successfully!'); + //set((state) => state.fetchTreeData()); + } else { + console.error('Failed to create catalog:', response.msg); + Toast.error('Failed to create catalog:' + response.msg); + } + } catch (error) { + console.error('Failed to create catalog:', error); + Toast.error('Failed to create catalog:' + error); + } }, }), { diff --git a/paimon-web-ui/src/store/initialState.ts b/paimon-web-ui/src/store/initialState.ts index 3d0bcd0a5..6e16ca529 100644 --- a/paimon-web-ui/src/store/initialState.ts +++ b/paimon-web-ui/src/store/initialState.ts @@ -18,21 +18,11 @@ under the License. */ /** * Responsible for State - adding state types and initializing state values. */ -import {CatalogItem} from "@src/types/Catalog/data"; +import {CatalogItemList} from "@src/types/Catalog/data"; -export const initCatalogItem: CatalogItem = { - id: 0, - catalogName: '', - catalogType: '', - warehouse: '', - hiveUri: '', - hiveConfDir: '', - isDelete: false, - createTime: new Date(), - updateTime: new Date(), -} +export const initCatalogItem: CatalogItemList = []; -export type State = CatalogItem +export type State = CatalogItemList; export const initialState: State = { ...initCatalogItem From bb6ac69ca17dfee39c6daf1fea8bbee85dd3ae43 Mon Sep 17 00:00:00 2001 From: s7monk <“15512826113@163.com”> Date: Tue, 15 Aug 2023 11:25:32 +0800 Subject: [PATCH 4/6] fix ci error --- .../org/apache/paimon/web/api/catalog/CatalogCreatorTest.java | 3 +-- pom.xml | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/paimon-web-api/src/test/java/org/apache/paimon/web/api/catalog/CatalogCreatorTest.java b/paimon-web-api/src/test/java/org/apache/paimon/web/api/catalog/CatalogCreatorTest.java index 5d1d42a4c..a472ade28 100644 --- a/paimon-web-api/src/test/java/org/apache/paimon/web/api/catalog/CatalogCreatorTest.java +++ b/paimon-web-api/src/test/java/org/apache/paimon/web/api/catalog/CatalogCreatorTest.java @@ -33,8 +33,7 @@ public class CatalogCreatorTest { @Test public void testCreateFileSystemCatalog() { - // String warehouse = tempFile.toUri().toString(); - String warehouse = "file://D:/path/"; + String warehouse = tempFile.toUri().toString(); Catalog catalog = CatalogCreator.createFilesystemCatalog(warehouse); assertThat(catalog).isInstanceOf(FileSystemCatalog.class); } diff --git a/pom.xml b/pom.xml index 1194f2474..028091e6f 100644 --- a/pom.xml +++ b/pom.xml @@ -435,6 +435,9 @@ under the License. org.apache.maven.plugins maven-surefire-plugin ${maven-surefire-plugin.version} + + true + org.apache.maven.plugins From fb86d0db0e86a41d9b40b6835f0ce529d7c977d8 Mon Sep 17 00:00:00 2001 From: s7monk <“15512826113@163.com”> Date: Tue, 15 Aug 2023 13:04:00 +0800 Subject: [PATCH 5/6] fix ci error --- paimon-web-ui/index.html | 2 +- paimon-web-ui/package.json | 2 -- paimon-web-ui/src/pages/Layout/Header/index.tsx | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/paimon-web-ui/index.html b/paimon-web-ui/index.html index 49b9c5575..6d0b55bdc 100644 --- a/paimon-web-ui/index.html +++ b/paimon-web-ui/index.html @@ -23,7 +23,7 @@ - 巴别实时计算平台 + Apache Paimon
diff --git a/paimon-web-ui/package.json b/paimon-web-ui/package.json index fa6b4180d..7fe653762 100644 --- a/paimon-web-ui/package.json +++ b/paimon-web-ui/package.json @@ -24,8 +24,6 @@ "react-bootstrap": "^2.8.0", "react-dom": "^18.2.0", "react-icons": "^4.10.1", - "react-redux": "^8.1.2", - "redux": "^4.2.1", "zustand": "^4.4.1" }, "devDependencies": { diff --git a/paimon-web-ui/src/pages/Layout/Header/index.tsx b/paimon-web-ui/src/pages/Layout/Header/index.tsx index e4d033f13..34910088b 100644 --- a/paimon-web-ui/src/pages/Layout/Header/index.tsx +++ b/paimon-web-ui/src/pages/Layout/Header/index.tsx @@ -64,7 +64,7 @@ const HeaderRoot = ()=> { header={{ logo: Apache Paimon, - text: '巴别实时计算平台' + text: 'Apache Paimon' }} mode={"horizontal"} defaultSelectedKeys={['Home']} From 5226e5d60db9a9446410b1832f78edbb514ed17d Mon Sep 17 00:00:00 2001 From: s7monk <“15512826113@163.com”> Date: Tue, 15 Aug 2023 15:34:08 +0800 Subject: [PATCH 6/6] handle state --- .../components/CatalogTree/index.tsx | 33 ++++---- .../Metadata/components/LeftContent/index.tsx | 46 +++-------- paimon-web-ui/src/store/catalogStore.ts | 28 ++++++- paimon-web-ui/src/store/createStore.ts | 79 ------------------- paimon-web-ui/src/store/index.ts | 20 ----- paimon-web-ui/src/store/initialState.ts | 29 ------- paimon-web-ui/src/store/useState.ts | 21 ----- 7 files changed, 53 insertions(+), 203 deletions(-) delete mode 100644 paimon-web-ui/src/store/createStore.ts delete mode 100644 paimon-web-ui/src/store/index.ts delete mode 100644 paimon-web-ui/src/store/initialState.ts delete mode 100644 paimon-web-ui/src/store/useState.ts diff --git a/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogTree/index.tsx b/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogTree/index.tsx index 709d82be6..e3fdd71f7 100644 --- a/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogTree/index.tsx +++ b/paimon-web-ui/src/pages/Metadata/components/LeftContent/components/CatalogTree/index.tsx @@ -17,9 +17,9 @@ under the License. */ import {Input, Tree} from '@douyinfe/semi-ui'; import { IconSearch, IconFile } from "@douyinfe/semi-icons"; -import Api from "@api/api.ts"; import {useEffect, useState} from "react"; import styles from "./catalog-tree.module.less" +import { useCatalogStore } from "@src/store/catalogStore.ts"; const CatalogTree = () => { @@ -31,26 +31,23 @@ const CatalogTree = () => { }; const [treeData, setTreeData] = useState([]); + const fetchCatalogData = useCatalogStore(state => state.fetchCatalogData); + const catalogItemList = useCatalogStore(state => state.catalogItemList); useEffect(() => { - const fetchData = async () => { - try { - const result = await Api.getAllCatalogs(); - if (result && result.data) { - const transformedData = result.data.map(item => ({ - label: item.catalogName, - value: item.catalogName, - key: item.id.toString(), - })); - setTreeData(transformedData); - } - } catch (error) { - console.error('Failed to get catalogs:', error); - } - }; + // Fetch the catalog data when the component mounts + fetchCatalogData(); + }, [fetchCatalogData]); - fetchData(); - }, []); + useEffect(() => { + // Update treeData when catalogItemList changes + const transformedData = catalogItemList.map(item => ({ + label: item.catalogName, + value: item.catalogName, + key: item.id.toString(), + })); + setTreeData(transformedData); + }, [catalogItemList]); const renderLabel = (x: any) => { const className = x.className; diff --git a/paimon-web-ui/src/pages/Metadata/components/LeftContent/index.tsx b/paimon-web-ui/src/pages/Metadata/components/LeftContent/index.tsx index b56737d48..b03a999fa 100644 --- a/paimon-web-ui/src/pages/Metadata/components/LeftContent/index.tsx +++ b/paimon-web-ui/src/pages/Metadata/components/LeftContent/index.tsx @@ -16,16 +16,18 @@ specific language governing permissions and limitations under the License. */ import { IconPlus } from "@douyinfe/semi-icons"; -import { Toast } from '@douyinfe/semi-ui'; import CatalogTree from "@pages/Metadata/components/LeftContent/components/CatalogTree"; -import {useState} from "react"; +import { useState } from "react"; import CatalogModalForm from "@pages/Metadata/components/LeftContent/components/CatalogModalForm"; -import Api from "@api/api.ts"; +import {useCatalogStore} from "@src/store/catalogStore.ts"; import styles from "./left-content.module.less"; const MetadataSidebar = () => { const [showModal, setShowModal] = useState(false); + const createFilesystemCatalog = useCatalogStore(state => state.createFileSystemCatalog); + const createHiveCatalog = useCatalogStore(state => state.createHiveCatalog); + const fetchCatalogData = useCatalogStore(state => state.fetchCatalogData); const handleOpenModal = () => { setShowModal(true); @@ -53,38 +55,16 @@ const MetadataSidebar = () => { }; if (formData.catalogType === 'filesystem') { - Api.createFileSystemCatalog(catalogProp) - .then((response: any) => { - if (response.code === 200) { - Toast.success('Catalog created successfully!'); - resolve(); // Resolve the promise when done - } else { - console.error('Failed to create catalog:', response.msg); - Toast.error('Failed to create catalog:' + response.msg); - reject(response.message); // Reject the promise on error - } - }) - .catch((error: any) => { - console.error('Failed to create catalog:', error); - Toast.error('Failed to create catalog:' + error); - reject(error); // Reject the promise on error + createFilesystemCatalog(catalogProp) + .then(() => { + fetchCatalogData(); + resolve(); }) } else { - Api.createHiveCatalog(catalogProp) - .then((response: any) => { - if (response.code === 200) { - Toast.success('Catalog created successfully!'); - resolve(); // Resolve the promise when done - } else { - console.error('Failed to create catalog:', response.msg); - Toast.error('Failed to create catalog:' + response.msg); - reject(response.message); // Reject the promise on error - } - }) - .catch((error: any) => { - console.error('Failed to create catalog:', error); - Toast.error('Failed to create catalog:' + error); - reject(error); // Reject the promise on error + createHiveCatalog(catalogProp) + .then(() => { + fetchCatalogData(); + resolve(); }) } resolve(); diff --git a/paimon-web-ui/src/store/catalogStore.ts b/paimon-web-ui/src/store/catalogStore.ts index 84ab2d0d4..a1efcf8f8 100644 --- a/paimon-web-ui/src/store/catalogStore.ts +++ b/paimon-web-ui/src/store/catalogStore.ts @@ -17,15 +17,15 @@ under the License. */ import {create} from 'zustand'; import {persist} from "zustand/middleware"; -import Result = API.Result; import {CatalogItemList} from "@src/types/Catalog/data"; import Api from "@api/api.ts"; import {Toast} from "@douyinfe/semi-ui"; type Store = { - catalogItemList: CatalogItemList[]; + catalogItemList: CatalogItemList; createFileSystemCatalog: (catalogProp: Prop.CatalogProp) => Promise; createHiveCatalog: (catalogProp: Prop.CatalogProp) => Promise; + fetchCatalogData: () => Promise; }; export const useCatalogStore = create()(persist( @@ -56,7 +56,6 @@ export const useCatalogStore = create()(persist( } if (response.code === 200) { Toast.success('Catalog created successfully!'); - //set((state) => state.fetchTreeData()); } else { console.error('Failed to create catalog:', response.msg); Toast.error('Failed to create catalog:' + response.msg); @@ -66,6 +65,29 @@ export const useCatalogStore = create()(persist( Toast.error('Failed to create catalog:' + error); } }, + fetchCatalogData: async () => { + try { + const result = await Api.getAllCatalogs(); + if (result && result.data) { + const newCatalogItemList = result.data.map((item) => { + return { + id: item.id, + catalogName: item.catalogName, + catalogType: item.catalogType, + warehouse: item.warehouse, + hiveUri: item.hiveUri, + hiveConfDir: item.hiveConfDir, + isDelete: item.isDelete, + createTime: item.createTime, + updateTime: item.updateTime + }; + }); + set((state) => ({ ...state, catalogItemList: newCatalogItemList })); + } + } catch (error) { + console.error('Failed to get catalogs:', error); + } + }, }),{ name: 'catalog-storage' } diff --git a/paimon-web-ui/src/store/createStore.ts b/paimon-web-ui/src/store/createStore.ts deleted file mode 100644 index 7944c04c4..000000000 --- a/paimon-web-ui/src/store/createStore.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* 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. */ - -/** - * Responsible for creating Store method and Action method - */ -import {create} from 'zustand'; -import {persist} from "zustand/middleware"; -import type {State} from './initialState'; -import {initialState} from './initialState'; -import Api from "@api/api.ts"; -import {Toast} from "@douyinfe/semi-ui"; - -interface Action { - createFileSystemCatalog: (catalogProp: Prop.CatalogProp) => Promise; - createHiveCatalog: (catalogProp: Prop.CatalogProp) => Promise; -} - -export type Store = State & Action; - -export const useStore = create()(persist( - (set) => ({ - ...initialState, - - createFileSystemCatalog: async (catalogProp) => { - try { - const response = await Api.createFileSystemCatalog(catalogProp); - if (!response) { - throw new Error('No response from createFileSystemCatalog'); - } - if (response.code === 200) { - Toast.success('Catalog created successfully!'); - //set((state) => state.fetchTreeData()); - } else { - console.error('Failed to create catalog:', response.msg); - Toast.error('Failed to create catalog:' + response.msg); - } - } catch (error) { - console.error('Failed to create catalog:', error); - Toast.error('Failed to create catalog:' + error); - } - }, - createHiveCatalog: async (catalogProp) => { - try { - const response = await Api.createHiveCatalog(catalogProp); - if (!response) { - throw new Error('No response from createFileSystemCatalog'); - } - if (response.code === 200) { - Toast.success('Catalog created successfully!'); - //set((state) => state.fetchTreeData()); - } else { - console.error('Failed to create catalog:', response.msg); - Toast.error('Failed to create catalog:' + response.msg); - } - } catch (error) { - console.error('Failed to create catalog:', error); - Toast.error('Failed to create catalog:' + error); - } - }, - - }), { - name: 'app-storage' - } -)) \ No newline at end of file diff --git a/paimon-web-ui/src/store/index.ts b/paimon-web-ui/src/store/index.ts deleted file mode 100644 index a6019f6a7..000000000 --- a/paimon-web-ui/src/store/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* 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 {useStore} from './createStore'; -export type {Store} from './createStore'; -export type {State} from './initialState'; \ No newline at end of file diff --git a/paimon-web-ui/src/store/initialState.ts b/paimon-web-ui/src/store/initialState.ts deleted file mode 100644 index 6e16ca529..000000000 --- a/paimon-web-ui/src/store/initialState.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* 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. */ - -/** - * Responsible for State - adding state types and initializing state values. - */ -import {CatalogItemList} from "@src/types/Catalog/data"; - -export const initCatalogItem: CatalogItemList = []; - -export type State = CatalogItemList; - -export const initialState: State = { - ...initCatalogItem -} \ No newline at end of file diff --git a/paimon-web-ui/src/store/useState.ts b/paimon-web-ui/src/store/useState.ts deleted file mode 100644 index 409d53b47..000000000 --- a/paimon-web-ui/src/store/useState.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* 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. */ - -/** - * Custom state hooks - */ -