diff --git a/web-console/src/console-application.tsx b/web-console/src/console-application.tsx
index 4f10977d90d7..58763b2f47c3 100644
--- a/web-console/src/console-application.tsx
+++ b/web-console/src/console-application.tsx
@@ -102,6 +102,7 @@ export class ConsoleApplication extends React.Component {
this.loadDataViewSeed = null;
this.taskId = null;
+ this.openDialog = null;
this.datasource = null;
this.onlyUnavailable = null;
this.initSql = null;
@@ -165,8 +167,9 @@ export class ConsoleApplication extends React.Component {
+ private goToTask = (taskId: string | null, openDialog: string | null = null) => {
this.taskId = taskId;
+ this.openDialog = openDialog;
window.location.hash = 'tasks';
this.resetInitialsWithDelay();
}
@@ -224,7 +227,7 @@ export class ConsoleApplication extends React.Component {
const { noSqlMode } = this.state;
- return this.wrapInViewContainer('tasks', , true);
+ return this.wrapInViewContainer('tasks', , true);
}
private wrappedServersView = () => {
diff --git a/web-console/src/views/load-data-view.scss b/web-console/src/views/load-data-view.scss
index 050672d27c91..5e08831de66e 100644
--- a/web-console/src/views/load-data-view.scss
+++ b/web-console/src/views/load-data-view.scss
@@ -46,6 +46,7 @@
.cards {
.bp3-card {
display: inline-block;
+ vertical-align: top;
width: 250px;
height: 140px;
margin-right: 15px;
diff --git a/web-console/src/views/load-data-view.tsx b/web-console/src/views/load-data-view.tsx
index 22a0dbb6ab7d..bbd9e76857d1 100644
--- a/web-console/src/views/load-data-view.tsx
+++ b/web-console/src/views/load-data-view.tsx
@@ -137,7 +137,7 @@ const VIEW_TITLE: Record = {
export interface LoadDataViewProps extends React.Props {
seed: LoadDataViewSeed | null;
- goToTask: (taskId: string | null) => void;
+ goToTask: (taskId: string | null, openDialog?: string | null) => void;
}
export interface LoadDataViewState {
@@ -370,6 +370,7 @@ export class LoadDataView extends React.Component
@@ -378,8 +379,10 @@ export class LoadDataView extends React.Component
- Welcome to the Druid data loader.
- This project is under active development and we plan to support many other sources of raw data, including stream hubs such as Apache Kafka and AWS Kinesis, in the next few releases.
+ Welcome to the Apache Druid graphical data loader.
+ This feature is under active development and currently only supports Druid's native batch ingestion.
+ We plan to continue building this out, including support for Druid's Apache Kafka, Apache Hadoop, and AWS Kinesis based ingestion methods, over the next few releases.
+ Until then, you can load from these and any other Druid ingestion source by clicking on Other.
{
@@ -398,10 +401,18 @@ export class LoadDataView extends React.Component
this.initWith({ type: 'index_parallel', firehoseType: 'http' })}>HTTP(s)
this.initWith({ type: 'index_parallel', firehoseType: 'static-s3' })}>AWS S3
- this.initWith({ type: 'index_parallel', firehoseType: 'static-google-blobstore' })}>Google Blobstore
+ this.initWith({ type: 'index_parallel', firehoseType: 'static-google-blobstore' })}>Google Cloud Storage
this.initWith({ type: 'index_parallel', firehoseType: 'local' })}>Local disk
+
+
+
Raw spec
+
+ goToTask(null, 'supervisor')}>Other (streaming)
+ goToTask(null, 'task')}>Other (batch)
+
+
>;
}
@@ -1179,6 +1190,22 @@ export class LoadDataView extends React.Component
+ {
+ Boolean(transformQueryState.error && transforms.length) &&
+
+
+ }
{this.renderTransformControls()}
diff --git a/web-console/src/views/tasks-view.tsx b/web-console/src/views/tasks-view.tsx
index 8acee1002803..6aee82055743 100644
--- a/web-console/src/views/tasks-view.tsx
+++ b/web-console/src/views/tasks-view.tsx
@@ -49,6 +49,7 @@ const taskTableColumns: string[] = ['Task ID', 'Type', 'Datasource', 'Created ti
export interface TasksViewProps extends React.Props {
taskId: string | null;
+ openDialog: string | null;
goToSql: (initSql: string) => void;
goToMiddleManager: (middleManager: string) => void;
goToLoadDataView: () => void;
@@ -117,7 +118,7 @@ export class TasksView extends React.Component {
private taskQueryManager: QueryManager;
private supervisorTableColumnSelectionHandler: TableColumnSelectionHandler;
private taskTableColumnSelectionHandler: TableColumnSelectionHandler;
- static statusRanking = {RUNNING: 4, PENDING: 3, WAITING: 2, SUCCESS: 1, FAILED: 1};
+ static statusRanking: Record = {RUNNING: 4, PENDING: 3, WAITING: 2, SUCCESS: 1, FAILED: 1};
constructor(props: TasksViewProps, context: any) {
super(props, context);
@@ -139,8 +140,8 @@ export class TasksView extends React.Component {
killTaskId: null,
- supervisorSpecDialogOpen: false,
- taskSpecDialogOpen: false,
+ supervisorSpecDialogOpen: props.openDialog === 'supervisor',
+ taskSpecDialogOpen: props.openDialog === 'task',
initSpec: null,
alertErrorMsg: null,
@@ -600,7 +601,7 @@ ORDER BY "rank" DESC, "created_time" DESC`);
Header: 'Status',
id: 'status',
width: 110,
- accessor: (row) => { return {status: row.status, created_time: row.created_time}; },
+ accessor: row => ({ status: row.status, created_time: row.created_time, toString: () => row.status }),
Cell: row => {
if (row.aggregated) return '';
const { status, location } = row.original;
@@ -617,20 +618,20 @@ ORDER BY "rank" DESC, "created_time" DESC`);
{errorMsg && this.setState({ alertErrorMsg: errorMsg })} title={errorMsg}> ?}
;
},
- PivotValue: (opt) => {
- const { subRows, value } = opt;
- if (!subRows || !subRows.length) return '';
- return `${subRows[0]._original['status']} (${subRows.length})`;
- },
- Aggregated: (opt: any) => {
- const { subRows, column } = opt;
- const previewValues = subRows.filter((d: any) => typeof d[column.id] !== 'undefined').map((row: any) => row._original[column.id]);
- const previewCount = countBy(previewValues);
- return {Object.keys(previewCount).sort().map(v => `${v} (${previewCount[v]})`).join(', ')};
- },
sortMethod: (d1, d2) => {
- const statusRanking: any = TasksView.statusRanking;
- return statusRanking[d1.status] - statusRanking[d2.status] || d1.created_time.localeCompare(d2.created_time);
+ const typeofD1 = typeof d1;
+ const typeofD2 = typeof d2;
+ if (typeofD1 !== typeofD2) return 0;
+ switch (typeofD1) {
+ case 'string':
+ return TasksView.statusRanking[d1] - TasksView.statusRanking[d2];
+
+ case 'object':
+ return TasksView.statusRanking[d1.status] - TasksView.statusRanking[d2.status] || d1.created_time.localeCompare(d2.created_time);
+
+ default:
+ return 0;
+ }
},
filterMethod: (filter: Filter, row: any) => {
return booleanCustomTableFilter(filter, row.status.status);