mirror of https://github.com/apache/druid.git
Web console: Better inline docs (#11128)
* better highlight * better highlighting * add spec
This commit is contained in:
parent
fdc3c2f362
commit
4caa221d72
|
@ -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
|
||||
|
||||
---
|
||||
|
||||
|
|
1
pom.xml
1
pom.xml
|
@ -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>
|
||||
|
|
|
@ -45,6 +45,7 @@ exports.SQL_KEYWORDS = [
|
|||
'RIGHT',
|
||||
'OUTER',
|
||||
'FULL',
|
||||
'CROSS',
|
||||
];
|
||||
|
||||
exports.SQL_EXPRESSION_PARTS = [
|
||||
|
|
|
@ -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][];
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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`] = `
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue