Skip to content

feat(webui): Add timestamp key selector to guided Presto UI.#1332

Merged
davemarco merged 10 commits into
y-scope:mainfrom
davemarco:timekey
Oct 1, 2025
Merged

feat(webui): Add timestamp key selector to guided Presto UI.#1332
davemarco merged 10 commits into
y-scope:mainfrom
davemarco:timekey

Conversation

@davemarco

@davemarco davemarco commented Sep 25, 2025

Copy link
Copy Markdown
Contributor

Description

Adds timekey selector to UI, and range input. Timekey uses sql query to pull timestamps. It also filters based on whether column is a timestamp or not. I asked devin and user set timestamp is always the same constant in the database.

Screenshot 2025-09-25 at 11 00 04 AM

Checklist

  • The PR satisfies the contribution guidelines.
  • This is a breaking change and that has been indicated in the PR title, OR this isn't a
    breaking change.
  • Necessary docs have been updated, OR no docs need to be updated.

Validation performed

Tested a couple datasets and timestamps. It appears to reset when you change dataset.


Summary by CodeRabbit

  • New Features

    • Added a Time Key control to Guided Presto searches to choose a timestamp column; auto-selects the first available, warns if none found, shows fetch errors, and clears when dataset changes.
    • Search state now tracks the selected Time Key so selections persist while composing queries.
  • UI

    • Placed Time Key between From and Where; includes loading and disabled states and adjusted grid layout.
    • Time range picker now has a max width for improved responsiveness.

@coderabbitai

coderabbitai Bot commented Sep 25, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds a timestamp key selection UI and data flow for Guided Presto: state field and updater, new TimestampKey components, SQL to fetch timestamp columns (uses new COLUMN_METADATA table suffix), layout/CSS adjustments, and a TimeRangeInput width limit.

Changes

Cohort / File(s) Summary
SQL table suffix update
components/webui/client/src/config/sql-table-suffix.ts
Adds enum member COLUMN_METADATA = "column_metadata".
Presto search state
components/webui/client/src/pages/SearchPage/SearchState/Presto/index.tsx
Adds timestampKey: Nullable<string> to state with default null and updateTimestampKey updater.
TimestampKey feature (component + data)
components/webui/client/src/pages/SearchPage/SearchControls/Presto/GuidedControls/TimestampKey/index.tsx, components/webui/client/src/pages/SearchPage/SearchControls/Presto/GuidedControls/TimestampKey/TimestampKeySelect.tsx, components/webui/client/src/pages/SearchPage/SearchControls/Presto/GuidedControls/TimestampKey/sql.ts
New TimestampKey container and TimestampKeySelect component. Adds fetchTimestampColumns(datasetName) which builds SQL referencing SqlTableSuffix.COLUMN_METADATA, queries via querySql, and returns timestamp column names. Select auto-selects first result, handles loading/error/empty states, and syncs with global state.
GuidedControls integration and layout
components/webui/client/src/pages/SearchPage/SearchControls/Presto/GuidedControls/index.tsx, components/webui/client/src/pages/SearchPage/SearchControls/Presto/GuidedControls/index.module.css
Inserts TimestampKey into GuidedControls grid and adds TimeRangeInput to buttons row. CSS: .select grid-column changed to span 2; new .timestampKey class with grid-column: span 1; display: flex.
Time range input style
components/webui/client/src/pages/SearchPage/SearchControls/TimeRangeInput/index.module.css
Adds max-width: 320px to .rangePicker (keeps existing min-width).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as User
  participant GC as GuidedControls
  participant TK as TimestampKeySelect
  participant RQ as React Query
  participant SQL as buildTimestampColumnsSql
  participant Q as querySql
  participant PB as Presto Backend
  participant S as Presto Search State

  U->>GC: Open/Change dataset
  GC->>TK: Render with dataset
  TK->>RQ: useQuery(["timestampColumns", dataset])
  RQ->>SQL: Build SQL (uses COLUMN_METADATA)
  SQL-->>RQ: SQL string
  RQ->>Q: Execute SQL
  Q->>PB: Send query
  PB-->>Q: Rows [{name, type}]
  Q-->>RQ: Data
  alt Data available
    TK->>S: updateTimestampKey(firstName or null)
  else Error or empty
    TK-->>U: Show error/warning and clear timestampKey
  end
  U->>TK: User selects timestamp key
  TK->>S: updateTimestampKey(selected)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly describes the main feature introduced by the changeset—adding a timestamp key selector to the guided Presto UI—without extraneous detail or noise, accurately reflecting the primary intent of the pull request.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🧪 Early access (Sonnet 4.5): enabled

