2019-01-31 20:26:41 -05:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2019-04-07 23:19:08 -04:00
|
|
|
import { Intent } from '@blueprintjs/core';
|
|
|
|
import { IconNames } from '@blueprintjs/icons';
|
2019-06-08 01:27:19 -04:00
|
|
|
import classNames from 'classnames';
|
|
|
|
import React from 'react';
|
2019-04-07 23:19:08 -04:00
|
|
|
import { HashRouter, Route, Switch } from 'react-router-dom';
|
2019-03-17 12:23:17 -04:00
|
|
|
|
2019-11-15 22:45:14 -05:00
|
|
|
import { HeaderActiveTab, HeaderBar, Loader } from './components';
|
2019-01-31 20:26:41 -05:00
|
|
|
import { AppToaster } from './singletons/toaster';
|
2019-11-06 02:39:14 -05:00
|
|
|
import { QueryManager } from './utils';
|
2019-10-31 23:59:36 -04:00
|
|
|
import { Capabilities } from './utils/capabilities';
|
2019-06-17 16:14:42 -04:00
|
|
|
import {
|
|
|
|
DatasourcesView,
|
|
|
|
HomeView,
|
2019-11-20 09:53:40 -05:00
|
|
|
IngestionView,
|
2019-06-17 16:14:42 -04:00
|
|
|
LoadDataView,
|
|
|
|
LookupsView,
|
|
|
|
QueryView,
|
|
|
|
SegmentsView,
|
2019-11-06 02:39:14 -05:00
|
|
|
ServicesView,
|
2019-06-17 16:14:42 -04:00
|
|
|
} from './views';
|
2019-03-17 12:23:17 -04:00
|
|
|
|
2019-04-07 23:19:08 -04:00
|
|
|
import './console-application.scss';
|
2019-01-31 20:26:41 -05:00
|
|
|
|
2019-06-30 22:33:16 -04:00
|
|
|
export interface ConsoleApplicationProps {
|
2019-08-19 16:27:34 -04:00
|
|
|
exampleManifestsUrl?: string;
|
2019-01-31 20:26:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface ConsoleApplicationState {
|
2019-10-31 23:59:36 -04:00
|
|
|
capabilities: Capabilities;
|
2019-04-23 19:15:02 -04:00
|
|
|
capabilitiesLoading: boolean;
|
2019-01-31 20:26:41 -05:00
|
|
|
}
|
|
|
|
|
2019-06-21 19:52:33 -04:00
|
|
|
export class ConsoleApplication extends React.PureComponent<
|
|
|
|
ConsoleApplicationProps,
|
|
|
|
ConsoleApplicationState
|
|
|
|
> {
|
2019-07-09 20:31:23 -04:00
|
|
|
private capabilitiesQueryManager: QueryManager<null, Capabilities>;
|
2019-01-31 20:26:41 -05:00
|
|
|
|
2019-11-15 22:45:14 -05:00
|
|
|
static shownNotifications() {
|
2019-04-23 19:15:02 -04:00
|
|
|
AppToaster.show({
|
|
|
|
icon: IconNames.ERROR,
|
|
|
|
intent: Intent.DANGER,
|
|
|
|
timeout: 120000,
|
2019-11-15 22:45:14 -05:00
|
|
|
message: (
|
|
|
|
<>
|
|
|
|
It appears that the the service serving this console is not responding. The console will
|
|
|
|
not function at the moment
|
|
|
|
</>
|
|
|
|
),
|
2019-04-23 19:15:02 -04:00
|
|
|
});
|
2019-01-31 20:26:41 -05:00
|
|
|
}
|
|
|
|
|
2019-07-31 10:13:25 -04:00
|
|
|
private supervisorId?: string;
|
|
|
|
private taskId?: string;
|
2019-12-04 23:21:07 -05:00
|
|
|
private taskGroupId?: string;
|
2019-07-31 10:13:25 -04:00
|
|
|
private openDialog?: string;
|
|
|
|
private datasource?: string;
|
|
|
|
private onlyUnavailable?: boolean;
|
|
|
|
private initQuery?: string;
|
|
|
|
private middleManager?: string;
|
2019-01-31 20:26:41 -05:00
|
|
|
|
|
|
|
constructor(props: ConsoleApplicationProps, context: any) {
|
|
|
|
super(props, context);
|
|
|
|
this.state = {
|
2019-11-06 02:39:14 -05:00
|
|
|
capabilities: Capabilities.FULL,
|
2019-06-21 19:52:33 -04:00
|
|
|
capabilitiesLoading: true,
|
2019-01-31 20:26:41 -05:00
|
|
|
};
|
2019-04-05 15:40:43 -04:00
|
|
|
|
2019-04-23 19:15:02 -04:00
|
|
|
this.capabilitiesQueryManager = new QueryManager({
|
2019-06-30 22:33:16 -04:00
|
|
|
processQuery: async () => {
|
2019-11-06 02:39:14 -05:00
|
|
|
const capabilities = await Capabilities.detectCapabilities();
|
2019-11-15 22:45:14 -05:00
|
|
|
if (!capabilities) ConsoleApplication.shownNotifications();
|
2019-11-06 02:39:14 -05:00
|
|
|
return capabilities || Capabilities.FULL;
|
2019-04-23 19:15:02 -04:00
|
|
|
},
|
2019-06-30 22:33:16 -04:00
|
|
|
onStateChange: ({ result, loading }) => {
|
2019-04-23 19:15:02 -04:00
|
|
|
this.setState({
|
2019-11-06 02:39:14 -05:00
|
|
|
capabilities: result || Capabilities.FULL,
|
2019-06-21 19:52:33 -04:00
|
|
|
capabilitiesLoading: loading,
|
2019-04-23 19:15:02 -04:00
|
|
|
});
|
2019-06-21 19:52:33 -04:00
|
|
|
},
|
2019-04-23 19:15:02 -04:00
|
|
|
});
|
2019-01-31 20:26:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount(): void {
|
2019-07-09 20:31:23 -04:00
|
|
|
this.capabilitiesQueryManager.runQuery(null);
|
2019-04-23 19:15:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount(): void {
|
|
|
|
this.capabilitiesQueryManager.terminate();
|
2019-01-31 20:26:41 -05:00
|
|
|
}
|
|
|
|
|
2019-05-03 20:14:57 -04:00
|
|
|
private resetInitialsWithDelay() {
|
2019-01-31 20:26:41 -05:00
|
|
|
setTimeout(() => {
|
2019-06-30 22:33:16 -04:00
|
|
|
this.taskId = undefined;
|
2019-12-04 23:21:07 -05:00
|
|
|
this.taskGroupId = undefined;
|
2019-06-30 22:33:16 -04:00
|
|
|
this.supervisorId = undefined;
|
|
|
|
this.openDialog = undefined;
|
|
|
|
this.datasource = undefined;
|
|
|
|
this.onlyUnavailable = undefined;
|
|
|
|
this.initQuery = undefined;
|
|
|
|
this.middleManager = undefined;
|
2019-01-31 20:26:41 -05:00
|
|
|
}, 50);
|
|
|
|
}
|
|
|
|
|
2019-07-31 10:13:25 -04:00
|
|
|
private goToLoadData = (supervisorId?: string, taskId?: string) => {
|
2019-05-25 01:52:26 -04:00
|
|
|
if (taskId) this.taskId = taskId;
|
|
|
|
if (supervisorId) this.supervisorId = supervisorId;
|
2019-05-03 20:14:57 -04:00
|
|
|
window.location.hash = 'load-data';
|
|
|
|
this.resetInitialsWithDelay();
|
2019-06-21 19:52:33 -04:00
|
|
|
};
|
2019-05-03 20:14:57 -04:00
|
|
|
|
2019-07-31 10:13:25 -04:00
|
|
|
private goToDatasources = (datasource: string) => {
|
|
|
|
this.datasource = datasource;
|
|
|
|
window.location.hash = 'datasources';
|
2019-05-03 20:14:57 -04:00
|
|
|
this.resetInitialsWithDelay();
|
2019-06-21 19:52:33 -04:00
|
|
|
};
|
2019-01-31 20:26:41 -05:00
|
|
|
|
|
|
|
private goToSegments = (datasource: string, onlyUnavailable = false) => {
|
2019-07-31 10:13:25 -04:00
|
|
|
this.datasource = datasource;
|
2019-01-31 20:26:41 -05:00
|
|
|
this.onlyUnavailable = onlyUnavailable;
|
|
|
|
window.location.hash = 'segments';
|
2019-05-03 20:14:57 -04:00
|
|
|
this.resetInitialsWithDelay();
|
2019-06-21 19:52:33 -04:00
|
|
|
};
|
2019-01-31 20:26:41 -05:00
|
|
|
|
2019-12-04 23:21:07 -05:00
|
|
|
private goToIngestionWithTaskGroupId = (taskGroupId?: string, openDialog?: string) => {
|
|
|
|
this.taskGroupId = taskGroupId;
|
2019-07-31 10:13:25 -04:00
|
|
|
if (openDialog) this.openDialog = openDialog;
|
2019-11-20 09:53:40 -05:00
|
|
|
window.location.hash = 'ingestion';
|
2019-07-31 10:13:25 -04:00
|
|
|
this.resetInitialsWithDelay();
|
|
|
|
};
|
|
|
|
|
2019-11-20 09:53:40 -05:00
|
|
|
private goToIngestionWithDatasource = (datasource?: string, openDialog?: string) => {
|
2019-08-01 21:15:22 -04:00
|
|
|
this.datasource = datasource;
|
|
|
|
if (openDialog) this.openDialog = openDialog;
|
2019-11-20 09:53:40 -05:00
|
|
|
window.location.hash = 'ingestion';
|
2019-08-01 21:15:22 -04:00
|
|
|
this.resetInitialsWithDelay();
|
|
|
|
};
|
|
|
|
|
2019-01-31 20:26:41 -05:00
|
|
|
private goToMiddleManager = (middleManager: string) => {
|
|
|
|
this.middleManager = middleManager;
|
2019-11-06 02:39:14 -05:00
|
|
|
window.location.hash = 'services';
|
2019-05-03 20:14:57 -04:00
|
|
|
this.resetInitialsWithDelay();
|
2019-06-21 19:52:33 -04:00
|
|
|
};
|
2019-01-31 20:26:41 -05:00
|
|
|
|
2019-06-17 16:14:42 -04:00
|
|
|
private goToQuery = (initQuery: string) => {
|
|
|
|
this.initQuery = initQuery;
|
2019-05-03 20:14:57 -04:00
|
|
|
window.location.hash = 'query';
|
|
|
|
this.resetInitialsWithDelay();
|
2019-06-21 19:52:33 -04:00
|
|
|
};
|
2019-01-31 20:26:41 -05:00
|
|
|
|
2019-06-21 19:52:33 -04:00
|
|
|
private wrapInViewContainer = (
|
|
|
|
active: HeaderActiveTab,
|
|
|
|
el: JSX.Element,
|
|
|
|
classType: 'normal' | 'narrow-pad' = 'normal',
|
|
|
|
) => {
|
2019-10-31 23:59:36 -04:00
|
|
|
const { capabilities } = this.state;
|
2019-04-05 15:40:43 -04:00
|
|
|
|
2019-06-21 19:52:33 -04:00
|
|
|
return (
|
|
|
|
<>
|
2019-11-15 22:45:14 -05:00
|
|
|
<HeaderBar active={active} capabilities={capabilities} />
|
2019-06-21 19:52:33 -04:00
|
|
|
<div className={classNames('view-container', classType)}>{el}</div>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
2019-05-03 20:14:57 -04:00
|
|
|
|
|
|
|
private wrappedHomeView = () => {
|
2019-10-31 23:59:36 -04:00
|
|
|
const { capabilities } = this.state;
|
|
|
|
return this.wrapInViewContainer(null, <HomeView capabilities={capabilities} />);
|
2019-06-21 19:52:33 -04:00
|
|
|
};
|
2019-05-03 20:14:57 -04:00
|
|
|
|
|
|
|
private wrappedLoadDataView = () => {
|
2019-08-19 16:27:34 -04:00
|
|
|
const { exampleManifestsUrl } = this.props;
|
|
|
|
|
2019-06-21 19:52:33 -04:00
|
|
|
return this.wrapInViewContainer(
|
|
|
|
'load-data',
|
|
|
|
<LoadDataView
|
|
|
|
initSupervisorId={this.supervisorId}
|
|
|
|
initTaskId={this.taskId}
|
2019-08-19 16:27:34 -04:00
|
|
|
exampleManifestsUrl={exampleManifestsUrl}
|
2019-12-04 23:21:07 -05:00
|
|
|
goToIngestion={this.goToIngestionWithTaskGroupId}
|
2019-06-21 19:52:33 -04:00
|
|
|
/>,
|
|
|
|
'narrow-pad',
|
|
|
|
);
|
|
|
|
};
|
2019-05-03 20:14:57 -04:00
|
|
|
|
2019-06-17 16:14:42 -04:00
|
|
|
private wrappedQueryView = () => {
|
2019-06-21 19:52:33 -04:00
|
|
|
return this.wrapInViewContainer('query', <QueryView initQuery={this.initQuery} />);
|
|
|
|
};
|
2019-05-03 20:14:57 -04:00
|
|
|
|
|
|
|
private wrappedDatasourcesView = () => {
|
2019-10-31 23:59:36 -04:00
|
|
|
const { capabilities } = this.state;
|
2019-06-21 19:52:33 -04:00
|
|
|
return this.wrapInViewContainer(
|
|
|
|
'datasources',
|
|
|
|
<DatasourcesView
|
2019-07-31 10:13:25 -04:00
|
|
|
initDatasource={this.datasource}
|
2019-06-21 19:52:33 -04:00
|
|
|
goToQuery={this.goToQuery}
|
2019-11-20 09:53:40 -05:00
|
|
|
goToTask={this.goToIngestionWithDatasource}
|
2019-06-21 19:52:33 -04:00
|
|
|
goToSegments={this.goToSegments}
|
2019-10-31 23:59:36 -04:00
|
|
|
capabilities={capabilities}
|
2019-06-21 19:52:33 -04:00
|
|
|
/>,
|
|
|
|
);
|
|
|
|
};
|
2019-05-03 20:14:57 -04:00
|
|
|
|
|
|
|
private wrappedSegmentsView = () => {
|
2019-10-31 23:59:36 -04:00
|
|
|
const { capabilities } = this.state;
|
2019-06-21 19:52:33 -04:00
|
|
|
return this.wrapInViewContainer(
|
|
|
|
'segments',
|
|
|
|
<SegmentsView
|
|
|
|
datasource={this.datasource}
|
|
|
|
onlyUnavailable={this.onlyUnavailable}
|
|
|
|
goToQuery={this.goToQuery}
|
2019-10-31 23:59:36 -04:00
|
|
|
capabilities={capabilities}
|
2019-06-21 19:52:33 -04:00
|
|
|
/>,
|
|
|
|
);
|
|
|
|
};
|
2019-05-03 20:14:57 -04:00
|
|
|
|
2019-11-20 09:53:40 -05:00
|
|
|
private wrappedIngestionView = () => {
|
2019-10-31 23:59:36 -04:00
|
|
|
const { capabilities } = this.state;
|
2019-06-21 19:52:33 -04:00
|
|
|
return this.wrapInViewContainer(
|
2019-11-20 09:53:40 -05:00
|
|
|
'ingestion',
|
|
|
|
<IngestionView
|
2019-12-04 23:21:07 -05:00
|
|
|
taskGroupId={this.taskGroupId}
|
2019-08-01 21:15:22 -04:00
|
|
|
datasourceId={this.datasource}
|
2019-06-21 19:52:33 -04:00
|
|
|
openDialog={this.openDialog}
|
2019-07-31 10:13:25 -04:00
|
|
|
goToDatasource={this.goToDatasources}
|
2019-06-21 19:52:33 -04:00
|
|
|
goToQuery={this.goToQuery}
|
|
|
|
goToMiddleManager={this.goToMiddleManager}
|
2019-07-31 10:13:25 -04:00
|
|
|
goToLoadData={this.goToLoadData}
|
2019-10-31 23:59:36 -04:00
|
|
|
capabilities={capabilities}
|
2019-06-21 19:52:33 -04:00
|
|
|
/>,
|
|
|
|
);
|
|
|
|
};
|
2019-05-03 20:14:57 -04:00
|
|
|
|
2019-11-06 02:39:14 -05:00
|
|
|
private wrappedServicesView = () => {
|
2019-10-31 23:59:36 -04:00
|
|
|
const { capabilities } = this.state;
|
2019-06-21 19:52:33 -04:00
|
|
|
return this.wrapInViewContainer(
|
2019-11-06 02:39:14 -05:00
|
|
|
'services',
|
|
|
|
<ServicesView
|
2019-06-21 19:52:33 -04:00
|
|
|
middleManager={this.middleManager}
|
|
|
|
goToQuery={this.goToQuery}
|
2019-12-04 23:21:07 -05:00
|
|
|
goToTask={this.goToIngestionWithTaskGroupId}
|
2019-10-31 23:59:36 -04:00
|
|
|
capabilities={capabilities}
|
2019-06-21 19:52:33 -04:00
|
|
|
/>,
|
|
|
|
);
|
|
|
|
};
|
2019-05-03 20:14:57 -04:00
|
|
|
|
|
|
|
private wrappedLookupsView = () => {
|
2019-06-21 19:52:33 -04:00
|
|
|
return this.wrapInViewContainer('lookups', <LookupsView />);
|
|
|
|
};
|
2019-05-03 20:14:57 -04:00
|
|
|
|
2019-07-27 04:46:37 -04:00
|
|
|
render(): JSX.Element {
|
2019-05-03 20:14:57 -04:00
|
|
|
const { capabilitiesLoading } = this.state;
|
2019-01-31 20:26:41 -05:00
|
|
|
|
2019-04-23 19:15:02 -04:00
|
|
|
if (capabilitiesLoading) {
|
2019-06-21 19:52:33 -04:00
|
|
|
return (
|
|
|
|
<div className="loading-capabilities">
|
2019-10-31 23:59:36 -04:00
|
|
|
<Loader loadingText="" loading />
|
2019-06-21 19:52:33 -04:00
|
|
|
</div>
|
|
|
|
);
|
2019-04-23 19:15:02 -04:00
|
|
|
}
|
|
|
|
|
2019-06-21 19:52:33 -04:00
|
|
|
return (
|
|
|
|
<HashRouter hashType="noslash">
|
|
|
|
<div className="console-application">
|
|
|
|
<Switch>
|
|
|
|
<Route path="/load-data" component={this.wrappedLoadDataView} />
|
|
|
|
|
2019-11-20 09:53:40 -05:00
|
|
|
<Route path="/ingestion" component={this.wrappedIngestionView} />
|
2019-06-21 19:52:33 -04:00
|
|
|
<Route path="/datasources" component={this.wrappedDatasourcesView} />
|
|
|
|
<Route path="/segments" component={this.wrappedSegmentsView} />
|
2019-11-06 02:39:14 -05:00
|
|
|
<Route path="/services" component={this.wrappedServicesView} />
|
2019-06-21 19:52:33 -04:00
|
|
|
|
2019-10-31 23:59:36 -04:00
|
|
|
<Route path="/query" component={this.wrappedQueryView} />
|
|
|
|
|
2019-06-21 19:52:33 -04:00
|
|
|
<Route path="/lookups" component={this.wrappedLookupsView} />
|
|
|
|
<Route component={this.wrappedHomeView} />
|
|
|
|
</Switch>
|
|
|
|
</div>
|
|
|
|
</HashRouter>
|
|
|
|
);
|
2019-01-31 20:26:41 -05:00
|
|
|
}
|
|
|
|
}
|