Skip to content

Commit

Permalink
Merge branch 'main' into web-console/news-ui
Browse files Browse the repository at this point in the history
  • Loading branch information
insmac committed Nov 6, 2023
2 parents 46cc4d5 + 6182010 commit 76033e4
Show file tree
Hide file tree
Showing 13 changed files with 139 additions and 52 deletions.
13 changes: 13 additions & 0 deletions packages/web-console/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,19 @@ and this project adheres to
- `Fixed` for any bug fixes.
- `Security` in case of vulnerabilities.

## 0.2.8 - 2023.10.16

### Changed

- Update Webpack config, add hot module reloading, enable webpack tree-shaking,
reduce build size [#205](https://github.com/questdb/ui/pull/205)

### Fixed

- table list disappears after erroneous SQL execution
[#204](https://github.com/questdb/ui/pull/204)
- render crash when grid is empty [#198](https://github.com/questdb/ui/pull/198)

## 0.2.7 - 2023.09.08

### Changed
Expand Down
2 changes: 1 addition & 1 deletion packages/web-console/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@questdb/web-console",
"version": "0.2.7",
"version": "0.2.8",
"license": "Apache-2.0",
"description": "QuestDB Console",
"files": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export const Dialog = ({
if (!isValidTableName(value)) {
return helpers.error("string.validTableName")
}
if (action === "add" && tables?.find((table) => table.name === value)) {
if (action === "add" && tables?.find((table) => table.table_name === value)) {
return helpers.error("string.uniqueTableName")
}
return value
Expand Down Expand Up @@ -144,7 +144,7 @@ export const Dialog = ({
}
return value
})
.unique((a, b) => a.name === b.name)
.unique((a, b) => a.table_name === b.table_name)
.messages({
"array.required": "Please add at least one column",
"array.unique": "Column names must be unique",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ export const createSchemaCompletionProvider = (questDBTables: Table[] = []) => {
return {
suggestions: questDBTables.map((item) => {
return {
label: item.name,
label: item.table_name,
kind: CompletionItemKind.Class,
insertText:
openQuote
? item.name + (nextCharQuote ? "" : "\"")
: /^[a-z0-9_]+$/i.test(item.name) ? item.name : `"${item.name}"`,
? item.table_name + (nextCharQuote ? "" : "\"")
: /^[a-z0-9_]+$/i.test(item.table_name) ? item.table_name : `"${item.table_name}"`,
range,
}
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,15 @@ export const ImportCSVFiles = ({ onViewData }: Props) => {
const partitionBy =
result.status === FileCheckStatus.EXISTS && tables
? await (async () => {
const table = tables.find((t) => t.name === file.name)
const table = tables.find((t) => t.table_name === file.name)
return table?.partitionBy ?? "NONE"
})()
: "NONE"

const timestamp =
result.status === FileCheckStatus.EXISTS && tables
? await (async () => {
const table = tables.find((t) => t.name === file.name)
const table = tables.find((t) => t.table_name === file.name)
return table?.designatedTimestamp ?? ""
})()
: ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@
*
******************************************************************************/

import React from "react"
import React, { useMemo } from "react"
import styled from "styled-components"
import { Text } from "../../../../components"
import { format } from "date-fns/fp"
import { format } from "date-fns"
import { fetchUserLocale, getLocaleFromLanguage } from "../../../../utils"

type Props = {
createdAt: Date
Expand All @@ -36,6 +37,14 @@ const TimestampText = styled(Text)`
margin-right: 0.5rem;
`

export const Timestamp = ({ createdAt }: Props) => (
<TimestampText color="gray2">[{format("HH:mm:ss", createdAt)}]</TimestampText>
)
export const Timestamp = ({ createdAt }: Props) => {
const userLocale = useMemo(fetchUserLocale, [])

return (
<TimestampText color="gray2">
[
{format(createdAt, "pppp", { locale: getLocaleFromLanguage(userLocale) })}
]
</TimestampText>
)
}
26 changes: 13 additions & 13 deletions packages/web-console/src/scenes/Schema/Table/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type Props = QuestDB.Table &
designatedTimestamp: string
description?: string
isScrolling: boolean
name: string
table_name: string
partitionBy: string
expanded?: boolean
onChange: (name: string) => void
Expand Down Expand Up @@ -113,7 +113,7 @@ const Table = ({
description,
isScrolling,
designatedTimestamp,
name,
table_name,
partitionBy,
expanded = false,
walEnabled,
Expand All @@ -124,21 +124,21 @@ const Table = ({
const tables = useSelector(selectors.query.getTables)

const showColumns = async (name: string) => {
const response = await quest.showColumns(name)
const response = await quest.showColumns(table_name)
if (response && response.type === QuestDB.Type.DQL) {
setColumns(response.data)
}
}

useEffect(() => {
if (tables && expanded && name) {
void showColumns(name)
if (tables && expanded && table_name) {
void showColumns(table_name)
}
}, [tables, name])
}, [tables, table_name])

const tree: TreeNode[] = [
{
name,
name: table_name,
kind: "table",
initiallyOpen: expanded,
children: [
Expand All @@ -147,8 +147,8 @@ const Table = ({
initiallyOpen: true,
wrapper: Columns,
async onOpen({ setChildren }) {
onChange(name)
const response = (await quest.showColumns(name)) ?? []
onChange(table_name)
const response = (await quest.showColumns(table_name)) ?? []

if (response && response.type === QuestDB.Type.DQL) {
setColumns(response.data)
Expand Down Expand Up @@ -178,14 +178,14 @@ const Table = ({

render({ toggleOpen, isLoading }) {
return (
<ContextMenuTrigger id={name}>
<ContextMenuTrigger id={table_name}>
<Title
description={description}
kind="table"
name={name}
name={table_name}
onClick={() => {
toggleOpen()
onChange(name)
onChange(table_name)
}}
partitionBy={partitionBy}
walEnabled={walEnabled}
Expand All @@ -202,7 +202,7 @@ const Table = ({
<Wrapper _height={columns ? columns.length * 30 : 0}>
{!isScrolling && (
<ContextualMenu
name={name}
name={table_name}
partitionBy={partitionBy}
walEnabled={walEnabled}
/>
Expand Down
12 changes: 7 additions & 5 deletions packages/web-console/src/scenes/Schema/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import {
Tooltip,
} from "../../components"
import { actions, selectors } from "../../store"
import { color, ErrorResult } from "../../utils"
import { color, ErrorResult, isServerError } from "../../utils"
import * as QuestDB from "../../utils/questdb"
import Table from "./Table"
import LoadingError from "./LoadingError"
Expand Down Expand Up @@ -129,7 +129,9 @@ const Schema = ({
}
},
(error) => {
setLoadingError(error)
if (isServerError(error)) {
setLoadingError(error)
}
},
() => {
setLoading(false)
Expand Down Expand Up @@ -198,10 +200,10 @@ const Schema = ({
tables?.map((table) => (
<Table
designatedTimestamp={table.designatedTimestamp}
expanded={table.name === opened}
expanded={table.table_name === opened}
isScrolling={isScrolling}
key={table.name}
name={table.name}
key={table.table_name}
table_name={table.table_name}
onChange={handleChange}
partitionBy={table.partitionBy}
walEnabled={table.walEnabled}
Expand Down
9 changes: 9 additions & 0 deletions packages/web-console/src/utils/fetchUserLocale.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Function to determine the user's preferred language or locale using the `navigator` object.
* @returns {string} The user's preferred language or locale.
*/
export const fetchUserLocale = () => {
return navigator.languages && navigator.languages.length
? navigator.languages[0]
: navigator.language
}
28 changes: 28 additions & 0 deletions packages/web-console/src/utils/getLocaleFromLanguage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Locale } from "date-fns"
import { enUS, fr, es, de, ja, ko, zhCN } from "date-fns/locale"

/**
* Function to retrieve a date-fns Locale object based on a specified language code.
*
* This function takes a language code as input and returns the corresponding date-fns Locale object.
* It uses a predefined mapping of language codes to Locale objects. If the input language code is not found
* in the mapping, it defaults to the English (United States) Locale.
*
* @param {string} language - The language code (e.g., "en-US", "fr-FR", "es-ES") for which to retrieve the Locale.
* @returns {Locale} The date-fns Locale object corresponding to the input language code, or the English (United States) Locale as the default.
*/
export const getLocaleFromLanguage = (language: string) => {
const localeMap: { [key: string]: Locale } = {
"en-US": enUS, // English (United States)
"fr-FR": fr, // French (France)
"es-ES": es, // Spanish (Spain)
"de-DE": de, // German (Germany)
"ja-JP": ja, // Japanese (Japan)
"ko-KR": ko, // Korean (South Korea),
"zh-CN": zhCN, // Chinese (Simplified, China)
// add more language support here
}

// If the language is not found in the map, default to English (United States)
return localeMap[language] || enUS
}
3 changes: 3 additions & 0 deletions packages/web-console/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
******************************************************************************/

export * from "./copyToClipboard"
export * from "./isServerError"
export * from "./fetch"
export * from "./fromFetch"
export * from "./questdb"
Expand All @@ -31,3 +32,5 @@ export * from "./styled"
export * from "./formatSql"
export * from "./platform"
export * from "./pick"
export * from "./fetchUserLocale"
export * from "./getLocaleFromLanguage"
5 changes: 5 additions & 0 deletions packages/web-console/src/utils/isServerError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// isServerError takes api response and checks if the error is of type server error or timeout
// returns true if server error type
export const isServerError = (response: Response): boolean => {
return response.status === 408 || response.status >= 500;
};
60 changes: 39 additions & 21 deletions packages/web-console/src/utils/questdb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* limitations under the License.
*
******************************************************************************/
import { isServerError } from "../utils";
import { BusEvent } from "../consts"
import { TelemetryConfigShape } from "./../store/Telemetry/types"

Expand Down Expand Up @@ -77,6 +78,7 @@ type RawResult = RawDqlResult | RawDdlResult | RawErrorResult

export type ErrorResult = RawErrorResult & {
type: Type.ERROR
status: number
}

export type QueryRawResult =
Expand All @@ -97,7 +99,7 @@ export type QueryResult<T extends Record<string, any>> =
| DdlResult

export type Table = {
name: string
table_name: string
partitionBy: string
designatedTimestamp: string
walEnabled: boolean
Expand Down Expand Up @@ -355,39 +357,55 @@ export class Client {
}
}

const errorPayload = {
error: `QuestDB is not reachable [${response.status}]`,
position: -1,
query,
type: Type.ERROR,
const errorPayload: Record<string, string | number> = {
status: response.status,
error: response.statusText,
}

bus.trigger(BusEvent.MSG_CONNECTION_ERROR, {
...errorPayload,
status: response.status,
})
if (isServerError(response)) {
errorPayload.error = `QuestDB is not reachable [${response.status}]`;
errorPayload.position = -1;
errorPayload.query = query;
errorPayload.type = Type.ERROR;
bus.trigger(BusEvent.MSG_CONNECTION_ERROR, errorPayload)
}

// eslint-disable-next-line prefer-promise-reject-errors
return await Promise.reject(errorPayload)
}

async showTables(): Promise<QueryResult<Table>> {
const response = await this.query<Table>("tables();")
type BackwardsCompatibleTable = Table & {
/** @deprecated use `table_name` instead */
name: string
}

const response = await this.query<BackwardsCompatibleTable>("tables();")

if (response.type === Type.DQL) {
return {
...response,
data: response.data.slice().sort((a, b) => {
if (a.name > b.name) {
return 1
}

if (a.name < b.name) {
return -1
}
data: response.data
.slice()
.sort((a, b) => {
const aName = a.table_name ?? a.name
const bName = b.table_name ?? b.name
if (aName > bName) {
return 1
}

if (aName < bName) {
return -1
}

return 0
})

return 0
}),
// @TODO: remove this once upstream questdb releases version with `table_name`
.map((table) => ({
...table,
table_name: table.table_name ?? table.name,
})),
}
}

Expand Down

0 comments on commit 76033e4

Please sign in to comment.