Skip to content

Commit

Permalink
feat: upgrade codemirror 5 to codemirror 6 (#1510)
Browse files Browse the repository at this point in the history
* feat: upgrade codemirror 5 to codemirror 6

* fix linter

* upgrade typescript to fix lint errors and address comments

* hide the accept button when readonly

* update yarn.lock

* update tsconfig
  • Loading branch information
jczhong84 authored Nov 13, 2024
1 parent d106e2e commit a7840a1
Show file tree
Hide file tree
Showing 33 changed files with 1,738 additions and 1,708 deletions.
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "querybook",
"version": "3.34.3",
"version": "3.35.0",
"description": "A Big Data Webapp",
"private": true,
"scripts": {
Expand Down Expand Up @@ -36,7 +36,11 @@
"@babel/preset-env": "^7.16.0",
"@babel/preset-react": "^7.16.0",
"@babel/preset-typescript": "^7.16.0",
"@codemirror/lang-sql": "^6.8.0",
"@types/diff": "^5.0.2",
"@uiw/codemirror-extensions-events": "^4.23.6",
"@uiw/codemirror-themes": "^4.23.5",
"@uiw/react-codemirror": "^4.23.5",
"@welldone-software/why-did-you-render": "^6.1.1",
"axios": "^1.2.2",
"bignumber.js": "^9.0.1",
Expand All @@ -46,10 +50,11 @@
"clean-webpack-plugin": "3.0.0",
"clsx": "^1.2.1",
"codemirror": "^5.64.0",
"cronstrue": "2.47.0",
"codemirror-copilot": "^0.0.7",
"core-decorators": "0.20.0",
"core-js": "^3.19.1",
"cron-parser": "^4.7.0",
"cronstrue": "2.47.0",
"dagre": "^0.8.5",
"dompurify": "^3.1.7",
"draft-js": "0.11.7",
Expand Down Expand Up @@ -102,7 +107,7 @@
"socket.io-client": "^4.5.2",
"sql-formatter": "^12.1.2",
"styled-components": "5.3.9",
"typescript": "4.4.4",
"typescript": "^5.6.3",
"webpack": "5.76.0",
"webpack-cli": "4.7.0",
"yaml-loader": "^0.8.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import React from 'react';
import React, { useCallback, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';

import { IFunctionDescription } from 'const/metastore';
import { fetchFunctionDocumentationIfNeeded } from 'redux/dataSources/action';
import { IStoreState } from 'redux/store/types';
import { ShowMoreText } from 'ui/ShowMoreText/ShowMoreText';

interface IProps {
Expand Down Expand Up @@ -41,3 +44,32 @@ export const FunctionDocumentationTooltip: React.FunctionComponent<IProps> = ({

return <div>{functionsDOM}</div>;
};

export const FunctionDocumentationTooltipByName: React.FunctionComponent<{
language: string;
functionName: string;
}> = ({ language, functionName }) => {
const dispatch = useDispatch();
const functionDocumentationByNameByLanguage = useSelector(
(state: IStoreState) =>
state.dataSources.functionDocumentation.byNameByLanguage
);

useEffect(() => {
if (language) {
dispatch(fetchFunctionDocumentationIfNeeded(language));
}
}, [language]);

const functionDefs = functionDocumentationByNameByLanguage?.[language];
const functionNameLower = (functionName || '').toLowerCase();
const functionDef = functionDefs?.[functionNameLower];

if (!functionDef) {
return null;
}

return (
<FunctionDocumentationTooltip functionDocumentations={functionDef} />
);
};
55 changes: 55 additions & 0 deletions querybook/webapp/components/CodeMirrorTooltip/LintTooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { useCallback, useMemo } from 'react';

import { Button } from 'ui/Button/Button';

interface IProps {
message: string;
suggestion?: string;
readonly?: boolean;
onAcceptSuggestion?: (suggestion: string) => void;
}

const SUGGESTION_MAX_LENGTH = 40;

export const LintTooltip: React.FunctionComponent<IProps> = ({
message,
suggestion,
readonly = false,
onAcceptSuggestion,
}) => {
const truncatedSuggestion = useMemo(
() =>
suggestion && suggestion.length > SUGGESTION_MAX_LENGTH
? suggestion.slice(0, SUGGESTION_MAX_LENGTH - 3) + '...'
: suggestion,
[suggestion]
);

const onClick = useCallback(() => {
onAcceptSuggestion(suggestion);
}, [onAcceptSuggestion, suggestion]);

return (
<div className="rich-text-content">
<div>{message}</div>
{truncatedSuggestion && (
<div className="mt8">
<div>
Replace with <code>{truncatedSuggestion}</code>
</div>
{!readonly && onAcceptSuggestion && (
<div className="mt8 right-align">
<Button
title="Accept"
onClick={onClick}
theme="fill"
color="confirm"
icon="Check"
/>
</div>
)}
</div>
)}
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
margin: 0;
overflow: hidden;
display: flex;

.QueryEditor {
flex: 1;
}
Expand Down
55 changes: 11 additions & 44 deletions querybook/webapp/components/DataDocQueryCell/DataDocQueryCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,7 @@ import { SurveySurfaceType } from 'const/survey';
import { triggerSurvey } from 'hooks/ui/useSurveyTrigger';
import { trackClick } from 'lib/analytics';
import CodeMirror from 'lib/codemirror';
import { createSQLLinter } from 'lib/codemirror/codemirror-lint';
import {
getQueryAsExplain,
getSelectedQuery,
IRange,
} from 'lib/sql-helper/sql-lexer';
import { getQueryAsExplain } from 'lib/sql-helper/sql-lexer';
import { DEFAULT_ROW_LIMIT } from 'lib/sql-helper/sql-limiter';
import { getPossibleTranspilers } from 'lib/templated-query/transpile';
import { enableResizable } from 'lib/utils';
Expand All @@ -66,7 +61,6 @@ import { Modal } from 'ui/Modal/Modal';
import { IResizableTextareaHandles } from 'ui/ResizableTextArea/ResizableTextArea';
import { AccentText } from 'ui/StyledText/StyledText';

import { ISelectedRange } from './common';
import { ErrorQueryCell } from './ErrorQueryCell';

import './DataDocQueryCell.scss';
Expand Down Expand Up @@ -114,7 +108,7 @@ interface IState {

modifiedAt: number;
focused: boolean;
selectedRange: ISelectedRange;
hasSelection: boolean;
queryCollapsedOverride: boolean;
showQuerySnippetModal: boolean;
showRenderedTemplateModal: boolean;
Expand Down Expand Up @@ -143,7 +137,7 @@ class DataDocQueryCellComponent extends React.PureComponent<IProps, IState> {
meta: props.meta,
modifiedAt: 0,
focused: false,
selectedRange: null,
hasSelection: false,
queryCollapsedOverride: null,
showQuerySnippetModal: false,
showRenderedTemplateModal: false,
Expand Down Expand Up @@ -281,9 +275,9 @@ class DataDocQueryCellComponent extends React.PureComponent<IProps, IState> {
}

@bind
public onSelection(query: string, selectedRange: IRange) {
public onSelection(hasSelection: boolean) {
this.setState({
selectedRange,
hasSelection,
});
}

Expand Down Expand Up @@ -312,27 +306,9 @@ class DataDocQueryCellComponent extends React.PureComponent<IProps, IState> {
});
}

@decorate(memoizeOne)
public createGetLintAnnotations(
engineId: number,
templatedVariables: TDataDocMetaVariables
) {
return createSQLLinter(engineId, templatedVariables);
}

@bind
public focus() {
if (
!(
this.queryEditorRef.current &&
this.queryEditorRef.current.getEditor
)
) {
return;
}

const editor = this.queryEditorRef.current.getEditor();
editor.focus();
this.queryEditorRef.current?.focus();
}

@bind
Expand Down Expand Up @@ -443,10 +419,7 @@ class DataDocQueryCellComponent extends React.PureComponent<IProps, IState> {
public async getTransformedQuery() {
const { templatedVariables = [] } = this.props;
const { query } = this.state;
const selectedRange =
this.queryEditorRef.current &&
this.queryEditorRef.current.getEditorSelection();
const rawQuery = getSelectedQuery(query, selectedRange);
const rawQuery = this.queryEditorRef.current?.getSelection?.() ?? query;

return transformQuery(
rawQuery,
Expand Down Expand Up @@ -778,7 +751,7 @@ class DataDocQueryCellComponent extends React.PureComponent<IProps, IState> {

isEditable,
} = this.props;
const { meta, query, selectedRange } = this.state;
const { meta, query, hasSelection } = this.state;

const queryTitleDOM = isEditable ? (
<QueryCellTitle
Expand Down Expand Up @@ -809,7 +782,7 @@ class DataDocQueryCellComponent extends React.PureComponent<IProps, IState> {
queryEngineById={queryEngineById}
queryEngines={queryEngines}
disabled={!isEditable}
hasSelection={selectedRange != null}
hasSelection={hasSelection}
engineId={this.engineId}
onRunClick={this.onRunButtonClick}
onEngineIdSelect={this.handleMetaChange.bind(
Expand Down Expand Up @@ -901,15 +874,9 @@ class DataDocQueryCellComponent extends React.PureComponent<IProps, IState> {
engine={queryEngine}
cellId={cellId}
height={isFullScreen ? 'full' : 'auto'}
templatedVariables={this.props.templatedVariables}
onFullScreen={this.props.toggleFullScreen}
getLintErrors={
this.hasQueryValidators
? this.createGetLintAnnotations(
this.engineId,
this.props.templatedVariables
)
: null
}
hasQueryLint={this.hasQueryValidators}
onLintCompletion={this.onLintCompletion}
/>
{openSnippetDOM}
Expand Down
4 changes: 2 additions & 2 deletions querybook/webapp/components/QueryComposer/QueryComposer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
overflow-y: auto;
overflow-x: hidden;
position: relative;
border-radius: var(--border-radius);
border-radius: var(--border-radius-sm);

.SearchAndReplaceBar {
position: absolute;
Expand All @@ -45,7 +45,7 @@
flex: 1;
overflow-y: scroll;
background-color: var(--bg-lightest);
border-radius: var(--border-radius);
border-radius: var(--border-radius-sm);

.hide-execution {
cursor: pointer;
Expand Down
49 changes: 9 additions & 40 deletions querybook/webapp/components/QueryComposer/QueryComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ import { useSurveyTrigger } from 'hooks/ui/useSurveyTrigger';
import { useBrowserTitle } from 'hooks/useBrowserTitle';
import { useTrackView } from 'hooks/useTrackView';
import { trackClick } from 'lib/analytics';
import { createSQLLinter } from 'lib/codemirror/codemirror-lint';
import { replaceStringIndices, searchText } from 'lib/data-doc/search';
import { getSelectedQuery, IRange } from 'lib/sql-helper/sql-lexer';
import { DEFAULT_ROW_LIMIT } from 'lib/sql-helper/sql-limiter';
import { getPossibleTranspilers } from 'lib/templated-query/transpile';
import { enableResizable, getQueryEngineId, sleep } from 'lib/utils';
Expand Down Expand Up @@ -295,9 +293,7 @@ function useQueryEditorHelpers() {
}, []);

const handleFocusEditor = useCallback(() => {
if (queryEditorRef.current) {
queryEditorRef.current.getEditor()?.focus();
}
queryEditorRef.current?.focus();
}, []);

useEffect(() => {
Expand Down Expand Up @@ -334,27 +330,6 @@ function useKeyMap(
}, [clickOnRunButton, queryEngines, setEngineId]);
}

function useQueryLint(
queryEngine: IQueryEngine,
templatedVariables: IDataDocMetaVariable[]
) {
const hasQueryValidators = Boolean(queryEngine?.feature_params?.validator);

const getLintAnnotations = useMemo(() => {
if (!hasQueryValidators) {
return null;
}

return (query: string, cm: CodeMirror.Editor) =>
createSQLLinter(queryEngine.id, templatedVariables)(query, cm);
}, [hasQueryValidators, queryEngine?.id, templatedVariables]);

return {
hasQueryValidators,
getLintAnnotations,
};
}

function useTranspileQuery(
currentQueryEngine: IQueryEngine,
queryEngines: IQueryEngine[],
Expand Down Expand Up @@ -464,10 +439,7 @@ const QueryComposer: React.FC = () => {
}, []);

const { queryEditorRef, handleFormatQuery } = useQueryEditorHelpers();
const { getLintAnnotations, hasQueryValidators } = useQueryLint(
engine,
templatedVariables
);
const hasQueryValidators = Boolean(engine?.feature_params?.validator);
const {
transpilerConfig,
startQueryTranspile,
Expand Down Expand Up @@ -506,9 +478,8 @@ const QueryComposer: React.FC = () => {
}, [executionId, query, engine.id, templatedVariables]);

const getCurrentSelectedQuery = useCallback(() => {
const selectedRange = queryEditorRef.current?.getEditorSelection();
return getSelectedQuery(query, selectedRange);
}, [query, queryEditorRef]);
return queryEditorRef.current?.getSelection?.() ?? query;
}, [queryEditorRef, query]);

const triggerSurvey = useSurveyTrigger();

Expand Down Expand Up @@ -588,12 +559,9 @@ const QueryComposer: React.FC = () => {
const keyMap = useKeyMap(clickOnRunButton, queryEngines, setEngineId);

const [editorHasSelection, setEditorHasSelection] = useState(false);
const handleEditorSelection = React.useCallback(
(_: string, range: IRange) => {
setEditorHasSelection(!!range);
},
[]
);
const handleEditorSelection = React.useCallback((hasSelection: boolean) => {
setEditorHasSelection(hasSelection);
}, []);

const scrollToCollapseExecution = React.useCallback(
(event, direction, elementRef) => {
Expand Down Expand Up @@ -633,10 +601,11 @@ const QueryComposer: React.FC = () => {
keyMap={keyMap}
height="full"
engine={engine}
hasQueryLint={hasQueryValidators}
onSelection={handleEditorSelection}
getLintErrors={getLintAnnotations}
onLintCompletion={setHasLintErrors}
onTablesChange={handleTablesChange}
templatedVariables={templatedVariables}
/>
</>
);
Expand Down
Loading

0 comments on commit a7840a1

Please sign in to comment.