This is an automated email from the ASF dual-hosted git repository.
vogievetsky pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new 1ca0edb8c9 Web console: Fixes query cancel NPE and more (#13786)
1ca0edb8c9 is described below
commit 1ca0edb8c9545b451ecc235ced5ea0188cbbf7d3
Author: Vadim Ogievetsky <[email protected]>
AuthorDate: Wed Feb 15 15:02:50 2023 -0800
Web console: Fixes query cancel NPE and more (#13786)
* add null icon
* empty string table cell
* enable views only if they will work
* make sure method exists
* use SQL compatible nulls for e2e tests
---
web-console/script/druid | 1 +
.../__snapshots__/table-cell.spec.tsx.snap | 8 +++++
.../src/components/table-cell/table-cell.scss | 3 +-
.../src/components/table-cell/table-cell.spec.tsx | 7 +++++
.../src/components/table-cell/table-cell.tsx | 32 ++++++++++----------
web-console/src/console-application.tsx | 34 ++++++++++++++--------
web-console/src/singletons/api.ts | 2 +-
web-console/src/utils/types.ts | 3 ++
8 files changed, 60 insertions(+), 30 deletions(-)
diff --git a/web-console/script/druid b/web-console/script/druid
index 18f10313d5..7ffbeeee2a 100755
--- a/web-console/script/druid
+++ b/web-console/script/druid
@@ -64,6 +64,7 @@ function _build_distribution() {
&& cp
"$(_get_code_root)/extensions-core/testing-tools/target/druid-testing-tools-$(_get_druid_version).jar"
extensions/druid-testing-tools/ \
&& echo -e "\n\ndruid.extensions.loadList=[\"druid-hdfs-storage\",
\"druid-kafka-indexing-service\", \"druid-datasketches\",
\"druid-multi-stage-query\", \"druid-testing-tools\"]" >>
conf/druid/single-server/micro-quickstart/_common/common.runtime.properties \
&& echo -e "\n\ndruid.server.http.allowedHttpMethods=[\"HEAD\"]" >>
conf/druid/single-server/micro-quickstart/_common/common.runtime.properties \
+ && echo -e "\n\ndruid.generic.useDefaultValueForNull=false" >>
conf/druid/single-server/micro-quickstart/_common/common.runtime.properties \
)
}
diff --git
a/web-console/src/components/table-cell/__snapshots__/table-cell.spec.tsx.snap
b/web-console/src/components/table-cell/__snapshots__/table-cell.spec.tsx.snap
index 5ed0f31589..2f6b6f1298 100644
---
a/web-console/src/components/table-cell/__snapshots__/table-cell.spec.tsx.snap
+++
b/web-console/src/components/table-cell/__snapshots__/table-cell.spec.tsx.snap
@@ -65,6 +65,14 @@ exports[`TableCell matches snapshot array short 1`] = `
</div>
`;
+exports[`TableCell matches snapshot empty string 1`] = `
+<div
+ class="table-cell empty"
+>
+ empty
+</div>
+`;
+
exports[`TableCell matches snapshot null 1`] = `
<div
class="table-cell null"
diff --git a/web-console/src/components/table-cell/table-cell.scss
b/web-console/src/components/table-cell/table-cell.scss
index 3a7b4db695..62c80d4663 100644
--- a/web-console/src/components/table-cell/table-cell.scss
+++ b/web-console/src/components/table-cell/table-cell.scss
@@ -21,7 +21,8 @@
.table-cell {
padding: $table-cell-v-padding $table-cell-h-padding;
- &.null {
+ &.null,
+ &.empty {
font-style: italic;
}
diff --git a/web-console/src/components/table-cell/table-cell.spec.tsx
b/web-console/src/components/table-cell/table-cell.spec.tsx
index 74648dccb0..3aac5ac360 100644
--- a/web-console/src/components/table-cell/table-cell.spec.tsx
+++ b/web-console/src/components/table-cell/table-cell.spec.tsx
@@ -29,6 +29,13 @@ describe('TableCell', () => {
expect(container.firstChild).toMatchSnapshot();
});
+ it('matches snapshot empty string', () => {
+ const tableCell = <TableCell value="" />;
+
+ const { container } = render(tableCell);
+ expect(container.firstChild).toMatchSnapshot();
+ });
+
it('matches snapshot simple', () => {
const tableCell = <TableCell value="Hello World" />;
diff --git a/web-console/src/components/table-cell/table-cell.tsx
b/web-console/src/components/table-cell/table-cell.tsx
index 78f080b306..9e390774ee 100644
--- a/web-console/src/components/table-cell/table-cell.tsx
+++ b/web-console/src/components/table-cell/table-cell.tsx
@@ -90,22 +90,22 @@ export const TableCell = React.memo(function
TableCell(props: TableCellProps) {
);
}
- if (value !== '' && value != null) {
- if (value instanceof Date) {
- const dateValue = value.valueOf();
- return (
- <div className="table-cell timestamp" title={String(value.valueOf())}>
- {isNaN(dateValue) ? 'Unusable date' : value.toISOString()}
- </div>
- );
- } else if (isSimpleArray(value)) {
- return renderTruncated(`[${value.join(', ')}]`);
- } else if (typeof value === 'object') {
- return renderTruncated(JSONBig.stringify(value));
- } else {
- return renderTruncated(String(value));
- }
- } else {
+ if (value === '') {
+ return <div className="table-cell empty">empty</div>;
+ } else if (value == null) {
return <div className="table-cell null">null</div>;
+ } else if (value instanceof Date) {
+ const dateValue = value.valueOf();
+ return (
+ <div className="table-cell timestamp" title={String(value.valueOf())}>
+ {isNaN(dateValue) ? 'Unusable date' : value.toISOString()}
+ </div>
+ );
+ } else if (isSimpleArray(value)) {
+ return renderTruncated(`[${value.join(', ')}]`);
+ } else if (typeof value === 'object') {
+ return renderTruncated(JSONBig.stringify(value));
+ } else {
+ return renderTruncated(String(value));
}
});
diff --git a/web-console/src/console-application.tsx
b/web-console/src/console-application.tsx
index 1ddd3676b4..5683a101b5 100644
--- a/web-console/src/console-application.tsx
+++ b/web-console/src/console-application.tsx
@@ -356,7 +356,7 @@ export class ConsoleApplication extends React.PureComponent<
};
render(): JSX.Element {
- const { capabilitiesLoading } = this.state;
+ const { capabilities, capabilitiesLoading } = this.state;
if (capabilitiesLoading) {
return (
@@ -371,15 +371,24 @@ export class ConsoleApplication extends
React.PureComponent<
<HashRouter hashType="noslash">
<div className="console-application">
<Switch>
- <Route path="/data-loader"
component={this.wrappedDataLoaderView} />
- <Route
- path="/streaming-data-loader"
- component={this.wrappedStreamingDataLoaderView}
- />
- <Route
- path="/classic-batch-data-loader"
- component={this.wrappedClassicBatchDataLoaderView}
- />
+ {capabilities.hasCoordinatorAccess() && (
+ <Route path="/data-loader"
component={this.wrappedDataLoaderView} />
+ )}
+ {capabilities.hasCoordinatorAccess() && (
+ <Route
+ path="/streaming-data-loader"
+ component={this.wrappedStreamingDataLoaderView}
+ />
+ )}
+ {capabilities.hasCoordinatorAccess() && (
+ <Route
+ path="/classic-batch-data-loader"
+ component={this.wrappedClassicBatchDataLoaderView}
+ />
+ )}
+ {capabilities.hasCoordinatorAccess() &&
capabilities.hasMultiStageQuery() && (
+ <Route path="/sql-data-loader"
component={this.wrappedSqlDataLoaderView} />
+ )}
<Route path="/ingestion" component={this.wrappedIngestionView} />
<Route path="/datasources"
component={this.wrappedDatasourcesView} />
@@ -393,9 +402,10 @@ export class ConsoleApplication extends
React.PureComponent<
path={['/workbench/:tabId', '/workbench']}
component={this.wrappedWorkbenchView}
/>
- <Route path="/sql-data-loader"
component={this.wrappedSqlDataLoaderView} />
- <Route path="/lookups" component={this.wrappedLookupsView} />
+ {capabilities.hasCoordinatorAccess() && (
+ <Route path="/lookups" component={this.wrappedLookupsView} />
+ )}
<Route component={this.wrappedHomeView} />
</Switch>
</div>
diff --git a/web-console/src/singletons/api.ts
b/web-console/src/singletons/api.ts
index 6b49ac95a3..abc9eae69b 100644
--- a/web-console/src/singletons/api.ts
+++ b/web-console/src/singletons/api.ts
@@ -39,7 +39,7 @@ export class Api {
return Promise.reject(new Error(message));
}
- if (error.config.method?.toLowerCase() === 'get' &&
nonEmptyString(responseData)) {
+ if (error.config?.method?.toLowerCase() === 'get' &&
nonEmptyString(responseData)) {
return Promise.reject(new Error(responseData));
}
diff --git a/web-console/src/utils/types.ts b/web-console/src/utils/types.ts
index d2c08525dc..4fb547ebdf 100644
--- a/web-console/src/utils/types.ts
+++ b/web-console/src/utils/types.ts
@@ -78,6 +78,9 @@ export function dataTypeToIcon(dataType: string): IconName {
case 'COMPLEX<JSON>':
return IconNames.DIAGRAM_TREE;
+ case 'NULL':
+ return IconNames.CIRCLE;
+
default:
if (typeUpper.startsWith('ARRAY')) return IconNames.ARRAY;
if (typeUpper.startsWith('COMPLEX')) return IconNames.ASTERISK;
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]