This is an automated email from the ASF dual-hosted git repository. tai pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/master by this push: new 16459ad style: DOCTYPE tag, and related CSS cleanup/refactoring (#10302) 16459ad is described below commit 16459ad401d916d0ce7ca6ffa6775fdcb8a37ae8 Author: Evan Rusackas <e...@preset.io> AuthorDate: Wed Jul 29 18:49:32 2020 -0700 style: DOCTYPE tag, and related CSS cleanup/refactoring (#10302) --- .../integration/explore/AdhocMetrics.test.ts | 55 ++++++------ .../cypress/integration/explore/advanced.test.ts | 18 ++-- .../cypress/integration/explore/control.test.ts | 12 +-- .../cypress/integration/explore/filter_box.test.js | 4 +- .../explore/visualizations/line.test.ts | 4 +- .../src/components/ListView/ListView.tsx | 8 ++ .../explore/components/AdhocMetricEditPopover.jsx | 8 +- .../components/AdhocMetricEditPopoverTitle.jsx | 6 +- .../explore/components/ControlPanelsContainer.jsx | 69 ++++++++------ .../src/explore/components/ExploreChartPanel.jsx | 26 ++++-- .../explore/components/ExploreViewContainer.jsx | 100 +++++++++------------ .../src/explore/components/QueryAndSaveBtns.css | 21 ----- .../src/explore/components/QueryAndSaveBtns.jsx | 88 ++++++++++++------ superset-frontend/stylesheets/superset.less | 3 + superset/templates/superset/basic.html | 2 +- superset/templates/superset/paper-theme.html | 2 +- .../templates/superset/reports/slice_data.html | 1 + superset/templates/superset/theme.html | 8 +- superset/templates/superset/traceback.html | 7 +- 19 files changed, 247 insertions(+), 195 deletions(-) diff --git a/superset-frontend/cypress-base/cypress/integration/explore/AdhocMetrics.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/AdhocMetrics.test.ts index ef7dc9b..59722a0 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/AdhocMetrics.test.ts +++ b/superset-frontend/cypress-base/cypress/integration/explore/AdhocMetrics.test.ts @@ -26,25 +26,27 @@ describe('AdhocMetrics', () => { it('Clear metric and set simple adhoc metric', () => { const metric = 'sum(sum_girls)'; - const metricName = 'Girl Births'; + const metricName = 'Sum Girls'; cy.visitChartByName('Num Births Trend'); cy.verifySliceSuccess({ waitAlias: '@postJson' }); - cy.get('[data-test=metrics]').within(() => { - cy.get('.Select__clear-indicator').click(); - cy.get('.Select__control input').type('sum_girls'); - cy.get('.Select__option--is-focused').trigger('mousedown').click(); - }); + cy.get('[data-test=metrics]').find('.Select__clear-indicator').click(); - cy.get('#metrics-edit-popover').within(() => { - cy.get('.popover-title').within(() => { - cy.get('span').click(); - cy.get('input').type(metricName); - }); - cy.get('button').contains('Save').click(); - }); - cy.get('.Select__multi-value__label').contains(metricName); + cy.get('[data-test=metrics]') + .find('.Select__control input') + .type('sum_girls', { force: true }); + + cy.get('[data-test=metrics]') + .find('.Select__option--is-focused') + .trigger('mousedown') + .click(); + + cy.get('[data-test="AdhocMetricEditTitle#trigger"]').click(); + cy.get('[data-test="AdhocMetricEditTitle#input"]').type(metricName); + cy.get('[data-test="AdhocMetricEdit#save"]').contains('Save').click(); + + cy.get('.metrics-select .metric-option').contains(metricName); cy.get('button.query').click(); cy.verifySliceSuccess({ @@ -59,20 +61,21 @@ describe('AdhocMetrics', () => { cy.verifySliceSuccess({ waitAlias: '@postJson' }); // select column "num" - cy.get('[data-test=metrics]').within(() => { - cy.get('.Select__clear-indicator').click(); - cy.get('.Select__control').click(); - cy.get('.Select__control input').type('num'); - cy.get('.option-label').contains(/^num$/).click(); - }); + cy.get('[data-test=metrics]').find('.Select__clear-indicator').click(); + + cy.get('[data-test=metrics]').find('.Select__control').click(); + + cy.get('[data-test=metrics]').find('.Select__control input').type('num'); + + cy.get('[data-test=metrics]').find('.option-label').last().click(); // add custom SQL - cy.get('#metrics-edit-popover').within(() => { - cy.get('#adhoc-metric-edit-tabs-tab-SQL').click(); - cy.get('.ace_content').click(); - cy.get('.ace_text-input').type('/COUNT(DISTINCT name)', { force: true }); - cy.get('button').contains('Save').click(); - }); + cy.get('#adhoc-metric-edit-tabs-tab-SQL').click(); + cy.get('#metrics-edit-popover').find('.ace_content').click(); + cy.get('#metrics-edit-popover') + .find('.ace_text-input') + .type('/COUNT(DISTINCT name)', { force: true }); + cy.get('#metrics-edit-popover').find('button').contains('Save').click(); cy.get('button.query').click(); diff --git a/superset-frontend/cypress-base/cypress/integration/explore/advanced.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/advanced.test.ts index 4a21f00..624bac6 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/advanced.test.ts +++ b/superset-frontend/cypress-base/cypress/integration/explore/advanced.test.ts @@ -30,14 +30,18 @@ describe('Advanced analytics', () => { cy.get('.panel-title').contains('Advanced Analytics').click(); - cy.get('[data-test=time_compare]').within(() => { - cy.get('.Select__control').click(); - cy.get('input[type=text]').type('28 days{enter}'); + cy.get('[data-test=time_compare]').find('.Select__control').click(); + cy.get('[data-test=time_compare]') + .find('input[type=text]') + .type('28 days{enter}'); - cy.get('.Select__control').click(); - cy.get('input[type=text]').type('364 days{enter}'); - cy.get('.Select__multi-value__label').contains('364 days'); - }); + cy.get('[data-test=time_compare]').find('.Select__control').click(); + cy.get('[data-test=time_compare]') + .find('input[type=text]') + .type('364 days{enter}'); + cy.get('[data-test=time_compare]') + .find('.Select__multi-value__label') + .contains('364 days'); cy.get('button.query').click(); cy.wait('@postJson'); diff --git a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts index d7a4509..ef4fef5 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts +++ b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts @@ -46,16 +46,10 @@ describe('Datasource control', () => { cy.get('.modal-footer button').contains('Save').click(); cy.get('.modal-footer button').contains('OK').click(); // select new metric - cy.get('.metrics-select:eq(0)').click(); - cy.get('.metrics-select:eq(0) input[type="text"]') + cy.get('[data-test=metrics]') + .find('.Select__control input') .focus() - .type(newMetricName); - cy.get('.metrics-select:eq(0) .Select__menu .Select__option') - .contains(newMetricName) - .click(); - cy.get('.metrics-select:eq(0) .Select__multi-value__label') - .contains(newMetricName) - .click(); + .type(newMetricName, { force: true }); // delete metric cy.get('#datasource_menu').click(); cy.get('a').contains('Edit Datasource').click(); diff --git a/superset-frontend/cypress-base/cypress/integration/explore/filter_box.test.js b/superset-frontend/cypress-base/cypress/integration/explore/filter_box.test.js index b9793b3..4be0a45 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/filter_box.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/filter_box.test.js @@ -35,8 +35,6 @@ describe('Edit FilterBox Chart', () => { it('should work with default date filter', () => { verify(VIZ_DEFAULTS); // Filter box should default to having a date filter with no filter selected - cy.get('div.filter_box').within(() => { - cy.get('span').contains('No filter'); - }); + cy.get('div.filter_box').contains('No filter'); }); }); diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/line.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/line.test.ts index 76a9086..5c64007 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/line.test.ts +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/line.test.ts @@ -46,9 +46,9 @@ describe('Visualization > Line', () => { }); it('should allow negative values in Y bounds', () => { - cy.get('#controlSections-tab-display').click(); + cy.get('#controlSections-tab-display').click().wait(1000); cy.get('span').contains('Y Axis Bounds').scrollIntoView(); - cy.get('input[placeholder="Min"]').type('-0.1', { delay: 100 }); + cy.get('input[placeholder="Min"]').type('-0.1', { delay: 100 }).wait(1000); cy.get('.alert-warning').should('not.exist'); }); diff --git a/superset-frontend/src/components/ListView/ListView.tsx b/superset-frontend/src/components/ListView/ListView.tsx index 0afc44b..2f797e9 100644 --- a/superset-frontend/src/components/ListView/ListView.tsx +++ b/superset-frontend/src/components/ListView/ListView.tsx @@ -50,6 +50,9 @@ const ListViewStyles = styled.div` background: white; position: sticky; top: 0; + &:first-of-type { + padding-left: ${({ theme }) => theme.gridUnit * 4}px; + } } } } @@ -152,6 +155,11 @@ const ListViewStyles = styled.div` overflow: hidden; white-space: nowrap; max-width: 300px; + line-height: 1; + vertical-align: middle; + &:first-of-type { + padding-left: ${({ theme }) => theme.gridUnit * 4}px; + } } .sort-icon { diff --git a/superset-frontend/src/explore/components/AdhocMetricEditPopover.jsx b/superset-frontend/src/explore/components/AdhocMetricEditPopover.jsx index 8f7be4e..e94a7bb 100644 --- a/superset-frontend/src/explore/components/AdhocMetricEditPopover.jsx +++ b/superset-frontend/src/explore/components/AdhocMetricEditPopover.jsx @@ -271,6 +271,7 @@ export default class AdhocMetricEditPopover extends React.Component { className="adhoc-metric-edit-tab" eventKey={EXPRESSION_TYPES.SQL} title="Custom SQL" + data-test="adhoc-metric-edit-tab#custom" > {this.props.datasourceType !== 'druid' ? ( <FormGroup> @@ -304,11 +305,16 @@ export default class AdhocMetricEditPopover extends React.Component { bsStyle={hasUnsavedChanges && stateIsValid ? 'primary' : 'default'} bsSize="small" className="m-r-5" + data-test="AdhocMetricEdit#save" onClick={this.onSave} > Save </Button> - <Button bsSize="small" onClick={this.props.onClose}> + <Button + bsSize="small" + onClick={this.props.onClose} + data-test="AdhocMetricEdit#cancel" + > Close </Button> <i diff --git a/superset-frontend/src/explore/components/AdhocMetricEditPopoverTitle.jsx b/superset-frontend/src/explore/components/AdhocMetricEditPopoverTitle.jsx index 5b5b926..d4eed6f 100644 --- a/superset-frontend/src/explore/components/AdhocMetricEditPopoverTitle.jsx +++ b/superset-frontend/src/explore/components/AdhocMetricEditPopoverTitle.jsx @@ -70,6 +70,7 @@ export default class AdhocMetricEditPopoverTitle extends React.Component { value={adhocMetric.hasCustomLabel ? adhocMetric.label : ''} autoFocus onChange={onChange} + data-test="AdhocMetricEditTitle#input" /> ) : ( <OverlayTrigger @@ -81,7 +82,10 @@ export default class AdhocMetricEditPopoverTitle extends React.Component { onBlur={this.onBlur} className="AdhocMetricEditPopoverTitle" > - <span className="inline-editable"> + <span + className="inline-editable" + data-test="AdhocMetricEditTitle#trigger" + > {adhocMetric.hasCustomLabel ? adhocMetric.label : 'My Metric'} <i diff --git a/superset-frontend/src/explore/components/ControlPanelsContainer.jsx b/superset-frontend/src/explore/components/ControlPanelsContainer.jsx index ff451ff..c3c175b 100644 --- a/superset-frontend/src/explore/components/ControlPanelsContainer.jsx +++ b/superset-frontend/src/explore/components/ControlPanelsContainer.jsx @@ -23,6 +23,7 @@ import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import { Alert, Tab, Tabs } from 'react-bootstrap'; import { t } from '@superset-ui/translation'; +import styled from '@superset-ui/style'; import ControlPanelSection from './ControlPanelSection'; import ControlRow from './ControlRow'; @@ -40,6 +41,25 @@ const propTypes = { isDatasourceMetaLoading: PropTypes.bool.isRequired, }; +const Styles = styled.div` + max-height: 100%; + .remove-alert { + cursor: 'pointer'; + } + #controlSections { + display: flex; + flex-direction: column; + max-height: 100%; + } + .nav-tabs { + flex: 0 0 1; + } + .tab-content { + overflow: auto; + flex: 1 1 100%; + } +`; + class ControlPanelsContainer extends React.Component { constructor(props) { super(props); @@ -145,6 +165,7 @@ class ControlPanelsContainer extends React.Component { </ControlPanelSection> ); } + render() { const querySectionsToRender = []; const displaySectionsToRender = []; @@ -170,32 +191,30 @@ class ControlPanelsContainer extends React.Component { }); return ( - <div className="scrollbar-container"> - <div className="scrollbar-content"> - {this.props.alert && ( - <Alert bsStyle="warning"> - {this.props.alert} - <i - role="button" - tabIndex={0} - className="fa fa-close pull-right" - onClick={this.removeAlert} - style={{ cursor: 'pointer' }} - /> - </Alert> - )} - <Tabs id="controlSections"> - <Tab eventKey="query" title={t('Data')}> - {querySectionsToRender.map(this.renderControlPanelSection)} + <Styles> + {this.props.alert && ( + <Alert bsStyle="warning"> + {this.props.alert} + <i + role="button" + tabIndex={0} + className="fa fa-close pull-right" + onClick={this.removeAlert} + style={{ cursor: 'pointer' }} + /> + </Alert> + )} + <Tabs id="controlSections"> + <Tab eventKey="query" title={t('Data')}> + {querySectionsToRender.map(this.renderControlPanelSection)} + </Tab> + {displaySectionsToRender.length > 0 && ( + <Tab eventKey="display" title={t('Customize')}> + {displaySectionsToRender.map(this.renderControlPanelSection)} </Tab> - {displaySectionsToRender.length > 0 && ( - <Tab eventKey="display" title={t('Customize')}> - {displaySectionsToRender.map(this.renderControlPanelSection)} - </Tab> - )} - </Tabs> - </div> - </div> + )} + </Tabs> + </Styles> ); } } diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index 36975a0..74eaed9 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -18,8 +18,8 @@ */ import React from 'react'; import PropTypes from 'prop-types'; -import { Panel } from 'react-bootstrap'; import { ParentSize } from '@vx/responsive'; +import styled from '@superset-ui/style'; import { chartPropShape } from '../../dashboard/util/propShapes'; import ChartContainer from '../../chart/ChartContainer'; import ExploreChartHeader from './ExploreChartHeader'; @@ -49,6 +49,19 @@ const propTypes = { triggerRender: PropTypes.bool, }; +const Styles = styled.div` + background-color: ${({ theme }) => theme.colors.grayscale.light5}; + padding: ${({ theme }) => theme.gridUnit * 4}px; + height: 100%; + display: flex; + flex-direction: column; + align-items: stretch; + align-content: stretch; + div:last-of-type { + flex-basis: 100%; + } +`; + class ExploreChartPanel extends React.PureComponent { renderChart() { const { chart } = this.props; @@ -113,13 +126,12 @@ class ExploreChartPanel extends React.PureComponent { chart={this.props.chart} /> ); + return ( - <div className="chart-container"> - <Panel style={{ height: this.props.height }}> - <Panel.Heading>{header}</Panel.Heading> - <Panel.Body>{this.renderChart()}</Panel.Body> - </Panel> - </div> + <Styles className="chart-container"> + <div>{header}</div> + <div>{this.renderChart()}</div> + </Styles> ); } } diff --git a/superset-frontend/src/explore/components/ExploreViewContainer.jsx b/superset-frontend/src/explore/components/ExploreViewContainer.jsx index 40fb3fd..6104216 100644 --- a/superset-frontend/src/explore/components/ExploreViewContainer.jsx +++ b/superset-frontend/src/explore/components/ExploreViewContainer.jsx @@ -21,6 +21,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; +import styled from '@superset-ui/style'; import { t } from '@superset-ui/translation'; import ExploreChartPanel from './ExploreChartPanel'; @@ -40,20 +41,6 @@ import { LOG_ACTIONS_MOUNT_EXPLORER, LOG_ACTIONS_CHANGE_EXPLORE_CONTROLS, } from '../../logger/LogUtils'; -import Hotkeys from '../../components/Hotkeys'; - -// Prolly need to move this to a global context -const keymap = { - RUN: 'ctrl + r, ctrl + enter', - SAVE: 'ctrl + s', -}; - -const getHotKeys = () => - Object.keys(keymap).map(k => ({ - name: k, - descr: keymap[k], - key: k, - })); const propTypes = { actions: PropTypes.object.isRequired, @@ -70,6 +57,25 @@ const propTypes = { impressionId: PropTypes.string, }; +const Styles = styled.div` + height: ${({ height }) => height}; + min-height: ${({ height }) => height}; + overflow: hidden; + text-align: left; + position: relative; + width: 100%; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + align-items: stretch; + .control-pane { + display: flex; + flex-direction: column; + padding: 0 ${({ theme }) => 2 * theme.gridUnit}px; + max-height: 100%; + } +`; + class ExploreViewContainer extends React.Component { constructor(props) { super(props); @@ -325,12 +331,9 @@ class ExploreViewContainer extends React.Component { if (this.props.standalone) { return this.renderChartContainer(); } + return ( - <div - id="explore-container" - className="container-fluid" - style={{ height: this.state.height, overflow: 'hidden' }} - > + <Styles id="explore-container" height={this.state.height}> {this.state.showModal && ( <SaveModal onHide={this.toggleModal} @@ -339,45 +342,27 @@ class ExploreViewContainer extends React.Component { sliceName={this.props.sliceName} /> )} - <div className="row"> - <div className="col-sm-4"> - <div - style={{ - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - }} - > - <QueryAndSaveBtns - canAdd={!!(this.props.can_add || this.props.can_overwrite)} - onQuery={this.onQuery} - onSave={this.toggleModal} - onStop={this.onStop} - loading={this.props.chart.chartStatus === 'loading'} - chartIsStale={this.state.chartIsStale} - errorMessage={this.renderErrorMessage()} - datasourceType={this.props.datasource_type} - /> - <div className="m-l-5 text-muted"> - <Hotkeys - header="Keyboard shortcuts" - hotkeys={getHotKeys()} - placement="right" - /> - </div> - </div> - <br /> - <ControlPanelsContainer - actions={this.props.actions} - form_data={this.props.form_data} - controls={this.props.controls} - datasource_type={this.props.datasource_type} - isDatasourceMetaLoading={this.props.isDatasourceMetaLoading} - /> - </div> - <div className="col-sm-8">{this.renderChartContainer()}</div> + <div className="col-sm-4 control-pane"> + <QueryAndSaveBtns + canAdd={!!(this.props.can_add || this.props.can_overwrite)} + onQuery={this.onQuery} + onSave={this.toggleModal} + onStop={this.onStop} + loading={this.props.chart.chartStatus === 'loading'} + chartIsStale={this.state.chartIsStale} + errorMessage={this.renderErrorMessage()} + datasourceType={this.props.datasource_type} + /> + <ControlPanelsContainer + actions={this.props.actions} + form_data={this.props.form_data} + controls={this.props.controls} + datasource_type={this.props.datasource_type} + isDatasourceMetaLoading={this.props.isDatasourceMetaLoading} + /> </div> - </div> + <div className="col-sm-8">{this.renderChartContainer()}</div> + </Styles> ); } } @@ -433,6 +418,7 @@ function mapDispatchToProps(dispatch) { } export { ExploreViewContainer }; + export default connect( mapStateToProps, mapDispatchToProps, diff --git a/superset-frontend/src/explore/components/QueryAndSaveBtns.css b/superset-frontend/src/explore/components/QueryAndSaveBtns.css deleted file mode 100644 index 4ea4dce..0000000 --- a/superset-frontend/src/explore/components/QueryAndSaveBtns.css +++ /dev/null @@ -1,21 +0,0 @@ -/** - * 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. - */ -.save-btn { - width: 100px; -} diff --git a/superset-frontend/src/explore/components/QueryAndSaveBtns.jsx b/superset-frontend/src/explore/components/QueryAndSaveBtns.jsx index e2ec4ef..a8bba79 100644 --- a/superset-frontend/src/explore/components/QueryAndSaveBtns.jsx +++ b/superset-frontend/src/explore/components/QueryAndSaveBtns.jsx @@ -21,9 +21,10 @@ import PropTypes from 'prop-types'; import { ButtonGroup, OverlayTrigger, Tooltip } from 'react-bootstrap'; import classnames from 'classnames'; import { t } from '@superset-ui/translation'; +import styled from '@superset-ui/style'; import Button from '../../components/Button'; -import './QueryAndSaveBtns.css'; +import Hotkeys from '../../components/Hotkeys'; const propTypes = { canAdd: PropTypes.bool.isRequired, @@ -41,6 +42,30 @@ const defaultProps = { disabled: false, }; +// Prolly need to move this to a global context +const keymap = { + RUN: 'ctrl + r, ctrl + enter', + SAVE: 'ctrl + s', +}; + +const getHotKeys = () => + Object.keys(keymap).map(k => ({ + name: k, + descr: keymap[k], + key: k, + })); + +const Styles = styled.div` + display: flex; + flex-direction: row; + align-items: center; + padding-bottom: ${({ theme }) => 2 * theme.gridUnit}px; + + .save-btn { + width: 100px; + } +`; + export default function QueryAndSaveBtns({ canAdd, onQuery, @@ -79,33 +104,42 @@ export default function QueryAndSaveBtns({ ); return ( - <div> - <ButtonGroup className="query-and-save"> - {qryOrStopButton} - <Button - className={saveClasses} - data-target="#save_modal" - data-toggle="modal" - disabled={saveButtonDisabled} - onClick={onSave} - > - <i className="fa fa-plus-circle" /> Save - </Button> - </ButtonGroup> - {errorMessage && ( - <span> - {' '} - <OverlayTrigger - placement="right" - overlay={ - <Tooltip id={'query-error-tooltip'}>{errorMessage}</Tooltip> - } + <Styles> + <div> + <ButtonGroup className="query-and-save"> + {qryOrStopButton} + <Button + className={saveClasses} + data-target="#save_modal" + data-toggle="modal" + disabled={saveButtonDisabled} + onClick={onSave} > - <i className="fa fa-exclamation-circle text-danger fa-lg" /> - </OverlayTrigger> - </span> - )} - </div> + <i className="fa fa-plus-circle" /> Save + </Button> + </ButtonGroup> + {errorMessage && ( + <span> + {' '} + <OverlayTrigger + placement="right" + overlay={ + <Tooltip id={'query-error-tooltip'}>{errorMessage}</Tooltip> + } + > + <i className="fa fa-exclamation-circle text-danger fa-lg" /> + </OverlayTrigger> + </span> + )} + </div> + <div className="m-l-5 text-muted"> + <Hotkeys + header="Keyboard shortcuts" + hotkeys={getHotKeys()} + placement="right" + /> + </div> + </Styles> ); } diff --git a/superset-frontend/stylesheets/superset.less b/superset-frontend/stylesheets/superset.less index 3b7b452..4eab5d9 100644 --- a/superset-frontend/stylesheets/superset.less +++ b/superset-frontend/stylesheets/superset.less @@ -444,6 +444,9 @@ table.table-no-hover tr:hover { line-height: 2px; border-radius: 50%; box-shadow: 2px 2px 4px -1px fade(@darkest, @opacity-light); + i { + width: 10px; + } } iframe { diff --git a/superset/templates/superset/basic.html b/superset/templates/superset/basic.html index 3fa2591..a315746 100644 --- a/superset/templates/superset/basic.html +++ b/superset/templates/superset/basic.html @@ -21,7 +21,7 @@ {% from 'superset/partials/asset_bundle.html' import css_bundle, js_bundle with context %} {% set favicons = appbuilder.app.config['FAVICONS'] %} - +<!DOCTYPE html> <html> <head> <title> diff --git a/superset/templates/superset/paper-theme.html b/superset/templates/superset/paper-theme.html index 02e15a2..edf5013 100644 --- a/superset/templates/superset/paper-theme.html +++ b/superset/templates/superset/paper-theme.html @@ -520,7 +520,7 @@ </div> <div class="row"> <div class="col-sm-4"> - <div class="panel panel-default"> + <div class="panel panel-default f1"> <div class="panel-heading"> <h3 class="panel-title">Panel title</h3> </div> diff --git a/superset/templates/superset/reports/slice_data.html b/superset/templates/superset/reports/slice_data.html index 08c8a55..c478cd0 100644 --- a/superset/templates/superset/reports/slice_data.html +++ b/superset/templates/superset/reports/slice_data.html @@ -16,6 +16,7 @@ specific language governing permissions and limitations under the License. #} +<!DOCTYPE html> <html> <head> </head> diff --git a/superset/templates/superset/theme.html b/superset/templates/superset/theme.html index e159e19..f8ebf8f 100644 --- a/superset/templates/superset/theme.html +++ b/superset/templates/superset/theme.html @@ -803,7 +803,7 @@ <div class="row"> <div class="col-lg-6"> <h2 id="nav-tabs">Tabs</h2> - <div class="panel panel-default"> + <div class="panel panel-default f2"> <div class="panel-body"> <div class="bs-component"> <ul class="nav nav-tabs"> @@ -1184,13 +1184,13 @@ <div class="row"> <div class="col-lg-4"> <div class="bs-component"> - <div class="panel panel-default"> + <div class="panel panel-default f3"> <div class="panel-body"> Basic panel </div> </div> - <div class="panel panel-default"> + <div class="panel panel-default f4"> <div class="panel-body"> Panel content </div> @@ -1200,7 +1200,7 @@ </div> <div class="col-lg-4"> <div class="bs-component"> - <div class="panel panel-default"> + <div class="panel panel-default f5"> <div class="panel-heading"> <h3 class="panel-title">Panel default</h3> </div> diff --git a/superset/templates/superset/traceback.html b/superset/templates/superset/traceback.html index 9e690ef..548c431 100644 --- a/superset/templates/superset/traceback.html +++ b/superset/templates/superset/traceback.html @@ -15,14 +15,15 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -#} +#}} +<!DOCTYPE html> <html> <body> <h1>Sorry, something went wrong</h1> <h3>500 - Internal Server Error</h3> - <hr> + <hr /> <h2>Stacktrace</h2> - <hr> + <hr /> <code> <pre> {{ error_msg }}