[sqllab] show partition metadata for Presto (#1342)

This commit is contained in:
Maxime Beauchemin
2016-10-19 09:17:08 -07:00
committed by GitHub
parent 2edce5bf8a
commit c255e89219
15 changed files with 390 additions and 87 deletions

View File

@@ -55,7 +55,7 @@ class SouthPane extends React.Component {
return (
<div className="SouthPane">
<Tabs bsStyle="tabs" id={shortid.generate()}>
<Tab title="Results" eventKey={1} id={shortid.generate()}>
<Tab title="Results" eventKey={1}>
<div style={{ overflow: 'auto' }}>
{results}
</div>

View File

@@ -28,7 +28,7 @@ import shortid from 'shortid';
import SouthPane from './SouthPane';
import Timer from './Timer';
import SqlEditorTopToolbar from './SqlEditorTopToolbar';
import SqlEditorLeftBar from './SqlEditorLeftBar';
class SqlEditor extends React.Component {
constructor(props) {
@@ -252,7 +252,7 @@ class SqlEditor extends React.Component {
<div className="SqlEditor" style={{ minHeight: this.sqlEditorHeight() }}>
<Row>
<Col md={3}>
<SqlEditorTopToolbar queryEditor={this.props.queryEditor} />
<SqlEditorLeftBar queryEditor={this.props.queryEditor} />
</Col>
<Col md={9}>
<AceEditor

View File

@@ -4,14 +4,13 @@ import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as Actions from '../actions';
import shortid from 'shortid';
import Select from 'react-select';
import { Label, Button } from 'react-bootstrap';
import TableElement from './TableElement';
import DatabaseSelect from './DatabaseSelect';
class SqlEditorTopToolbar extends React.Component {
class SqlEditorLeftBar extends React.Component {
constructor(props) {
super(props);
this.state = {
@@ -79,12 +78,11 @@ class SqlEditorTopToolbar extends React.Component {
changeTable(tableOpt) {
const tableName = tableOpt.value;
const qe = this.props.queryEditor;
const url = `/caravel/table/${qe.dbId}/${tableName}/${qe.schema}/`;
let url = `/caravel/table/${qe.dbId}/${tableName}/${qe.schema}/`;
this.setState({ tableLoading: true });
$.get(url, (data) => {
this.props.actions.addTable({
id: shortid.generate(),
this.props.actions.mergeTable({
dbId: this.props.queryEditor.dbId,
queryEditorId: this.props.queryEditor.id,
name: data.name,
@@ -102,6 +100,18 @@ class SqlEditorTopToolbar extends React.Component {
});
this.setState({ tableLoading: false });
});
url = `/caravel/extra_table_metadata/${qe.dbId}/${tableName}/${qe.schema}/`;
$.get(url, (data) => {
const table = {
dbId: this.props.queryEditor.dbId,
queryEditorId: this.props.queryEditor.id,
schema: qe.schema,
name: tableName,
};
Object.assign(table, data);
this.props.actions.mergeTable(table);
});
}
render() {
let networkAlert = null;
@@ -158,14 +168,14 @@ class SqlEditorTopToolbar extends React.Component {
}
}
SqlEditorTopToolbar.propTypes = {
SqlEditorLeftBar.propTypes = {
queryEditor: React.PropTypes.object,
tables: React.PropTypes.array,
actions: React.PropTypes.object,
networkOn: React.PropTypes.bool,
};
SqlEditorTopToolbar.defaultProps = {
SqlEditorLeftBar.defaultProps = {
tables: [],
};
@@ -182,4 +192,4 @@ function mapDispatchToProps(dispatch) {
};
}
export default connect(mapStateToProps, mapDispatchToProps)(SqlEditorTopToolbar);
export default connect(mapStateToProps, mapDispatchToProps)(SqlEditorLeftBar);

View File

@@ -116,7 +116,6 @@ class TabbedSqlEditors extends React.Component {
key={qe.id}
title={tabTitle}
eventKey={qe.id}
id={`a11y-query-editor-${qe.id}`}
>
<div className="panel panel-default">
<div className="panel-body">

View File

@@ -1,11 +1,23 @@
import React from 'react';
import { ButtonGroup } from 'react-bootstrap';
import { ButtonGroup, Well } from 'react-bootstrap';
import Link from './Link';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as Actions from '../actions';
import shortid from 'shortid';
import ModalTrigger from '../../components/ModalTrigger.jsx';
import ModalTrigger from '../../components/ModalTrigger';
import CopyToClipboard from '../../components/CopyToClipboard';
const propTypes = {
table: React.PropTypes.object,
queryEditor: React.PropTypes.object,
actions: React.PropTypes.object,
};
const defaultProps = {
table: null,
actions: {},
};
class TableElement extends React.Component {
setSelectStar() {
@@ -40,40 +52,85 @@ class TableElement extends React.Component {
collapseTable(e) {
e.preventDefault();
this.props.actions.collapseTable.bind(this, this.props.table)();
this.props.actions.collapseTable(this.props.table);
}
expandTable(e) {
e.preventDefault();
this.props.actions.expandTable.bind(this, this.props.table)();
this.props.actions.expandTable(this.props.table);
}
removeTable() {
this.props.actions.removeTable(this.props.table);
}
render() {
const table = this.props.table;
let metadata = null;
let buttonToggle;
if (this.props.table.expanded) {
let header;
if (table.partitions) {
let partitionQuery;
let partitionClipBoard;
if (table.partitions.partitionQuery) {
partitionQuery = table.partitions.partitionQuery;
const tt = 'Copy partition query to clipboard';
partitionClipBoard = (
<CopyToClipboard
text={partitionQuery}
shouldShowText={false}
tooltipText={tt}
copyNode={<i className="fa fa-clipboard" />}
/>
);
}
let latest = [];
for (const k in table.partitions.latest) {
latest.push(`${k}=${table.partitions.latest[k]}`);
}
latest = latest.join('/');
header = (
<Well bsSize="small">
<div>
<small>
latest partition: {latest}
</small> {partitionClipBoard}
</div>
</Well>
);
}
if (table.expanded) {
buttonToggle = (
<a
href="#"
onClick={(e) => { this.collapseTable(e); }}
>
<strong>{this.props.table.name}</strong>
<strong>{table.name}</strong>
<small className="m-l-5"><i className="fa fa-minus" /></small>
</a>
);
metadata = (
<div>
{this.props.table.columns.map((col) => (
<div className="clearfix" key={shortid.generate()}>
<div className="pull-left m-l-10">
{col.name}
</div>
<div className="pull-right text-muted">
<small> {col.type}</small>
</div>
</div>
))}
<hr />
{header}
<div className="table-columns">
{table.columns.map((col) => {
let name = col.name;
if (col.indexed) {
name = <strong>{col.name}</strong>;
}
return (
<div className="clearfix table-column" key={shortid.generate()}>
<div className="pull-left m-l-10">
{name}
</div>
<div className="pull-right text-muted">
<small> {col.type}</small>
</div>
</div>);
})}
<hr />
</div>
</div>
);
} else {
@@ -82,34 +139,34 @@ class TableElement extends React.Component {
href="#"
onClick={(e) => { this.expandTable(e); }}
>
{this.props.table.name}
{table.name}
<small className="m-l-5"><i className="fa fa-plus" /></small>
</a>
);
}
let keyLink;
if (this.props.table.indexes && this.props.table.indexes.length > 0) {
if (table.indexes && table.indexes.length > 0) {
keyLink = (
<ModalTrigger
modalTitle={
<div>
Keys for table <strong>{this.props.table.name}</strong>
Keys for table <strong>{table.name}</strong>
</div>
}
modalBody={
<pre>{JSON.stringify(this.props.table.indexes, null, 4)}</pre>
<pre>{JSON.stringify(table.indexes, null, 4)}</pre>
}
triggerNode={
<Link
className="fa fa-key pull-left m-l-2"
tooltip={`View indexes (${this.props.table.indexes.length})`}
tooltip={`View indexes (${table.indexes.length})`}
/>
}
/>
);
}
return (
<div>
<div className="TableElement">
<div className="clearfix">
<div className="pull-left">
{buttonToggle}
@@ -131,26 +188,22 @@ class TableElement extends React.Component {
/>
<Link
className="fa fa-trash pull-left m-l-2"
onClick={this.props.actions.removeTable.bind(this, this.props.table)}
onClick={this.removeTable.bind(this)}
tooltip="Remove from workspace"
href="#"
/>
</ButtonGroup>
</div>
</div>
{metadata}
<div>
{metadata}
</div>
</div>
);
}
}
TableElement.propTypes = {
table: React.PropTypes.object,
queryEditor: React.PropTypes.object,
actions: React.PropTypes.object,
};
TableElement.defaultProps = {
table: null,
};
TableElement.propTypes = propTypes;
TableElement.defaultProps = defaultProps;
function mapDispatchToProps(dispatch) {
return {
@@ -158,3 +211,4 @@ function mapDispatchToProps(dispatch) {
};
}
export default connect(null, mapDispatchToProps)(TableElement);
export { TableElement };