Web console: Better inline docs (#11128)

* better highlight

* better highlighting

* add spec
This commit is contained in:
Vadim Ogievetsky 2021-04-19 14:36:53 -07:00 committed by GitHub
parent fdc3c2f362
commit 4caa221d72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 59 additions and 80 deletions

View File

@ -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
---

View File

@ -1970,7 +1970,6 @@
<exclude>.github/pull_request_template.md</exclude>
<exclude>git.version</exclude>
<exclude>node_modules/**</exclude>
<exclude>coordinator-console/**</exclude>
<exclude>src/**/*.snap</exclude>
<exclude>examples/conf/**</exclude>
<exclude>.asf.yaml</exclude>

View File

@ -45,6 +45,7 @@ exports.SQL_KEYWORDS = [
'RIGHT',
'OUTER',
'FULL',
'CROSS',
];
exports.SQL_EXPRESSION_PARTS = [

View File

@ -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][];

View File

@ -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"
}

View File

@ -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",

View File

@ -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]),
]);
}
}

View File

@ -2,21 +2,9 @@
exports[`query input correctly formats helper HTML 1`] = `
"
<div class=\\"function-doc\\">
<div class=\\"function-doc-name\\">
<b>COUNT</b>
</div>
<hr />
<div>
<b>Syntax:</b>
</div>
<div>COUNT(*)</div>
<br />
<div>
<b>Description:</b>
</div>
<div>Counts the number of things</div>
</div>"
<div class=\\"doc-name\\">COUNT</div>
<div class=\\"doc-syntax\\">COUNT(*)</div>
<div class=\\"doc-description\\">Counts the number of things</div>"
`;
exports[`query input matches snapshot 1`] = `

View File

@ -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;
}
}

View File

@ -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',

View File

@ -66,32 +66,42 @@ export class QueryInput extends React.PureComponent<QueryInputProps, QueryInputS
SQL_EXPRESSION_PARTS.map(v => ({ 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<QueryInputProps, QueryInputS
},
getDocTooltip: (item: any) => {
if (item.meta === 'function') {
item.docHTML = QueryInput.completerToHtml(item);
item.docHTML = QueryInput.makeDocHtml(item);
}
},
});
}
static completerToHtml(item: any) {
static makeDocHtml(item: any) {
return `
<div class="function-doc">
<div class="function-doc-name">
<b>${escape(item.caption)}</b>
</div>
<hr />
<div>
<b>Syntax:</b>
</div>
<div>${escape(item.syntax)}</div>
<br />
<div>
<b>Description:</b>
</div>
<div>${escape(item.description)}</div>
</div>`;
<div class="doc-name">${escape(item.caption)}</div>
<div class="doc-syntax">${escape(item.syntax)}</div>
<div class="doc-description">${escape(item.description)}</div>`;
}
static getDerivedStateFromProps(props: QueryInputProps, state: QueryInputState) {