You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lens.apache.org by am...@apache.org on 2016/09/17 05:30:49 UTC
lens git commit: LENS-1303 : Query lists on UI will use time filters
Repository: lens
Updated Branches:
refs/heads/master 7947acda7 -> b438aa2f2
LENS-1303 : Query lists on UI will use time filters
Project: http://git-wip-us.apache.org/repos/asf/lens/repo
Commit: http://git-wip-us.apache.org/repos/asf/lens/commit/b438aa2f
Tree: http://git-wip-us.apache.org/repos/asf/lens/tree/b438aa2f
Diff: http://git-wip-us.apache.org/repos/asf/lens/diff/b438aa2f
Branch: refs/heads/master
Commit: b438aa2f22992fc0e29f6ec10527959da0cefdf4
Parents: 7947acd
Author: Rajat Khandelwal <pr...@apache.org>
Authored: Sat Sep 17 10:57:37 2016 +0530
Committer: Amareshwari Sriramadasu <am...@apache.org>
Committed: Sat Sep 17 10:57:37 2016 +0530
----------------------------------------------------------------------
lens-ui/app/actions/AdhocQueryActions.js | 37 ++++-
lens-ui/app/adapters/AdhocQueryAdapter.js | 23 +++
lens-ui/app/components/CubeSchemaComponent.js | 2 +-
.../app/components/QueryOperationsComponent.js | 12 +-
lens-ui/app/components/QueryPreviewComponent.js | 4 +
lens-ui/app/components/QueryResultsComponent.js | 153 +++++++++++++------
lens-ui/app/constants/AdhocQueryConstants.js | 3 +
lens-ui/app/stores/AdhocQueryStore.js | 68 +++++----
8 files changed, 216 insertions(+), 86 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lens/blob/b438aa2f/lens-ui/app/actions/AdhocQueryActions.js
----------------------------------------------------------------------
diff --git a/lens-ui/app/actions/AdhocQueryActions.js b/lens-ui/app/actions/AdhocQueryActions.js
index 38f2794..421f7ea 100644
--- a/lens-ui/app/actions/AdhocQueryActions.js
+++ b/lens-ui/app/actions/AdhocQueryActions.js
@@ -288,7 +288,42 @@ let AdhocQueryActions = {
});
});
},
-
+ getQueryHandles (secretToken, email, options) {
+ AdhocQueryAdapter.getQueryHandles(secretToken, email, options)
+ .then(function (handles) {
+ AppDispatcher.dispatch({
+ actionType: AdhocQueryConstants.RECEIVE_QUERY_HANDLES,
+ payload: { handles: handles }
+ });
+ }, function (error) {
+ AppDispatcher.dispatch({
+ actionType: AdhocQueryConstants.RECEIVE_QUERY_HANDLES_FAILED,
+ payload: {
+ responseCode: error.status,
+ responseMessage: error.statusText
+ }
+ });
+ });
+ },
+ getQueriesDetails (secretToken, handles) {
+ if (handles && handles.length) {
+ AdhocQueryAdapter.getQueriesDetails(secretToken, handles)
+ .then(function (queries) {
+ AppDispatcher.dispatch({
+ actionType: AdhocQueryConstants.RECEIVE_QUERIES,
+ payload: {queries: queries}
+ });
+ }, function (error) {
+ AppDispatcher.dispatch({
+ actionType: AdhocQueryConstants.RECEIVE_QUERIES_FAILED,
+ payload: {
+ responseCode: error.status,
+ responseMessage: error.statusText
+ }
+ });
+ });
+ }
+ },
getQuery (secretToken, handle) {
AdhocQueryAdapter.getQuery(secretToken, handle)
.then(function (query) {
http://git-wip-us.apache.org/repos/asf/lens/blob/b438aa2f/lens-ui/app/adapters/AdhocQueryAdapter.js
----------------------------------------------------------------------
diff --git a/lens-ui/app/adapters/AdhocQueryAdapter.js b/lens-ui/app/adapters/AdhocQueryAdapter.js
index a54274f..9e3cc45 100644
--- a/lens-ui/app/adapters/AdhocQueryAdapter.js
+++ b/lens-ui/app/adapters/AdhocQueryAdapter.js
@@ -150,6 +150,29 @@ let AdhocQueryAdapter = {
}));
});
},
+ getQueryHandles (secretToken, email, options) {
+ let queryOptions = {};
+ queryOptions.sessionid = secretToken;
+ queryOptions.user = email;
+ var state;
+ if (options && options.state) {
+ state = options.state.toUpperCase();
+ }
+ let handlesUrl = baseUrl + urls.query + '?sessionid=' + secretToken + '&user=' +
+ email;
+ if (state) handlesUrl += '&state=' + state;
+ if (options.fromDate) handlesUrl += "&fromDate="+options.fromDate;
+ if (options.toDate) handlesUrl += "&toDate="+options.toDate;
+ return BaseAdapter.get(handlesUrl);
+ },
+ getQueriesDetails (secretToken, handles) {
+ let url = baseUrl + urls.query + '?sessionid=' + secretToken;
+ return Promise.all(handles.map((handle) => {
+ let queryUrl = baseUrl + urls.query + '/' + handle +
+ '?sessionid=' + secretToken + '&queryHandle=' + handle;
+ return BaseAdapter.get(queryUrl);
+ }));
+ },
getQueryResult (secretToken, handle, queryMode) {
// on page refresh, the store won't have queryMode so fetch query
http://git-wip-us.apache.org/repos/asf/lens/blob/b438aa2f/lens-ui/app/components/CubeSchemaComponent.js
----------------------------------------------------------------------
diff --git a/lens-ui/app/components/CubeSchemaComponent.js b/lens-ui/app/components/CubeSchemaComponent.js
index 9c23b9f..6a2b7af 100644
--- a/lens-ui/app/components/CubeSchemaComponent.js
+++ b/lens-ui/app/components/CubeSchemaComponent.js
@@ -182,7 +182,7 @@ function constructExpressionTable(cubeName, expressions) {
return (
<div className='table-responsive'>
<table className='table table-striped'>
- <caption className='bg-primary text-center'>Join Chains</caption>
+ <caption className='bg-primary text-center'>Expressions</caption>
<thead>{header}</thead>
<tbody>{table}</tbody>
</table>
http://git-wip-us.apache.org/repos/asf/lens/blob/b438aa2f/lens-ui/app/components/QueryOperationsComponent.js
----------------------------------------------------------------------
diff --git a/lens-ui/app/components/QueryOperationsComponent.js b/lens-ui/app/components/QueryOperationsComponent.js
index e4cc1e7..fc43e9d 100644
--- a/lens-ui/app/components/QueryOperationsComponent.js
+++ b/lens-ui/app/components/QueryOperationsComponent.js
@@ -56,24 +56,24 @@ class QueryOperations extends React.Component {
<div className={panelBodyClassName}>
<ul style={{listStyle: 'none', paddingLeft: '0px',
marginBottom: '0px'}}>
- <li><Link to='results'>All</Link></li>
+ <li><Link to='results' query={{fromDate: 'now.day-2days'}}>All</Link></li>
<li>
- <Link to='results' query={{category: 'running'}}>
+ <Link to='results' query={{state: 'running'}}>
Running
</Link>
</li>
<li>
- <Link to='results' query={{category: 'successful'}}>
- Completed
+ <Link to='results' query={{state: 'successful', fromDate: 'now.day-2days'}}>
+ Successful
</Link>
</li>
<li>
- <Link to='results' query={{category: 'queued'}}>
+ <Link to='results' query={{state: 'queued'}}>
Queued
</Link>
</li>
<li>
- <Link to='results' query={{category: 'failed'}}>
+ <Link to='results' query={{state: 'failed', fromDate: 'now.day-2days'}}>
Failed
</Link>
</li>
http://git-wip-us.apache.org/repos/asf/lens/blob/b438aa2f/lens-ui/app/components/QueryPreviewComponent.js
----------------------------------------------------------------------
diff --git a/lens-ui/app/components/QueryPreviewComponent.js b/lens-ui/app/components/QueryPreviewComponent.js
index a29f2d8..3681399 100644
--- a/lens-ui/app/components/QueryPreviewComponent.js
+++ b/lens-ui/app/components/QueryPreviewComponent.js
@@ -108,6 +108,10 @@ class QueryPreview extends React.Component {
paddingBottom: '0px'}} key={'preview' + handle}>
<div className='row'>
<div className='col-lg-4 col-sm-4'>
+ <span className='text-muted'>Handle </span>
+ <strong>{ query.queryHandle.handleId || 'Unknown'}</strong>
+ </div>
+ <div className='col-lg-4 col-sm-4'>
<span className='text-muted'>Name </span>
<strong>{ query.queryName || 'Not specified'}</strong>
</div>
http://git-wip-us.apache.org/repos/asf/lens/blob/b438aa2f/lens-ui/app/components/QueryResultsComponent.js
----------------------------------------------------------------------
diff --git a/lens-ui/app/components/QueryResultsComponent.js b/lens-ui/app/components/QueryResultsComponent.js
index 01f0e30..eed200b 100644
--- a/lens-ui/app/components/QueryResultsComponent.js
+++ b/lens-ui/app/components/QueryResultsComponent.js
@@ -1,21 +1,21 @@
/**
-* 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.
-*/
+ * 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 React from 'react';
@@ -25,58 +25,68 @@ import UserStore from '../stores/UserStore';
import AdhocQueryActions from '../actions/AdhocQueryActions';
import QueryPreview from './QueryPreviewComponent';
-// this method fetches the results based on props.query.category
-function getResults (props) {
- let email = UserStore.getUserDetails().email;
- let secretToken = UserStore.getUserDetails().secretToken;
-
- if (props.query.category) {
- // fetch either running or completed results
- AdhocQueryActions
- .getQueries(secretToken, email, { state: props.query.category });
- } else {
- // fetch all
- AdhocQueryActions.getQueries(secretToken, email);
- }
+// this method fetches the results based on props.query.state
+function getResults(query) {
+ AdhocQueryActions
+ .getQueryHandles(UserStore.getUserDetails().secretToken, UserStore.getUserDetails().email, query);
}
-function getQueries () {
- return AdhocQueryStore.getQueries();
+function getQueryHandles() {
+ return AdhocQueryStore.getQueryHandles();
}
class QueryResults extends React.Component {
- constructor (props) {
+ constructor(props) {
super(props);
- this.state = { queries: {}, queriesReceived: false };
+ this.state = {queries: {}, queriesReceived: false};
this._onChange = this._onChange.bind(this);
-
- getResults(props);
+ this.adjustRange = this.adjustRange.bind(this);
+ getResults(props.query);
}
- componentDidMount () {
+ componentDidMount() {
AdhocQueryStore.addChangeListener(this._onChange);
}
- componentWillUnmount () {
+ componentWillUnmount() {
AdhocQueryStore.removeChangeListener(this._onChange);
}
- componentWillReceiveProps (props) {
- getResults(props);
+ componentWillReceiveProps(props) {
+ getResults(props.query);
this.setState({queries: {}, queriesReceived: false});
}
+ fetchDetailsAndSetTimeout(handles) {
+ AdhocQueryActions.getQueriesDetails(UserStore.getUserDetails().secretToken, handles);
+ }
+ adjustRange(event) {
+ event.preventDefault();
+ let query = JSON.parse(JSON.stringify(this.props.query));
+ if (this.refs.fromDate.getDOMNode().value) {
+ query.fromDate = this.refs.fromDate.getDOMNode().value;
+ } else {
+ delete query['fromDate'];
+ }
+ if (this.refs.toDate.getDOMNode().value) {
+ query.toDate = this.refs.toDate.getDOMNode().value;
+ } else {
+ delete query['toDate'];
+ }
+ var { router } = this.context;
+ router.transitionTo('results', {}, query);
+ }
- render () {
+ render() {
let queries = '';
let queryMap = this.state.queries;
+ let queriesToRefresh = []
queries = Object.keys(queryMap)
- .sort(function (a, b) {
- return queryMap[b].submissionTime - queryMap[a].submissionTime;
- })
.map((queryHandle) => {
let query = queryMap[queryHandle];
-
+ if (query.status.status == "RUNNING" || query.status.status == "QUEUED") {
+ queriesToRefresh.push(query.queryHandle.handleId);
+ }
return (
<QueryPreview key={query.queryHandle.handleId} {...query} />
);
@@ -91,18 +101,28 @@ class QueryResults extends React.Component {
let queriesLength = Object.keys(this.state.queries).length;
if (!queriesLength && !this.state.queriesReceived) {
- queries = <Loader size='8px' margin='2px' />;
+ queries = <Loader size='8px' margin='2px'/>;
} else if (!queriesLength && this.state.queriesReceived) {
queries = <div className='alert alert-danger'>
<strong>Sorry</strong>, there were no queries to be shown.
</div>;
}
-
+ if (queriesToRefresh && queriesToRefresh.length) {
+ // refresh in 5 seconds
+ setTimeout(this.fetchDetailsAndSetTimeout, 5000, queriesToRefresh);
+ }
return (
<section>
<div style={{border: '1px solid #dddddd', borderRadius: '4px',
padding: '0px 8px 8px 8px'}}>
<h3 style={{margin: '8px 10px'}}>Results</h3>
+ <form className='form-range' onSubmit={this.adjustRange}>
+ <input ref='fromDate' required={false} defaultValue={this.props.query.fromDate} id='fromDate'
+ placeholder='now-30years' autoFocus/>
+ <input ref='toDate' required={false} defaultValue={this.props.query.toDate} id='toDate' placeholder='now'
+ autoFocus/>
+ <button className='btn btn-primary' type='submit'>Fetch</button>
+ </form>
<hr style={{marginTop: '6px'}}/>
<div>
{queries}
@@ -112,9 +132,44 @@ class QueryResults extends React.Component {
);
}
- _onChange () {
- this.setState({queries: getQueries(), queriesReceived: true});
+ _onChange() {
+ let handles = getQueryHandles();
+ let queries = handles.map((handle) => (
+ AdhocQueryStore.getQueryDetails(handle) || {
+ "queryHandle": {
+ "handleId": handle
+ },
+ "userQuery": handle,
+ //"submittedUser": undefined,
+ //"priority": "VERY_LOW",
+ //"isPersistent": true,
+ //"selectedDriverName": "hive/prod",
+ //"driverQuery": "cube select ...",
+ "status": {
+ "progress": -1.0,
+ "status": "UNKNOWN"
+ //"isResultSetAvailable": false,
+ //"errorMessage": "Query execution failed!"
+ },
+ //"queryConf": {},
+ //"submissionTime": 1468403280197,
+ //"launchTime": 1468403284328,
+ //"driverStartTime": 1468403280581,
+ //"driverFinishTime": 1468403350769,
+ //"finishTime": 1468403373582,
+ //"closedTime": 0,
+ "queryName": "Loading..."
+ }
+ ));
+ this.setState({queries: queries, queriesReceived: true});
+ AdhocQueryActions.getQueriesDetails(UserStore.getUserDetails().secretToken,
+ handles.filter(handle=>(!(AdhocQueryStore.getQueryDetails(handle)))));
}
}
+QueryResults.contextTypes = {
+ router: React.PropTypes.func
+};
+
+
export default QueryResults;
http://git-wip-us.apache.org/repos/asf/lens/blob/b438aa2f/lens-ui/app/constants/AdhocQueryConstants.js
----------------------------------------------------------------------
diff --git a/lens-ui/app/constants/AdhocQueryConstants.js b/lens-ui/app/constants/AdhocQueryConstants.js
index 7eceb6f..2ba42d3 100644
--- a/lens-ui/app/constants/AdhocQueryConstants.js
+++ b/lens-ui/app/constants/AdhocQueryConstants.js
@@ -32,6 +32,9 @@ const AdhocQueryConstants = KeyMirror({
RECEIVE_QUERIES: null,
RECEIVE_QUERIES_FAILED: null,
+ RECEIVE_QUERY_HANDLES: null,
+ RECEIVE_QUERY_HANDLES_FAILED: null,
+
RECEIVE_QUERY_RESULT: null,
RECEIVE_QUERY_RESULT_FAILED: null,
http://git-wip-us.apache.org/repos/asf/lens/blob/b438aa2f/lens-ui/app/stores/AdhocQueryStore.js
----------------------------------------------------------------------
diff --git a/lens-ui/app/stores/AdhocQueryStore.js b/lens-ui/app/stores/AdhocQueryStore.js
index d8891c2..99aa2f1 100644
--- a/lens-ui/app/stores/AdhocQueryStore.js
+++ b/lens-ui/app/stores/AdhocQueryStore.js
@@ -1,21 +1,21 @@
/**
-* 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.
-*/
+ * 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 assign from 'object-assign';
import { EventEmitter } from 'events';
@@ -33,7 +33,7 @@ var adhocDetails = {
dbName: Config.dbName
};
-function receiveQueryHandle (payload) {
+function receiveQueryHandle(payload) {
if (typeof payload.queryHandle === 'string') {
adhocDetails.queryHandle = payload.queryHandle;
return;
@@ -44,23 +44,22 @@ function receiveQueryHandle (payload) {
adhocDetails.queryHandle = id;
}
-function receiveQueries (payload) {
- let queries = payload.queries;
- let queryObjects = {};
-
- queries.forEach((query) => {
- queryObjects[query.lensQuery.queryHandle.handleId] = query.lensQuery;
+function receiveQueries(payload) {
+ adhocDetails.queries = adhocDetails.queries || {};
+ payload.queries.forEach((query) => {
+ adhocDetails.queries[query.lensQuery.queryHandle.handleId] = query.lensQuery;
});
-
- adhocDetails.queries = queryObjects;
+}
+function receiveQueryHandles(payload) {
+ adhocDetails.handles = payload.handles.map(handle=>handle.queryHandle.handleId);
}
-function receiveQuery (payload) {
+function receiveQuery(payload) {
let query = payload.query;
adhocDetails.queries[query.queryHandle.handleId] = query;
}
-function receiveQueryResult (payload) {
+function receiveQueryResult(payload) {
let queryResult = {};
queryResult.type = payload && payload.type;
@@ -83,7 +82,12 @@ let AdhocQueryStore = assign({}, EventEmitter.prototype, {
getQueries () {
return adhocDetails.queries;
},
-
+ getQueryHandles () {
+ return adhocDetails.handles;
+ },
+ getQueryDetails (handle) {
+ return adhocDetails.queries[handle];
+ },
getQueryResult (handle) {
return adhocDetails.queryResults[handle];
},
@@ -121,6 +125,11 @@ AppDispatcher.register((action) => {
AdhocQueryStore.emitChange();
break;
+ case AdhocQueryConstants.RECEIVE_QUERY_HANDLES:
+ receiveQueryHandles(action.payload);
+ AdhocQueryStore.emitChange();
+ break;
+
case AdhocQueryConstants.RECEIVE_QUERY_RESULT:
receiveQueryResult(action.payload);
AdhocQueryStore.emitChange();
@@ -132,6 +141,7 @@ AppDispatcher.register((action) => {
break;
case AdhocQueryConstants.RECEIVE_QUERY_HANDLE_FAILED:
+ case AdhocQueryConstants.RECEIVE_QUERY_HANDLES_FAILED:
AdhocQueryStore.emitChange(action.payload);
break;
}