diff --git a/src/assets/icons/flask.svg b/src/assets/icons/flask.svg deleted file mode 100644 index 9c58699226..0000000000 --- a/src/assets/icons/flask.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/src/assets/icons/star.svg b/src/assets/icons/star.svg deleted file mode 100644 index 536ff01485..0000000000 --- a/src/assets/icons/star.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/containers/AppWithClusters/AppWithClusters.tsx b/src/containers/AppWithClusters/AppWithClusters.tsx index 7256c60f3f..2141dce1bb 100644 --- a/src/containers/AppWithClusters/AppWithClusters.tsx +++ b/src/containers/AppWithClusters/AppWithClusters.tsx @@ -29,7 +29,7 @@ export interface AppWithClustersProps { const defaultUserSettings = settings; -defaultUserSettings[1].sections[0].settings.push({ +defaultUserSettings[2].sections[0].settings.push({ title: i18n('settings.useClusterBalancerAsBackend.title'), helpPopoverContent: i18n('settings.useClusterBalancerAsBackend.popover'), settingKey: USE_CLUSTER_BALANCER_AS_BACKEND_KEY, diff --git a/src/containers/Tenant/Query/QueryEditor/QueryEditor.tsx b/src/containers/Tenant/Query/QueryEditor/QueryEditor.tsx index e50cd0e6b4..8f0654dfaf 100644 --- a/src/containers/Tenant/Query/QueryEditor/QueryEditor.tsx +++ b/src/containers/Tenant/Query/QueryEditor/QueryEditor.tsx @@ -26,6 +26,7 @@ import { import {useSetting, useQueryModes} from '../../../../utils/hooks'; import {QUERY_ACTIONS} from '../../../../utils/query'; import {parseJson} from '../../../../utils/utils'; +import {useEditorOptions} from './helpers'; import { InitialPaneState, @@ -48,14 +49,6 @@ import i18n from '../i18n'; import './QueryEditor.scss'; -const EDITOR_OPTIONS = { - automaticLayout: true, - selectOnLineNumbers: true, - minimap: { - enabled: false, - }, -}; - const CONTEXT_MENU_GROUP_ID = 'navigation'; const RESULT_TYPES = { EXECUTE: 'execute', @@ -93,6 +86,7 @@ interface QueryEditorProps { } function QueryEditor(props: QueryEditorProps) { + const editorOptions = useEditorOptions(); const { path, setTenantPath: setPath, @@ -422,7 +416,7 @@ function QueryEditor(props: QueryEditorProps) { (() => { + const useAutocomplete = Boolean(enableAutocomplete); + return { + quickSuggestions: useAutocomplete, + suggestOnTriggerCharacters: useAutocomplete, + ...EDITOR_OPTIONS, + }; + }, [enableAutocomplete]); + + return options; +} diff --git a/src/containers/UserSettings/i18n/en.json b/src/containers/UserSettings/i18n/en.json index 15e92ee57f..cfcb1f4c5b 100644 --- a/src/containers/UserSettings/i18n/en.json +++ b/src/containers/UserSettings/i18n/en.json @@ -5,6 +5,12 @@ "page.experiments": "Experiments", "section.experiments": "Experiments", + "page.editor": "Editor", + "section.dev-setting": "Development settings", + + "settings.editor.autocomplete.title": "Enable autocomplete", + "settings.editor.autocomplete.description": "You’re always able to get suggestions by pressing Ctrl+Space.", + "settings.theme.title": "Interface theme", "settings.theme.option-dark": "Dark", "settings.theme.option-light": "Light", diff --git a/src/containers/UserSettings/settings.tsx b/src/containers/UserSettings/settings.tsx index 7ee510d241..c4fa21524a 100644 --- a/src/containers/UserSettings/settings.tsx +++ b/src/containers/UserSettings/settings.tsx @@ -1,7 +1,6 @@ import type {IconProps} from '@gravity-ui/uikit'; -import favoriteFilledIcon from '../../assets/icons/star.svg'; -import flaskIcon from '../../assets/icons/flask.svg'; +import {PencilToSquare, Flask, StarFill} from '@gravity-ui/icons'; import { INVERTED_DISKS_KEY, @@ -11,6 +10,7 @@ import { USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY, QUERY_USE_MULTI_SCHEMA_KEY, BINARY_DATA_IN_PLAIN_TEXT_DISPLAY, + ENABLE_AUTOCOMPLETE, } from '../../utils/constants'; import {Lang, defaultLang} from '../../utils/i18n'; @@ -107,6 +107,12 @@ export const queryUseMultiSchemaSetting: SettingProps = { helpPopoverContent: i18n('settings.queryUseMultiSchema.popover'), }; +export const enableAutocompleteSetting: SettingProps = { + settingKey: ENABLE_AUTOCOMPLETE, + title: i18n('settings.editor.autocomplete.title'), + description: i18n('settings.editor.autocomplete.description'), +}; + export const appearanceSection: SettingsSection = { id: 'appearanceSection', title: i18n('section.appearance'), @@ -117,18 +123,29 @@ export const experimentsSection: SettingsSection = { title: i18n('section.experiments'), settings: [useNodesEndpointSetting, useVirtualTables, queryUseMultiSchemaSetting], }; +export const devSettingsSection: SettingsSection = { + id: 'devSettingsSection', + title: i18n('section.dev-setting'), + settings: [enableAutocompleteSetting], +}; export const generalPage: SettingsPage = { id: 'generalPage', title: i18n('page.general'), - icon: {data: favoriteFilledIcon, height: 14, width: 14}, + icon: {data: StarFill, height: 14, width: 14}, sections: [appearanceSection], }; export const experimentsPage: SettingsPage = { id: 'experimentsPage', title: i18n('page.experiments'), - icon: {data: flaskIcon}, + icon: {data: Flask}, sections: [experimentsSection], }; +export const editorPage: SettingsPage = { + id: 'editorPage', + title: i18n('page.editor'), + icon: {data: PencilToSquare}, + sections: [devSettingsSection], +}; -export const settings: YDBEmbeddedUISettings = [generalPage, experimentsPage]; +export const settings: YDBEmbeddedUISettings = [generalPage, editorPage, experimentsPage]; diff --git a/src/services/settings.ts b/src/services/settings.ts index 824e0ffce0..5314ece3d9 100644 --- a/src/services/settings.ts +++ b/src/services/settings.ts @@ -15,6 +15,7 @@ import { USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY, USE_CLUSTER_BALANCER_AS_BACKEND_KEY, BINARY_DATA_IN_PLAIN_TEXT_DISPLAY, + ENABLE_AUTOCOMPLETE, } from '../utils/constants'; import {QUERY_ACTIONS, QUERY_MODES} from '../utils/query'; import {parseJson} from '../utils/utils'; @@ -37,6 +38,7 @@ export const DEFAULT_USER_SETTINGS: SettingsObject = { [PARTITIONS_HIDDEN_COLUMNS_KEY]: [], [USE_BACKEND_PARAMS_FOR_TABLES_KEY]: false, [USE_CLUSTER_BALANCER_AS_BACKEND_KEY]: true, + [ENABLE_AUTOCOMPLETE]: false, }; class SettingsManager { diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 751494c7d7..64182967ba 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -130,3 +130,5 @@ export const USE_BACKEND_PARAMS_FOR_TABLES_KEY = 'useBackendParamsForTables'; export const QUERY_USE_MULTI_SCHEMA_KEY = 'queryUseMultiSchema'; export const USE_CLUSTER_BALANCER_AS_BACKEND_KEY = 'useClusterBalancerAsBacked'; + +export const ENABLE_AUTOCOMPLETE = 'enableAutocomplete'; diff --git a/src/utils/yqlSuggestions/constants.ts b/src/utils/yqlSuggestions/constants.ts index 2a874a4bf0..0a6abf2e74 100644 --- a/src/utils/yqlSuggestions/constants.ts +++ b/src/utils/yqlSuggestions/constants.ts @@ -89,15 +89,8 @@ export const SimpleFunctions = [ 'Unwrap', 'Nothing', 'Callable', - 'Pickle', - 'StablePickle', - 'Unpickle', 'StaticMap', 'StaticZip', - 'AggregationFactory', - 'AggregateTransformInput', - 'AggregateTransformOutput', - 'AggregateFlatten', 'ListCreate', 'AsListStrict', 'ListLength', @@ -380,10 +373,6 @@ const RawUdfs = { 'UnescapeC', ], - Compress: ['BZip2', 'Brotli', 'Gzip', 'Lzma', 'Snappy', 'Zlib', 'Zstd'], - - TryDecompress: ['BZip2', 'Brotli', 'Gzip', 'Lzma', 'Snappy', 'Xz', 'Zlib', 'Zstd'], - Unicode: [ 'Find', 'Fold', @@ -658,8 +647,6 @@ const RawUdfs = { 'Replace', ], - Protobuf: ['Parse', 'Serialize', 'TryParse'], - Digest: [ 'Argon2', 'Blake2B', @@ -692,8 +679,6 @@ const RawUdfs = { 'XXH3_128', ], - Decompress: ['BZip2', 'Brotli', 'Gzip', 'Lzma', 'Snappy', 'Xz', 'Zlib', 'Zstd'], - Histogram: [ 'CalcLowerBound', 'CalcLowerBoundSafe', @@ -724,47 +709,6 @@ export const WindowFunctions = [ 'SessionState', ]; -export const TableFunction = [ - 'CONCAT', - 'EACH', - 'RANGE', - 'LIKE', - 'REGEXP', - 'CONCAT_STRICT', - 'RANGE_STRICT', - 'FILTER', - 'FOLDER', - 'WalkFolders', -]; +export const TableFunction = []; -export const Pragmas = [ - 'TablePathPrefix', - 'AnsiInForEmptyOrNullableItemsCollections', - 'File', - 'Folder', - 'Library', - 'Warning', - 'package', - 'override_library', - 'AutoCommit', - 'DqEngine', - 'SimpleColumns', - 'DisableSimpleColumns', - 'CoalesceJoinKeysOnQualifiedAll', - 'StrictJoinKeyTypes', - 'AnsiRankForNullableKeys', - 'AnsiCurrentRow', - 'AnsiOrderByLimitInUnionAll', - 'OrderedColumns', - 'DisableOrderedColumns', - 'PositionalUnionAll', - 'RegexUseRe2', - 'ClassicDivision', - 'AllowDotInAlias', - 'WarnUnnamedColumns', - 'GroupByLimit', - 'GroupByCubeLimit', - 'config.flags', - 'kikimr.IsolationLevel', - 'Kikimr.ScanQuery', -]; +export const Pragmas = ['TablePathPrefix', 'Warning']; diff --git a/src/utils/yqlSuggestions/yqlSuggestions.ts b/src/utils/yqlSuggestions/yqlSuggestions.ts index d4a8cc5b7f..cd29a3d2f2 100644 --- a/src/utils/yqlSuggestions/yqlSuggestions.ts +++ b/src/utils/yqlSuggestions/yqlSuggestions.ts @@ -1,4 +1,4 @@ -import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; +import type Monaco from 'monaco-editor'; import {CursorPosition, parseYqlQuery} from '@gravity-ui/websql-autocomplete'; import { @@ -17,10 +17,10 @@ import { export function createProvideSuggestionsFunction(database: string) { return async ( - model: monaco.editor.ITextModel, - monacoCursorPosition: monaco.Position, - _context: monaco.languages.CompletionContext, - _token: monaco.CancellationToken, + model: Monaco.editor.ITextModel, + monacoCursorPosition: Monaco.Position, + _context: Monaco.languages.CompletionContext, + _token: Monaco.CancellationToken, ) => { const cursorPosition: CursorPosition = { line: monacoCursorPosition.lineNumber, @@ -40,20 +40,20 @@ export function createProvideSuggestionsFunction(database: string) { } async function getSuggestions( - model: monaco.editor.ITextModel, + model: Monaco.editor.ITextModel, cursorPosition: CursorPosition, - rangeToInsertSuggestion: monaco.IRange, + rangeToInsertSuggestion: Monaco.IRange, database: string, -): Promise { +): Promise { const parseResult = parseYqlQuery(model.getValue(), cursorPosition); - let entitiesSuggestions: monaco.languages.CompletionItem[] = []; - let functionsSuggestions: monaco.languages.CompletionItem[] = []; - let aggregateFunctionsSuggestions: monaco.languages.CompletionItem[] = []; - let windowFunctionsSuggestions: monaco.languages.CompletionItem[] = []; - let tableFunctionsSuggestions: monaco.languages.CompletionItem[] = []; - let udfsSuggestions: monaco.languages.CompletionItem[] = []; - let simpleTypesSuggestions: monaco.languages.CompletionItem[] = []; - let pragmasSuggestions: monaco.languages.CompletionItem[] = []; + let entitiesSuggestions: Monaco.languages.CompletionItem[] = []; + let functionsSuggestions: Monaco.languages.CompletionItem[] = []; + let aggregateFunctionsSuggestions: Monaco.languages.CompletionItem[] = []; + let windowFunctionsSuggestions: Monaco.languages.CompletionItem[] = []; + let tableFunctionsSuggestions: Monaco.languages.CompletionItem[] = []; + let udfsSuggestions: Monaco.languages.CompletionItem[] = []; + let simpleTypesSuggestions: Monaco.languages.CompletionItem[] = []; + let pragmasSuggestions: Monaco.languages.CompletionItem[] = []; if (parseResult.suggestEntity) { entitiesSuggestions = await generateEntitiesSuggestion(rangeToInsertSuggestion); @@ -100,7 +100,7 @@ async function getSuggestions( parseResult.suggestKeywords, ); - const suggestions: monaco.languages.CompletionItem[] = [ + const suggestions: Monaco.languages.CompletionItem[] = [ ...entitiesSuggestions, ...functionsSuggestions, ...windowFunctionsSuggestions, @@ -118,12 +118,12 @@ async function getSuggestions( } function getRangeToInsertSuggestion( - model: monaco.editor.ITextModel, - cursorPosition: monaco.Position, -): monaco.IRange { + model: Monaco.editor.ITextModel, + cursorPosition: Monaco.Position, +): Monaco.IRange { const {startColumn: lastWordStartColumn, endColumn: lastWordEndColumn} = model.getWordUntilPosition(cursorPosition); - // https://github.com/microsoft/monaco-editor/discussions/3639#discussioncomment-5190373 if user already typed "$" sign, it should not be duplicated + // https://github.com/microsoft/Monaco-editor/discussions/3639#discussioncomment-5190373 if user already typed "$" sign, it should not be duplicated const dollarBeforeLastWordStart = model.getLineContent(cursorPosition.lineNumber)[lastWordStartColumn - 2] === '$' ? 1 : 0; return {