Skip to content

feat(web-console): show table icon description in the tooltip #443

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 30, 2025
Merged
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
31 changes: 31 additions & 0 deletions packages/browser-tests/cypress/integration/console/schema.spec.js
Original file line number Diff line number Diff line change
@@ -73,6 +73,24 @@ describe("questdb schema with working tables", () => {
});
});

it("should show the table icon description in the tooltip", () => {
cy.getByDataHook("schema-table-title")
.contains("btc_trades")
.getByDataHook("table-icon")
.realHover();

cy.wait(1200);

cy.getByDataHook("tooltip").should(
"contain",
`WAL-based table. Partitioned by "day", ordered on "timestamp" column.`
);
cy.getByDataHook("tooltip").should(
"contain",
"WAL-based tables are the current and most up-to-date table format. This format supports advanced data recovery, replication and high-throughput ingestion. This is the recommended format if your table contains time-series data that has a designated timestamp."
);
});

it("should filter the table with input field", () => {
// Table name search
cy.get('input[name="table_filter"]').type("btc_trades");
@@ -427,6 +445,19 @@ describe("materialized views", () => {
cy.getByDataHook("schema-matview-title").should("contain", "btc_trades_mv");
});

it("should show the table icon description in the tooltip for a materialized view", () => {
cy.expandMatViews();
cy.getByDataHook("schema-matview-title")
.contains("btc_trades_mv")
.getByDataHook("table-icon")
.realHover();
cy.wait(1200);
cy.getByDataHook("tooltip").should(
"contain",
`Partitioned by "week", ordered on "timestamp" column.`
);
});

it("should show the base table and copy schema for a materialized view", () => {
cy.expandMatViews();
cy.getByDataHook("schema-matview-title")
3 changes: 2 additions & 1 deletion packages/web-console/src/scenes/Schema/Row/index.tsx
Original file line number Diff line number Diff line change
@@ -432,7 +432,8 @@ const Row = ({
>
{isTableKind && (
<TableIcon
isPartitioned={partitionBy && partitionBy !== "NONE"}
designatedTimestamp={designatedTimestamp}
partitionBy={partitionBy}
walEnabled={walEnabled}
isMaterializedView={kind === "matview"}
/>
Original file line number Diff line number Diff line change
@@ -375,6 +375,7 @@ const VirtualTables: FC<VirtualTablesProps> = ({
navigateInTree={navigateInTree}
partitionBy={item.partitionBy}
walEnabled={item.walEnabled}
designatedTimestamp={item.designatedTimestamp}
id={item.id}
errors={[
...(item.matViewData?.view_status === 'invalid' ?
Original file line number Diff line number Diff line change
@@ -100,6 +100,7 @@ export const createTableNode = (
isExpanded: getSectionExpanded(tableId),
partitionBy: table.partitionBy,
walEnabled: table.walEnabled,
designatedTimestamp: table.designatedTimestamp,
walTableData,
children: [
{
64 changes: 51 additions & 13 deletions packages/web-console/src/scenes/Schema/table-icon.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import React, { FC } from "react"
import styled from "styled-components"
import { Table } from "@styled-icons/remix-line"
import { PopperHover } from "../../components/PopperHover"
import { Tooltip } from "../../components/Tooltip"
import { color } from '../../utils'
import * as QuestDB from "../../utils/questdb"

type TableIconProps = {
walEnabled?: boolean
isPartitioned?: boolean
partitionBy?: QuestDB.PartitionBy
designatedTimestamp?: string
isMaterializedView?: boolean
}

@@ -59,15 +63,49 @@ export const MaterializedViewIcon = ({ height = "14px", width = "14px" }) => (
</svg>
)

export const TableIcon: FC<TableIconProps> = ({ walEnabled, isPartitioned, isMaterializedView }) => (
<Root>
{isMaterializedView ? (
<MaterializedViewIcon height="14px" width="14px" />
) : (
<>
{!walEnabled && <Asterisk>*</Asterisk>}
{isPartitioned ? <Table size="14px" /> : <NonPartitionedTableIcon height="14px" />}
</>
)}
</Root>
)
export const TableIcon: FC<TableIconProps> = ({ walEnabled, partitionBy, designatedTimestamp, isMaterializedView }) => {
const isPartitioned = partitionBy && partitionBy !== "NONE"
const partitionText = isPartitioned ? `Partitioned by \"${partitionBy.toLowerCase()}\"` : "Unpartitioned"
const timestampText = !!designatedTimestamp ? `ordered on \"${designatedTimestamp}\" column` : "unordered"
const walText = walEnabled ? "WAL-based table" : "Legacy table format"
const fullHeader = `${walText}. ${partitionText}, ${timestampText}.`
const description = walEnabled
? "WAL-based tables are the current and most up-to-date table format. This format supports advanced data recovery, replication and high-throughput ingestion. This is the recommended format if your table contains time-series data that has a designated timestamp."
: "Legacy table format, without WAL (write-ahead-log). This table format should only be used when table does not have timestamp column and generally not a time series. These tables are not replicated and could be slower to ingress data into."

if (isMaterializedView) {
return (
<PopperHover
trigger={
<Root data-hook="table-icon">
<MaterializedViewIcon height="14px" width="14px" />
</Root>
}
delay={1000}
placement="bottom"
>
<Tooltip>{partitionText}, {timestampText}.</Tooltip>
</PopperHover>
)
}

return (
<PopperHover
trigger={
<Root data-hook="table-icon">
{!walEnabled && <Asterisk>*</Asterisk>}
{isPartitioned ? <Table size="14px" /> : <NonPartitionedTableIcon height="14px" />}
</Root>
}
delay={1000}
placement="bottom"
>
<Tooltip>
{fullHeader}
<br />
<br />
{description}
</Tooltip>
</PopperHover>
)
}