From 5df5cf78c67981fce890850ebe5224a7f025403e Mon Sep 17 00:00:00 2001 From: akageun <13219787+akageun@users.noreply.github.com> Date: Mon, 23 Sep 2024 22:59:56 +0900 Subject: [PATCH] Apply Table Import (#116) * Table import --- cassdio-core/build.gradle | 3 +- .../cassdio/common/utils/CsvHelper.java | 10 ++ .../keyspace/table/ClusterCsvProvider.java | 69 +++++++++ .../table/ClusterTableCsvProvider.java | 36 +++++ .../table/ClusterTableRowCommander.java | 31 ++++ .../cluster/keyspace/table/TableDTO.java | 30 ++++ .../column/ClusterTableColumnCommander.java | 8 +- .../keyspace/table/ClusterTableApi.java | 26 +--- .../keyspace/table/ClusterTableRequest.java | 28 ++++ .../keyspace/table/ClusterTableRowApi.java | 128 ++++++++++++++++ .../cluster/modal/table-detail-modal.js | 1 - .../cluster/modal/table-import-modal.js | 137 +++++++++++++++++- .../src/pages/cluster/cluster-table-page.js | 36 +++-- .../src/remotes/clusterTableRowImportApi.js | 18 +++ 14 files changed, 512 insertions(+), 49 deletions(-) create mode 100644 cassdio-core/src/main/java/kr/hakdang/cassdio/common/utils/CsvHelper.java create mode 100644 cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterCsvProvider.java create mode 100644 cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterTableCsvProvider.java create mode 100644 cassdio-web/src/main/java/kr/hakdang/cassdio/web/route/cluster/keyspace/table/ClusterTableRequest.java create mode 100644 cassdio-web/src/main/java/kr/hakdang/cassdio/web/route/cluster/keyspace/table/ClusterTableRowApi.java create mode 100644 cassdio-web/src/main/webapp/src/remotes/clusterTableRowImportApi.js diff --git a/cassdio-core/build.gradle b/cassdio-core/build.gradle index d74798f6..1880952f 100644 --- a/cassdio-core/build.gradle +++ b/cassdio-core/build.gradle @@ -12,11 +12,12 @@ dependencies { // Json implementation("org.springframework.boot:spring-boot-starter-json") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.1") - + implementation("org.apache.commons:commons-csv:1.9.0") // CommonsLang3 api("org.apache.commons:commons-lang3:3.13.0") api("com.google.guava:guava:33.0.0-jre") api("org.apache.commons:commons-collections4:4.4") + api("org.apache.commons:commons-csv:1.9.0") // Cache implementation("org.springframework.boot:spring-boot-starter-cache") diff --git a/cassdio-core/src/main/java/kr/hakdang/cassdio/common/utils/CsvHelper.java b/cassdio-core/src/main/java/kr/hakdang/cassdio/common/utils/CsvHelper.java new file mode 100644 index 00000000..6348a6f8 --- /dev/null +++ b/cassdio-core/src/main/java/kr/hakdang/cassdio/common/utils/CsvHelper.java @@ -0,0 +1,10 @@ +package kr.hakdang.cassdio.common.utils; + +/** + * CsvHelper + * + * @author akageun + * @since 2024-08-19 + */ +public class CsvHelper { +} diff --git a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterCsvProvider.java b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterCsvProvider.java new file mode 100644 index 00000000..a33513b6 --- /dev/null +++ b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterCsvProvider.java @@ -0,0 +1,69 @@ +package kr.hakdang.cassdio.core.domain.cluster.keyspace.table; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.csv.CSVRecord; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * ClusterTableCsvProvider + * + * @author akageun + * @since 2024-08-08 + */ +@Slf4j +@Service +public class ClusterCsvProvider { + + public void importerCsvSampleDownload(Writer writer, List headerList) { + CSVFormat csvFormat = CSVFormat.DEFAULT.builder() + .setHeader(headerList.toArray(String[]::new)) + .build(); + + try (final CSVPrinter printer = new CSVPrinter(writer, csvFormat)) { + log.info("create complete importer csv sample"); + + printer.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + + public List> importCsvReader(Reader reader, List columnList) throws IOException { + CSVFormat csvFormat = CSVFormat.DEFAULT.builder() + .setHeader(columnList.toArray(String[]::new)) + .setSkipHeaderRecord(true) + .setTrim(true) + .build(); + + Iterable records = csvFormat.parse(reader); + //Validation 방식에 대해 고민 필요 + + List> values = new ArrayList<>(); + + for (CSVRecord record : records) { + + Map map = new HashMap<>(); + + for (String column : columnList) { + map.put(column, StringUtils.defaultIfBlank(record.get(column), "")); + } + + values.add(map); + } + + return values; + } + +} diff --git a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterTableCsvProvider.java b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterTableCsvProvider.java new file mode 100644 index 00000000..7b66fd4b --- /dev/null +++ b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterTableCsvProvider.java @@ -0,0 +1,36 @@ +package kr.hakdang.cassdio.core.domain.cluster.keyspace.table; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.io.Writer; +import java.util.List; + +/** + * ClusterTableCsvProvider + * + * @author akageun + * @since 2024-08-08 + */ +@Slf4j +@Service +public class ClusterTableCsvProvider { + + public void importerCsvSampleDownload(Writer writer, List sortedColumnList) { + CSVFormat csvFormat = CSVFormat.DEFAULT.builder() + .setHeader(sortedColumnList.toArray(String[]::new)) + .build(); + + try (final CSVPrinter printer = new CSVPrinter(writer, csvFormat)) { + //printer.printRecord(author, title); + log.info("create complete importer csv sample"); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + +} diff --git a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterTableRowCommander.java b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterTableRowCommander.java index f719e816..d2e996f2 100644 --- a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterTableRowCommander.java +++ b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/ClusterTableRowCommander.java @@ -1,18 +1,27 @@ package kr.hakdang.cassdio.core.domain.cluster.keyspace.table; import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.cql.BatchStatement; +import com.datastax.oss.driver.api.core.cql.DefaultBatchType; import com.datastax.oss.driver.api.core.cql.ResultSet; import com.datastax.oss.driver.api.core.cql.SimpleStatement; import com.datastax.oss.driver.api.querybuilder.QueryBuilder; +import com.datastax.oss.driver.api.querybuilder.insert.InsertInto; +import com.datastax.oss.driver.api.querybuilder.insert.JsonInsert; import com.datastax.oss.protocol.internal.util.Bytes; +import com.google.common.collect.Lists; +import kr.hakdang.cassdio.common.utils.Jsons; import kr.hakdang.cassdio.core.domain.cluster.BaseClusterCommander; import kr.hakdang.cassdio.core.domain.cluster.CqlSessionSelectResults; import kr.hakdang.cassdio.core.domain.cluster.keyspace.CassdioColumnDefinition; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import java.time.Duration; +import java.util.List; +import java.util.Map; /** * ClusterTableRowCommander @@ -42,4 +51,26 @@ public CqlSessionSelectResults rowSelect(String clusterId, TableDTO.ClusterTable resultSet.getExecutionInfo().getPagingState() ); } + + public void rowInserts(TableDTO.ClusterTableRowImportArgs args, List> values) { + if (CollectionUtils.isEmpty(values)) { + return; + } + + CqlSession session = cqlSessionFactory.get(args.getClusterId()); + + for (List> list : Lists.partition(values, args.getPerCommitSize())) { + BatchStatement batchStatement = BatchStatement.newInstance(args.getBatchType()); + + for (Map map : list) { + batchStatement = batchStatement.add( + QueryBuilder.insertInto(args.getKeyspace(), args.getTable()) + .json(Jsons.toJson(map)) + .build() + ); + } + + session.execute(batchStatement); + } + } } diff --git a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/TableDTO.java b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/TableDTO.java index 9e1fd985..60684792 100644 --- a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/TableDTO.java +++ b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/TableDTO.java @@ -1,11 +1,14 @@ package kr.hakdang.cassdio.core.domain.cluster.keyspace.table; +import com.datastax.oss.driver.api.core.cql.BatchType; +import com.datastax.oss.driver.api.core.cql.DefaultBatchType; import io.micrometer.common.util.StringUtils; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.ToString; +import org.apache.commons.lang3.EnumUtils; /** * ClusterTableArgs @@ -99,4 +102,31 @@ public ClusterTableRowArgs(String keyspace, String table, int pageSize, int time } } + @ToString + @Getter + @NoArgsConstructor(access = AccessLevel.PRIVATE) + public static class ClusterTableRowImportArgs { + private String clusterId; + private String keyspace; + private String table; + + private BatchType batchType; + private int perCommitSize = 50; + + @Builder + public ClusterTableRowImportArgs( + String clusterId, + String keyspace, + String table, + String batchTypeCode, + int perCommitSize + ) { + this.clusterId = clusterId; + this.keyspace = keyspace; + this.table = table; + this.batchType = EnumUtils.getEnum(DefaultBatchType.class, batchTypeCode); + this.perCommitSize = perCommitSize; + } + } + } diff --git a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/column/ClusterTableColumnCommander.java b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/column/ClusterTableColumnCommander.java index 71d3e02d..c83b4f46 100644 --- a/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/column/ClusterTableColumnCommander.java +++ b/cassdio-core/src/main/java/kr/hakdang/cassdio/core/domain/cluster/keyspace/table/column/ClusterTableColumnCommander.java @@ -13,13 +13,13 @@ import kr.hakdang.cassdio.core.domain.cluster.keyspace.CassdioColumnDefinition; import kr.hakdang.cassdio.core.domain.cluster.keyspace.table.CassandraSystemTable; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; import org.springframework.stereotype.Service; import java.time.Duration; import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import static com.datastax.oss.driver.api.querybuilder.QueryBuilder.bindMarker; import static java.util.Collections.emptyList; @@ -40,7 +40,6 @@ public CqlSessionSelectResults columnList(String clusterId, String keyspace, Str public CqlSessionSelectResults columnList(String clusterId, String keyspace, String table, List columnList) { CqlSession session = cqlSessionFactory.get(clusterId); - SimpleStatement statement; Select select = getColumnTable(session, keyspace) @@ -69,6 +68,11 @@ public CqlSessionSelectResults columnList(String clusterId, String keyspace, Str ); } + public List columnSortedList(String clusterId, String keyspace, String table) { + CqlSessionSelectResults results = columnList(clusterId, keyspace, table); + return results.getRows().stream().map(row -> String.valueOf(row.get("column_name"))).collect(Collectors.toList()); + } + private String makeSortValue(Map row) { ColumnKind columnKind = ColumnKind.findByCode(String.valueOf(row.get("kind"))); return String.format("%s-%s", columnKind.getOrder(), row.get("position")); diff --git a/cassdio-web/src/main/java/kr/hakdang/cassdio/web/route/cluster/keyspace/table/ClusterTableApi.java b/cassdio-web/src/main/java/kr/hakdang/cassdio/web/route/cluster/keyspace/table/ClusterTableApi.java index 372362c6..8c24f1c7 100644 --- a/cassdio-web/src/main/java/kr/hakdang/cassdio/web/route/cluster/keyspace/table/ClusterTableApi.java +++ b/cassdio-web/src/main/java/kr/hakdang/cassdio/web/route/cluster/keyspace/table/ClusterTableApi.java @@ -3,6 +3,7 @@ import jakarta.validation.Valid; import kr.hakdang.cassdio.core.domain.cluster.CqlSessionSelectResult; import kr.hakdang.cassdio.core.domain.cluster.CqlSessionSelectResults; +import kr.hakdang.cassdio.core.domain.cluster.keyspace.table.ClusterCsvProvider; import kr.hakdang.cassdio.core.domain.cluster.keyspace.table.ClusterTableCommander; import kr.hakdang.cassdio.core.domain.cluster.keyspace.table.ClusterTableGetCommander; import kr.hakdang.cassdio.core.domain.cluster.keyspace.table.ClusterTableListCommander; @@ -13,7 +14,6 @@ import kr.hakdang.cassdio.web.common.dto.response.ApiResponse; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -33,20 +33,19 @@ public class ClusterTableApi { private final ClusterTableCommander clusterTableCommander; private final ClusterTableListCommander clusterTableListCommander; private final ClusterTableGetCommander clusterTableGetCommander; - private final ClusterTableRowCommander clusterTableRowCommander; + private final ClusterTableColumnCommander clusterTableColumnCommander; + public ClusterTableApi( ClusterTableCommander clusterTableCommander, ClusterTableListCommander clusterTableListCommander, ClusterTableGetCommander clusterTableGetCommander, - ClusterTableRowCommander clusterTableRowCommander, ClusterTableColumnCommander clusterTableColumnCommander ) { this.clusterTableCommander = clusterTableCommander; this.clusterTableListCommander = clusterTableListCommander; this.clusterTableGetCommander = clusterTableGetCommander; - this.clusterTableRowCommander = clusterTableRowCommander; this.clusterTableColumnCommander = clusterTableColumnCommander; } @@ -106,25 +105,6 @@ public ApiResponse> getTableColumn( return ApiResponse.ok(responseMap); } - @GetMapping("/table/{table}/row") - public ApiResponse> tableRow( - @PathVariable String clusterId, - @PathVariable String keyspace, - @PathVariable String table, - @ModelAttribute ClusterTableRowRequest request - ) { - Map responseMap = new HashMap<>(); - CqlSessionSelectResults result1 = clusterTableRowCommander.rowSelect(clusterId, request.makeArgs(keyspace, table)); - - responseMap.put("nextCursor", result1.getNextCursor()); - responseMap.put("rows", result1.getRows()); - responseMap.put("rowHeader", result1.getRowHeader()); - - responseMap.put("columnList", clusterTableColumnCommander.columnList(clusterId, keyspace, table)); - - return ApiResponse.ok(responseMap); - } - //권한 추가해서 ADMIN 만 동작할 수 있도록 해야함. @DeleteMapping("/table/{table}/drop") public ApiResponse tableDrop( diff --git a/cassdio-web/src/main/java/kr/hakdang/cassdio/web/route/cluster/keyspace/table/ClusterTableRequest.java b/cassdio-web/src/main/java/kr/hakdang/cassdio/web/route/cluster/keyspace/table/ClusterTableRequest.java new file mode 100644 index 00000000..262ef7c8 --- /dev/null +++ b/cassdio-web/src/main/java/kr/hakdang/cassdio/web/route/cluster/keyspace/table/ClusterTableRequest.java @@ -0,0 +1,28 @@ +package kr.hakdang.cassdio.web.route.cluster.keyspace.table; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * ClusterTableRequest + * + * @author akageun + * @since 2024-08-19 + */ +public class ClusterTableRequest { + + @Getter + @NoArgsConstructor(access = AccessLevel.PRIVATE) + public static class TableRowImportRequest { + private int perCommitSize; + private String batchTypeCode; + + @Builder + public TableRowImportRequest(int perCommitSize, String batchTypeCode) { + this.perCommitSize = perCommitSize; + this.batchTypeCode = batchTypeCode; + } + } +} diff --git a/cassdio-web/src/main/java/kr/hakdang/cassdio/web/route/cluster/keyspace/table/ClusterTableRowApi.java b/cassdio-web/src/main/java/kr/hakdang/cassdio/web/route/cluster/keyspace/table/ClusterTableRowApi.java new file mode 100644 index 00000000..be5901b3 --- /dev/null +++ b/cassdio-web/src/main/java/kr/hakdang/cassdio/web/route/cluster/keyspace/table/ClusterTableRowApi.java @@ -0,0 +1,128 @@ +package kr.hakdang.cassdio.web.route.cluster.keyspace.table; + +import jakarta.servlet.http.HttpServletResponse; +import kr.hakdang.cassdio.core.domain.cluster.CqlSessionSelectResults; +import kr.hakdang.cassdio.core.domain.cluster.keyspace.table.ClusterCsvProvider; +import kr.hakdang.cassdio.core.domain.cluster.keyspace.table.ClusterTableRowCommander; +import kr.hakdang.cassdio.core.domain.cluster.keyspace.table.TableDTO; +import kr.hakdang.cassdio.core.domain.cluster.keyspace.table.column.ClusterTableColumnCommander; +import kr.hakdang.cassdio.web.common.dto.response.ApiResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static java.util.Collections.emptyMap; + +/** + * ClusterTableRowApi + * + * @author akageun + * @since 2024-08-19 + */ +@Slf4j +@RestController +@RequestMapping("/api/cassandra/cluster/{clusterId}/keyspace/{keyspace}") +public class ClusterTableRowApi { + + private final ClusterTableRowCommander clusterTableRowCommander; + private final ClusterCsvProvider clusterCsvProvider; + private final ClusterTableColumnCommander clusterTableColumnCommander; + + public ClusterTableRowApi( + ClusterTableRowCommander clusterTableRowCommander, + ClusterCsvProvider clusterCsvProvider, + ClusterTableColumnCommander clusterTableColumnCommander + ) { + this.clusterTableRowCommander = clusterTableRowCommander; + this.clusterCsvProvider = clusterCsvProvider; + this.clusterTableColumnCommander = clusterTableColumnCommander; + } + + @GetMapping("/table/{table}/row") + public ApiResponse> tableRow( + @PathVariable String clusterId, + @PathVariable String keyspace, + @PathVariable String table, + @ModelAttribute ClusterTableRowRequest request + ) { + Map responseMap = new HashMap<>(); + CqlSessionSelectResults result1 = clusterTableRowCommander.rowSelect(clusterId, request.makeArgs(keyspace, table)); + + responseMap.put("nextCursor", result1.getNextCursor()); + responseMap.put("rows", result1.getRows()); + responseMap.put("rowHeader", result1.getRowHeader()); + + responseMap.put("columnList", clusterTableColumnCommander.columnList(clusterId, keyspace, table)); + + return ApiResponse.ok(responseMap); + } + + @PostMapping("/table/{table}/row/import/sample") + public ApiResponse> importerSampleDownload( + HttpServletResponse response, + @PathVariable String clusterId, + @PathVariable String keyspace, + @PathVariable String table + ) throws IOException { + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); + response.setContentType("text/csv; charset=UTF-8"); + String exportFileName = "sample-" + LocalDateTime.now() + ".csv"; //TODO : Formatting + + response.setHeader("Content-disposition", "attachment;filename=" + exportFileName); + + Map responseMap = new HashMap<>(); + + List columnList = clusterTableColumnCommander.columnSortedList(clusterId, keyspace, table); + + clusterCsvProvider.importerCsvSampleDownload(response.getWriter(), columnList); + + return ApiResponse.ok(responseMap); + } + + @PostMapping("/table/{table}/row/import") + public ApiResponse> importUpload( + @PathVariable String clusterId, + @PathVariable String keyspace, + @PathVariable String table, + @RequestParam("file") MultipartFile file, + ClusterTableRequest.TableRowImportRequest request + ) throws IOException { + + try (Reader reader = new BufferedReader(new InputStreamReader(file.getInputStream()))) { + List columnList = clusterTableColumnCommander.columnSortedList(clusterId, keyspace, table); + + List> values = clusterCsvProvider.importCsvReader( + reader, columnList + ); + + clusterTableRowCommander.rowInserts( + TableDTO.ClusterTableRowImportArgs.builder() + .clusterId(clusterId) + .keyspace(keyspace) + .table(table) + .batchTypeCode(request.getBatchTypeCode()) + .perCommitSize(request.getPerCommitSize()) + .build() + , values); + } + + + return ApiResponse.ok(emptyMap()); + } +} diff --git a/cassdio-web/src/main/webapp/src/components/cluster/modal/table-detail-modal.js b/cassdio-web/src/main/webapp/src/components/cluster/modal/table-detail-modal.js index 91e721c2..b46fb630 100644 --- a/cassdio-web/src/main/webapp/src/components/cluster/modal/table-detail-modal.js +++ b/cassdio-web/src/main/webapp/src/components/cluster/modal/table-detail-modal.js @@ -3,7 +3,6 @@ import {Modal} from "react-bootstrap"; import TableDetailModalInfo from "./detail/table-detail-modal-info"; import TableDetailModalDescribe from "./detail/table-detail-modal-describe"; import TableDetailModalColumnList from "./detail/table-detail-modal-column-list"; -import {CassdioUtils} from "utils/cassdioUtils"; import clusterTableDetailApi from "remotes/clusterTableDetailApi"; const TableDetailModal = ({show, handleClose, clusterId, keyspaceName, tableName}) => { diff --git a/cassdio-web/src/main/webapp/src/components/cluster/modal/table-import-modal.js b/cassdio-web/src/main/webapp/src/components/cluster/modal/table-import-modal.js index 18948aab..a81388a2 100644 --- a/cassdio-web/src/main/webapp/src/components/cluster/modal/table-import-modal.js +++ b/cassdio-web/src/main/webapp/src/components/cluster/modal/table-import-modal.js @@ -1,10 +1,71 @@ -import {useEffect} from "react"; +import {useEffect, useState} from "react"; import {Modal} from "react-bootstrap"; +import axios from "axios"; +import {toast} from "react-toastify"; +import clusterTableRowImportApi from "../../../remotes/clusterTableRowImportApi"; -const TableImportModal = (props) => { +const TableImportModal = ({show, handleClose, clusterId, keyspaceName, tableName}) => { - const show = props.show; - const handleClose = props.handleClose; + const [importOptions, setImportOptions] = useState({ + perCommitSize: 50, + batchTypeCode: 'LOGGED', + }); + + const importSampleDownload = async () => { + const config = { + method: "POST", + url: `/api/cassandra/cluster/${clusterId}/keyspace/${keyspaceName}/table/${tableName}/row/import/sample`, + responseType: "blob", + }; + const response = await axios(config); + const name = response.headers["content-disposition"] + .split("filename=")[1] + .replace(/"/g, ""); + const url = window.URL.createObjectURL(new Blob([response.data])); + const link = document.createElement("a"); + link.href = url; + link.setAttribute("download", name); + link.style.cssText = "display:none"; + document.body.appendChild(link); + link.click(); + link.remove(); + } + + const [files, setFiles] = useState([]); + + const handleFilesChange = (e) => { + setFiles(Array.from(e.target.files)); + } + + const importFileUpload = (evt) => { + evt.preventDefault(); + + if (!files || files.length <= 0) { + toast.warn('File Empty'); + return; + } + + const formData = new FormData(); + + formData.append('file', files[0]) + formData.append(`perCommitSize`, importOptions.perCommitSize) + formData.append(`batchTypeCode`, importOptions.batchTypeCode) + + + clusterTableRowImportApi({ + clusterId, keyspaceName, tableName, formData + }).then((data) => { + if (!data.ok) { + return; + } + + toast.info(`complete`); + + }).finally(() => { + + }); + + } useEffect(() => { //show component @@ -17,14 +78,76 @@ const TableImportModal = (props) => { return ( <> - + - Data Importer + + Data Importer + + + + - Import + <> +
+
+ {/**/} + +
+
+ +
+
+ Option +
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+
+ diff --git a/cassdio-web/src/main/webapp/src/pages/cluster/cluster-table-page.js b/cassdio-web/src/main/webapp/src/pages/cluster/cluster-table-page.js index 6a0927a8..6e0515fc 100644 --- a/cassdio-web/src/main/webapp/src/pages/cluster/cluster-table-page.js +++ b/cassdio-web/src/main/webapp/src/pages/cluster/cluster-table-page.js @@ -75,21 +75,21 @@ const ClusterTablePage = () => { Detail - {/*
*/} - {/* */} - {/* */} - {/*
*/} + setShowExport(true); + }} + >Export + + + {/* MAP, Set 등 다 구현하려면 어려움 추후 대응 필요해보임*/} {/*