Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type Props = {
isEditLocked: boolean
hasWalSetting: boolean
walEnabled?: boolean
onOpenChange: (openedFileName: string | undefined) => void
onOpenChange: (openedFileName?: string) => void
onSchemaChange: (values: SchemaFormValues) => void
name: string
schema: SchemaColumn[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ const FileTextBox = styled(Box)`
type Props = {
files: ProcessedFile[]
onDialogToggle: (open: boolean) => void
onFileRemove: (filename: string) => void
onFileUpload: (filename: string) => void
onFilePropertyChange: (filename: string, file: Partial<ProcessedFile>) => void
onFileRemove: (id: string) => void
onFileUpload: (id: string) => void
onFilePropertyChange: (id: string, file: Partial<ProcessedFile>) => void
}

export const FilesToUpload = ({
Expand All @@ -71,11 +71,11 @@ export const FilesToUpload = ({
onFileUpload,
}: Props) => {
const [renameDialogOpen, setRenameDialogOpen] = React.useState<
string | null
string | undefined
>()

const [schemaDialogOpen, setSchemaDialogOpen] = React.useState<
string | null
string | undefined
>()

useEffect(() => {
Expand Down Expand Up @@ -157,13 +157,12 @@ export const FilesToUpload = ({
align: "flex-end",
width: "200px",
render: ({ data }) => {
const name = data.table_name ?? data.fileObject.name
return (
<RenameTableDialog
open={renameDialogOpen === name}
onOpenChange={setRenameDialogOpen}
open={renameDialogOpen === data.id}
onOpenChange={(f) => setRenameDialogOpen(f?.id)}
onNameChange={(name) => {
onFilePropertyChange(data.fileObject.name, {
onFilePropertyChange(data.id, {
table_name: name,
})
}}
Expand Down Expand Up @@ -197,10 +196,12 @@ export const FilesToUpload = ({
return (
<TableSchemaDialog
action="import"
open={schemaDialogOpen === name}
onOpenChange={setSchemaDialogOpen}
open={schemaDialogOpen === data.id}
onOpenChange={(name?: string) =>
setSchemaDialogOpen(name ? data.id : undefined)
}
onSchemaChange={(schema) => {
onFilePropertyChange(data.fileObject.name, {
onFilePropertyChange(data.id, {
schema: schema.schemaColumns,
partitionBy: schema.partitionBy,
timestamp: schema.timestamp,
Expand Down Expand Up @@ -246,7 +247,7 @@ export const FilesToUpload = ({
name="overwrite"
defaultValue={data.settings.overwrite ? "true" : "false"}
onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>
onFilePropertyChange(data.fileObject.name, {
onFilePropertyChange(data.id, {
settings: {
...data.settings,
overwrite: e.target.value === "true",
Expand Down
66 changes: 20 additions & 46 deletions packages/web-console/src/scenes/Import/ImportCSVFiles/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,18 @@ import { useSelector } from "react-redux"
import { selectors } from "../../../store"
import { DEFAULT_TIMESTAMP_FORMAT, MAX_UNCOMMITTED_ROWS } from "./const"
import { useIsVisible } from "../../../components/Hooks"
import {
extractPrecionFromGeohash,
isGeoHash,
mapColumnTypeToQuestDB,
mapColumnTypeToUI,
uuid,
} from "./utils"

type Props = {
onImported: (result: UploadResult) => void
}

const isGeoHash = (type: string) => type.startsWith("GEOHASH")

function extractPrecionFromGeohash(geohash: string) {
const regex = /\(([^)]+)\)/g
const matches = regex.exec(geohash)
if (matches && matches.length > 1) {
return matches[1]
}
return ""
}

const mapColumnTypeToUI = (type: string) => {
if (isGeoHash(type)) {
return "GEOHASH"
} else return type.toUpperCase()
}

const mapColumnTypeToQuestDB = (column: SchemaColumn) => {
if (column.type === "GEOHASH") {
return {
...column,
type: `GEOHASH(${column.precision})`,
}
}
return column
}

export const ImportCSVFiles = ({ onImported }: Props) => {
const { quest } = useContext(QuestContext)
const [filesDropped, setFilesDropped] = useState<ProcessedFile[]>([])
Expand All @@ -52,13 +32,10 @@ export const ImportCSVFiles = ({ onImported }: Props) => {
const rootRef = useRef<HTMLDivElement>(null)
const isVisible = useIsVisible(rootRef)

const setFileProperties = (
filename: string,
file: Partial<ProcessedFile>,
) => {
const setFileProperties = (id: string, file: Partial<ProcessedFile>) => {
setFilesDropped((files) =>
files.map((f) => {
if (f.table_name === filename) {
if (f.id === id) {
return {
...f,
...file,
Expand All @@ -70,7 +47,7 @@ export const ImportCSVFiles = ({ onImported }: Props) => {
}

const setIsUploading = (file: ProcessedFile, isUploading: boolean) => {
setFileProperties(file.table_name, { isUploading })
setFileProperties(file.id, { isUploading })
}

const getFileConfigs = async (files: File[]): Promise<ProcessedFile[]> => {
Expand Down Expand Up @@ -117,6 +94,7 @@ export const ImportCSVFiles = ({ onImported }: Props) => {
: ""

return {
id: uuid(),
fileObject: file,
table_name: file.name,
status: result.status,
Expand Down Expand Up @@ -175,10 +153,8 @@ export const ImportCSVFiles = ({ onImported }: Props) => {
<FilesToUpload
files={filesDropped}
onDialogToggle={setDialogOpen}
onFileUpload={async (filename) => {
const file = filesDropped.find(
(f) => f.table_name === filename,
) as ProcessedFile
onFileUpload={async (id) => {
const file = filesDropped.find((f) => f.id === id) as ProcessedFile

if (file.isUploading) {
return
Expand All @@ -193,12 +169,12 @@ export const ImportCSVFiles = ({ onImported }: Props) => {
partitionBy: file.partitionBy,
timestamp: file.timestamp,
onProgress: (progress) => {
setFileProperties(file.table_name, {
setFileProperties(file.id, {
uploadProgress: progress,
})
},
})
setFileProperties(file.table_name, {
setFileProperties(file.id, {
uploaded: response.status === "OK",
uploadResult: response.status === "OK" ? response : undefined,
schema:
Expand Down Expand Up @@ -232,28 +208,26 @@ export const ImportCSVFiles = ({ onImported }: Props) => {
setIsUploading(file, false)
} catch (err) {
setIsUploading(file, false)
setFileProperties(file.table_name, {
setFileProperties(file.id, {
uploaded: false,
uploadResult: undefined,
uploadProgress: 0,
error: "Upload error",
})
}
}}
onFileRemove={(filename) => {
const file = filesDropped.find(
(f) => f.table_name === filename,
) as ProcessedFile
onFileRemove={(id) => {
const file = filesDropped.find((f) => f.id === id) as ProcessedFile
setFilesDropped(
filesDropped.filter(
(f) => f.fileObject.name !== file.fileObject.name,
),
)
}}
onFilePropertyChange={async (filename, partialFile) => {
onFilePropertyChange={async (id, partialFile) => {
const processedFiles = await Promise.all(
filesDropped.map(async (file) => {
if (file.fileObject.name === filename) {
if (file.id === id) {
// Only check for file existence if table name is changed
const result = partialFile.table_name
? await quest.checkCSVFile(partialFile.table_name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const StyledDescription = styled(Dialog.Description)`

type Props = {
open: boolean
onOpenChange: (openedFileName: string | undefined) => void
onOpenChange: (file?: ProcessedFile) => void
onNameChange: (name: string) => void
file: ProcessedFile
}
Expand Down Expand Up @@ -61,7 +61,7 @@ export const RenameTableDialog = ({
<Button
skin="transparent"
prefixIcon={<Edit size="14px" />}
onClick={() => onOpenChange(name)}
onClick={() => onOpenChange(file)}
>
{shortenText(name, 20)}
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { UploadResult, UploadModeSettings } from "utils"
import { SchemaColumn } from "../../../components/TableSchemaDialog/types"

export type ProcessedFile = {
id: string
fileObject: File
status: string
table_name: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const UploadActions = ({
disabled={file.isUploading}
skin="primary"
prefixIcon={<Upload2 size="18px" />}
onClick={() => onUpload(file.table_name)}
onClick={() => onUpload(file.id)}
>
{file.isUploading ? "Uploading..." : "Upload"}
</Button>
Expand All @@ -44,7 +44,7 @@ export const UploadActions = ({
disabled={file.isUploading}
skin="secondary"
onClick={() => {
onRemove(file.table_name)
onRemove(file.id)
}}
>
<Close size="18px" />
Expand Down
49 changes: 49 additions & 0 deletions packages/web-console/src/scenes/Import/ImportCSVFiles/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { SchemaColumn } from "components/TableSchemaDialog/types"

export const isGeoHash = (type: string) => type.startsWith("GEOHASH")

export const extractPrecionFromGeohash = (geohash: string) => {
const regex = /\(([^)]+)\)/g
const matches = regex.exec(geohash)
if (matches && matches.length > 1) {
return matches[1]
}
return ""
}

export const mapColumnTypeToUI = (type: string) => {
if (isGeoHash(type)) {
return "GEOHASH"
} else return type.toUpperCase()
}

export const mapColumnTypeToQuestDB = (column: SchemaColumn) => {
if (column.type === "GEOHASH") {
return {
...column,
type: `GEOHASH(${column.precision})`,
}
}
return column
}

const str = () =>
(
"00000000000000000" + (Math.random() * 0xffffffffffffffff).toString(16)
).slice(-16)

export const uuid = () => {
Comment thread
jerrinot marked this conversation as resolved.
const a = str()
const b = str()
return (
a.slice(0, 8) +
"-" +
a.slice(8, 12) +
"-4" +
a.slice(13) +
"-a" +
b.slice(1, 4) +
"-" +
b.slice(4)
)
}