From 4caa221d72473f8307489d814f58bcfabde4c57e Mon Sep 17 00:00:00 2001 From: Vadim Ogievetsky Date: Mon, 19 Apr 2021 14:36:53 -0700 Subject: [PATCH] Web console: Better inline docs (#11128) * better highlight * better highlighting * add spec --- licenses.yaml | 2 +- pom.xml | 5 +- web-console/lib/keywords.js | 1 + web-console/lib/sql-docs.d.ts | 13 +---- web-console/package-lock.json | 6 +- web-console/package.json | 2 +- web-console/script/create-sql-docs.js | 23 ++++---- .../__snapshots__/query-input.spec.tsx.snap | 18 +----- .../query-view/query-input/query-input.scss | 11 ++-- .../query-input/query-input.spec.tsx | 2 +- .../query-view/query-input/query-input.tsx | 56 +++++++++---------- 11 files changed, 59 insertions(+), 80 deletions(-) diff --git a/licenses.yaml b/licenses.yaml index 7144496da4b..034b463ffa2 100644 --- a/licenses.yaml +++ b/licenses.yaml @@ -5143,7 +5143,7 @@ license_category: binary module: web-console license_name: Apache License version 2.0 copyright: Imply Data -version: 0.10.5 +version: 0.10.7 --- diff --git a/pom.xml b/pom.xml index 568d8152785..c47e04ab69a 100644 --- a/pom.xml +++ b/pom.xml @@ -269,7 +269,7 @@ com.amazonaws aws-java-sdk-sts ${aws.sdk.version} - + com.ning compress-lzf @@ -1312,7 +1312,7 @@ org/apache/druid/query/TruncatedResponseContextException.class - org/apache/druid/common/aws/AWSCredentials* + org/apache/druid/common/aws/AWSCredentials* @@ -1970,7 +1970,6 @@ .github/pull_request_template.md git.version node_modules/** - coordinator-console/** src/**/*.snap examples/conf/** .asf.yaml diff --git a/web-console/lib/keywords.js b/web-console/lib/keywords.js index e476dfbd27a..4a8c249ed0e 100644 --- a/web-console/lib/keywords.js +++ b/web-console/lib/keywords.js @@ -45,6 +45,7 @@ exports.SQL_KEYWORDS = [ 'RIGHT', 'OUTER', 'FULL', + 'CROSS', ]; exports.SQL_EXPRESSION_PARTS = [ diff --git a/web-console/lib/sql-docs.d.ts b/web-console/lib/sql-docs.d.ts index c4c9c34b3a2..8c30d0c7021 100644 --- a/web-console/lib/sql-docs.d.ts +++ b/web-console/lib/sql-docs.d.ts @@ -16,14 +16,5 @@ * limitations under the License. */ -export interface SyntaxDescription { - name: string; - description: string; -} - -export interface FunctionSyntaxDescription extends SyntaxDescription { - arguments: string; -} - -export const SQL_DATA_TYPES: SyntaxDescription[]; -export const SQL_FUNCTIONS: FunctionSyntaxDescription[]; +export const SQL_DATA_TYPES: [name: string, runtime: string, description: string][]; +export const SQL_FUNCTIONS: [name: string, args: string, description: string][]; diff --git a/web-console/package-lock.json b/web-console/package-lock.json index ca1ce60f159..850b7c165bc 100644 --- a/web-console/package-lock.json +++ b/web-console/package-lock.json @@ -7374,9 +7374,9 @@ } }, "druid-query-toolkit": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.10.5.tgz", - "integrity": "sha512-qdH1FsjxAgGnXHtk9F88j3XT+/KLYfuPcVCMxBBolYE1/O1O6in5FDW+id8ek0JT/+astNMGKjfh6IUk9s/YkQ==", + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.10.7.tgz", + "integrity": "sha512-+1f8LrGTi0FML8H5Rfou6fJGlEtex7gWwsS9fDgxL1fs7eJkdaTrgvCUT/sFxfR3HmcEBktbmS4mShiBZztLoQ==", "requires": { "tslib": "^2.0.2" } diff --git a/web-console/package.json b/web-console/package.json index a58149d567e..cf7f69fdfab 100644 --- a/web-console/package.json +++ b/web-console/package.json @@ -73,7 +73,7 @@ "d3-axis": "^1.0.12", "d3-scale": "^3.2.0", "d3-selection": "^1.4.0", - "druid-query-toolkit": "^0.10.5", + "druid-query-toolkit": "^0.10.7", "file-saver": "^2.0.2", "fontsource-open-sans": "^3.0.9", "has-own-prop": "^2.0.0", diff --git a/web-console/script/create-sql-docs.js b/web-console/script/create-sql-docs.js index 86ec0d70d75..05abeb4c429 100755 --- a/web-console/script/create-sql-docs.js +++ b/web-console/script/create-sql-docs.js @@ -34,23 +34,22 @@ const readDoc = async () => { const functionDocs = []; const dataTypeDocs = []; for (let line of lines) { - const functionMatch = line.match(/^\|`(\w+)(\(.*\))`\|(.+)\|$/); + const functionMatch = line.match(/^\|`(\w+)\((.*)\)`\|(.+)\|$/); if (functionMatch) { - functionDocs.push({ - name: functionMatch[1], - arguments: functionMatch[2], - description: unwrapMarkdownLinks(functionMatch[3]), - }); + functionDocs.push([ + functionMatch[1], + functionMatch[2], + unwrapMarkdownLinks(functionMatch[3]), + ]); } const dataTypeMatch = line.match(/^\|([A-Z]+)\|([A-Z]+)\|(.*)\|(.*)\|$/); if (dataTypeMatch) { - dataTypeDocs.push({ - name: dataTypeMatch[1], - description: unwrapMarkdownLinks( - dataTypeMatch[4] || `Druid runtime type: ${dataTypeMatch[2]}`, - ), - }); + dataTypeDocs.push([ + dataTypeMatch[1], + dataTypeMatch[2], + unwrapMarkdownLinks(dataTypeMatch[4]), + ]); } } diff --git a/web-console/src/views/query-view/query-input/__snapshots__/query-input.spec.tsx.snap b/web-console/src/views/query-view/query-input/__snapshots__/query-input.spec.tsx.snap index d3616a03298..15c562d50a6 100644 --- a/web-console/src/views/query-view/query-input/__snapshots__/query-input.spec.tsx.snap +++ b/web-console/src/views/query-view/query-input/__snapshots__/query-input.spec.tsx.snap @@ -2,21 +2,9 @@ exports[`query input correctly formats helper HTML 1`] = ` " -
-
- COUNT -
-
-
- Syntax: -
-
COUNT(*)
-
-
- Description: -
-
Counts the number of things
-
" +
COUNT
+
COUNT(*)
+
Counts the number of things
" `; exports[`query input matches snapshot 1`] = ` diff --git a/web-console/src/views/query-view/query-input/query-input.scss b/web-console/src/views/query-view/query-input/query-input.scss index eca2db6707e..22edf5a73c5 100644 --- a/web-console/src/views/query-view/query-input/query-input.scss +++ b/web-console/src/views/query-view/query-input/query-input.scss @@ -68,11 +68,14 @@ background: $dark-gray2; } - hr { - margin: 10px 0; + .doc-name { + font-size: 18px; + border-bottom: 2px solid gray; + padding-bottom: 4px; } - .function-doc-name { - font-size: 18px; + .doc-syntax { + padding-top: 8px; + padding-bottom: 10px; } } diff --git a/web-console/src/views/query-view/query-input/query-input.spec.tsx b/web-console/src/views/query-view/query-input/query-input.spec.tsx index b0b198e5d43..62bcc8c709f 100644 --- a/web-console/src/views/query-view/query-input/query-input.spec.tsx +++ b/web-console/src/views/query-view/query-input/query-input.spec.tsx @@ -33,7 +33,7 @@ describe('query input', () => { it('correctly formats helper HTML', () => { expect( - QueryInput.completerToHtml({ + QueryInput.makeDocHtml({ caption: 'COUNT', syntax: 'COUNT(*)', description: 'Counts the number of things', diff --git a/web-console/src/views/query-view/query-input/query-input.tsx b/web-console/src/views/query-view/query-input/query-input.tsx index f94f805a10e..346b556fb5b 100644 --- a/web-console/src/views/query-view/query-input/query-input.tsx +++ b/web-console/src/views/query-view/query-input/query-input.tsx @@ -66,32 +66,42 @@ export class QueryInput extends React.PureComponent ({ name: v, value: v, score: 0, meta: 'keyword' })), SQL_CONSTANTS.map(v => ({ name: v, value: v, score: 0, meta: 'constant' })), SQL_DYNAMICS.map(v => ({ name: v, value: v, score: 0, meta: 'dynamic' })), - SQL_DATA_TYPES.map(v => ({ name: v.name, value: v.name, score: 0, meta: 'type' })), + SQL_DATA_TYPES.map(([name, runtime, description]) => ({ + name, + value: name, + score: 0, + meta: 'type', + syntax: `Druid runtime type: ${runtime}`, + description, + })), ); - const keywordCompleter = { - getCompletions: (_editor: any, _session: any, _pos: any, _prefix: any, callback: any) => { - return callback(null, keywordList); - }, - }; - langTools.setCompleters([ langTools.snippetCompleter, langTools.textCompleter, - keywordCompleter, + { + getCompletions: (_editor: any, _session: any, _pos: any, _prefix: any, callback: any) => { + return callback(null, keywordList); + }, + getDocTooltip: (item: any) => { + if (item.meta === 'type') { + item.docHTML = QueryInput.makeDocHtml(item); + } + }, + }, ]); } static addFunctionAutoCompleter(): void { if (!langTools) return; - const functionList: any[] = SQL_FUNCTIONS.map(entry => { + const functionList: any[] = SQL_FUNCTIONS.map(([name, args, description]) => { return { - value: entry.name, + value: name, score: 80, meta: 'function', - syntax: entry.name + entry.arguments, - description: entry.description, + syntax: `${name}(${args})`, + description, completer: { insertMatch: (editor: any, data: any) => { editor.completer.insertMatch({ value: data.caption }); @@ -106,29 +116,17 @@ export class QueryInput extends React.PureComponent { if (item.meta === 'function') { - item.docHTML = QueryInput.completerToHtml(item); + item.docHTML = QueryInput.makeDocHtml(item); } }, }); } - static completerToHtml(item: any) { + static makeDocHtml(item: any) { return ` -
-
- ${escape(item.caption)} -
-
-
- Syntax: -
-
${escape(item.syntax)}
-
-
- Description: -
-
${escape(item.description)}
-
`; +
${escape(item.caption)}
+
${escape(item.syntax)}
+
${escape(item.description)}
`; } static getDerivedStateFromProps(props: QueryInputProps, state: QueryInputState) {