mirror of
https://github.com/apache/superset.git
synced 2024-09-17 11:09:47 -04:00
Moved dataPreviewId to table object
This commit is contained in:
parent
902d26bba8
commit
56f5b736dd
@ -32,8 +32,7 @@ export const REQUEST_QUERY_RESULTS = 'REQUEST_QUERY_RESULTS';
|
||||
export const QUERY_SUCCESS = 'QUERY_SUCCESS';
|
||||
export const QUERY_FAILED = 'QUERY_FAILED';
|
||||
export const CLEAR_QUERY_RESULTS = 'CLEAR_QUERY_RESULTS';
|
||||
export const HIDE_DATA_PREVIEW = 'HIDE_DATA_PREVIEW';
|
||||
export const CLOSE_DATA_PREVIEW = 'CLOSE_DATA_PREVIEW';
|
||||
export const REMOVE_DATA_PREVIEW = 'REMOVE_DATA_PREVIEW';
|
||||
|
||||
export function resetState() {
|
||||
return { type: RESET_STATE };
|
||||
@ -66,12 +65,8 @@ export function clearQueryResults(query) {
|
||||
return { type: CLEAR_QUERY_RESULTS, query };
|
||||
}
|
||||
|
||||
export function hideDataPreview() {
|
||||
return { type: HIDE_DATA_PREVIEW };
|
||||
}
|
||||
|
||||
export function closeDataPreview(dataPreviewQueryId) {
|
||||
return { type: CLOSE_DATA_PREVIEW, dataPreviewQueryId };
|
||||
export function removeDataPreview(table) {
|
||||
return { type: REMOVE_DATA_PREVIEW, table };
|
||||
}
|
||||
|
||||
export function requestQueryResults(query) {
|
||||
@ -209,21 +204,33 @@ export function queryEditorSetSelectedText(queryEditor, sql) {
|
||||
return { type: QUERY_EDITOR_SET_SELECTED_TEXT, queryEditor, sql };
|
||||
}
|
||||
|
||||
export function mergeTable(table) {
|
||||
return { type: MERGE_TABLE, table };
|
||||
export function mergeTable(table, query) {
|
||||
return { type: MERGE_TABLE, table, query };
|
||||
}
|
||||
|
||||
export function addTable(query, tableName) {
|
||||
return function (dispatch) {
|
||||
let url = `/caravel/table/${query.dbId}/${tableName}/${query.schema}/`;
|
||||
$.get(url, (data) => {
|
||||
dispatch(
|
||||
mergeTable(Object.assign(data, {
|
||||
const dataPreviewQuery = {
|
||||
dbId: query.dbId,
|
||||
sql: data.selectStar,
|
||||
tableName,
|
||||
sqlEditorId: null,
|
||||
tab: '',
|
||||
runAsync: false,
|
||||
ctas: false,
|
||||
};
|
||||
// Run query to get preview data for table
|
||||
dispatch(runQuery(dataPreviewQuery));
|
||||
// Merge table to tables in state
|
||||
dispatch(mergeTable(
|
||||
Object.assign(data, {
|
||||
dbId: query.dbId,
|
||||
queryEditorId: query.id,
|
||||
schema: query.schema,
|
||||
expanded: true,
|
||||
}))
|
||||
}), dataPreviewQuery)
|
||||
);
|
||||
})
|
||||
.fail(() => {
|
||||
|
@ -0,0 +1,58 @@
|
||||
import * as Actions from '../actions';
|
||||
import React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { Modal } from 'react-bootstrap';
|
||||
|
||||
import ResultSet from './ResultSet';
|
||||
|
||||
const propTypes = {
|
||||
queries: React.PropTypes.object,
|
||||
actions: React.PropTypes.object,
|
||||
showDataPreviewModal: React.PropTypes.bool,
|
||||
dataPreviewQueryId: React.PropTypes.string,
|
||||
};
|
||||
|
||||
class DataPreviewModal extends React.PureComponent {
|
||||
hide() {
|
||||
this.props.actions.hideDataPreview();
|
||||
}
|
||||
render() {
|
||||
if (this.props.showDataPreviewModal && this.props.dataPreviewQueryId) {
|
||||
const query = this.props.queries[this.props.dataPreviewQueryId];
|
||||
return (
|
||||
<Modal
|
||||
show={this.props.showDataPreviewModal}
|
||||
onHide={this.hide.bind(this)}
|
||||
bsStyle="lg"
|
||||
>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>
|
||||
Data preview for <strong>{query.tableName}</strong>
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<ResultSet query={query} visualize={false} csv={false} actions={this.props.actions} />
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
DataPreviewModal.propTypes = propTypes;
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
queries: state.queries,
|
||||
showDataPreviewModal: state.showDataPreviewModal,
|
||||
dataPreviewQueryId: state.dataPreviewQueryId,
|
||||
};
|
||||
}
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(Actions, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(DataPreviewModal);
|
@ -5,33 +5,34 @@ import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as Actions from '../actions';
|
||||
import React from 'react';
|
||||
import { areArraysShallowEqual } from '../../reduxUtils';
|
||||
|
||||
import shortid from 'shortid';
|
||||
|
||||
// editorQueries are queries executed by users
|
||||
// passed from SqlEditor component
|
||||
// queries are all queries executed
|
||||
// passed from global state for the purpose of data preview tabs
|
||||
/*
|
||||
editorQueries are queries executed by users passed from SqlEditor component
|
||||
dataPrebiewQueries are all queries executed for preview of table data (from SqlEditorLeft)
|
||||
*/
|
||||
const propTypes = {
|
||||
editorQueries: React.PropTypes.array.isRequired,
|
||||
queries: React.PropTypes.object.isRequired,
|
||||
dataPreviewQueries: React.PropTypes.array.isRequired,
|
||||
actions: React.PropTypes.object.isRequired,
|
||||
dataPreviewQueryIds: React.PropTypes.array,
|
||||
activeSouthPaneTab: React.PropTypes.string,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
dataPreviewQueryIds: [],
|
||||
activeSouthPaneTab: 'Results',
|
||||
};
|
||||
|
||||
class SouthPane extends React.PureComponent {
|
||||
closeDataPreviewTab(id) {
|
||||
this.props.actions.closeDataPreview(id);
|
||||
}
|
||||
switchTab(id) {
|
||||
this.props.actions.setActiveSouthPaneTab(id);
|
||||
}
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return !areArraysShallowEqual(this.props.editorQueries, nextProps.editorQueries)
|
||||
|| !areArraysShallowEqual(this.props.dataPreviewQueries, nextProps.dataPreviewQueries)
|
||||
|| this.props.activeSouthPaneTab !== nextProps.activeSouthPaneTab;
|
||||
}
|
||||
render() {
|
||||
let latestQuery;
|
||||
const props = this.props;
|
||||
@ -47,24 +48,15 @@ class SouthPane extends React.PureComponent {
|
||||
results = <Alert bsStyle="info">Run a query to display results here</Alert>;
|
||||
}
|
||||
|
||||
const dataPreviewTabs = props.dataPreviewQueryIds.map((id) => {
|
||||
const query = props.queries[id];
|
||||
const tabTitle = (
|
||||
<div>
|
||||
{query.tableName}
|
||||
<i className="fa fa-close" onClick={this.closeDataPreviewTab.bind(this, id)} />
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
const dataPreviewTabs = props.dataPreviewQueries.map((query) => (
|
||||
<Tab
|
||||
title={tabTitle}
|
||||
eventKey={id}
|
||||
key={id}
|
||||
title={query.tableName}
|
||||
eventKey={query.id}
|
||||
key={query.id}
|
||||
>
|
||||
<ResultSet query={query} visualize={false} csv={false} actions={props.actions} />
|
||||
</Tab>
|
||||
);
|
||||
});
|
||||
));
|
||||
|
||||
return (
|
||||
<div className="SouthPane">
|
||||
@ -97,9 +89,7 @@ class SouthPane extends React.PureComponent {
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
dataPreviewQueryIds: state.dataPreviewQueryIds,
|
||||
activeSouthPaneTab: state.activeSouthPaneTab,
|
||||
queries: state.queries,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,8 @@ const propTypes = {
|
||||
latestQuery: React.PropTypes.object,
|
||||
networkOn: React.PropTypes.bool,
|
||||
tables: React.PropTypes.array.isRequired,
|
||||
queries: React.PropTypes.array.isRequired,
|
||||
editorQueries: React.PropTypes.array.isRequired,
|
||||
dataPreviewQueries: React.PropTypes.array.isRequired,
|
||||
queryEditor: React.PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
@ -225,7 +226,8 @@ class SqlEditor extends React.PureComponent {
|
||||
{editorBottomBar}
|
||||
<br />
|
||||
<SouthPane
|
||||
editorQueries={this.props.queries}
|
||||
editorQueries={this.props.editorQueries}
|
||||
dataPreviewQueries={this.props.dataPreviewQueries}
|
||||
actions={this.props.actions}
|
||||
/>
|
||||
</Col>
|
||||
|
@ -118,6 +118,15 @@ class TabbedSqlEditors extends React.PureComponent {
|
||||
database = this.props.databases[qe.dbId];
|
||||
}
|
||||
const state = (latestQuery) ? latestQuery.state : '';
|
||||
|
||||
const dataPreviewQueries = [];
|
||||
this.props.tables.forEach((table) => {
|
||||
const queryId = table.dataPreviewQueryId;
|
||||
if (queryId) {
|
||||
dataPreviewQueries.push(this.props.queries[queryId]);
|
||||
}
|
||||
});
|
||||
|
||||
const tabTitle = (
|
||||
<div>
|
||||
<div className={'circle ' + state} /> {qe.title} {' '}
|
||||
@ -152,7 +161,8 @@ class TabbedSqlEditors extends React.PureComponent {
|
||||
<SqlEditor
|
||||
tables={this.props.tables.filter((t) => (t.queryEditorId === qe.id))}
|
||||
queryEditor={qe}
|
||||
queries={this.state.queriesArray}
|
||||
editorQueries={this.state.queriesArray}
|
||||
dataPreviewQueries={dataPreviewQueries}
|
||||
latestQuery={latestQuery}
|
||||
database={database}
|
||||
actions={this.props.actions}
|
||||
|
@ -51,18 +51,7 @@ class TableElement extends React.PureComponent {
|
||||
|
||||
removeTable() {
|
||||
this.setState({ expanded: false });
|
||||
}
|
||||
dataPreviewModal() {
|
||||
const query = {
|
||||
dbId: this.props.table.dbId,
|
||||
sql: this.props.table.selectStar,
|
||||
tableName: this.props.table.name,
|
||||
sqlEditorId: null,
|
||||
tab: '',
|
||||
runAsync: false,
|
||||
ctas: false,
|
||||
};
|
||||
this.props.actions.runQuery(query);
|
||||
this.props.actions.removeDataPreview(this.props.table);
|
||||
}
|
||||
toggleSortColumns() {
|
||||
this.setState({ sortColumns: !this.state.sortColumns });
|
||||
@ -192,12 +181,6 @@ class TableElement extends React.PureComponent {
|
||||
'Original table column order'}
|
||||
href="#"
|
||||
/>
|
||||
<Link
|
||||
className="fa fa-search-plus pull-left m-l-2"
|
||||
onClick={this.dataPreviewModal.bind(this)}
|
||||
tooltip="Data preview"
|
||||
href="#"
|
||||
/>
|
||||
{table.selectStar &&
|
||||
<CopyToClipboard
|
||||
copyNode={
|
||||
@ -211,7 +194,7 @@ class TableElement extends React.PureComponent {
|
||||
<Link
|
||||
className="fa fa-trash table-remove pull-left m-l-2"
|
||||
onClick={this.removeTable.bind(this)}
|
||||
tooltip="Remove from panel"
|
||||
tooltip="Remove table preview"
|
||||
href="#"
|
||||
/>
|
||||
</ButtonGroup>
|
||||
|
@ -23,7 +23,6 @@ export const initialState = {
|
||||
tabHistory: [defaultQueryEditor.id],
|
||||
tables: [],
|
||||
queriesLastUpdate: 0,
|
||||
dataPreviewQueryIds: [],
|
||||
activeSouthPaneTab: 'Results',
|
||||
};
|
||||
|
||||
@ -86,29 +85,29 @@ export const sqlLabReducer = function (state, action) {
|
||||
}
|
||||
});
|
||||
if (existingTable) {
|
||||
if (action.query) {
|
||||
at.dataPreviewQueryId = action.query.id;
|
||||
}
|
||||
return alterInArr(state, 'tables', existingTable, at);
|
||||
}
|
||||
at.id = shortid.generate();
|
||||
return addToArr(state, 'tables', at);
|
||||
// for new table, associate Id of query for data preview
|
||||
at.dataPreviewQueryId = null;
|
||||
let newState = addToArr(state, 'tables', at);
|
||||
if (action.query) {
|
||||
newState = alterInArr(newState, 'tables', at, { dataPreviewQueryId: action.query.id });
|
||||
}
|
||||
return newState;
|
||||
},
|
||||
[actions.EXPAND_TABLE]() {
|
||||
return alterInArr(state, 'tables', action.table, { expanded: true });
|
||||
},
|
||||
[actions.CLOSE_DATA_PREVIEW]() {
|
||||
[actions.REMOVE_DATA_PREVIEW]() {
|
||||
const queries = Object.assign({}, state.queries);
|
||||
const newDataPreviewQueryIds = [];
|
||||
delete queries[action.dataPreviewQueryId];
|
||||
state.dataPreviewQueryIds.forEach((id) => {
|
||||
if (action.dataPreviewQueryId !== id) {
|
||||
newDataPreviewQueryIds.push(id);
|
||||
}
|
||||
});
|
||||
delete queries[action.table.dataPreviewQueryId];
|
||||
const newState = alterInArr(state, 'tables', action.table, { dataPreviewQueryId: null });
|
||||
return Object.assign(
|
||||
{}, state, {
|
||||
queries,
|
||||
dataPreviewQueryIds: newDataPreviewQueryIds,
|
||||
activeSouthPaneTab: 'Results',
|
||||
});
|
||||
{}, newState, { queries });
|
||||
},
|
||||
[actions.COLLAPSE_TABLE]() {
|
||||
return alterInArr(state, 'tables', action.table, { expanded: false });
|
||||
@ -126,9 +125,6 @@ export const sqlLabReducer = function (state, action) {
|
||||
newState = Object.assign({}, state, { queries });
|
||||
}
|
||||
} else {
|
||||
const newIds = state.dataPreviewQueryIds;
|
||||
newIds.push(action.query.id);
|
||||
newState.dataPreviewQueryIds = newIds;
|
||||
newState.activeSouthPaneTab = action.query.id;
|
||||
}
|
||||
newState = addToObject(newState, 'queries', action.query);
|
||||
|
@ -24,9 +24,9 @@ describe('TableElement', () => {
|
||||
React.isValidElement(<TableElement {...mockedProps} />)
|
||||
).to.equal(true);
|
||||
});
|
||||
it('has 3 Link elements', () => {
|
||||
it('has 2 Link elements', () => {
|
||||
const wrapper = shallow(<TableElement {...mockedProps} />);
|
||||
expect(wrapper.find(Link)).to.have.length(3);
|
||||
expect(wrapper.find(Link)).to.have.length(2);
|
||||
});
|
||||
it('has 14 columns', () => {
|
||||
const wrapper = shallow(<TableElement {...mockedProps} />);
|
||||
|
@ -11,6 +11,7 @@ export const table = {
|
||||
schema: 'caravel',
|
||||
name: 'ab_user',
|
||||
id: 'r11Vgt60',
|
||||
dataPreviewQueryId: null,
|
||||
partitions: {
|
||||
cols: ['username'],
|
||||
latest: 'bob',
|
||||
@ -255,8 +256,8 @@ export const initialState = {
|
||||
queryEditors: [defaultQueryEditor],
|
||||
tabHistory: [defaultQueryEditor.id],
|
||||
tables: [],
|
||||
workspaceQueries: [],
|
||||
queriesLastUpdate: 0,
|
||||
dataPreviewQueryIds: [],
|
||||
activeSouthPaneTab: 'Results',
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user