We are currently testing the Sonnet 4.5 model, which is expected to improve code review quality. However, this model may lead to increased noise levels in the review comments. Please disable the early access features if the noise level causes any inconvenience.

Note:

  • Public repositories are always opted into early access features.
  • You can enable or disable early access features from the CodeRabbit UI or by updating the CodeRabbit configuration file.

Comment @coderabbitai help to get the list of available commands and usage tips.

@davemarco davemarco marked this pull request as ready for review September 26, 2025 15:02
@davemarco davemarco requested a review from a team as a code owner September 26, 2025 15:02
coderabbitai[bot]

This comment was marked as outdated.

@hoophalab hoophalab left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me in general. There are some coding style nitpicks

Comment on lines +39 to +50
useEffect(() => {
if (isSuccess) {
if ("undefined" !== typeof data[0] && null === timestampKey) {
updateTimestampKey(data[0]);
}
}
}, [
isSuccess,
data,
timestampKey,
updateTimestampKey
]);

@hoophalab hoophalab Sep 29, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
useEffect(() => {
if (isSuccess) {
if ("undefined" !== typeof data[0] && null === timestampKey) {
updateTimestampKey(data[0]);
}
}
}, [
isSuccess,
data,
timestampKey,
updateTimestampKey
]);
useEffect(() => {
if (isSuccess) {
const timestampKey = data.at(0)
if ("undefined" !== typeof timestampKey && null === timestampKey){
const {updateTimestampKey} = usePrestoSearchState.getState()
updateTimestampKey(timestampKey);
}
}
}, [
isSuccess,
data,
timestampKey,
]);

two nitpicks:

  1. I remember you said we should use getState in callbacks to avoid dependencies?
  2. how about using array.at?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. for one. we need the states in other places anyways, so the component will rerender regardless.
  2. what are the benefits of array.at vs. []?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davemarco davemarco left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed review

Comment on lines +39 to +50
useEffect(() => {
if (isSuccess) {
if ("undefined" !== typeof data[0] && null === timestampKey) {
updateTimestampKey(data[0]);
}
}
}, [
isSuccess,
data,
timestampKey,
updateTimestampKey
]);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. for one. we need the states in other places anyways, so the component will rerender regardless.
  2. what are the benefits of array.at vs. []?

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (2)
components/webui/client/src/pages/SearchPage/SearchControls/Presto/GuidedControls/TimestampKey/TimestampKeySelect.tsx (2)

100-100: Normalize null to undefined for Select value.

Ant Design's Select expects undefined to represent "no selection". Passing null can cause warnings or unexpected behaviour.

Apply this diff:

-                value={timestampKey}
+                value={timestampKey ?? undefined}

Based on past review comments.


41-52: Simplify the guard and reduce hook dependencies.

The current guard checks typeof timestampKeys[0] without first verifying the array has elements. Additionally, using getState() in the effect callback reduces unnecessary dependencies.

Apply this diff:

     useEffect(() => {
         if (isSuccess) {
-            if ("undefined" !== typeof timestampKeys[0] && null === timestampKey) {
-                updateTimestampKey(timestampKeys[0]);
+            const firstKey = timestampKeys?.at(0);
+            if ("undefined" !== typeof firstKey && null === timestampKey) {
+                const {updateTimestampKey} = usePrestoSearchState.getState();
+                updateTimestampKey(firstKey);
             }
         }
     }, [
         isSuccess,
         timestampKeys,
         timestampKey,
-        updateTimestampKey,
     ]);

This uses array.at(0) for safer access, ensures firstKey is defined, and retrieves updateTimestampKey from state to avoid re-running on updater reference changes.

Based on past review comments.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f687144 and 91ed890.

📒 Files selected for processing (1)
  • components/webui/client/src/pages/SearchPage/SearchControls/Presto/GuidedControls/TimestampKey/TimestampKeySelect.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}

⚙️ CodeRabbit configuration file

  • Prefer false == <expression> rather than !<expression>.

Files:

  • components/webui/client/src/pages/SearchPage/SearchControls/Presto/GuidedControls/TimestampKey/TimestampKeySelect.tsx
🧬 Code graph analysis (1)
components/webui/client/src/pages/SearchPage/SearchControls/Presto/GuidedControls/TimestampKey/TimestampKeySelect.tsx (2)
components/webui/client/src/pages/SearchPage/SearchControls/Presto/GuidedControls/TimestampKey/sql.ts (1)
  • fetchTimestampColumns (50-50)
