Skip to content
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

feat: upgrade codemirror 5 to codemirror 6 #1510

Merged
merged 6 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
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
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
Loading