You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by vo...@apache.org on 2023/05/05 22:45:26 UTC
[druid] branch master updated: Web console: misc bug fixes (#14216)
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 4c15e978f1 Web console: misc bug fixes (#14216)
4c15e978f1 is described below
commit 4c15e978f136f60008435a927ee2c0cb1858ada7
Author: Vadim Ogievetsky <va...@ogievetsky.com>
AuthorDate: Fri May 5 15:45:19 2023 -0700
Web console: misc bug fixes (#14216)
* fixing little things
* clear edit columns when switching to SQL tab
* updated snapshots
---
.../druid-models/ingestion-spec/ingestion-spec.tsx | 10 +-
.../react-table-pagination.tsx | 6 +-
web-console/src/utils/sampler.ts | 5 +-
.../__snapshots__/load-data-view.spec.tsx.snap | 202 ++++++++++++++++++++-
.../src/views/load-data-view/load-data-view.tsx | 11 +-
.../schema-step/schema-step.tsx | 26 ++-
6 files changed, 240 insertions(+), 20 deletions(-)
diff --git a/web-console/src/druid-models/ingestion-spec/ingestion-spec.tsx b/web-console/src/druid-models/ingestion-spec/ingestion-spec.tsx
index 8741668b59..24d52373d0 100644
--- a/web-console/src/druid-models/ingestion-spec/ingestion-spec.tsx
+++ b/web-console/src/druid-models/ingestion-spec/ingestion-spec.tsx
@@ -2154,9 +2154,9 @@ export function issueWithSampleData(
if (firstData === '{') {
return (
<>
- This data looks like regular JSON object. For Druid to parse a text file it must have one
- row per event. Maybe look at{' '}
- <ExternalLink href="http://ndjson.org/">newline delimited JSON</ExternalLink> instead.
+ This data looks like multi-line formatted JSON object. For Druid to parse a text file it
+ must have one row per event. Consider reformatting your data as{' '}
+ <ExternalLink href="http://ndjson.org/">newline delimited JSON</ExternalLink>.
</>
);
}
@@ -2165,8 +2165,8 @@ export function issueWithSampleData(
return (
<>
This data looks like a multi-line JSON array. For Druid to parse a text file it must have
- one row per event. Maybe look at{' '}
- <ExternalLink href="http://ndjson.org/">newline delimited JSON</ExternalLink> instead.
+ one row per event. Consider reformatting your data as{' '}
+ <ExternalLink href="http://ndjson.org/">newline delimited JSON</ExternalLink>.
</>
);
}
diff --git a/web-console/src/react-table/react-table-pagination/react-table-pagination.tsx b/web-console/src/react-table/react-table-pagination/react-table-pagination.tsx
index 956cd7f8a2..04b2b0ea02 100644
--- a/web-console/src/react-table/react-table-pagination/react-table-pagination.tsx
+++ b/web-console/src/react-table/react-table-pagination/react-table-pagination.tsx
@@ -100,8 +100,8 @@ export const ReactTablePagination = React.memo(function ReactTablePagination(
const start = page * pageSize + 1;
let end = page * pageSize + pageSize;
- if (nonEmptyArray(sortedData)) {
- end = Math.min(end, page * pageSize + sortedData.length);
+ if (nonEmptyArray(sortedData) && (page === 0 || sortedData.length > pageSize)) {
+ end = Math.min(end, sortedData.length);
}
let pageInfo = 'Showing';
@@ -110,7 +110,7 @@ export const ReactTablePagination = React.memo(function ReactTablePagination(
} else {
pageInfo += '...';
}
- if (ofText && Array.isArray(sortedData)) {
+ if (ofText && nonEmptyArray(sortedData)) {
pageInfo += ` ${ofText} ${formatInteger(sortedData.length)}`;
}
diff --git a/web-console/src/utils/sampler.ts b/web-console/src/utils/sampler.ts
index 67f883a580..622584e667 100644
--- a/web-console/src/utils/sampler.ts
+++ b/web-console/src/utils/sampler.ts
@@ -171,7 +171,10 @@ export async function getProxyOverlordModules(): Promise<string[]> {
throw new Error(getDruidErrorMessage(e));
}
- return statusResp.data.modules.map((m: any) => m.artifact);
+ const { modules } = statusResp.data;
+ if (!Array.isArray(modules)) throw new Error('unexpected result from overlord/status');
+
+ return modules.map((m: any) => m.artifact);
}
export async function postToSampler(
diff --git a/web-console/src/views/load-data-view/__snapshots__/load-data-view.spec.tsx.snap b/web-console/src/views/load-data-view/__snapshots__/load-data-view.spec.tsx.snap
index 9cf8d12a9d..f5956786af 100644
--- a/web-console/src/views/load-data-view/__snapshots__/load-data-view.spec.tsx.snap
+++ b/web-console/src/views/load-data-view/__snapshots__/load-data-view.spec.tsx.snap
@@ -159,7 +159,148 @@ exports[`LoadDataView matches snapshot batch 1`] = `
<div
className="ingestion-cards"
>
- <React.Fragment />
+ <React.Fragment>
+ <Blueprint4.Card
+ className="ingestion-card"
+ elevation={1}
+ interactive={true}
+ onClick={[Function]}
+ >
+ <img
+ alt="Ingestion tile for index_parallel:s3"
+ src="/some/base_url/assets/s3.png"
+ />
+ <p>
+ Amazon S3
+ </p>
+ </Blueprint4.Card>
+ <Blueprint4.Card
+ className="ingestion-card"
+ elevation={1}
+ interactive={true}
+ onClick={[Function]}
+ >
+ <img
+ alt="Ingestion tile for index_parallel:azure"
+ src="/some/base_url/assets/azure.png"
+ />
+ <p>
+ Azure Data Lake
+ </p>
+ </Blueprint4.Card>
+ <Blueprint4.Card
+ className="ingestion-card"
+ elevation={1}
+ interactive={true}
+ onClick={[Function]}
+ >
+ <img
+ alt="Ingestion tile for index_parallel:google"
+ src="/some/base_url/assets/google.png"
+ />
+ <p>
+ Google Cloud Storage
+ </p>
+ </Blueprint4.Card>
+ <Blueprint4.Card
+ className="ingestion-card"
+ elevation={1}
+ interactive={true}
+ onClick={[Function]}
+ >
+ <img
+ alt="Ingestion tile for index_parallel:hdfs"
+ src="/some/base_url/assets/hdfs.png"
+ />
+ <p>
+ HDFS
+ </p>
+ </Blueprint4.Card>
+ <Blueprint4.Card
+ className="ingestion-card"
+ elevation={1}
+ interactive={true}
+ onClick={[Function]}
+ >
+ <img
+ alt="Ingestion tile for index_parallel:druid"
+ src="/some/base_url/assets/druid.png"
+ />
+ <p>
+ Reindex from Druid
+ </p>
+ </Blueprint4.Card>
+ <Blueprint4.Card
+ className="ingestion-card"
+ elevation={1}
+ interactive={true}
+ onClick={[Function]}
+ >
+ <img
+ alt="Ingestion tile for index_parallel:http"
+ src="/some/base_url/assets/http.png"
+ />
+ <p>
+ HTTP(s)
+ </p>
+ </Blueprint4.Card>
+ <Blueprint4.Card
+ className="ingestion-card"
+ elevation={1}
+ interactive={true}
+ onClick={[Function]}
+ >
+ <img
+ alt="Ingestion tile for index_parallel:local"
+ src="/some/base_url/assets/local.png"
+ />
+ <p>
+ Local disk
+ </p>
+ </Blueprint4.Card>
+ <Blueprint4.Card
+ className="ingestion-card"
+ elevation={1}
+ interactive={true}
+ onClick={[Function]}
+ >
+ <img
+ alt="Ingestion tile for index_parallel:inline"
+ src="/some/base_url/assets/inline.png"
+ />
+ <p>
+ Paste data
+ </p>
+ </Blueprint4.Card>
+ <Blueprint4.Card
+ className="ingestion-card"
+ elevation={1}
+ interactive={true}
+ onClick={[Function]}
+ >
+ <img
+ alt="Ingestion tile for example"
+ src="/some/base_url/assets/example.png"
+ />
+ <p>
+ Example data
+ </p>
+ </Blueprint4.Card>
+ </React.Fragment>
+ <Blueprint4.Card
+ className="ingestion-card"
+ elevation={1}
+ interactive={true}
+ onClick={[Function]}
+ >
+ <img
+ alt="Ingestion tile for other"
+ src="/some/base_url/assets/other.png"
+ />
+ <p>
+ Other
+ </p>
+ </Blueprint4.Card>
</div>
</div>
<div
@@ -336,7 +477,64 @@ exports[`LoadDataView matches snapshot streaming 1`] = `
<div
className="ingestion-cards"
>
- <React.Fragment />
+ <React.Fragment>
+ <Blueprint4.Card
+ className="ingestion-card"
+ elevation={1}
+ interactive={true}
+ onClick={[Function]}
+ >
+ <img
+ alt="Ingestion tile for kafka"
+ src="/some/base_url/assets/kafka.png"
+ />
+ <p>
+ Apache Kafka
+ </p>
+ </Blueprint4.Card>
+ <Blueprint4.Card
+ className="ingestion-card"
+ elevation={1}
+ interactive={true}
+ onClick={[Function]}
+ >
+ <img
+ alt="Ingestion tile for kinesis"
+ src="/some/base_url/assets/kinesis.png"
+ />
+ <p>
+ Amazon Kinesis
+ </p>
+ </Blueprint4.Card>
+ <Blueprint4.Card
+ className="ingestion-card"
+ elevation={1}
+ interactive={true}
+ onClick={[Function]}
+ >
+ <img
+ alt="Ingestion tile for azure-event-hubs"
+ src="/some/base_url/assets/azure-event-hubs.png"
+ />
+ <p>
+ Azure Event Hub
+ </p>
+ </Blueprint4.Card>
+ </React.Fragment>
+ <Blueprint4.Card
+ className="ingestion-card"
+ elevation={1}
+ interactive={true}
+ onClick={[Function]}
+ >
+ <img
+ alt="Ingestion tile for other"
+ src="/some/base_url/assets/other.png"
+ />
+ <p>
+ Other
+ </p>
+ </Blueprint4.Card>
</div>
</div>
<div
diff --git a/web-console/src/views/load-data-view/load-data-view.tsx b/web-console/src/views/load-data-view/load-data-view.tsx
index b332d277d3..6ea6946759 100644
--- a/web-console/src/views/load-data-view/load-data-view.tsx
+++ b/web-console/src/views/load-data-view/load-data-view.tsx
@@ -498,10 +498,10 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
overlordModules = await getProxyOverlordModules();
} catch (e) {
AppToaster.show({
- message: `Failed to get overlord modules: ${e.message}`,
+ message: `Failed to get the list of loaded modules from the overlord: ${e.message}`,
intent: Intent.DANGER,
});
- this.setState({ overlordModules: [] });
+ this.setState({ overlordModules: undefined });
return;
}
@@ -810,9 +810,10 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
disabled?: boolean,
): JSX.Element | undefined {
const { overlordModules, selectedComboType, spec } = this.state;
- if (!overlordModules) return;
const requiredModule = getRequiredModule(comboType);
- const goodToGo = !disabled && (!requiredModule || overlordModules.includes(requiredModule));
+ const goodToGo =
+ !disabled &&
+ (!requiredModule || !overlordModules || overlordModules.includes(requiredModule));
return (
<Card
@@ -1124,7 +1125,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
<p>
Please make sure that the
<Code>"{requiredModule}"</Code> extension is included in the{' '}
- <Code>loadList</Code>.
+ <Code>druid.extensions.loadList</Code>.
</p>
<p>
For more information please refer to the{' '}
diff --git a/web-console/src/views/sql-data-loader-view/schema-step/schema-step.tsx b/web-console/src/views/sql-data-loader-view/schema-step/schema-step.tsx
index 7446b60550..00b1e1ff2f 100644
--- a/web-console/src/views/sql-data-loader-view/schema-step/schema-step.tsx
+++ b/web-console/src/views/sql-data-loader-view/schema-step/schema-step.tsx
@@ -299,12 +299,30 @@ export const SchemaStep = function SchemaStep(props: SchemaStepProps) {
onQueryStringChange(parsedQuery.apply(queryAction).toString());
});
+ const handleModeSelect = (newMode: Mode) => {
+ if (newMode === 'sql' && editorColumn) {
+ if (editorColumn.dirty) {
+ AppToaster.show({
+ message:
+ 'Please save or discard the changes in the column editor before switching to the SQL tab.',
+ intent: Intent.WARNING,
+ });
+ return;
+ }
+
+ setEditorColumn(undefined);
+ }
+
+ setMode(newMode);
+ };
+
const handleColumnSelect = usePermanentCallback((index: number) => {
if (!ingestQueryPattern) return;
if (editorColumn?.dirty) {
AppToaster.show({
- message: 'Please save or discard the changes in the column editor.',
+ message:
+ 'Please save or discard the changes in the column editor before switching columns.',
intent: Intent.WARNING,
});
return;
@@ -697,20 +715,20 @@ export const SchemaStep = function SchemaStep(props: SchemaStepProps) {
text="Table"
disabled={!ingestQueryPattern}
active={effectiveMode === 'table'}
- onClick={() => setMode('table')}
+ onClick={() => handleModeSelect('table')}
/>
<Button
icon={IconNames.LIST_COLUMNS}
text="List"
disabled={!ingestQueryPattern}
active={effectiveMode === 'list'}
- onClick={() => setMode('list')}
+ onClick={() => handleModeSelect('list')}
/>
<Button
icon={IconNames.APPLICATION}
text="SQL"
active={effectiveMode === 'sql'}
- onClick={() => setMode('sql')}
+ onClick={() => handleModeSelect('sql')}
/>
</ButtonGroup>
{enableAnalyze && ingestQueryPattern?.metrics && (
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org