components/webui/client/src/pages/SearchPage/SearchState/typings.ts (1)
  • SEARCH_UI_STATE (31-31)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: package-image
  • GitHub Check: lint-check (macos-15)
  • GitHub Check: rust-checks (macos-15)
🔇 Additional comments (1)
components/webui/client/src/pages/SearchPage/SearchControls/Presto/GuidedControls/TimestampKey/TimestampKeySelect.tsx (1)

23-23: No action required – selectDataset is the actual state property and is defined and used consistently across the codebase.

Likely an incorrect or invalid review comment.

Comment on lines +10 to +12
import useSearchStore from "../../../../SearchState";
import usePrestoSearchState from "../../../../SearchState/Presto";
import {SEARCH_UI_STATE} from "../../../../SearchState/typings";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider consolidating SearchState imports.

The imports from SearchState and SearchState/Presto could be consolidated if SEARCH_UI_STATE were re-exported from the root SearchState module, reducing the need for consumers to import from multiple locations.

Based on past review comments.

🤖 Prompt for AI Agents
In
components/webui/client/src/pages/SearchPage/SearchControls/Presto/GuidedControls/TimestampKey/TimestampKeySelect.tsx
around lines 10 to 12, the file imports useSearchStore, usePrestoSearchState,
and SEARCH_UI_STATE from different paths; consolidate by re-exporting
SEARCH_UI_STATE from the root SearchState module and then update this file to
import SEARCH_UI_STATE from "../../../../SearchState" alongside the hooks so all
SearchState symbols come from one module, ensuring the root index.ts (or
equivalent) exports SEARCH_UI_STATE from "./typings".

Comment on lines +30 to +39
const {data: timestampKeys, isPending, isSuccess, isError} = useQuery({
queryKey: [
"timestampColumns",
dataset,
],
queryFn: () => (dataset ?
fetchTimestampColumns(dataset) :
[]),
enabled: null !== dataset,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Add type parameters to useQuery for type safety.

The useQuery call lacks generic type parameters, weakening type inference. Since fetchTimestampColumns returns Promise<string[]>, explicitly type the query.

Apply this diff:

-    const {data: timestampKeys, isPending, isSuccess, isError} = useQuery({
+    const {data: timestampKeys, isPending, isSuccess, isError} = useQuery<string[], Error>({
         queryKey: [
             "timestampColumns",
             dataset,
         ],
-        queryFn: () => (dataset ?
-            fetchTimestampColumns(dataset) :
-            []),
+        queryFn: ({queryKey}) => fetchTimestampColumns(queryKey[1] as string),
         enabled: null !== dataset,
     });

This eliminates the ternary (since enabled guards execution) and uses the queryKey parameter to avoid repeating the dataset reference.

Based on past review comments.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const {data: timestampKeys, isPending, isSuccess, isError} = useQuery({
queryKey: [
"timestampColumns",
dataset,
],
queryFn: () => (dataset ?
fetchTimestampColumns(dataset) :
[]),
enabled: null !== dataset,
});
const {data: timestampKeys, isPending, isSuccess, isError} = useQuery<string[], Error>({
queryKey: [
"timestampColumns",
dataset,
],
queryFn: ({queryKey}) => fetchTimestampColumns(queryKey[1] as string),
enabled: null !== dataset,
});
🤖 Prompt for AI Agents
In
components/webui/client/src/pages/SearchPage/SearchControls/Presto/GuidedControls/TimestampKey/TimestampKeySelect.tsx
around lines 30-39, the useQuery call lacks generic type parameters and uses a
ternary to guard dataset; update it to use useQuery<string[], Error> and
simplify the queryFn to use the queryKey param instead of repeating dataset
(e.g. queryFn: ({ queryKey }) => fetchTimestampColumns(queryKey[1] as string)),
remove the ternary as enabled: dataset != null already guards execution, and
keep enabled: dataset != null to prevent running when dataset is null.

@davemarco davemarco requested a review from hoophalab September 30, 2025 18:06

@hoophalab hoophalab left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm. final comments


useEffect(() => {
if (isSuccess) {
if ("undefined" !== typeof timestampKeys[0] && null === timestampKey) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i tried it but, but typescript support it since it dosent remember thats its not undefined. Like in the next line there is a type error since it thinks it can be undefined, even though we just checked

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can cache it in a local var and return if it's undefined?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think will make less readable

@davemarco davemarco requested a review from hoophalab September 30, 2025 19:38
@davemarco davemarco merged commit ce98ad2 into y-scope:main Oct 1, 2025
22 checks passed
junhaoliao pushed a commit to junhaoliao/clp that referenced this pull request May 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants