Skip to content

Commit

Permalink
feat: add column hover tooltip and column value auto completion (#1526)
Browse files Browse the repository at this point in the history
* feat: add column hover tooltip and column value auto completion

* comments

* address comments
  • Loading branch information
jczhong84 authored Dec 10, 2024
1 parent dff25db commit 7ee8219
Show file tree
Hide file tree
Showing 16 changed files with 634 additions and 430 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "querybook",
"version": "3.37.1",
"version": "3.38.0",
"description": "A Big Data Webapp",
"private": true,
"scripts": {
Expand Down
1 change: 1 addition & 0 deletions querybook/server/models/metastore.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ def to_dict(self, include_table=False):
"comment": self.comment,
"description": self.description,
"table_id": self.table_id,
"stats": self.statistics,
}

if include_table:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const FunctionDocumentationTooltip: React.FunctionComponent<IProps> = ({
return (
<div key={index}>
<div className="rich-text-content">
<div className="table-tooltip-header">{signature}</div>
<div className="tooltip-header">{signature}</div>

<div className="tooltip-title">Returns</div>
<div className="tooltip-content">{returnType}</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { ContentState } from 'draft-js';
import React from 'react';

import { TableTag } from 'components/DataTableTags/DataTableTags';
import { IDataColumn } from 'const/metastore';
import { useResource } from 'hooks/useResource';
import { TableColumnResource } from 'resource/table';
import { Tag, TagGroup } from 'ui/Tag/Tag';

interface IProps {
column: IDataColumn;
}

export const TableColumnTooltip: React.FunctionComponent<IProps> = ({
column,
}) => {
const { data: tags } = useResource(
React.useCallback(
() => TableColumnResource.getTags(column.id),
[column.id]
)
);

const tagsDOM = (tags || []).map((tag) => (
<TableTag tag={tag} readonly={true} key={tag.id} mini={true} />
));

const description =
typeof column.description === 'string'
? column.description
: (column.description as ContentState).getPlainText();

const statsDOM = (column.stats || []).map((stat, i) => {
const formattedValue = Array.isArray(stat.value)
? stat.value.join(', ')
: stat.value;
return (
<TagGroup key={stat.key}>
<Tag mini>{stat.key}</Tag>
<Tag highlighted mini>
{formattedValue}
</Tag>
</TagGroup>
);
});

const contentDOM = (
<>
<div className="tooltip-header flex-row">
<div>{column.name}</div>
</div>
{column.type && (
<div className="mt4 flex-row">
<div className="tooltip-title">Type:</div>
<div className="tooltip-content">{column.type}</div>
</div>
)}
{tagsDOM.length > 0 && (
<div className="DataTableTags flex-row">{tagsDOM}</div>
)}
{column.comment && (
<div className="mt4">
<div className="tooltip-title">Definition</div>
<div className="tooltip-content">{column.comment}</div>
</div>
)}
{description && (
<div className="mt4">
<div className="tooltip-title">Description</div>
<div className="tooltip-content">{description}</div>
</div>
)}
{statsDOM.length && (
<div className="mt4">
<div className="tooltip-title">Stats</div>
<div className="tooltip-content">{statsDOM}</div>
</div>
)}
</>
);

return <div className="rich-text-content">{contentDOM}</div>;
};
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export const TableTooltip: React.FunctionComponent<IProps> = ({

const contentDOM = (
<>
<div className="table-tooltip-header flex-row">
<div className="tooltip-header flex-row">
<div>{tableName}</div>
<div className="flex-row mt4 ml4">
{pinToSidebarButton}
Expand All @@ -110,7 +110,7 @@ export const TableTooltip: React.FunctionComponent<IProps> = ({
</>
);

return <div className="rich-text-content ">{contentDOM}</div>;
return <div className="rich-text-content">{contentDOM}</div>;
};

export const TableTooltipByName: React.FunctionComponent<{
Expand Down Expand Up @@ -144,7 +144,9 @@ export const TableTooltipByName: React.FunctionComponent<{
metastoreId
)
);
setTableId(table.id);
if (table) {
setTableId(table.id);
}
} catch (error) {
console.error('Error fetching table:', error);
}
Expand Down
4 changes: 2 additions & 2 deletions querybook/webapp/components/QueryEditor/QueryEditor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@
word-break: break-word;
font-size: var(--text-size);

.table-tooltip-header {
.tooltip-header {
font-size: var(--text-size);
color: var(--text-dark);
color: var(--color-accent-dark);
font-weight: var(--bold-font);
justify-content: space-between;
align-items: start;
Expand Down
20 changes: 9 additions & 11 deletions querybook/webapp/components/QueryEditor/QueryEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import toast from 'react-hot-toast';
import { TDataDocMetaVariables } from 'const/datadoc';
import KeyMap from 'const/keyMap';
import { IDataTable } from 'const/metastore';
import { useAutoCompleteExtension } from 'hooks/queryEditor/extensions/useAutoCompleteExtension';
import {
AutoCompleteType,
useAutoCompleteExtension,
} from 'hooks/queryEditor/extensions/useAutoCompleteExtension';
import { useEventsExtension } from 'hooks/queryEditor/extensions/useEventsExtension';
import { useHoverTooltipExtension } from 'hooks/queryEditor/extensions/useHoverTooltipExtension';
import { useKeyMapExtension } from 'hooks/queryEditor/extensions/useKeyMapExtension';
Expand All @@ -26,13 +29,12 @@ import { useOptionsExtension } from 'hooks/queryEditor/extensions/useOptionsExte
import { useSearchExtension } from 'hooks/queryEditor/extensions/useSearchExtension';
import { useSqlCompleteExtension } from 'hooks/queryEditor/extensions/useSqlCompleteExtension';
import { useStatusBarExtension } from 'hooks/queryEditor/extensions/useStatusBarExtension';
import { useAutoComplete } from 'hooks/queryEditor/useAutoComplete';
import { useCodeAnalysis } from 'hooks/queryEditor/useCodeAnalysis';
import { useLint } from 'hooks/queryEditor/useLint';
import { useSqlParser } from 'hooks/queryEditor/useSqlParser';
import useDeepCompareEffect from 'hooks/useDeepCompareEffect';
import { CodeMirrorKeyMap } from 'lib/codemirror';
import { mixedSQL } from 'lib/codemirror/codemirror-mixed';
import { AutoCompleteType } from 'lib/sql-helper/sql-autocompleter';
import { format, ISQLFormatOptions } from 'lib/sql-helper/sql-formatter';
import { TableToken } from 'lib/sql-helper/sql-lexer';
import { navigateWithinEnv } from 'lib/utils/query-string';
Expand Down Expand Up @@ -204,12 +206,7 @@ export const QueryEditor: React.FC<
language,
query: value,
});
const autoCompleterRef = useAutoComplete(
metastoreId,
autoCompleteType,
language,
codeAnalysis
);
const sqlParserRef = useSqlParser(metastoreId, language, codeAnalysis);

const tableReferences: TableToken[] = useMemo(
() =>
Expand Down Expand Up @@ -287,7 +284,8 @@ export const QueryEditor: React.FC<

const autoCompleteExtension = useAutoCompleteExtension({
view: editorRef.current?.view,
autoCompleterRef,
sqlParserRef,
type: autoCompleteType,
});

const lintExtension = useLintExtension({
Expand All @@ -296,7 +294,7 @@ export const QueryEditor: React.FC<

const { extension: hoverTooltipExtension, getTableAtCursor } =
useHoverTooltipExtension({
codeAnalysisRef,
sqlParserRef,
metastoreId,
language,
});
Expand Down
2 changes: 1 addition & 1 deletion querybook/webapp/const/metastore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ export interface IDataColumn {
name: string;
table_id: number;
type: string;
stats?: ITableColumnStats[];
}
export interface IDetailedDataColumn extends IDataColumn {
stats?: ITableColumnStats[];
tags?: ITag[];
data_element_association?: IDataElementAssociation;
}
Expand Down
Loading

0 comments on commit 7ee8219

Please sign in to comment.