Files
superset2/superset/assets/src/explore/components/controls/DatasourceControl.jsx
Chris Williams c065319508 [wip] dashboard builder v2 (#4528)
* [dashboard builder] Add dir structure for dashboard/v2, simplified Header, split pane, Draggable side panel

[grid] add <DashboardGrid />, <ResizableContainer />, and initial grid components.

[grid] gridComponents/ directory, add fixtures/ directory and test layout, add <Column />

[grid] working grid with gutters

[grid] design tweaks and polish, add <Tabs />

[header] add gradient header logo and favicon

[dnd] begin adding dnd functionality

[dnd] add util/isValidChild.js

[react-beautiful-dnd] iterate on dnd until blocked

[dnd] refactor to use react-dnd

[react-dnd] refactor to use composable <DashboardComponent /> structure

[dnd] factor out DashboardComponent, let components render dropInidcator and set draggableRef, add draggable tabs

[dnd] refactor to use redux, add DashboardComponent and DashboardGrid containers

[dragdroppable] rename horizontal/vertical => row/column

[builder] refactor into HoverMenu, add WithPopoverMenu

[builder] add editable header and disableDragDrop prop for Dragdroppable's

[builder] make tabs editable

[builder] add generic popover dropdown and header row style editability

[builder] add hover rowStyle dropdown, make row styles editable

[builder] add some new component icons, add popover with delete to charts

[builder] add preview icons, add popover menu to rows.

[builder] add IconButton and RowStyleDropdown

[resizable] use ResizableContainer instead of DimensionProvider, fix resize and delete bugs

[builder] fix bug with spacer

[builder] clean up, header.size => header.headerSize

[builder] support more drag/drop combinations by wrapping some components in rows upon drop. fix within list drop index. refactor some utils.

[builder][tabs] fix broken add tab button

[dashboard builder] don't pass dashboard layout to all dashboard components, improve drop indicator logic, fix delete component pure component bug

[dnd] refactor drop position logic

* fix rebase error, clean up css organization and use @less vars

* [dashboard-builder] add top-level tabs + undo-redo (#4626)

* [top-level-tabs] initial working version of top-level tabs

* [top-level-tabs] simplify redux and disable ability to displace top-level tabs with other tabs

* [top-level-tabs] improve tab drag and drop css

* [undo-redo] add redux undo redo

* [dnd] clean up dropResult shape, add new component source id + type, use css for drop indicator instead of styles and fix tab indicators.

* [top-level-tabs] add 'Collapse tab content' to delete tabs button

* [dnd] add depth validation to drag and drop logic

* [dashboard-builder] add resize action, enforce minimum width of columns, column children inherit column size when necessary, meta.rowStyle => meta.background, add background to columns

* [dashboard-builder] make sure getChildWidth returns a number

* [dashboard builder] static layout + toasts (#4763)

* [dashboard-builder] remove spacer component

* [dashboard-builder] better transparent indicator, better grid gutter logic, no dragging top-level tabs, headers are multiples of grid unit, fix row height granularity, update redux state key dashboard => dashboardLayout

* [dashboard-builder] don't blast column child dimensions on resize

* [dashboard-builder] ResizableContainer min size can't be smaller than size, fix row style, role=none on WithPopoverMenu container

* [edit mode] add edit mode to redux and propogate to all <DashboardComponent />s

* [toasts] add Toast component, ToastPresenter container and component, and toast redux actions + reducers

* [dashboard-builder] add info toast when dropResult overflows parent

* [dashboard builder] git mv to src/ post-rebase

* Dashboard builder rebased + linted (#4849)

* define dashboard redux state

* update dashboard state reducer

* dashboard layout converter + grid render

* builder pane + slice adder

* Dashboard header + slice header controls

* fix linting

* 2nd code review comments

* [dashboard builder] improve perf (#4855)

* address major perf + css issues

[dashboard builder] fix dashboard filters and some css

[dashboard builder] use VIZ_TYPES, move stricter .eslintrc to dashboard/, more css fixes

[builder] delete GridCell and GridLayout, remove some unused css. fix broken tabs.

* [builder] fix errors post-rebase

* [builder] add support for custom DragDroppable drag layer and add AddSliceDragPreview

* [AddSliceDragPreview] fix type check

* [dashboard builder] add prettier and update all files

* [dashboard builder] merge v2/ directory int dashboard/

* [dashboard builder] move component/*Container => containers/*

* add sticky tabs + sidepane, better tabs perf, better container hierarchy, better chart header (#4893)

* dashboard header, slice header UI improvement

* add slider and sticky

* dashboard header, slice header UI improvement

* make builder pane floating

* [dashboard builder] add sticky top-level tabs, refactor for performant tabs

* [dashboard builder] visually distinct containers, icons for undo-redo, fix some isValidChild bugs

* [dashboard builder] better undo redo <> save changes state, notify upon reaching undo limit

* [dashboard builder] hook up edit + create component actions to saved-state pop.

* [dashboard builder] visual refinement, refactor Dashboard header content and updates into layout for undo-redo, refactor save dashboard modal to use toasts instead of notify.

* [dashboard builder] refactor chart name update logic to use layout for undo redo, save slice name changes on dashboard save

* add slider and sticky

* [dashboard builder] fix layout converter slice_id + chartId type casting, don't change grid size upon edit (perf)

* [dashboard builder] don't set version key in getInitialState

* [dashboard builder] make top level tabs addition/removal undoable, fix double sticky tabs + side panel.

* [dashboard builder] fix sticky tabs offset bug

* [dashboard builder] fix drag preview width, css polish, fix rebase issue

* [dashboard builder] fix side pane labels and hove z-index

* Markdown for dashboard (#4962)

* fix dashboard server-side unit tests (#5009)

* Dashboard save button (#4979)

* save button

* fix slices list height

* save custom css

* merge save-dash changes from dashboard v1
https://github.com/apache/incubator-superset/pull/4900
https://github.com/apache/incubator-superset/pull/5051

* [dashboard v2] check for default_filters before json_loads-ing them (#5064)

[dashboard v2] check for default_filters before json-loads-ing them

* [dashboard v2] fix bugs from rebase

* [dashboard v2] tests! (#5066)

* [dashboard v2][tests] add tests for newComponentFactory, isValidChild, dropOverflowsParent, and dnd-reorder

* [dashboard v2][tests] add tests for componentIsResizable, findParentId, getChartIdsFromLayout, newEntitiesFromDrop, and getDropPosition

* [dashboard v2][tests] add mockStore, mockState, and tests for DragDroppable, DashboardBuilder, DashboardGrid, ToastPresenter, and Toast

* [dashboard builder][tests] separate files for state tree fixtures, add ChartHolder, Chart, Divider, Header, Row tests and WithDragDropContext helper

* [dashboard v2][tests] fix dragdrop context with util/getDragDropManager, add test for menu/* and resizable/*, and new components

* [dashboard v2][tests] fix and re-write Dashboard tests, add getFormDataWithExtraFilters_spec

* [dashboard v2][tests] add reducer tests, fix lint error

* [dashboard-v2][tests] add actions/dashboardLayout_spec

* [dashboard v2] fix some prop bugs, open side pane on edit, fix slice name bug

* [dashboard v2] fix slice name save bug

* [dashboard v2] fix lint errors

* [dashboard v2] fix filters bug and add test

* [dashboard v2] fix getFormDataWithExtraFilters_spec

* [dashboard v2] logging updates (#5087)

* [dashboard v2] initial logging refactor

* [dashboard v2] clean up logger

* [logger] update explore with new log events, add refresh dashboard + refresh dashboard chart actions

* [logging] add logger_spec.js, fix reducers/dashboardState_spec + gridComponents/Chart_spec

* [dashboard v2][logging] refactor for bulk logging in python

* [logging] tweak python, fix and remove dup start_offset entries

* [dashboard v2][logging] add dashboard_first_load event

* [dashboard v2][logging] add slice_ids to dashboard pane load event

* [tests] fix npm test script

* Fix: update slices list when add/remove multiple slices (#5138)

* [dashboard v2] add v1 switch (#5126)

* [dashboard] copy all dashboard v1 into working v1 switch

* [dashboard] add functional v1 <> v2 switch with messaging

* [dashboard] add v2 logging to v1 dashboard, add read-v2-changes link, add client logging to track v1 <> v2 switches

* [dashboard] Remove default values for feedback url + v2 auto convert date

* [dashboard v2] fix misc UI/UX issues

* [dashboard v2] fix Markdown persistance issues and css, fix copy dash title, don't enforce shallow hovering with drop indicator

* [dashboard v2] improve non-shallow drop target UX, fix Markdown drop indicator, clarify slice adder filter/sort

* [dashboard v2] delete empty rows on drag or delete events that leave them without children, add test

* [dashboard v2] improve v1<>v2 switch modals, add convert to v2 badge in v1, fix unsaved changes issue in preview mode, don't auto convert column child widths for now

* [dashboard v2][dnd] add drop position cache to fix non-shallow drops

* [dashboard] fix test script with glob instead of recurse, fix tests, add temp fix for tab nesting, ignore v1 lint errors

* [dashboard] v2 badge style tweaks, add back v1 _set_dash_metadata for v1 editing

* [dashboard] fix python linting and tests

* [dashboard] lint tests

* add slice from explore view (#5141)

* Fix dashboard position row data (#5131)

* add slice_name to markdown

(cherry picked from commit 14b01f1)

* set min grid width be 1 column

* remove empty column

* check total columns count <= 12

* scan position data and fix rows

* fix dashboard url with default_filters

* [dashboard v2]  better grid drop ux, fix tab bugs 🐛 (#5151)

* [dashboard v2] add empty droptarget to dashboard grid for better ux and update test

* [dashboard] reset tab index upon top-level tab deletion, fix findparentid bug

* [dashboard] update v1<>v2 modal link for tracking

* Fix: Should pass slice_can_edit flag down (#5159)

* [dash builder fix] combine markdown and slice name, slice picker height (#5165)

* combine markdown code and markdown slice name

* allow dynamic height for slice picker cell

* add word break for long datasource name

* [fix] new dashboard state (#5213)

* [dashboard v2] ui + ux fixes (#5208)

* [dashboard v2] use <Loading /> throughout, small loading gif, improve row/column visual hierarchy, add cached data pop

* [dashboard v2] lots of polish

* [dashboard v2] remove markdown padding on edit, more opaque slice drag preview, unsavedChanges=true upon moving a component, fix initial load logging.

* [dashboard v2] gray loading.gif, sticky header, undo/redo keyboard shortcuts, fix move component saved changes update, v0 double scrollbar fix

* [dashboard v2] move UndoRedoKeylisteners into Header, render only in edit mode, show visual feedback for keyboard shortcut, hide hover menu in top-level tabs

* [dashboard v2] fix grid + sidepane height issues

* [dashboard v2] add auto-resize functionality, update tests. cache findParentId results.

* [dashboard v2][tests] add getDetailedComponentWidth_spec.js

* [dashboard v2] fix lint

* [fix] layout converter fix (#5218)

* [fix] layout converter fix

* add changed_on into initial sliceEntity data

* add unit tests for SliceAdder component

* remove old fixtures file

* [dashboard v2] remove webpack-cli, fresh yarn.lock post-rebase

* [dashboard v2] lint javascript

* [dashboard v2] fix python tests

* [Fix] import/export dash in V2 (#5273)

* [dashboard v2] add markdown tests (#5275)

* [dashboard v2] add Markdown tests

* [dashboard v2][mocks] fix markdown mock
2018-06-25 09:17:22 -07:00

232 lines
6.5 KiB
JavaScript

/* global notify */
import React from 'react';
import PropTypes from 'prop-types';
import { Table } from 'reactable';
import {
Row,
Col,
Collapse,
Label,
FormControl,
Modal,
OverlayTrigger,
Tooltip,
Well,
} from 'react-bootstrap';
import ControlHeader from '../ControlHeader';
import Loading from '../../../components/Loading';
import { t } from '../../../locales';
import ColumnOption from '../../../components/ColumnOption';
import MetricOption from '../../../components/MetricOption';
const propTypes = {
description: PropTypes.string,
label: PropTypes.string,
name: PropTypes.string.isRequired,
onChange: PropTypes.func,
value: PropTypes.string.isRequired,
datasource: PropTypes.object,
};
const defaultProps = {
onChange: () => {},
};
export default class DatasourceControl extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
showModal: false,
filter: '',
loading: true,
showDatasource: false,
};
this.toggleShowDatasource = this.toggleShowDatasource.bind(this);
this.onChange = this.onChange.bind(this);
this.onEnterModal = this.onEnterModal.bind(this);
this.toggleModal = this.toggleModal.bind(this);
this.changeSearch = this.changeSearch.bind(this);
this.setSearchRef = this.setSearchRef.bind(this);
this.selectDatasource = this.selectDatasource.bind(this);
}
onChange(vizType) {
this.props.onChange(vizType);
this.setState({ showModal: false });
}
onEnterModal() {
if (this.searchRef) {
this.searchRef.focus();
}
const url = '/superset/datasources/';
const that = this;
if (!this.state.datasources) {
$.ajax({
type: 'GET',
url,
success: (data) => {
const datasources = data.map(ds => ({
rawName: ds.name,
connection: ds.connection,
schema: ds.schema,
name: (
<a
href="#"
onClick={this.selectDatasource.bind(this, ds.uid)}
className="datasource-link"
>
{ds.name}
</a>
),
type: ds.type,
}));
that.setState({ loading: false, datasources });
},
error() {
that.setState({ loading: false });
notify.error(t('Something went wrong while fetching the datasource list'));
},
});
}
}
setSearchRef(searchRef) {
this.searchRef = searchRef;
}
toggleShowDatasource() {
this.setState({ showDatasource: !this.state.showDatasource });
}
toggleModal() {
this.setState({ showModal: !this.state.showModal });
}
changeSearch(event) {
this.setState({ filter: event.target.value });
}
selectDatasource(datasourceId) {
this.setState({ showModal: false });
this.props.onChange(datasourceId);
}
renderModal() {
return (
<Modal
show={this.state.showModal}
onHide={this.toggleModal}
onEnter={this.onEnterModal}
onExit={this.setSearchRef}
bsSize="lg"
>
<Modal.Header closeButton>
<Modal.Title>{t('Select a datasource')}</Modal.Title>
</Modal.Header>
<Modal.Body>
<div>
<FormControl
id="formControlsText"
inputRef={(ref) => {
this.setSearchRef(ref);
}}
type="text"
bsSize="sm"
value={this.state.filter}
placeholder={t('Search / Filter')}
onChange={this.changeSearch}
/>
</div>
{this.state.loading && <Loading />}
{this.state.datasources && (
<Table
columns={['name', 'type', 'schema', 'connection', 'creator']}
className="table table-condensed"
data={this.state.datasources}
itemsPerPage={20}
filterable={['rawName', 'type', 'connection', 'schema', 'creator']}
filterBy={this.state.filter}
hideFilterInput
/>
)}
</Modal.Body>
</Modal>
);
}
renderDatasource() {
const datasource = this.props.datasource;
return (
<div className="m-t-10">
<Well className="m-t-0">
<div className="m-b-10">
<Label>
<i className="fa fa-database" /> {datasource.database.backend}
</Label>
{` ${datasource.database.name} `}
</div>
<Row className="datasource-container">
<Col md={6}>
<strong>Columns</strong>
{datasource.columns.map(col => (
<div key={col.column_name}>
<ColumnOption showType column={col} />
</div>
))}
</Col>
<Col md={6}>
<strong>Metrics</strong>
{datasource.metrics.map(m => (
<div key={m.metric_name}>
<MetricOption metric={m} showType />
</div>
))}
</Col>
</Row>
</Well>
</div>
);
}
render() {
return (
<div>
<ControlHeader {...this.props} />
<OverlayTrigger
placement="right"
overlay={
<Tooltip id={'error-tooltip'}>{t('Click to point to another datasource')}</Tooltip>
}
>
<Label onClick={this.toggleModal} style={{ cursor: 'pointer' }} className="m-r-5">
{this.props.datasource.name}
</Label>
</OverlayTrigger>
<OverlayTrigger
placement="right"
overlay={
<Tooltip id={'edit-datasource-tooltip'}>
{t("Edit the datasource's configuration")}
</Tooltip>
}
>
<a href={this.props.datasource.edit_url}>
<i className="fa fa-edit m-r-5" />
</a>
</OverlayTrigger>
<OverlayTrigger
placement="right"
overlay={
<Tooltip id={'toggle-datasource-tooltip'}>{t('Show datasource configuration')}</Tooltip>
}
>
<a href="#">
<i
className={`fa fa-${this.state.showDatasource ? 'minus' : 'plus'}-square m-r-5`}
onClick={this.toggleShowDatasource}
/>
</a>
</OverlayTrigger>
<Collapse in={this.state.showDatasource}>{this.renderDatasource()}</Collapse>
{this.renderModal()}
</div>
);
}
}
DatasourceControl.propTypes = propTypes;
DatasourceControl.defaultProps = defaultProps;