You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by fj...@apache.org on 2019/09/03 23:11:26 UTC

[incubator-druid] branch 0.16.0-incubating updated: Web console: Fix segment re-ingest (#8454) (#8457)

This is an automated email from the ASF dual-hosted git repository.

fjy pushed a commit to branch 0.16.0-incubating
in repository https://gitbox.apache.org/repos/asf/incubator-druid.git


The following commit(s) were added to refs/heads/0.16.0-incubating by this push:
     new 00dd600  Web console: Fix segment re-ingest (#8454) (#8457)
00dd600 is described below

commit 00dd600160b4b395a09ee75a48994bac07f7c6aa
Author: Clint Wylie <cw...@apache.org>
AuthorDate: Tue Sep 3 16:11:12 2019 -0700

    Web console: Fix segment re-ingest (#8454) (#8457)
    
    * fixing ingest spec
    
    * rm console.log
    
    * ingest segment spec
    
    * make sure step query always being run
    
    * better example interface
    
    * add keywords
    
    * placeholders
    
    * do not overwrite datasource name in data loader spec
    
    * fix comment typo
---
 web-console/lib/keywords.js                        |   8 +-
 web-console/package-lock.json                      |   6 +-
 web-console/package.json                           |   2 +-
 .../datasource-columns-table.tsx                   |  52 ++---
 .../src/components/json-input/json-input.tsx       |   8 +-
 .../src/components/rule-editor/rule-editor.tsx     |   2 +
 web-console/src/components/show-json/show-json.tsx |   2 +-
 .../supervisor-statistics-table.tsx                |  13 +-
 ...coordinator-dynamic-config-dialog.spec.tsx.snap |   1 -
 .../coordinator-dynamic-config-dialog.tsx          |   1 -
 .../datasource-table-action-dialog.spec.tsx        |   1 -
 .../datasource-table-action-dialog.tsx             |   4 +-
 .../edit-context-dialog.spec.tsx                   |   2 +-
 .../__snapshots__/history-dialog.spec.tsx.snap     |   2 +-
 .../dialogs/history-dialog/history-dialog.spec.tsx |   1 -
 .../src/dialogs/history-dialog/history-dialog.tsx  |   6 +-
 .../lookup-edit-dialog/lookup-edit-dialog.spec.tsx |   1 -
 .../lookup-edit-dialog/lookup-edit-dialog.tsx      |   4 +-
 .../overload-dynamic-config-dialog.spec.tsx.snap   |   1 -
 .../overlord-dynamic-config-dialog.tsx             |   1 -
 .../dialogs/retention-dialog/retention-dialog.tsx  |   2 -
 .../segment-table-action-dialog.spec.tsx           |   1 -
 .../segment-table-action-dialog.tsx                |   4 +-
 .../__snapshots__/snitch-dialog.spec.tsx.snap      |  35 ++-
 .../dialogs/snitch-dialog/snitch-dialog.spec.tsx   |   2 +-
 .../src/dialogs/snitch-dialog/snitch-dialog.tsx    |  19 +-
 .../__snapshots__/status-dialog.spec.tsx.snap      | 134 ++++--------
 .../dialogs/status-dialog/status-dialog.spec.tsx   |  10 +-
 .../src/dialogs/status-dialog/status-dialog.tsx    |  12 +-
 .../supervisor-table-action-dialog.spec.tsx        |   3 +-
 .../supervisor-table-action-dialog.tsx             |   4 +-
 .../table-action-dialog.spec.tsx.snap              |  34 +++
 .../table-action-dialog.spec.tsx                   |   2 +-
 .../table-action-dialog/table-action-dialog.tsx    |  18 +-
 .../task-table-action-dialog.spec.tsx              |   1 -
 .../task-table-action-dialog.tsx                   |   4 +-
 web-console/src/entry.scss                         |   2 +
 web-console/src/entry.ts                           |   2 +-
 web-console/src/singletons/url-baser.ts            |   4 +-
 web-console/src/utils/general.tsx                  |   4 +-
 web-console/src/utils/ingestion-spec.tsx           |  36 +++-
 web-console/src/utils/sampler.ts                   | 130 ++++++++---
 .../src/views/datasource-view/datasource-view.tsx  |   1 -
 .../views/home-view/status-card/status-card.tsx    |  79 ++++---
 .../__snapshots__/example-picker.spec.tsx.snap     |  56 +++++
 .../example-picker/example-picker.spec.tsx}        |  21 +-
 .../example-picker/example-picker.tsx              |  77 +++++++
 .../src/views/load-data-view/load-data-view.tsx    | 240 ++++++++++++++-------
 .../__snapshots__/lookups-view.spec.tsx.snap       |  12 --
 .../src/views/lookups-view/lookups-view.tsx        |  16 +-
 .../src/views/segments-view/segments-view.tsx      |   1 -
 web-console/src/views/task-view/tasks-view.tsx     |   2 -
 52 files changed, 697 insertions(+), 389 deletions(-)

diff --git a/web-console/lib/keywords.js b/web-console/lib/keywords.js
index 85e6b7d..c7261cd 100644
--- a/web-console/lib/keywords.js
+++ b/web-console/lib/keywords.js
@@ -71,4 +71,10 @@ exports.SQL_EXPRESSION_PARTS = [
 
 exports.SQL_CONSTANTS = ['NULL', 'FALSE', 'TRUE'];
 
-exports.SQL_DYNAMICS = ['CURRENT_TIMESTAMP', 'CURRENT_DATE'];
+exports.SQL_DYNAMICS = [
+  'CURRENT_TIMESTAMP',
+  'CURRENT_DATE',
+  'LOCALTIME',
+  'LOCALTIMESTAMP',
+  'CURRENT_TIME',
+];
diff --git a/web-console/package-lock.json b/web-console/package-lock.json
index a4ae431..1fbb606 100644
--- a/web-console/package-lock.json
+++ b/web-console/package-lock.json
@@ -4428,9 +4428,9 @@
       "integrity": "sha512-0sYnfUHHMoajaud/i5BHKA12bUxiWEHJ9rxGqVEppFxsEcxef0TZQ5J59lU+UniEBcz/sG5fTESRyS7cOm3tSQ=="
     },
     "druid-query-toolkit": {
-      "version": "0.3.26",
-      "resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.3.26.tgz",
-      "integrity": "sha512-j9HcwHCx2YnFSefYc1oJDw8rPq5zSB0tpGkaMp2GkO9syKbdncKfUPugZ613c5XIOBe+j5Hqh/luqh4sLacHGQ==",
+      "version": "0.3.27",
+      "resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.3.27.tgz",
+      "integrity": "sha512-dGqTU3x9V1zPHAwng47hDihwKhx1UBJbIBJsOtFmlgb+D69iDcQVingPsjJOV+kHX2gVq/Azlhx6MZvC7+5tFQ==",
       "requires": {
         "tslib": "^1.10.0"
       }
diff --git a/web-console/package.json b/web-console/package.json
index 553938f..9cb57a5 100644
--- a/web-console/package.json
+++ b/web-console/package.json
@@ -61,7 +61,7 @@
     "d3": "^5.10.1",
     "d3-array": "^2.3.1",
     "druid-console": "0.0.2",
-    "druid-query-toolkit": "^0.3.26",
+    "druid-query-toolkit": "^0.3.27",
     "file-saver": "^2.0.2",
     "has-own-prop": "^2.0.0",
     "hjson": "^3.1.2",
diff --git a/web-console/src/components/datasource-columns-table/datasource-columns-table.tsx b/web-console/src/components/datasource-columns-table/datasource-columns-table.tsx
index d494fb9..983a97a 100644
--- a/web-console/src/components/datasource-columns-table/datasource-columns-table.tsx
+++ b/web-console/src/components/datasource-columns-table/datasource-columns-table.tsx
@@ -17,16 +17,16 @@
  */
 
 import React from 'react';
-import ReactTable, { Column } from 'react-table';
+import ReactTable from 'react-table';
 
-import { Loader } from '..';
 import { queryDruidSql, QueryManager } from '../../utils';
 import { ColumnMetadata } from '../../utils/column-metadata';
+import { Loader } from '../loader/loader';
 
 import './datasource-columns-table.scss';
 
 interface TableRow {
-  columnsName: string;
+  columnName: string;
   columnType: string;
 }
 
@@ -36,7 +36,7 @@ export interface DatasourceColumnsTableProps {
 }
 
 export interface DatasourceColumnsTableState {
-  columns?: any;
+  columns?: TableRow[];
   loading: boolean;
   error?: string;
 }
@@ -45,24 +45,26 @@ export class DatasourceColumnsTable extends React.PureComponent<
   DatasourceColumnsTableProps,
   DatasourceColumnsTableState
 > {
-  private supervisorStatisticsTableQueryManager: QueryManager<null, TableRow[]>;
+  private datasourceColumnsQueryManager: QueryManager<null, TableRow[]>;
 
   constructor(props: DatasourceColumnsTableProps, context: any) {
     super(props, context);
     this.state = {
       loading: true,
     };
-    this.supervisorStatisticsTableQueryManager = new QueryManager({
+
+    this.datasourceColumnsQueryManager = new QueryManager({
       processQuery: async () => {
         const { datasourceId } = this.props;
+
         const resp = await queryDruidSql<ColumnMetadata>({
           query: `SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS
           WHERE TABLE_SCHEMA = 'druid' AND TABLE_NAME = '${datasourceId}'`,
         });
-        const dimensionArray = resp.map(object => {
-          return { columnsName: object.COLUMN_NAME, columnType: object.DATA_TYPE };
+
+        return resp.map(object => {
+          return { columnName: object.COLUMN_NAME, columnType: object.DATA_TYPE };
         });
-        return dimensionArray;
       },
       onStateChange: ({ result, error, loading }) => {
         this.setState({ columns: result, error, loading });
@@ -71,30 +73,28 @@ export class DatasourceColumnsTable extends React.PureComponent<
   }
 
   componentDidMount(): void {
-    this.supervisorStatisticsTableQueryManager.runQuery(null);
+    this.datasourceColumnsQueryManager.runQuery(null);
   }
 
   renderTable(error?: string) {
     const { columns } = this.state;
-    console.log(columns);
-    const tableColumns: Column<TableRow>[] = [
-      {
-        Header: 'Column Name',
-        accessor: 'columnsName',
-      },
-      {
-        Header: 'Data Type',
-        accessor: 'columnType',
-      },
-    ];
 
     return (
       <ReactTable
-        data={this.state.columns ? this.state.columns : []}
-        showPagination={false}
-        defaultPageSize={15}
-        columns={tableColumns}
-        noDataText={error ? error : 'No statistics data found'}
+        data={columns || []}
+        defaultPageSize={20}
+        filterable
+        columns={[
+          {
+            Header: 'Column name',
+            accessor: 'columnName',
+          },
+          {
+            Header: 'Data type',
+            accessor: 'columnType',
+          },
+        ]}
+        noDataText={error ? error : 'No column data found'}
       />
     );
   }
diff --git a/web-console/src/components/json-input/json-input.tsx b/web-console/src/components/json-input/json-input.tsx
index c8d13a3..756ee16 100644
--- a/web-console/src/components/json-input/json-input.tsx
+++ b/web-console/src/components/json-input/json-input.tsx
@@ -19,7 +19,7 @@
 import React from 'react';
 import AceEditor from 'react-ace';
 
-import { parseStringToJSON, stringifyJSON, validJson } from '../../utils';
+import { parseStringToJson, stringifyJson, validJson } from '../../utils';
 
 interface JSONInputProps {
   onChange: (newJSONValue: any) => void;
@@ -45,7 +45,7 @@ export class JSONInput extends React.PureComponent<JSONInputProps, JSONInputStat
 
   componentDidMount(): void {
     const { value } = this.props;
-    const stringValue = stringifyJSON(value);
+    const stringValue = stringifyJson(value);
     this.setState({
       stringValue,
     });
@@ -54,7 +54,7 @@ export class JSONInput extends React.PureComponent<JSONInputProps, JSONInputStat
   componentWillReceiveProps(nextProps: JSONInputProps): void {
     if (JSON.stringify(nextProps.value) !== JSON.stringify(this.props.value)) {
       this.setState({
-        stringValue: stringifyJSON(nextProps.value),
+        stringValue: stringifyJson(nextProps.value),
       });
     }
   }
@@ -70,7 +70,7 @@ export class JSONInput extends React.PureComponent<JSONInputProps, JSONInputStat
         name="ace-editor"
         onChange={(e: string) => {
           this.setState({ stringValue: e });
-          if (validJson(e) || e === '') onChange(parseStringToJSON(e));
+          if (validJson(e) || e === '') onChange(parseStringToJson(e));
           if (updateInputValidity) updateInputValidity(validJson(e) || e === '');
         }}
         focus={focus}
diff --git a/web-console/src/components/rule-editor/rule-editor.tsx b/web-console/src/components/rule-editor/rule-editor.tsx
index 6ff916a..03882be 100644
--- a/web-console/src/components/rule-editor/rule-editor.tsx
+++ b/web-console/src/components/rule-editor/rule-editor.tsx
@@ -295,6 +295,7 @@ export class RuleEditor extends React.PureComponent<RuleEditorProps, RuleEditorS
                     onChange={(e: any) =>
                       onChange(RuleEditor.changePeriod(rule, e.target.value as any))
                     }
+                    placeholder="P1D"
                   />
                 )}
                 {ruleTimeType === 'ByInterval' && (
@@ -303,6 +304,7 @@ export class RuleEditor extends React.PureComponent<RuleEditorProps, RuleEditorS
                     onChange={(e: any) =>
                       onChange(RuleEditor.changeInterval(rule, e.target.value as any))
                     }
+                    placeholder="2010-01-01/2020-01-01"
                   />
                 )}
               </ControlGroup>
diff --git a/web-console/src/components/show-json/show-json.tsx b/web-console/src/components/show-json/show-json.tsx
index 15fcdde..b8282bf 100644
--- a/web-console/src/components/show-json/show-json.tsx
+++ b/web-console/src/components/show-json/show-json.tsx
@@ -93,7 +93,7 @@ export class ShowJson extends React.PureComponent<ShowJsonProps, ShowJsonState>
               onClick={() => {
                 copy(jsonValue ? jsonValue : '', { format: 'text/plain' });
                 AppToaster.show({
-                  message: 'JSON copied to clipboard',
+                  message: 'JSON value copied to clipboard',
                   intent: Intent.SUCCESS,
                 });
               }}
diff --git a/web-console/src/components/supervisor-statistics-table/supervisor-statistics-table.tsx b/web-console/src/components/supervisor-statistics-table/supervisor-statistics-table.tsx
index 5c5ab32..67afd0a 100644
--- a/web-console/src/components/supervisor-statistics-table/supervisor-statistics-table.tsx
+++ b/web-console/src/components/supervisor-statistics-table/supervisor-statistics-table.tsx
@@ -21,10 +21,10 @@ import axios from 'axios';
 import React from 'react';
 import ReactTable, { Column } from 'react-table';
 
-import { Loader } from '..';
 import { UrlBaser } from '../../singletons/url-baser';
 import { QueryManager } from '../../utils';
 import { deepGet } from '../../utils/object-change';
+import { Loader } from '../loader/loader';
 
 import './supervisor-statistics-table.scss';
 
@@ -61,14 +61,15 @@ export class SupervisorStatisticsTable extends React.PureComponent<
   SupervisorStatisticsTableProps,
   SupervisorStatisticsTableState
 > {
-  private supervisorStatisticsTableQueryManager: QueryManager<null, TableRow[]>;
+  private supervisorStatisticsQueryManager: QueryManager<null, TableRow[]>;
 
   constructor(props: SupervisorStatisticsTableProps, context: any) {
     super(props, context);
     this.state = {
       loading: true,
     };
-    this.supervisorStatisticsTableQueryManager = new QueryManager({
+
+    this.supervisorStatisticsQueryManager = new QueryManager({
       processQuery: async () => {
         const { endpoint } = this.props;
         const resp = await axios.get(endpoint);
@@ -89,7 +90,7 @@ export class SupervisorStatisticsTable extends React.PureComponent<
   }
 
   componentDidMount(): void {
-    this.supervisorStatisticsTableQueryManager.runQuery(null);
+    this.supervisorStatisticsQueryManager.runQuery(null);
   }
 
   renderCell(data: StatsEntry | undefined) {
@@ -103,10 +104,10 @@ export class SupervisorStatisticsTable extends React.PureComponent<
 
   renderTable(error?: string) {
     const { data } = this.state;
-    console.log(data);
+
     let columns: Column<TableRow>[] = [
       {
-        Header: 'Task Id',
+        Header: 'Task ID',
         id: 'task_id',
         accessor: d => d.taskId,
       },
diff --git a/web-console/src/dialogs/coordinator-dynamic-config-dialog/__snapshots__/coordinator-dynamic-config-dialog.spec.tsx.snap b/web-console/src/dialogs/coordinator-dynamic-config-dialog/__snapshots__/coordinator-dynamic-config-dialog.spec.tsx.snap
index 05e80ff..c66c987 100644
--- a/web-console/src/dialogs/coordinator-dynamic-config-dialog/__snapshots__/coordinator-dynamic-config-dialog.spec.tsx.snap
+++ b/web-console/src/dialogs/coordinator-dynamic-config-dialog/__snapshots__/coordinator-dynamic-config-dialog.spec.tsx.snap
@@ -9,7 +9,6 @@ exports[`coordinator dynamic config matches snapshot 1`] = `
   >
     <div
       class="bp3-overlay-backdrop bp3-overlay-appear bp3-overlay-appear-active"
-      tabindex="0"
     />
     <div
       class="bp3-dialog-container bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
diff --git a/web-console/src/dialogs/coordinator-dynamic-config-dialog/coordinator-dynamic-config-dialog.tsx b/web-console/src/dialogs/coordinator-dynamic-config-dialog/coordinator-dynamic-config-dialog.tsx
index 18818ca..181eb27 100644
--- a/web-console/src/dialogs/coordinator-dynamic-config-dialog/coordinator-dynamic-config-dialog.tsx
+++ b/web-console/src/dialogs/coordinator-dynamic-config-dialog/coordinator-dynamic-config-dialog.tsx
@@ -118,7 +118,6 @@ export class CoordinatorDynamicConfigDialog extends React.PureComponent<
     return (
       <SnitchDialog
         className="coordinator-dynamic-config-dialog"
-        isOpen
         onSave={this.saveClusterConfig}
         onClose={onClose}
         title="Coordinator dynamic config"
diff --git a/web-console/src/dialogs/datasource-table-action-dialog/datasource-table-action-dialog.spec.tsx b/web-console/src/dialogs/datasource-table-action-dialog/datasource-table-action-dialog.spec.tsx
index c6f0723..0f6d19e 100644
--- a/web-console/src/dialogs/datasource-table-action-dialog/datasource-table-action-dialog.spec.tsx
+++ b/web-console/src/dialogs/datasource-table-action-dialog/datasource-table-action-dialog.spec.tsx
@@ -28,7 +28,6 @@ describe('Datasource table action dialog', () => {
         datasourceId="test"
         actions={[{ title: 'test', onAction: () => null }]}
         onClose={() => {}}
-        isOpen
       />
     );
     render(datasourceTableActionDialog);
diff --git a/web-console/src/dialogs/datasource-table-action-dialog/datasource-table-action-dialog.tsx b/web-console/src/dialogs/datasource-table-action-dialog/datasource-table-action-dialog.tsx
index 8289216..c604f14 100644
--- a/web-console/src/dialogs/datasource-table-action-dialog/datasource-table-action-dialog.tsx
+++ b/web-console/src/dialogs/datasource-table-action-dialog/datasource-table-action-dialog.tsx
@@ -16,14 +16,13 @@
  * limitations under the License.
  */
 
-import { IDialogProps } from '@blueprintjs/core';
 import React from 'react';
 
 import { DatasourceColumnsTable } from '../../components/datasource-columns-table/datasource-columns-table';
 import { BasicAction } from '../../utils/basic-action';
 import { SideButtonMetaData, TableActionDialog } from '../table-action-dialog/table-action-dialog';
 
-interface DatasourceTableActionDialogProps extends IDialogProps {
+interface DatasourceTableActionDialogProps {
   datasourceId?: string;
   actions: BasicAction[];
   onClose: () => void;
@@ -59,7 +58,6 @@ export class DatasourceTableActionDialog extends React.PureComponent<
 
     return (
       <TableActionDialog
-        isOpen
         sideButtonMetadata={taskTableSideButtonMetadata}
         onClose={onClose}
         title={`Datasource: ${datasourceId}`}
diff --git a/web-console/src/dialogs/edit-context-dialog/edit-context-dialog.spec.tsx b/web-console/src/dialogs/edit-context-dialog/edit-context-dialog.spec.tsx
index 602bc2e..9d760d6 100644
--- a/web-console/src/dialogs/edit-context-dialog/edit-context-dialog.spec.tsx
+++ b/web-console/src/dialogs/edit-context-dialog/edit-context-dialog.spec.tsx
@@ -24,7 +24,7 @@ import { EditContextDialog } from './edit-context-dialog';
 describe('clipboard dialog', () => {
   it('matches snapshot', () => {
     const compactionDialog = (
-      <EditContextDialog queryContext={{}} onQueryContextChange={() => null} onClose={() => null} />
+      <EditContextDialog queryContext={{}} onQueryContextChange={() => null} onClose={() => {}} />
     );
     render(compactionDialog);
     expect(document.body.lastChild).toMatchSnapshot();
diff --git a/web-console/src/dialogs/history-dialog/__snapshots__/history-dialog.spec.tsx.snap b/web-console/src/dialogs/history-dialog/__snapshots__/history-dialog.spec.tsx.snap
index a39d629..fdf97e9 100644
--- a/web-console/src/dialogs/history-dialog/__snapshots__/history-dialog.spec.tsx.snap
+++ b/web-console/src/dialogs/history-dialog/__snapshots__/history-dialog.spec.tsx.snap
@@ -16,7 +16,7 @@ exports[`history dialog matches snapshot 1`] = `
       tabindex="0"
     >
       <div
-        class="bp3-dialog"
+        class="bp3-dialog history-dialog"
       >
         <div
           class="history-record-container"
diff --git a/web-console/src/dialogs/history-dialog/history-dialog.spec.tsx b/web-console/src/dialogs/history-dialog/history-dialog.spec.tsx
index 176f35a..9ed39ee 100644
--- a/web-console/src/dialogs/history-dialog/history-dialog.spec.tsx
+++ b/web-console/src/dialogs/history-dialog/history-dialog.spec.tsx
@@ -29,7 +29,6 @@ describe('history dialog', () => {
           { auditTime: 'test', auditInfo: 'test', payload: JSON.stringify({ name: 'test' }) },
           { auditTime: 'test', auditInfo: 'test', payload: JSON.stringify({ name: 'test' }) },
         ]}
-        isOpen
       />
     );
     render(historyDialog);
diff --git a/web-console/src/dialogs/history-dialog/history-dialog.tsx b/web-console/src/dialogs/history-dialog/history-dialog.tsx
index 9553c9b..389d9fa 100644
--- a/web-console/src/dialogs/history-dialog/history-dialog.tsx
+++ b/web-console/src/dialogs/history-dialog/history-dialog.tsx
@@ -16,14 +16,14 @@
  * limitations under the License.
  */
 
-import { Card, Dialog, Divider, IDialogProps } from '@blueprintjs/core';
+import { Card, Dialog, Divider } from '@blueprintjs/core';
 import React from 'react';
 
 import { JSONCollapse } from '../../components';
 
 import './history-dialog.scss';
 
-interface HistoryDialogProps extends IDialogProps {
+interface HistoryDialogProps {
   historyRecords: any[];
 }
 
@@ -71,7 +71,7 @@ export class HistoryDialog extends React.PureComponent<HistoryDialogProps> {
 
   render(): React.ReactNode {
     return (
-      <Dialog isOpen {...this.props}>
+      <Dialog className="history-dialog" isOpen {...this.props}>
         {this.renderRecords()}
       </Dialog>
     );
diff --git a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.spec.tsx b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.spec.tsx
index 0793637..b243f14 100644
--- a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.spec.tsx
+++ b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.spec.tsx
@@ -25,7 +25,6 @@ describe('lookup edit dialog', () => {
   it('matches snapshot', () => {
     const lookupEditDialog = (
       <LookupEditDialog
-        isOpen
         onClose={() => {}}
         onSubmit={() => {}}
         onChange={() => {}}
diff --git a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.tsx b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.tsx
index c7a19af..1c79639 100644
--- a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.tsx
+++ b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.tsx
@@ -33,7 +33,6 @@ import { validJson } from '../../utils';
 import './lookup-edit-dialog.scss';
 
 export interface LookupEditDialogProps {
-  isOpen: boolean;
   onClose: () => void;
   onSubmit: () => void;
   onChange: (field: string, value: string) => void;
@@ -86,7 +85,6 @@ export class LookupEditDialog extends React.PureComponent<LookupEditDialogProps>
 
   render(): JSX.Element {
     const {
-      isOpen,
       onClose,
       onSubmit,
       lookupSpec,
@@ -103,7 +101,7 @@ export class LookupEditDialog extends React.PureComponent<LookupEditDialogProps>
     return (
       <Dialog
         className="lookup-edit-dialog"
-        isOpen={isOpen}
+        isOpen
         onClose={onClose}
         title={isEdit ? 'Edit lookup' : 'Add lookup'}
       >
diff --git a/web-console/src/dialogs/overlord-dynamic-config-dialog/__snapshots__/overload-dynamic-config-dialog.spec.tsx.snap b/web-console/src/dialogs/overlord-dynamic-config-dialog/__snapshots__/overload-dynamic-config-dialog.spec.tsx.snap
index d913e34..c5b2326 100644
--- a/web-console/src/dialogs/overlord-dynamic-config-dialog/__snapshots__/overload-dynamic-config-dialog.spec.tsx.snap
+++ b/web-console/src/dialogs/overlord-dynamic-config-dialog/__snapshots__/overload-dynamic-config-dialog.spec.tsx.snap
@@ -9,7 +9,6 @@ exports[`overload dynamic config matches snapshot 1`] = `
   >
     <div
       class="bp3-overlay-backdrop bp3-overlay-appear bp3-overlay-appear-active"
-      tabindex="0"
     />
     <div
       class="bp3-dialog-container bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
diff --git a/web-console/src/dialogs/overlord-dynamic-config-dialog/overlord-dynamic-config-dialog.tsx b/web-console/src/dialogs/overlord-dynamic-config-dialog/overlord-dynamic-config-dialog.tsx
index ad0ea17..b94d0d8 100644
--- a/web-console/src/dialogs/overlord-dynamic-config-dialog/overlord-dynamic-config-dialog.tsx
+++ b/web-console/src/dialogs/overlord-dynamic-config-dialog/overlord-dynamic-config-dialog.tsx
@@ -120,7 +120,6 @@ export class OverlordDynamicConfigDialog extends React.PureComponent<
     return (
       <SnitchDialog
         className="overlord-dynamic-config-dialog"
-        isOpen
         onSave={this.saveConfig}
         onClose={onClose}
         title="Overlord dynamic config"
diff --git a/web-console/src/dialogs/retention-dialog/retention-dialog.tsx b/web-console/src/dialogs/retention-dialog/retention-dialog.tsx
index 790ff06..4783757 100644
--- a/web-console/src/dialogs/retention-dialog/retention-dialog.tsx
+++ b/web-console/src/dialogs/retention-dialog/retention-dialog.tsx
@@ -171,8 +171,6 @@ export class RetentionDialog extends React.PureComponent<
       <SnitchDialog
         className="retention-dialog"
         saveDisabled={false}
-        canOutsideClickClose={false}
-        isOpen
         onClose={onCancel}
         title={`Edit retention rules: ${datasource}${
           datasource === '_default' ? ' (cluster defaults)' : ''
diff --git a/web-console/src/dialogs/segments-table-action-dialog/segment-table-action-dialog.spec.tsx b/web-console/src/dialogs/segments-table-action-dialog/segment-table-action-dialog.spec.tsx
index 46e4c57..dd31379 100644
--- a/web-console/src/dialogs/segments-table-action-dialog/segment-table-action-dialog.spec.tsx
+++ b/web-console/src/dialogs/segments-table-action-dialog/segment-table-action-dialog.spec.tsx
@@ -29,7 +29,6 @@ describe('task table action dialog', () => {
         segmentId="test"
         actions={[{ title: 'test', onAction: () => null }]}
         onClose={() => {}}
-        isOpen
       />
     );
     render(taskTableActionDialog);
diff --git a/web-console/src/dialogs/segments-table-action-dialog/segment-table-action-dialog.tsx b/web-console/src/dialogs/segments-table-action-dialog/segment-table-action-dialog.tsx
index 8a952e5..3271101 100644
--- a/web-console/src/dialogs/segments-table-action-dialog/segment-table-action-dialog.tsx
+++ b/web-console/src/dialogs/segments-table-action-dialog/segment-table-action-dialog.tsx
@@ -16,14 +16,13 @@
  * limitations under the License.
  */
 
-import { IDialogProps } from '@blueprintjs/core';
 import React from 'react';
 
 import { ShowJson } from '../../components';
 import { BasicAction } from '../../utils/basic-action';
 import { SideButtonMetaData, TableActionDialog } from '../table-action-dialog/table-action-dialog';
 
-interface SegmentTableActionDialogProps extends IDialogProps {
+interface SegmentTableActionDialogProps {
   segmentId?: string;
   datasourceId?: string;
   actions: BasicAction[];
@@ -60,7 +59,6 @@ export class SegmentTableActionDialog extends React.PureComponent<
 
     return (
       <TableActionDialog
-        isOpen
         sideButtonMetadata={taskTableSideButtonMetadata}
         onClose={onClose}
         title={`Segment: ${segmentId}`}
diff --git a/web-console/src/dialogs/snitch-dialog/__snapshots__/snitch-dialog.spec.tsx.snap b/web-console/src/dialogs/snitch-dialog/__snapshots__/snitch-dialog.spec.tsx.snap
index 47092ba..d223804 100644
--- a/web-console/src/dialogs/snitch-dialog/__snapshots__/snitch-dialog.spec.tsx.snap
+++ b/web-console/src/dialogs/snitch-dialog/__snapshots__/snitch-dialog.spec.tsx.snap
@@ -9,7 +9,6 @@ exports[`snitch dialog matches snapshot 1`] = `
   >
     <div
       class="bp3-overlay-backdrop bp3-overlay-appear bp3-overlay-appear-active"
-      tabindex="0"
     />
     <div
       class="bp3-dialog-container bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
@@ -19,6 +18,40 @@ exports[`snitch dialog matches snapshot 1`] = `
         class="bp3-dialog snitch-dialog"
       >
         <div
+          class="bp3-dialog-header"
+        >
+          <h4
+            class="bp3-heading"
+          >
+            Be snitchin
+          </h4>
+          <button
+            aria-label="Close"
+            class="bp3-button bp3-minimal bp3-dialog-close-button"
+            type="button"
+          >
+            <span
+              class="bp3-icon bp3-icon-small-cross"
+              icon="small-cross"
+            >
+              <svg
+                data-icon="small-cross"
+                height="20"
+                viewBox="0 0 20 20"
+                width="20"
+              >
+                <desc>
+                  small-cross
+                </desc>
+                <path
+                  d="M11.41 10l3.29-3.29c.19-.18.3-.43.3-.71a1.003 1.003 0 00-1.71-.71L10 8.59l-3.29-3.3a1.003 1.003 0 00-1.42 1.42L8.59 10 5.3 13.29c-.19.18-.3.43-.3.71a1.003 1.003 0 001.71.71l3.29-3.3 3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 00.71-1.71L11.41 10z"
+                  fill-rule="evenodd"
+                />
+              </svg>
+            </span>
+          </button>
+        </div>
+        <div
           class="bp3-dialog-body"
         />
         <div
diff --git a/web-console/src/dialogs/snitch-dialog/snitch-dialog.spec.tsx b/web-console/src/dialogs/snitch-dialog/snitch-dialog.spec.tsx
index 1c73826..ff3a5c6 100644
--- a/web-console/src/dialogs/snitch-dialog/snitch-dialog.spec.tsx
+++ b/web-console/src/dialogs/snitch-dialog/snitch-dialog.spec.tsx
@@ -23,7 +23,7 @@ import { SnitchDialog } from './snitch-dialog';
 
 describe('snitch dialog', () => {
   it('matches snapshot', () => {
-    const snitchDialog = <SnitchDialog onSave={() => {}} isOpen />;
+    const snitchDialog = <SnitchDialog title="Be snitchin" onSave={() => {}} onClose={() => {}} />;
     render(snitchDialog);
     expect(document.body.lastChild).toMatchSnapshot();
   });
diff --git a/web-console/src/dialogs/snitch-dialog/snitch-dialog.tsx b/web-console/src/dialogs/snitch-dialog/snitch-dialog.tsx
index fc8b4f4..985d16d 100644
--- a/web-console/src/dialogs/snitch-dialog/snitch-dialog.tsx
+++ b/web-console/src/dialogs/snitch-dialog/snitch-dialog.tsx
@@ -16,15 +16,7 @@
  * limitations under the License.
  */
 
-import {
-  Button,
-  Classes,
-  Dialog,
-  FormGroup,
-  IDialogProps,
-  InputGroup,
-  Intent,
-} from '@blueprintjs/core';
+import { Button, Classes, Dialog, FormGroup, InputGroup, Intent } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import classNames from 'classnames';
 import React from 'react';
@@ -33,10 +25,13 @@ import { HistoryDialog } from '../history-dialog/history-dialog';
 
 import './snitch-dialog.scss';
 
-export interface SnitchDialogProps extends IDialogProps {
+export interface SnitchDialogProps {
+  title: string;
+  className?: string;
   onSave: (comment: string) => void;
   saveDisabled?: boolean;
   onReset?: () => void;
+  onClose: () => void;
   historyRecords?: any[];
 }
 
@@ -121,7 +116,7 @@ export class SnitchDialog extends React.PureComponent<SnitchDialogProps, SnitchD
     if (!historyRecords) return null;
 
     return (
-      <HistoryDialog {...this.props} className="history-dialog" historyRecords={historyRecords}>
+      <HistoryDialog {...this.props} historyRecords={historyRecords}>
         <div className={Classes.DIALOG_FOOTER_ACTIONS}>
           <Button onClick={this.back} icon={IconNames.ARROW_LEFT}>
             Back
@@ -187,7 +182,7 @@ export class SnitchDialog extends React.PureComponent<SnitchDialogProps, SnitchD
     const propsClone: any = Object.assign({}, this.props);
     propsClone.className = classNames('snitch-dialog', propsClone.className);
     return (
-      <Dialog isOpen {...propsClone}>
+      <Dialog isOpen {...propsClone} canOutsideClickClose={false}>
         <div className={Classes.DIALOG_BODY}>{children}</div>
         <div className={Classes.DIALOG_FOOTER}>{this.renderActions(saveDisabled)}</div>
       </Dialog>
diff --git a/web-console/src/dialogs/status-dialog/__snapshots__/status-dialog.spec.tsx.snap b/web-console/src/dialogs/status-dialog/__snapshots__/status-dialog.spec.tsx.snap
index a215194..004c512 100644
--- a/web-console/src/dialogs/status-dialog/__snapshots__/status-dialog.spec.tsx.snap
+++ b/web-console/src/dialogs/status-dialog/__snapshots__/status-dialog.spec.tsx.snap
@@ -1,6 +1,6 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`table action dialog matches snapshot 1`] = `
+exports[`status dialog matches snapshot 1`] = `
 <div
   class="bp3-portal"
 >
@@ -9,13 +9,14 @@ exports[`table action dialog matches snapshot 1`] = `
   >
     <div
       class="bp3-overlay-backdrop bp3-overlay-appear bp3-overlay-appear-active"
+      tabindex="0"
     />
     <div
       class="bp3-dialog-container bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
       tabindex="0"
     >
       <div
-        class="bp3-dialog spec-dialog"
+        class="bp3-dialog status-dialog"
       >
         <div
           class="bp3-dialog-header"
@@ -23,7 +24,7 @@ exports[`table action dialog matches snapshot 1`] = `
           <h4
             class="bp3-heading"
           >
-            spec-dialog
+            Status
           </h4>
           <button
             aria-label="Close"
@@ -52,92 +53,59 @@ exports[`table action dialog matches snapshot 1`] = `
           </button>
         </div>
         <div
-          class=" ace_editor ace-tm spec-dialog-textarea"
-          id="brace-editor"
-          style="width: 100%; height: 500px;"
+          class="status-dialog-main-area"
         >
-          <textarea
-            autocapitalize="off"
-            autocorrect="off"
-            class="ace_text-input"
-            spellcheck="false"
-            style="opacity: 0;"
-            wrap="off"
-          />
           <div
-            aria-hidden="true"
-            class="ace_gutter"
+            class="show-json"
           >
             <div
-              class="ace_layer ace_gutter-layer ace_folding-enabled"
-            />
-            <div
-              class="ace_gutter-active-line"
-            />
-          </div>
-          <div
-            class="ace_scroller"
-          >
-            <div
-              class="ace_content"
+              class="top-actions"
             >
               <div
-                class="ace_layer ace_print-margin-layer"
+                class="bp3-button-group right-buttons"
               >
-                <div
-                  class="ace_print-margin"
-                  style="left: 4px; visibility: hidden;"
-                />
-              </div>
-              <div
-                class="ace_layer ace_marker-layer"
-              />
-              <div
-                class="ace_layer ace_text-layer"
-                style="padding: 0px 4px;"
-              />
-              <div
-                class="ace_layer ace_marker-layer"
-              />
-              <div
-                class="ace_layer ace_cursor-layer ace_hidden-cursors"
-              >
-                <div
-                  class="ace_cursor"
-                />
+                <button
+                  class="bp3-button bp3-disabled bp3-minimal"
+                  disabled=""
+                  tabindex="-1"
+                  type="button"
+                >
+                  <span
+                    class="bp3-button-text"
+                  >
+                    Save
+                  </span>
+                </button>
+                <button
+                  class="bp3-button bp3-disabled bp3-minimal"
+                  disabled=""
+                  tabindex="-1"
+                  type="button"
+                >
+                  <span
+                    class="bp3-button-text"
+                  >
+                    Copy
+                  </span>
+                </button>
+                <button
+                  class="bp3-button bp3-disabled bp3-minimal"
+                  disabled=""
+                  tabindex="-1"
+                  type="button"
+                >
+                  <span
+                    class="bp3-button-text"
+                  >
+                    View raw
+                  </span>
+                </button>
               </div>
             </div>
-          </div>
-          <div
-            class="ace_scrollbar ace_scrollbar-v"
-            style="display: none; width: 20px;"
-          >
-            <div
-              class="ace_scrollbar-inner"
-              style="width: 20px;"
-            />
-          </div>
-          <div
-            class="ace_scrollbar ace_scrollbar-h"
-            style="display: none; height: 20px;"
-          >
             <div
-              class="ace_scrollbar-inner"
-              style="height: 20px;"
+              class="main-area"
             />
           </div>
-          <div
-            style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: hidden;"
-          >
-            <div
-              style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
-            />
-            <div
-              style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; overflow: visible;"
-            >
-              XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-            </div>
-          </div>
         </div>
         <div
           class="bp3-dialog-footer"
@@ -146,23 +114,13 @@ exports[`table action dialog matches snapshot 1`] = `
             class="bp3-dialog-footer-actions"
           >
             <button
-              class="bp3-button"
-              type="button"
-            >
-              <span
-                class="bp3-button-text"
-              >
-                Close
-              </span>
-            </button>
-            <button
               class="bp3-button bp3-intent-primary"
               type="button"
             >
               <span
                 class="bp3-button-text"
               >
-                Submit
+                Close
               </span>
             </button>
           </div>
diff --git a/web-console/src/dialogs/status-dialog/status-dialog.spec.tsx b/web-console/src/dialogs/status-dialog/status-dialog.spec.tsx
index 625eb93..d323665 100644
--- a/web-console/src/dialogs/status-dialog/status-dialog.spec.tsx
+++ b/web-console/src/dialogs/status-dialog/status-dialog.spec.tsx
@@ -19,14 +19,12 @@
 import { render } from '@testing-library/react';
 import React from 'react';
 
-import { SpecDialog } from '..';
+import { StatusDialog } from './status-dialog';
 
-describe('table action dialog', () => {
+describe('status dialog', () => {
   it('matches snapshot', () => {
-    const tableActionDialog = (
-      <SpecDialog onClose={() => null} title={'spec-dialog'} onSubmit={() => null} />
-    );
-    render(tableActionDialog);
+    const statusDialog = <StatusDialog onClose={() => {}} />;
+    render(statusDialog);
     expect(document.body.lastChild).toMatchSnapshot();
   });
 });
diff --git a/web-console/src/dialogs/status-dialog/status-dialog.tsx b/web-console/src/dialogs/status-dialog/status-dialog.tsx
index 2f3e43d..0785f66 100644
--- a/web-console/src/dialogs/status-dialog/status-dialog.tsx
+++ b/web-console/src/dialogs/status-dialog/status-dialog.tsx
@@ -16,26 +16,26 @@
  * limitations under the License.
  */
 
-import { Button, Classes, Dialog, IDialogProps, Intent } from '@blueprintjs/core';
+import { Button, Classes, Dialog, Intent } from '@blueprintjs/core';
 import React from 'react';
 
 import { ShowJson } from '../../components';
+import { UrlBaser } from '../../singletons/url-baser';
 
 import './status-dialog.scss';
 
-interface StatusDialogProps extends IDialogProps {
+interface StatusDialogProps {
   onClose: () => void;
-  title: string;
 }
 
 export class StatusDialog extends React.PureComponent<StatusDialogProps> {
   render(): JSX.Element {
-    const { onClose, title, isOpen } = this.props;
+    const { onClose } = this.props;
 
     return (
-      <Dialog className={'status-dialog'} onClose={onClose} isOpen={isOpen} title={title}>
+      <Dialog className={'status-dialog'} onClose={onClose} isOpen title="Status">
         <div className={'status-dialog-main-area'}>
-          <ShowJson endpoint={`/status`} downloadFilename={'status'} />
+          <ShowJson endpoint={UrlBaser.base(`/status`)} downloadFilename={'status'} />
         </div>
         <div className={Classes.DIALOG_FOOTER}>
           <div className={Classes.DIALOG_FOOTER_ACTIONS}>
diff --git a/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.spec.tsx b/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.spec.tsx
index 18ef377..9c4c05a 100644
--- a/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.spec.tsx
+++ b/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.spec.tsx
@@ -21,7 +21,7 @@ import React from 'react';
 
 import { SupervisorTableActionDialog } from './supervisor-table-action-dialog';
 
-const basicAction = { title: 'test', onAction: () => null };
+const basicAction = { title: 'test', onAction: () => {} };
 
 describe('supervisor table action dialog', () => {
   it('matches snapshot', () => {
@@ -30,7 +30,6 @@ describe('supervisor table action dialog', () => {
         supervisorId={'test'}
         actions={[basicAction, basicAction, basicAction, basicAction]}
         onClose={() => {}}
-        isOpen
       />
     );
     render(supervisorTableActionDialog);
diff --git a/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.tsx b/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.tsx
index 8720b78..2ea3927 100644
--- a/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.tsx
+++ b/web-console/src/dialogs/supervisor-table-action-dialog/supervisor-table-action-dialog.tsx
@@ -16,7 +16,6 @@
  * limitations under the License.
  */
 
-import { IDialogProps } from '@blueprintjs/core';
 import React from 'react';
 
 import { ShowJson } from '../../components';
@@ -26,7 +25,7 @@ import { BasicAction } from '../../utils/basic-action';
 import { deepGet } from '../../utils/object-change';
 import { SideButtonMetaData, TableActionDialog } from '../table-action-dialog/table-action-dialog';
 
-interface SupervisorTableActionDialogProps extends IDialogProps {
+interface SupervisorTableActionDialogProps {
   supervisorId: string;
   actions: BasicAction[];
   onClose: () => void;
@@ -79,7 +78,6 @@ export class SupervisorTableActionDialog extends React.PureComponent<
 
     return (
       <TableActionDialog
-        isOpen
         sideButtonMetadata={supervisorTableSideButtonMetadata}
         onClose={onClose}
         title={`Supervisor: ${supervisorId}`}
diff --git a/web-console/src/dialogs/table-action-dialog/__snapshots__/table-action-dialog.spec.tsx.snap b/web-console/src/dialogs/table-action-dialog/__snapshots__/table-action-dialog.spec.tsx.snap
index ec333f3..315dc75 100644
--- a/web-console/src/dialogs/table-action-dialog/__snapshots__/table-action-dialog.spec.tsx.snap
+++ b/web-console/src/dialogs/table-action-dialog/__snapshots__/table-action-dialog.spec.tsx.snap
@@ -19,6 +19,40 @@ exports[`table action dialog matches snapshot 1`] = `
         class="bp3-dialog table-action-dialog"
       >
         <div
+          class="bp3-dialog-header"
+        >
+          <h4
+            class="bp3-heading"
+          >
+            Table dummy actions
+          </h4>
+          <button
+            aria-label="Close"
+            class="bp3-button bp3-minimal bp3-dialog-close-button"
+            type="button"
+          >
+            <span
+              class="bp3-icon bp3-icon-small-cross"
+              icon="small-cross"
+            >
+              <svg
+                data-icon="small-cross"
+                height="20"
+                viewBox="0 0 20 20"
+                width="20"
+              >
+                <desc>
+                  small-cross
+                </desc>
+                <path
+                  d="M11.41 10l3.29-3.29c.19-.18.3-.43.3-.71a1.003 1.003 0 00-1.71-.71L10 8.59l-3.29-3.3a1.003 1.003 0 00-1.42 1.42L8.59 10 5.3 13.29c-.19.18-.3.43-.3.71a1.003 1.003 0 001.71.71l3.29-3.3 3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 00.71-1.71L11.41 10z"
+                  fill-rule="evenodd"
+                />
+              </svg>
+            </span>
+          </button>
+        </div>
+        <div
           class="bp3-dialog-body"
         >
           <div
diff --git a/web-console/src/dialogs/table-action-dialog/table-action-dialog.spec.tsx b/web-console/src/dialogs/table-action-dialog/table-action-dialog.spec.tsx
index 5e5ff8b..0de6017 100644
--- a/web-console/src/dialogs/table-action-dialog/table-action-dialog.spec.tsx
+++ b/web-console/src/dialogs/table-action-dialog/table-action-dialog.spec.tsx
@@ -25,9 +25,9 @@ describe('table action dialog', () => {
   it('matches snapshot', () => {
     const tableActionDialog = (
       <TableActionDialog
+        title="Table dummy actions"
         sideButtonMetadata={[{ icon: 'badge', text: 'test' }]}
         onClose={() => {}}
-        isOpen
       />
     );
     render(tableActionDialog);
diff --git a/web-console/src/dialogs/table-action-dialog/table-action-dialog.tsx b/web-console/src/dialogs/table-action-dialog/table-action-dialog.tsx
index b7c04a3..f128495 100644
--- a/web-console/src/dialogs/table-action-dialog/table-action-dialog.tsx
+++ b/web-console/src/dialogs/table-action-dialog/table-action-dialog.tsx
@@ -16,16 +16,7 @@
  * limitations under the License.
  */
 
-import {
-  Button,
-  Classes,
-  Dialog,
-  Icon,
-  IconName,
-  IDialogProps,
-  Intent,
-  Popover,
-} from '@blueprintjs/core';
+import { Button, Classes, Dialog, Icon, IconName, Intent, Popover } from '@blueprintjs/core';
 import { IconNames } from '@blueprintjs/icons';
 import React from 'react';
 
@@ -40,7 +31,8 @@ export interface SideButtonMetaData {
   onClick?: () => void;
 }
 
-interface TableActionDialogProps extends IDialogProps {
+interface TableActionDialogProps {
+  title: string;
   sideButtonMetadata: SideButtonMetaData[];
   onClose: () => void;
   actions?: BasicAction[];
@@ -48,11 +40,11 @@ interface TableActionDialogProps extends IDialogProps {
 
 export class TableActionDialog extends React.PureComponent<TableActionDialogProps> {
   render(): JSX.Element {
-    const { sideButtonMetadata, isOpen, onClose, title, actions, children } = this.props;
+    const { sideButtonMetadata, onClose, title, actions, children } = this.props;
     const actionsMenu = actions ? basicActionsToMenu(actions) : undefined;
 
     return (
-      <Dialog className="table-action-dialog" isOpen={isOpen} onClose={onClose} title={title}>
+      <Dialog className="table-action-dialog" isOpen onClose={onClose} title={title}>
         <div className={Classes.DIALOG_BODY}>
           <div className="side-bar">
             {sideButtonMetadata.map((d, i) => (
diff --git a/web-console/src/dialogs/task-table-action-dialog/task-table-action-dialog.spec.tsx b/web-console/src/dialogs/task-table-action-dialog/task-table-action-dialog.spec.tsx
index adaacd6..c35840a 100644
--- a/web-console/src/dialogs/task-table-action-dialog/task-table-action-dialog.spec.tsx
+++ b/web-console/src/dialogs/task-table-action-dialog/task-table-action-dialog.spec.tsx
@@ -30,7 +30,6 @@ describe('task table action dialog', () => {
         taskId={'test'}
         actions={[basicAction]}
         onClose={() => {}}
-        isOpen
       />
     );
     render(taskTableActionDialog);
diff --git a/web-console/src/dialogs/task-table-action-dialog/task-table-action-dialog.tsx b/web-console/src/dialogs/task-table-action-dialog/task-table-action-dialog.tsx
index 87987be..351bdb4 100644
--- a/web-console/src/dialogs/task-table-action-dialog/task-table-action-dialog.tsx
+++ b/web-console/src/dialogs/task-table-action-dialog/task-table-action-dialog.tsx
@@ -16,7 +16,6 @@
  * limitations under the License.
  */
 
-import { IDialogProps } from '@blueprintjs/core';
 import React from 'react';
 
 import { ShowJson, ShowLog } from '../../components';
@@ -24,7 +23,7 @@ import { BasicAction } from '../../utils/basic-action';
 import { deepGet } from '../../utils/object-change';
 import { SideButtonMetaData, TableActionDialog } from '../table-action-dialog/table-action-dialog';
 
-interface TaskTableActionDialogProps extends IDialogProps {
+interface TaskTableActionDialogProps {
   taskId: string;
   actions: BasicAction[];
   onClose: () => void;
@@ -79,7 +78,6 @@ export class TaskTableActionDialog extends React.PureComponent<
 
     return (
       <TableActionDialog
-        isOpen
         sideButtonMetadata={taskTableSideButtonMetadata}
         onClose={onClose}
         title={`Task: ${taskId}`}
diff --git a/web-console/src/entry.scss b/web-console/src/entry.scss
index fcea2e2..8e36392 100644
--- a/web-console/src/entry.scss
+++ b/web-console/src/entry.scss
@@ -24,7 +24,9 @@
 html,
 body {
   //font-family: 'Open Sans', Helvetica, Arial, sans-serif;
+  position: fixed;
   height: 100%;
+  width: 100%;
   overflow: hidden;
   font-size: 13px;
 }
diff --git a/web-console/src/entry.ts b/web-console/src/entry.ts
index 1f52c29..dc124e8 100644
--- a/web-console/src/entry.ts
+++ b/web-console/src/entry.ts
@@ -53,7 +53,7 @@ if (typeof consoleConfig.title === 'string') {
 
 if (consoleConfig.baseURL) {
   axios.defaults.baseURL = consoleConfig.baseURL;
-  UrlBaser.baseURL = consoleConfig.baseURL;
+  UrlBaser.baseUrl = consoleConfig.baseURL;
 }
 if (consoleConfig.customHeaderName && consoleConfig.customHeaderValue) {
   axios.defaults.headers.common[consoleConfig.customHeaderName] = consoleConfig.customHeaderValue;
diff --git a/web-console/src/singletons/url-baser.ts b/web-console/src/singletons/url-baser.ts
index df0cc6b..1cc9ac7 100644
--- a/web-console/src/singletons/url-baser.ts
+++ b/web-console/src/singletons/url-baser.ts
@@ -17,10 +17,10 @@
  */
 
 export class UrlBaser {
-  static baseURL: string = '';
+  static baseUrl: string = '';
 
   static base(url: string): string {
     if (!url.startsWith('/')) return url;
-    return UrlBaser.baseURL + url;
+    return UrlBaser.baseUrl + url;
   }
 }
diff --git a/web-console/src/utils/general.tsx b/web-console/src/utils/general.tsx
index 27c79c6..6444392 100644
--- a/web-console/src/utils/general.tsx
+++ b/web-console/src/utils/general.tsx
@@ -261,7 +261,7 @@ export function validJson(json: string): boolean {
 }
 
 // stringify JSON to string; if JSON is null, parse empty string ""
-export function stringifyJSON(item: any): string {
+export function stringifyJson(item: any): string {
   if (item != null) {
     return JSON.stringify(item, null, 2);
   } else {
@@ -270,7 +270,7 @@ export function stringifyJSON(item: any): string {
 }
 
 // parse string to JSON object; if string is empty, return null
-export function parseStringToJSON(s: string): JSON | null {
+export function parseStringToJson(s: string): JSON | null {
   if (s === '') {
     return null;
   } else {
diff --git a/web-console/src/utils/ingestion-spec.tsx b/web-console/src/utils/ingestion-spec.tsx
index 30a1903..27f88b0 100644
--- a/web-console/src/utils/ingestion-spec.tsx
+++ b/web-console/src/utils/ingestion-spec.tsx
@@ -229,6 +229,10 @@ export function getSpecType(spec: Partial<IngestionSpec>): IngestionType | undef
   );
 }
 
+export function isIngestSegment(spec: IngestionSpec): boolean {
+  return deepGet(spec, 'ioConfig.firehose.type') === 'ingestSegment';
+}
+
 export function changeParallel(spec: IngestionSpec, parallel: boolean): IngestionSpec {
   if (!hasParallelAbility(spec)) return spec;
   const newType = parallel ? 'index_parallel' : 'index';
@@ -777,14 +781,26 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
           placeholder:
             'https://example.com/path/to/file1.ext, https://example.com/path/to/file2.ext',
           info: (
-            <>
-              <p>
-                The full URI of your file. To ingest from multiple URIs, use commas to separate each
-                individual URI.
-              </p>
-            </>
+            <p>
+              The full URI of your file. To ingest from multiple URIs, use commas to separate each
+              individual URI.
+            </p>
           ),
         },
+        {
+          name: 'firehose.httpAuthenticationUsername',
+          label: 'HTTP auth username',
+          type: 'string',
+          placeholder: '(optional)',
+          info: <p>Username to use for authentication with specified URIs</p>,
+        },
+        {
+          name: 'firehose.httpAuthenticationPassword',
+          label: 'HTTP auth password',
+          type: 'string',
+          placeholder: '(optional)',
+          info: <p>Password to use for authentication with specified URIs</p>,
+        },
       ];
 
     case 'index:local':
@@ -841,9 +857,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
           type: 'string',
           placeholder: `${CURRENT_YEAR}-01-01/${CURRENT_YEAR + 1}-01-01`,
           suggestions: [
-            `${CURRENT_YEAR}/${CURRENT_YEAR + 1}`,
-            `${CURRENT_YEAR}-01-01/${CURRENT_YEAR + 1}-01-01`,
             `${CURRENT_YEAR}-01-01T00:00:00/${CURRENT_YEAR + 1}-01-01T00:00:00`,
+            `${CURRENT_YEAR}-01-01/${CURRENT_YEAR + 1}-01-01`,
+            `${CURRENT_YEAR}/${CURRENT_YEAR + 1}`,
           ],
           info: (
             <p>
@@ -1439,7 +1455,9 @@ function basenameFromFilename(filename: string): string | undefined {
   return filename.split('.')[0];
 }
 
-export function fillDataSourceName(spec: IngestionSpec): IngestionSpec {
+export function fillDataSourceNameIfNeeded(spec: IngestionSpec): IngestionSpec {
+  // Do not overwrite if the spec already has a name
+  if (deepGet(spec, 'dataSchema.dataSource')) return spec;
   const ioConfig = deepGet(spec, 'ioConfig');
   if (!ioConfig) return spec;
   const possibleName = guessDataSourceName(ioConfig);
diff --git a/web-console/src/utils/sampler.ts b/web-console/src/utils/sampler.ts
index bd33dd2..7f7e9f1 100644
--- a/web-console/src/utils/sampler.ts
+++ b/web-console/src/utils/sampler.ts
@@ -18,7 +18,7 @@
 
 import axios from 'axios';
 
-import { getDruidErrorMessage } from './druid-query';
+import { getDruidErrorMessage, queryDruidRune } from './druid-query';
 import { alphanumericCompare, filterMap, sortWithPrefixSuffix } from './general';
 import {
   DimensionsSpec,
@@ -27,6 +27,7 @@ import {
   IngestionSpec,
   IoConfig,
   isColumnTimestampSpec,
+  isIngestSegment,
   MetricSpec,
   Parser,
   ParseSpec,
@@ -35,6 +36,8 @@ import {
 } from './ingestion-spec';
 import { deepGet, deepSet, whitelistKeys } from './object-change';
 
+const MS_IN_HALF_HOUR = 30 * 60 * 1000;
+
 const SAMPLER_URL = `/druid/indexer/v1/sampler`;
 const BASE_SAMPLER_CONFIG: SamplerConfig = {
   // skipCache: true,
@@ -60,6 +63,14 @@ export interface SampleResponse {
   data: SampleEntry[];
 }
 
+export interface SampleResponseWithExtraInfo extends SampleResponse {
+  queryGranularity?: any;
+  timestampSpec?: any;
+  rollup?: boolean;
+  columns?: Record<string, any>;
+  aggregators?: Record<string, any>;
+}
+
 export interface SampleEntry {
   raw: string;
   parsed?: Record<string, any>;
@@ -167,17 +178,66 @@ function makeSamplerIoConfig(
   return ioConfig;
 }
 
+/**
+ * This function scopes down the interval of an ingestSegment firehose for the data sampler
+ * this is needed because the ingestSegment firehose gets the interval you are sampling over,
+ * looks up the corresponding segments and segment locations from metadata store, downloads
+ * every segment from deep storage to disk, and then maps all the segments into memory;
+ * and this happens in the constructor before the timer thread is even created meaning the sampler
+ * will time out on a larger interval.
+ * This is essentially a workaround for https://github.com/apache/incubator-druid/issues/8448
+ * @param ioConfig The IO Config to scope down the interval of
+ */
+export async function scopeDownIngestSegmentFirehoseIntervalIfNeeded(
+  ioConfig: IoConfig,
+): Promise<IoConfig> {
+  if (deepGet(ioConfig, 'firehose.type') !== 'ingestSegment') return ioConfig;
+  const interval = deepGet(ioConfig, 'firehose.interval');
+  const intervalParts = interval.split('/');
+  const start = new Date(intervalParts[0]);
+  if (isNaN(start.valueOf())) throw new Error(`could not decode interval start`);
+  const end = new Date(intervalParts[1]);
+  if (isNaN(end.valueOf())) throw new Error(`could not decode interval end`);
+
+  // Less than or equal to 1/2 hour so there is no need to adjust intervals
+  if (Math.abs(end.valueOf() - start.valueOf()) <= MS_IN_HALF_HOUR) return ioConfig;
+
+  const dataSourceMetadataResponse = await queryDruidRune({
+    queryType: 'dataSourceMetadata',
+    dataSource: deepGet(ioConfig, 'firehose.dataSource'),
+  });
+
+  const maxIngestedEventTime = new Date(
+    deepGet(dataSourceMetadataResponse, '0.result.maxIngestedEventTime'),
+  );
+
+  // If invalid maxIngestedEventTime do nothing
+  if (isNaN(maxIngestedEventTime.valueOf())) return ioConfig;
+
+  // If maxIngestedEventTime is before the start of the interval do nothing
+  if (maxIngestedEventTime < start) return ioConfig;
+
+  const newEnd = maxIngestedEventTime < end ? maxIngestedEventTime : end;
+  const newStart = new Date(newEnd.valueOf() - MS_IN_HALF_HOUR); // Set start to 1/2hr ago
+
+  return deepSet(
+    ioConfig,
+    'firehose.interval',
+    `${newStart.toISOString()}/${newEnd.toISOString()}`,
+  );
+}
+
 export async function sampleForConnect(
   spec: IngestionSpec,
   sampleStrategy: SampleStrategy,
-): Promise<SampleResponse> {
+): Promise<SampleResponseWithExtraInfo> {
   const samplerType = getSamplerType(spec);
-  const ioConfig: IoConfig = makeSamplerIoConfig(
-    deepGet(spec, 'ioConfig'),
-    samplerType,
-    sampleStrategy,
+  const ioConfig: IoConfig = await scopeDownIngestSegmentFirehoseIntervalIfNeeded(
+    makeSamplerIoConfig(deepGet(spec, 'ioConfig'), samplerType, sampleStrategy),
   );
 
+  const ingestSegmentMode = isIngestSegment(spec);
+
   const sampleSpec: SampleSpec = {
     type: samplerType,
     spec: {
@@ -200,7 +260,33 @@ export async function sampleForConnect(
     samplerConfig: BASE_SAMPLER_CONFIG,
   };
 
-  return postToSampler(sampleSpec, 'connect');
+  const samplerResponse: SampleResponseWithExtraInfo = await postToSampler(sampleSpec, 'connect');
+
+  if (!samplerResponse.data.length) return samplerResponse;
+
+  if (ingestSegmentMode) {
+    const segmentMetadataResponse = await queryDruidRune({
+      queryType: 'segmentMetadata',
+      dataSource: deepGet(ioConfig, 'firehose.dataSource'),
+      intervals: [deepGet(ioConfig, 'firehose.interval')],
+      merge: true,
+      lenientAggregatorMerge: true,
+      analysisTypes: ['timestampSpec', 'queryGranularity', 'aggregators', 'rollup'],
+    });
+
+    if (Array.isArray(segmentMetadataResponse) && segmentMetadataResponse.length === 1) {
+      const segmentMetadataResponse0 = segmentMetadataResponse[0];
+      samplerResponse.queryGranularity = segmentMetadataResponse0.queryGranularity;
+      samplerResponse.timestampSpec = segmentMetadataResponse0.timestampSpec;
+      samplerResponse.rollup = segmentMetadataResponse0.rollup;
+      samplerResponse.columns = segmentMetadataResponse0.columns;
+      samplerResponse.aggregators = segmentMetadataResponse0.aggregators;
+    } else {
+      throw new Error(`unexpected response from segmentMetadata query`);
+    }
+  }
+
+  return samplerResponse;
 }
 
 export async function sampleForParser(
@@ -209,10 +295,8 @@ export async function sampleForParser(
   cacheKey: string | undefined,
 ): Promise<SampleResponse> {
   const samplerType = getSamplerType(spec);
-  const ioConfig: IoConfig = makeSamplerIoConfig(
-    deepGet(spec, 'ioConfig'),
-    samplerType,
-    sampleStrategy,
+  const ioConfig: IoConfig = await scopeDownIngestSegmentFirehoseIntervalIfNeeded(
+    makeSamplerIoConfig(deepGet(spec, 'ioConfig'), samplerType, sampleStrategy),
   );
   const parser: Parser = deepGet(spec, 'dataSchema.parser') || {};
 
@@ -248,10 +332,8 @@ export async function sampleForTimestamp(
   cacheKey: string | undefined,
 ): Promise<SampleResponse> {
   const samplerType = getSamplerType(spec);
-  const ioConfig: IoConfig = makeSamplerIoConfig(
-    deepGet(spec, 'ioConfig'),
-    samplerType,
-    sampleStrategy,
+  const ioConfig: IoConfig = await scopeDownIngestSegmentFirehoseIntervalIfNeeded(
+    makeSamplerIoConfig(deepGet(spec, 'ioConfig'), samplerType, sampleStrategy),
   );
   const parser: Parser = deepGet(spec, 'dataSchema.parser') || {};
   const parseSpec: ParseSpec = deepGet(spec, 'dataSchema.parser.parseSpec') || {};
@@ -339,10 +421,8 @@ export async function sampleForTransform(
   cacheKey: string | undefined,
 ): Promise<SampleResponse> {
   const samplerType = getSamplerType(spec);
-  const ioConfig: IoConfig = makeSamplerIoConfig(
-    deepGet(spec, 'ioConfig'),
-    samplerType,
-    sampleStrategy,
+  const ioConfig: IoConfig = await scopeDownIngestSegmentFirehoseIntervalIfNeeded(
+    makeSamplerIoConfig(deepGet(spec, 'ioConfig'), samplerType, sampleStrategy),
   );
   const parser: Parser = deepGet(spec, 'dataSchema.parser') || {};
   const parseSpec: ParseSpec = deepGet(spec, 'dataSchema.parser.parseSpec') || {};
@@ -415,10 +495,8 @@ export async function sampleForFilter(
   cacheKey: string | undefined,
 ): Promise<SampleResponse> {
   const samplerType = getSamplerType(spec);
-  const ioConfig: IoConfig = makeSamplerIoConfig(
-    deepGet(spec, 'ioConfig'),
-    samplerType,
-    sampleStrategy,
+  const ioConfig: IoConfig = await scopeDownIngestSegmentFirehoseIntervalIfNeeded(
+    makeSamplerIoConfig(deepGet(spec, 'ioConfig'), samplerType, sampleStrategy),
   );
   const parser: Parser = deepGet(spec, 'dataSchema.parser') || {};
   const parseSpec: ParseSpec = deepGet(spec, 'dataSchema.parser.parseSpec') || {};
@@ -493,10 +571,8 @@ export async function sampleForSchema(
   cacheKey: string | undefined,
 ): Promise<SampleResponse> {
   const samplerType = getSamplerType(spec);
-  const ioConfig: IoConfig = makeSamplerIoConfig(
-    deepGet(spec, 'ioConfig'),
-    samplerType,
-    sampleStrategy,
+  const ioConfig: IoConfig = await scopeDownIngestSegmentFirehoseIntervalIfNeeded(
+    makeSamplerIoConfig(deepGet(spec, 'ioConfig'), samplerType, sampleStrategy),
   );
   const parser: Parser = deepGet(spec, 'dataSchema.parser') || {};
   const transformSpec: TransformSpec =
diff --git a/web-console/src/views/datasource-view/datasource-view.tsx b/web-console/src/views/datasource-view/datasource-view.tsx
index b8aa885..22bd689 100644
--- a/web-console/src/views/datasource-view/datasource-view.tsx
+++ b/web-console/src/views/datasource-view/datasource-view.tsx
@@ -1016,7 +1016,6 @@ GROUP BY 1`;
             datasourceId={datasourceTableActionDialogId}
             actions={actions}
             onClose={() => this.setState({ datasourceTableActionDialogId: undefined })}
-            isOpen
           />
         )}
       </div>
diff --git a/web-console/src/views/home-view/status-card/status-card.tsx b/web-console/src/views/home-view/status-card/status-card.tsx
index a55247d..7b8f907 100644
--- a/web-console/src/views/home-view/status-card/status-card.tsx
+++ b/web-console/src/views/home-view/status-card/status-card.tsx
@@ -21,41 +21,50 @@ import axios from 'axios';
 import React from 'react';
 
 import { StatusDialog } from '../../../dialogs/status-dialog/status-dialog';
-import { QueryManager } from '../../../utils';
+import { pluralIfNeeded, QueryManager } from '../../../utils';
 import { HomeViewCard } from '../home-view-card/home-view-card';
 
 export interface StatusCardProps {}
 
 export interface StatusCardState {
-  versionLoading: boolean;
-  version: string;
-  versionError?: string;
+  statusLoading: boolean;
+  version?: string;
+  extensionCount?: number;
+  statusError?: string;
 
   showStatusDialog: boolean;
 }
 
+interface StatusSummary {
+  version: string;
+  extensionCount: number;
+}
+
 export class StatusCard extends React.PureComponent<StatusCardProps, StatusCardState> {
-  private versionQueryManager: QueryManager<null, string>;
+  private versionQueryManager: QueryManager<null, StatusSummary>;
 
   constructor(props: StatusCardProps, context: any) {
     super(props, context);
-    this.state = {
-      versionLoading: true,
-      version: '',
 
+    this.state = {
+      statusLoading: true,
       showStatusDialog: false,
     };
 
     this.versionQueryManager = new QueryManager({
       processQuery: async () => {
         const statusResp = await axios.get('/status');
-        return statusResp.data.version;
+        return {
+          version: statusResp.data.version,
+          extensionCount: statusResp.data.modules.length,
+        };
       },
       onStateChange: ({ result, loading, error }) => {
         this.setState({
-          versionLoading: loading,
-          version: result,
-          versionError: error,
+          statusLoading: loading,
+          version: result ? result.version : undefined,
+          extensionCount: result ? result.extensionCount : undefined,
+          statusError: error,
         });
       },
     });
@@ -69,35 +78,39 @@ export class StatusCard extends React.PureComponent<StatusCardProps, StatusCardS
     this.versionQueryManager.terminate();
   }
 
+  private handleStatusDialogOpen = () => {
+    this.setState({ showStatusDialog: true });
+  };
+
+  private handleStatusDialogClose = () => {
+    this.setState({ showStatusDialog: false });
+  };
+
   renderStatusDialog() {
     const { showStatusDialog } = this.state;
-    if (!showStatusDialog) {
-      return null;
-    }
-    return (
-      <StatusDialog
-        onClose={() => this.setState({ showStatusDialog: false })}
-        title={'Status'}
-        isOpen
-      />
-    );
+    if (!showStatusDialog) return;
+
+    return <StatusDialog onClose={this.handleStatusDialogClose} />;
   }
 
   render(): JSX.Element {
-    const { version, versionLoading, versionError } = this.state;
+    const { version, extensionCount, statusLoading, statusError } = this.state;
 
     return (
-      <HomeViewCard
-        className="status-card"
-        onClick={() => this.setState({ showStatusDialog: true })}
-        icon={IconNames.GRAPH}
-        title="Status"
-        loading={versionLoading}
-        error={versionError}
-      >
-        {version ? `Apache Druid is running version ${version}` : ''}
+      <>
+        <HomeViewCard
+          className="status-card"
+          onClick={this.handleStatusDialogOpen}
+          icon={IconNames.GRAPH}
+          title="Status"
+          loading={statusLoading}
+          error={statusError}
+        >
+          {version && <p>{`Apache Druid is running version ${version}`}</p>}
+          {extensionCount && <p>{`${pluralIfNeeded(extensionCount, 'extension')} loaded`}</p>}
+        </HomeViewCard>
         {this.renderStatusDialog()}
-      </HomeViewCard>
+      </>
     );
   }
 }
diff --git a/web-console/src/views/load-data-view/example-picker/__snapshots__/example-picker.spec.tsx.snap b/web-console/src/views/load-data-view/example-picker/__snapshots__/example-picker.spec.tsx.snap
new file mode 100644
index 0000000..47010e0f
--- /dev/null
+++ b/web-console/src/views/load-data-view/example-picker/__snapshots__/example-picker.spec.tsx.snap
@@ -0,0 +1,56 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`example picker matches snapshot 1`] = `
+<div
+  class="bp3-form-group"
+>
+  <label
+    class="bp3-label"
+  >
+    Select example dataset
+     
+    <span
+      class="bp3-text-muted"
+    />
+  </label>
+  <div
+    class="bp3-form-content"
+  >
+    <div
+      class="bp3-html-select bp3-fill"
+    >
+      <select>
+        <option
+          value="0"
+        >
+          Wikipedia
+        </option>
+        <option
+          value="1"
+        >
+          Ex 2
+        </option>
+      </select>
+      <span
+        class="bp3-icon bp3-icon-double-caret-vertical"
+        icon="double-caret-vertical"
+      >
+        <svg
+          data-icon="double-caret-vertical"
+          height="16"
+          viewBox="0 0 16 16"
+          width="16"
+        >
+          <desc>
+            double-caret-vertical
+          </desc>
+          <path
+            d="M5 7h6a1.003 1.003 0 00.71-1.71l-3-3C8.53 2.11 8.28 2 8 2s-.53.11-.71.29l-3 3A1.003 1.003 0 005 7zm6 2H5a1.003 1.003 0 00-.71 1.71l3 3c.18.18.43.29.71.29s.53-.11.71-.29l3-3A1.003 1.003 0 0011 9z"
+            fill-rule="evenodd"
+          />
+        </svg>
+      </span>
+    </div>
+  </div>
+</div>
+`;
diff --git a/web-console/src/dialogs/history-dialog/history-dialog.spec.tsx b/web-console/src/views/load-data-view/example-picker/example-picker.spec.tsx
similarity index 68%
copy from web-console/src/dialogs/history-dialog/history-dialog.spec.tsx
copy to web-console/src/views/load-data-view/example-picker/example-picker.spec.tsx
index 176f35a..e5b070f 100644
--- a/web-console/src/dialogs/history-dialog/history-dialog.spec.tsx
+++ b/web-console/src/views/load-data-view/example-picker/example-picker.spec.tsx
@@ -19,20 +19,21 @@
 import { render } from '@testing-library/react';
 import React from 'react';
 
-import { HistoryDialog } from './history-dialog';
+import { ExamplePicker } from './example-picker';
 
-describe('history dialog', () => {
+describe('example picker', () => {
   it('matches snapshot', () => {
-    const historyDialog = (
-      <HistoryDialog
-        historyRecords={[
-          { auditTime: 'test', auditInfo: 'test', payload: JSON.stringify({ name: 'test' }) },
-          { auditTime: 'test', auditInfo: 'test', payload: JSON.stringify({ name: 'test' }) },
+    const examplePicker = (
+      <ExamplePicker
+        exampleManifests={[
+          { name: 'Wikipedia', description: 'stuff stuff', spec: {} },
+          { name: 'Ex 2', description: 'stuff stuff', spec: {} },
         ]}
-        isOpen
+        onSelectExample={() => {}}
       />
     );
-    render(historyDialog);
-    expect(document.body.lastChild).toMatchSnapshot();
+
+    const { container } = render(examplePicker);
+    expect(container.firstChild).toMatchSnapshot();
   });
 });
diff --git a/web-console/src/views/load-data-view/example-picker/example-picker.tsx b/web-console/src/views/load-data-view/example-picker/example-picker.tsx
new file mode 100644
index 0000000..39596ff
--- /dev/null
+++ b/web-console/src/views/load-data-view/example-picker/example-picker.tsx
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Button, Callout, FormGroup, HTMLSelect, Intent } from '@blueprintjs/core';
+import { IconNames } from '@blueprintjs/icons';
+import React from 'react';
+
+import { ExampleManifest } from '../../../utils/sampler';
+
+export interface ExamplePickerProps {
+  exampleManifests: ExampleManifest[];
+  onSelectExample: (exampleManifest: ExampleManifest) => void;
+}
+
+export interface ExamplePickerState {
+  selectedIndex: number;
+}
+
+export class ExamplePicker extends React.PureComponent<ExamplePickerProps, ExamplePickerState> {
+  constructor(props: ExamplePickerProps, context: any) {
+    super(props, context);
+    this.state = {
+      selectedIndex: 0,
+    };
+  }
+
+  render(): JSX.Element {
+    const { exampleManifests, onSelectExample } = this.props;
+    const { selectedIndex } = this.state;
+
+    return (
+      <>
+        <FormGroup label="Select example dataset">
+          <HTMLSelect
+            fill
+            value={selectedIndex}
+            onChange={e => this.setState({ selectedIndex: e.target.value as any })}
+          >
+            {exampleManifests.map((exampleManifest, i) => (
+              <option key={i} value={i}>
+                {exampleManifest.name}
+              </option>
+            ))}
+          </HTMLSelect>
+        </FormGroup>
+        <FormGroup>
+          <Callout>{exampleManifests[selectedIndex].description}</Callout>
+        </FormGroup>
+        <FormGroup>
+          <Button
+            text="Load example"
+            rightIcon={IconNames.ARROW_RIGHT}
+            intent={Intent.PRIMARY}
+            onClick={() => {
+              onSelectExample(exampleManifests[selectedIndex]);
+            }}
+          />
+        </FormGroup>
+      </>
+    );
+  }
+}
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 71d71c8..00eb64b 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
@@ -29,6 +29,7 @@ import {
   H5,
   HTMLSelect,
   Icon,
+  IconName,
   Intent,
   Popover,
   Switch,
@@ -71,7 +72,7 @@ import {
   DruidFilter,
   EMPTY_ARRAY,
   EMPTY_OBJECT,
-  fillDataSourceName,
+  fillDataSourceNameIfNeeded,
   fillParser,
   FlattenField,
   getDimensionMode,
@@ -101,6 +102,7 @@ import {
   IoConfig,
   isColumnTimestampSpec,
   isEmptyIngestionSpec,
+  isIngestSegment,
   isParallel,
   issueWithIoConfig,
   issueWithParser,
@@ -132,10 +134,12 @@ import {
   sampleForTimestamp,
   sampleForTransform,
   SampleResponse,
+  SampleResponseWithExtraInfo,
   SampleStrategy,
 } from '../../utils/sampler';
 import { computeFlattenPathsForData } from '../../utils/spec-utils';
 
+import { ExamplePicker } from './example-picker/example-picker';
 import { FilterTable } from './filter-table/filter-table';
 import { ParseDataTable } from './parse-data-table/parse-data-table';
 import { ParseTimeTable } from './parse-time-table/parse-time-table';
@@ -261,7 +265,7 @@ export interface LoadDataViewState {
   specialColumnsOnly: boolean;
 
   // for ioConfig
-  inputQueryState: QueryState<SampleEntry[]>;
+  inputQueryState: QueryState<SampleResponseWithExtraInfo>;
 
   // for parser
   parserQueryState: QueryState<HeaderAndRows>;
@@ -449,32 +453,36 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
     localStorageSet(LocalStorageKeys.INGESTION_SPEC, JSON.stringify(newSpec));
   };
 
+  renderActionCard(icon: IconName, title: string, caption: string, onClick: () => void) {
+    return (
+      <Card className={'spec-card'} interactive onClick={onClick}>
+        <Icon className="spec-card-icon" icon={icon} iconSize={30} />
+        <div className={'spec-card-header'}>
+          {title}
+          <div className={'spec-card-caption'}>{caption}</div>
+        </div>
+      </Card>
+    );
+  }
+
   render(): JSX.Element {
     const { step, continueToSpec } = this.state;
+
     if (!continueToSpec) {
       return (
         <div className={classNames('load-data-continue-view load-data-view')}>
-          <Card className={'spec-card'} interactive onClick={this.handleResetSpec}>
-            <Icon className="spec-card-icon" icon={IconNames.ASTERISK} iconSize={30} />
-            <div className={'spec-card-header'}>
-              Start a new spec
-              <div className={'spec-card-caption'}>Start a new ingestion flow</div>
-            </div>
-          </Card>
-          <Card
-            className={'spec-card'}
-            interactive
-            onClick={() => this.setState({ continueToSpec: true })}
-          >
-            <Icon className="spec-card-icon" icon={IconNames.REPEAT} iconSize={30} />
-            <div className={'spec-card-header'}>
-              Continue from previous spec
-              <div className={'spec-card-caption'}>
-                Continue from most recent spec you were working on
-              </div>
-            </div>
-          </Card>
-          {this.renderResetConfirm()}
+          {this.renderActionCard(
+            IconNames.ASTERISK,
+            'Start a new spec',
+            'Begin a new ingestion flow',
+            this.handleResetSpec,
+          )}
+          {this.renderActionCard(
+            IconNames.REPEAT,
+            'Continue from previous spec',
+            'Go back to the most recent spec you were working on',
+            this.handleContinueSpec,
+          )}
         </div>
       );
     }
@@ -586,9 +594,12 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
     });
   }
 
-  renderIngestionCard(comboType: IngestionComboTypeWithExtra, disabled?: boolean) {
+  renderIngestionCard(
+    comboType: IngestionComboTypeWithExtra,
+    disabled?: boolean,
+  ): JSX.Element | undefined {
     const { overlordModules, selectedComboType } = this.state;
-    if (!overlordModules) return null;
+    if (!overlordModules) return;
     const requiredModule = getRequiredModule(comboType);
     const goodToGo = !disabled && (!requiredModule || overlordModules.includes(requiredModule));
 
@@ -613,6 +624,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
     const { spec, exampleManifests } = this.state;
     const noExamples = Boolean(!exampleManifests || !exampleManifests.length);
 
+    const welcomeMessage = this.renderWelcomeStepMessage();
     return (
       <>
         <div className="main bp3-input">
@@ -629,7 +641,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
           {this.renderIngestionCard('other')}
         </div>
         <div className="control">
-          <Callout className="intro">{this.renderWelcomeStepMessage()}</Callout>
+          {welcomeMessage && <Callout className="intro">{welcomeMessage}</Callout>}
           {this.renderWelcomeStepControls()}
           {!isEmptyIngestionSpec(spec) && (
             <Button icon={IconNames.RESET} text="Reset spec" onClick={this.handleResetConfirm} />
@@ -639,15 +651,16 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
     );
   }
 
-  renderViewValueModal() {
+  renderViewValueModal(): JSX.Element | undefined {
     const { showViewValueModal, str } = this.state;
-    if (!showViewValueModal) return null;
+    if (!showViewValueModal) return;
+
     return (
       <ShowValueDialog onClose={() => this.setState({ showViewValueModal: false })} str={str} />
     );
   }
 
-  renderWelcomeStepMessage() {
+  renderWelcomeStepMessage(): JSX.Element | undefined {
     const { selectedComboType, exampleManifests } = this.state;
 
     if (!selectedComboType) {
@@ -735,9 +748,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
 
       case 'example':
         if (exampleManifests && exampleManifests.length) {
-          return <p>Pick one of these examples to get you started.</p>;
+          return; // Yield to example picker controls
         } else {
-          return <p>Could not load example.</p>;
+          return <p>Could not load examples.</p>;
         }
 
       case 'other':
@@ -756,12 +769,12 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
     }
   }
 
-  renderWelcomeStepControls() {
+  renderWelcomeStepControls(): JSX.Element | undefined {
     const { goToTask } = this.props;
     const { spec, selectedComboType, exampleManifests } = this.state;
 
     const issue = this.selectedIngestionTypeIssue();
-    if (issue) return null;
+    if (issue) return;
 
     switch (selectedComboType) {
       case 'index:http':
@@ -801,27 +814,17 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
         );
 
       case 'example':
+        if (!exampleManifests) return;
         return (
-          <>
-            {exampleManifests &&
-              exampleManifests.map((exampleManifest, i) => (
-                <FormGroup key={i}>
-                  <Button
-                    text={exampleManifest.name}
-                    rightIcon={IconNames.ARROW_RIGHT}
-                    intent={Intent.PRIMARY}
-                    title={exampleManifest.description}
-                    fill
-                    onClick={() => {
-                      this.updateSpec(exampleManifest.spec);
-                      setTimeout(() => {
-                        this.updateStep('connect');
-                      }, 10);
-                    }}
-                  />
-                </FormGroup>
-              ))}
-          </>
+          <ExamplePicker
+            exampleManifests={exampleManifests}
+            onSelectExample={exampleManifest => {
+              this.updateSpec(exampleManifest.spec);
+              setTimeout(() => {
+                this.updateStep('connect');
+              }, 10);
+            }}
+          />
         );
 
       case 'other':
@@ -847,23 +850,36 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
         );
 
       default:
-        return null;
+        return;
     }
   }
 
-  selectedIngestionTypeIssue(): JSX.Element | null {
+  selectedIngestionTypeIssue(): JSX.Element | undefined {
     const { selectedComboType, overlordModules } = this.state;
-    if (!selectedComboType || !overlordModules) return null;
+    if (!selectedComboType || !overlordModules) return;
 
     const requiredModule = getRequiredModule(selectedComboType);
-    if (!requiredModule || overlordModules.includes(requiredModule)) return null;
+    if (!requiredModule || overlordModules.includes(requiredModule)) return;
 
     return (
-      <p>
-        {`${getIngestionTitle(selectedComboType)} ingestion requires the `}
-        <strong>{requiredModule}</strong>
-        {` extension to be loaded.`}
-      </p>
+      <>
+        <p>
+          {`${getIngestionTitle(selectedComboType)} ingestion requires the `}
+          <strong>{requiredModule}</strong>
+          {` extension to be loaded.`}
+        </p>
+        <p>
+          Please make sure that the
+          <Code>"{requiredModule}"</Code> extension is included in the <Code>loadList</Code>.
+        </p>
+        <p>
+          For more information please refer to the{' '}
+          <ExternalLink href="https://druid.apache.org/docs/latest/operations/including-extensions">
+            documentation on loading extensions
+          </ExternalLink>
+          .
+        </p>
+      </>
     );
   }
 
@@ -872,13 +888,18 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
   };
 
   private handleResetSpec = () => {
-    this.setState({ showResetConfirm: false, step: 'welcome', continueToSpec: true });
+    this.setState({ showResetConfirm: false, continueToSpec: true });
     this.updateSpec({} as any);
+    this.updateStep('welcome');
+  };
+
+  private handleContinueSpec = () => {
+    this.setState({ continueToSpec: true });
   };
 
-  renderResetConfirm() {
+  renderResetConfirm(): JSX.Element | undefined {
     const { showResetConfirm } = this.state;
-    if (!showResetConfirm) return null;
+    if (!showResetConfirm) return;
 
     return (
       <Alert
@@ -929,7 +950,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
 
     this.setState({
       cacheKey: sampleResponse.cacheKey,
-      inputQueryState: new QueryState({ data: sampleResponse.data }),
+      inputQueryState: new QueryState({ data: sampleResponse }),
     });
   }
 
@@ -965,7 +986,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
     } else if (inputQueryState.error) {
       mainFill = <CenterMessage>{`Error: ${inputQueryState.error}`}</CenterMessage>;
     } else if (inputQueryState.data) {
-      const inputData = inputQueryState.data;
+      const inputData = inputQueryState.data.data;
       mainFill = (
         <TextArea
           className="raw-lines"
@@ -1054,9 +1075,61 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
           disabled: !inputQueryState.data,
           onNextStep: () => {
             if (!inputQueryState.data) return;
-            this.updateSpec(
-              fillDataSourceName(fillParser(spec, inputQueryState.data.map(l => l.raw))),
-            );
+            const inputData = inputQueryState.data;
+
+            if (isIngestSegment(spec)) {
+              let newSpec = fillParser(spec, []);
+
+              if (typeof inputData.rollup === 'boolean') {
+                newSpec = deepSet(newSpec, 'dataSchema.granularitySpec.rollup', inputData.rollup);
+              }
+
+              if (inputData.timestampSpec) {
+                newSpec = deepSet(
+                  newSpec,
+                  'dataSchema.parser.parseSpec.timestampSpec',
+                  inputData.timestampSpec,
+                );
+              }
+
+              if (inputData.queryGranularity) {
+                newSpec = deepSet(
+                  newSpec,
+                  'dataSchema.granularitySpec.queryGranularity',
+                  inputData.queryGranularity,
+                );
+              }
+
+              if (inputData.columns) {
+                const aggregators = inputData.aggregators || {};
+                newSpec = deepSet(
+                  newSpec,
+                  'dataSchema.parser.parseSpec.dimensionsSpec.dimensions',
+                  Object.keys(inputData.columns)
+                    .filter(k => k !== '__time' && !aggregators[k])
+                    .map(k => ({
+                      name: k,
+                      type: String(inputData.columns![k].type || 'string').toLowerCase(),
+                    })),
+                );
+              }
+
+              if (inputData.aggregators) {
+                newSpec = deepSet(
+                  newSpec,
+                  'dataSchema.metricsSpec',
+                  Object.values(inputData.aggregators),
+                );
+              }
+
+              this.updateSpec(fillDataSourceNameIfNeeded(newSpec));
+            } else {
+              this.updateSpec(
+                fillDataSourceNameIfNeeded(
+                  fillParser(spec, inputQueryState.data.data.map(l => l.raw)),
+                ),
+              );
+            }
           },
         })}
       </>
@@ -1231,7 +1304,16 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
           disabled: !parserQueryState.data,
           onNextStep: () => {
             if (!parserQueryState.data) return;
-            const possibleTimestampSpec = getTimestampSpec(parserQueryState.data);
+            let possibleTimestampSpec: TimestampSpec;
+            if (isIngestSegment(spec)) {
+              possibleTimestampSpec = {
+                column: '__time',
+                format: 'auto',
+              };
+            } else {
+              possibleTimestampSpec = getTimestampSpec(parserQueryState.data);
+            }
+
             if (possibleTimestampSpec) {
               const newSpec: IngestionSpec = deepSet(
                 spec,
@@ -1253,10 +1335,10 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
     });
   };
 
-  renderFlattenControls() {
+  renderFlattenControls(): JSX.Element | undefined {
     const { spec, selectedFlattenField, selectedFlattenFieldIndex } = this.state;
     const parseSpec: ParseSpec = deepGet(spec, 'dataSchema.parser.parseSpec') || EMPTY_OBJECT;
-    if (!parseSpecHasFlatten(parseSpec)) return null;
+    if (!parseSpecHasFlatten(parseSpec)) return;
 
     const close = () => {
       this.setState({
@@ -1640,9 +1722,11 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
           disabled: !transformQueryState.data,
           onNextStep: () => {
             if (!transformQueryState.data) return;
-            this.updateSpec(
-              updateSchemaWithSample(spec, transformQueryState.data, 'specific', true),
-            );
+            if (!isIngestSegment(spec)) {
+              this.updateSpec(
+                updateSchemaWithSample(spec, transformQueryState.data, 'specific', true),
+              );
+            }
           },
         })}
       </>
@@ -2640,9 +2724,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
     );
   }
 
-  renderParallelPickerIfNeeded() {
+  renderParallelPickerIfNeeded(): JSX.Element | undefined {
     const { spec } = this.state;
-    if (!hasParallelAbility(spec)) return null;
+    if (!hasParallelAbility(spec)) return;
 
     return (
       <FormGroup>
diff --git a/web-console/src/views/lookups-view/__snapshots__/lookups-view.spec.tsx.snap b/web-console/src/views/lookups-view/__snapshots__/lookups-view.spec.tsx.snap
index 58c894d..87d09b8 100755
--- a/web-console/src/views/lookups-view/__snapshots__/lookups-view.spec.tsx.snap
+++ b/web-console/src/views/lookups-view/__snapshots__/lookups-view.spec.tsx.snap
@@ -208,17 +208,5 @@ exports[`lookups view matches snapshot 1`] = `
     style={Object {}}
     subRowsKey="_subRows"
   />
-  <LookupEditDialog
-    allLookupTiers={Array []}
-    isEdit={false}
-    isOpen={false}
-    lookupName=""
-    lookupSpec=""
-    lookupTier=""
-    lookupVersion=""
-    onChange={[Function]}
-    onClose={[Function]}
-    onSubmit={[Function]}
-  />
 </div>
 `;
diff --git a/web-console/src/views/lookups-view/lookups-view.tsx b/web-console/src/views/lookups-view/lookups-view.tsx
index bf22f5f..52bdf18 100644
--- a/web-console/src/views/lookups-view/lookups-view.tsx
+++ b/web-console/src/views/lookups-view/lookups-view.tsx
@@ -180,26 +180,26 @@ export class LookupsView extends React.PureComponent<LookupsViewProps, LookupsVi
       isEdit,
     } = this.state;
     let endpoint = '/druid/coordinator/v1/lookups/config';
-    const specJSON: any = JSON.parse(lookupEditSpec);
-    let dataJSON: any;
+    const specJson: any = JSON.parse(lookupEditSpec);
+    let dataJson: any;
     if (isEdit) {
       endpoint = `${endpoint}/${lookupEditTier}/${lookupEditName}`;
-      dataJSON = {
+      dataJson = {
         version: lookupEditVersion,
-        lookupExtractorFactory: specJSON,
+        lookupExtractorFactory: specJson,
       };
     } else {
-      dataJSON = {
+      dataJson = {
         [lookupEditTier]: {
           [lookupEditName]: {
             version: lookupEditVersion,
-            lookupExtractorFactory: specJSON,
+            lookupExtractorFactory: specJson,
           },
         },
       };
     }
     try {
-      await axios.post(endpoint, dataJSON);
+      await axios.post(endpoint, dataJson);
       this.setState({
         lookupEditDialogOpen: false,
       });
@@ -346,10 +346,10 @@ export class LookupsView extends React.PureComponent<LookupsViewProps, LookupsVi
       lookupEditVersion,
       isEdit,
     } = this.state;
+    if (!lookupEditDialogOpen) return;
 
     return (
       <LookupEditDialog
-        isOpen={lookupEditDialogOpen}
         onClose={() => this.setState({ lookupEditDialogOpen: false })}
         onSubmit={() => this.submitLookupEdit()}
         onChange={this.handleChangeLookup}
diff --git a/web-console/src/views/segments-view/segments-view.tsx b/web-console/src/views/segments-view/segments-view.tsx
index cf6615d..adb36f8 100644
--- a/web-console/src/views/segments-view/segments-view.tsx
+++ b/web-console/src/views/segments-view/segments-view.tsx
@@ -711,7 +711,6 @@ export class SegmentsView extends React.PureComponent<SegmentsViewProps, Segment
             datasourceId={datasourceTableActionDialogId}
             actions={actions}
             onClose={() => this.setState({ segmentTableActionDialogId: undefined })}
-            isOpen
           />
         )}
       </>
diff --git a/web-console/src/views/task-view/tasks-view.tsx b/web-console/src/views/task-view/tasks-view.tsx
index 3b635ce..3316934 100644
--- a/web-console/src/views/task-view/tasks-view.tsx
+++ b/web-console/src/views/task-view/tasks-view.tsx
@@ -1204,7 +1204,6 @@ ORDER BY "rank" DESC, "created_time" DESC`;
         </Alert>
         {supervisorTableActionDialogId && (
           <SupervisorTableActionDialog
-            isOpen
             supervisorId={supervisorTableActionDialogId}
             actions={supervisorTableActionDialogActions}
             onClose={() => this.setState({ supervisorTableActionDialogId: undefined })}
@@ -1212,7 +1211,6 @@ ORDER BY "rank" DESC, "created_time" DESC`;
         )}
         {taskTableActionDialogId && taskTableActionDialogStatus && (
           <TaskTableActionDialog
-            isOpen
             status={taskTableActionDialogStatus}
             taskId={taskTableActionDialogId}
             actions={taskTableActionDialogActions}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org