mirror of https://github.com/apache/superset.git
style: Pass at propagating (and enhancing) Button component throughout Superset (#10649)
* getting rid of weird focus/active outline ring
* Buttons... buttons _everywhere_
* linting
* Nixing views/CRUD/dataset/Button component
* fixing 2 typing errors
* fixing more TS errors
* prefer src path for include
* one more real button, one less CSS class
* one more "button" to "Button"
* Published Status is now a proper clickable Label
* nixing the CRUD button again
* touching up stories, with SupersetButton story
* SIP-34 button colors
* adding polished package to mix colors
* updating button colors to match Superset theme
* abstracting away from bootstrap-specific props (might pivot libraries soon!)
* more abstraction from bsStyle/bsSize props
* exchanging styles for a prop
* linting
* restoring feature flag to stock
* using src alias
* last <button> replacement
* this classname would never be applied
* more linting action
* fixing unsupported bsSize 'medium', and cta typing error
* more cta action
* unnecessary styles
* errant bsSize prop
* cleanup
* tweaks to make new New button work
* Linting
* fixing a couple tests
* fixing theme based test failure
* margin tweak for NEW button
* another fixed test
* another fixed test
* fixing two more tests
* fixing last broken tests.
* always be linting
* Adding tertiary/dashed buttons
* cleaning up QueryAndSave buttons
* fixing "link" button styles
* fixing/updating link button styles
* cta buttons on Modal component
* linting.
* exporting button story knobs, making ALL knobs safe for export.
* capitalizing a file... no big whoop
* Basic button tests
* renaming button - temporarily
* renaming file to fix capitalization issue
* passing theme through to a difficult popover.
* fixin' a newly busted unit test
* lint fixin'
* oops, shouldn't have changed this prop!
* adding a dive() to themedShallow, and fixing a cypress/jest test
* addressing lint stuff
* touching up stories, with SupersetButton story
* SIP-34 button colors
* updating button colors to match Superset theme
* abstracting away from bootstrap-specific props (might pivot libraries soon!)
* linting
* restoring feature flag to stock
* cleanup
* Linting
* renaming button - temporarily
* renaming file to fix capitalization issue
* oops, shouldn't have changed this prop!
* adding a dive() to themedShallow, and fixing a cypress/jest test
* addressing lint stuff
* nixing new modal button
* Fixing another popover/button issue that should break cypress
* lint ✨
* passing classNames through to new button (should fix some tests)
* cleaning unused classes, making cypress tests use data attrs
* fixin' the test
* fixing another class-based test with data-test attr
* no longer passing theme as prop to buttons in popovers... themeprovider is better
* outline/border tweaks!
This commit is contained in:
parent
33fa9ebff1
commit
9fe30ab71e
|
@ -40,7 +40,7 @@ describe('AdhocFilters', () => {
|
|||
cy.get('button').contains('Save').click();
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.get('button[data-test="run-query-button"]').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
chartSelector: 'svg',
|
||||
|
@ -63,7 +63,7 @@ describe('AdhocFilters', () => {
|
|||
cy.get('button').contains('Save').click();
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.get('button[data-test="run-query-button"]').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
chartSelector: 'svg',
|
||||
|
|
|
@ -48,7 +48,7 @@ describe('AdhocMetrics', () => {
|
|||
|
||||
cy.get('.metrics-select .metric-option').contains(metricName);
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.get('button[data-test="run-query-button"]').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
querySubstring: `${metric} AS "${metricName}"`, // SQL statement
|
||||
|
@ -77,7 +77,7 @@ describe('AdhocMetrics', () => {
|
|||
.type('/COUNT(DISTINCT name)', { force: true });
|
||||
cy.get('#metrics-edit-popover').find('button').contains('Save').click();
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.get('button[data-test="run-query-button"]').click();
|
||||
|
||||
const metric = 'SUM(num)/COUNT(DISTINCT name)';
|
||||
cy.verifySliceSuccess({
|
||||
|
@ -103,7 +103,7 @@ describe('AdhocMetrics', () => {
|
|||
cy.get('button').contains('Save').click();
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.get('button[data-test="run-query-button"]').click();
|
||||
|
||||
const metric = 'SUM(num)';
|
||||
cy.verifySliceSuccess({
|
||||
|
@ -124,7 +124,7 @@ describe('AdhocMetrics', () => {
|
|||
});
|
||||
|
||||
const metric = 'AVG(sum_boys)';
|
||||
cy.get('button.query').click();
|
||||
cy.get('button[data-test="run-query-button"]').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
querySubstring: `${metric} AS "${metric}"`,
|
||||
|
|
|
@ -43,7 +43,7 @@ describe('Advanced analytics', () => {
|
|||
.find('.Select__multi-value__label')
|
||||
.contains('364 days');
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.get('button[data-test="run-query-button"]').click();
|
||||
cy.wait('@postJson');
|
||||
cy.reload();
|
||||
cy.verifySliceSuccess({
|
||||
|
@ -90,7 +90,7 @@ describe('Annotations', () => {
|
|||
cy.get('button').contains('OK').click();
|
||||
});
|
||||
|
||||
cy.get('button.query').click();
|
||||
cy.get('button[data-test="run-query-button"]').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@postJson',
|
||||
chartSelector: 'svg',
|
||||
|
|
|
@ -78,7 +78,7 @@ describe('Groupby control', () => {
|
|||
cy.get('.Select__control').click();
|
||||
cy.get('input[type=text]').type('state{enter}');
|
||||
});
|
||||
cy.get('button.query').click();
|
||||
cy.get('button[data-test="run-query-button"]').click();
|
||||
cy.verifySliceSuccess({ waitAlias: '@postJson', chartSelector: 'svg' });
|
||||
});
|
||||
});
|
||||
|
|
|
@ -34830,16 +34830,14 @@
|
|||
"version": "3.6.5",
|
||||
"resolved": "https://registry.npmjs.org/polished/-/polished-3.6.5.tgz",
|
||||
"integrity": "sha512-VwhC9MlhW7O5dg/z7k32dabcAFW1VI2+7fSe8cE/kXcfL7mVdoa5UxciYGW2sJU78ldDLT6+ROEKIZKFNTnUXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.10.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz",
|
||||
"integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==",
|
||||
"dev": true,
|
||||
"version": "7.11.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz",
|
||||
"integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
|
|
|
@ -145,6 +145,7 @@
|
|||
"mousetrap": "^1.6.1",
|
||||
"mustache": "^2.2.1",
|
||||
"omnibar": "^2.1.1",
|
||||
"polished": "^3.6.5",
|
||||
"prop-types": "^15.7.2",
|
||||
"re-resizable": "^4.3.1",
|
||||
"react": "^16.13.1",
|
||||
|
|
|
@ -51,5 +51,5 @@ export function styledShallow(
|
|||
theme: supersetTheme,
|
||||
...options?.wrappingComponentProps,
|
||||
},
|
||||
});
|
||||
}).dive();
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import Select from 'src/components/Select';
|
||||
import AddSliceContainer, {
|
||||
AddSliceContainerProps,
|
||||
|
@ -58,9 +58,9 @@ describe('AddSliceContainer', () => {
|
|||
});
|
||||
|
||||
it('renders a disabled button if no datasource is selected', () => {
|
||||
expect(
|
||||
wrapper.find(Button).dive().find('.btn[disabled=true]'),
|
||||
).toHaveLength(1);
|
||||
expect(wrapper.find(Button).dive().find({ disabled: true })).toHaveLength(
|
||||
1,
|
||||
);
|
||||
});
|
||||
|
||||
it('renders an enabled button if datasource is selected', () => {
|
||||
|
@ -70,9 +70,9 @@ describe('AddSliceContainer', () => {
|
|||
datasourceId: datasourceValue.split('__')[0],
|
||||
datasourceType: datasourceValue.split('__')[1],
|
||||
});
|
||||
expect(
|
||||
wrapper.find(Button).dive().find('.btn[disabled=false]'),
|
||||
).toHaveLength(1);
|
||||
expect(wrapper.find(Button).dive().find({ disabled: true })).toHaveLength(
|
||||
0,
|
||||
);
|
||||
});
|
||||
|
||||
it('formats explore url', () => {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import { supersetTheme, ThemeProvider } from '@superset-ui/style';
|
||||
import ConfirmStatusChange from 'src/components/ConfirmStatusChange';
|
||||
import Modal from 'src/components/Modal';
|
||||
|
@ -33,7 +33,7 @@ describe('ConfirmStatusChange', () => {
|
|||
<ConfirmStatusChange {...mockedProps}>
|
||||
{confirm => (
|
||||
<>
|
||||
<button id="btn1" onClick={confirm} />
|
||||
<Button id="btn1" onClick={confirm} />
|
||||
</>
|
||||
)}
|
||||
</ConfirmStatusChange>,
|
||||
|
@ -44,7 +44,7 @@ describe('ConfirmStatusChange', () => {
|
|||
);
|
||||
|
||||
it('opens a confirm modal', () => {
|
||||
wrapper.find('#btn1').props().onClick('foo');
|
||||
wrapper.find('#btn1').first().props().onClick('foo');
|
||||
|
||||
wrapper.update();
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
import { Provider } from 'react-redux';
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { styledMount as mount } from 'spec/helpers/theming';
|
||||
import sinon from 'sinon';
|
||||
|
||||
import DashboardComponent from 'src/dashboard/containers/DashboardComponent';
|
||||
|
|
|
@ -83,7 +83,10 @@ describe('DatasourceModal', () => {
|
|||
|
||||
it('saves on confirm', async () => {
|
||||
act(() => {
|
||||
wrapper.find('[className="m-r-5"]').props().onClick();
|
||||
wrapper
|
||||
.find('button[data-test="datasource-modal-save"]')
|
||||
.props()
|
||||
.onClick();
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
act(() => {
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
import { shallow } from 'enzyme';
|
||||
import { Button, Popover, Tab, Tabs } from 'react-bootstrap';
|
||||
import { Popover, Tab, Tabs } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
|
||||
import AdhocFilter, {
|
||||
EXPRESSION_TYPES,
|
||||
|
@ -117,9 +118,9 @@ describe('AdhocFilterEditPopover', () => {
|
|||
|
||||
it('highlights save if changes are present', () => {
|
||||
const { wrapper } = setup();
|
||||
expect(wrapper.find(Button).find({ bsStyle: 'primary' })).not.toExist();
|
||||
expect(wrapper.find(Button).find({ buttonStyle: 'primary' })).not.toExist();
|
||||
wrapper.instance().onAdhocFilterChange(sqlAdhocFilter);
|
||||
expect(wrapper.find(Button).find({ bsStyle: 'primary' })).toExist();
|
||||
expect(wrapper.find(Button).find({ buttonStyle: 'primary' })).toExist();
|
||||
});
|
||||
|
||||
it('will initiate a drag when clicked', () => {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
/* eslint-disable no-unused-expressions */
|
||||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
import { shallow } from 'enzyme';
|
||||
import { styledShallow as shallow } from 'spec/helpers/theming';
|
||||
import { OverlayTrigger } from 'react-bootstrap';
|
||||
|
||||
import Label from 'src/components/Label';
|
||||
|
@ -46,7 +46,7 @@ function setup(overrides) {
|
|||
datasource: {},
|
||||
...overrides,
|
||||
};
|
||||
const wrapper = shallow(<AdhocFilterOption {...props} />);
|
||||
const wrapper = shallow(<AdhocFilterOption {...props} />).dive();
|
||||
return { wrapper };
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
import { shallow } from 'enzyme';
|
||||
import { Button, FormGroup, Popover } from 'react-bootstrap';
|
||||
import { FormGroup, Popover } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
|
||||
import AdhocMetric, { EXPRESSION_TYPES } from 'src/explore/AdhocMetric';
|
||||
import AdhocMetricEditPopover from 'src/explore/components/AdhocMetricEditPopover';
|
||||
|
@ -117,9 +118,9 @@ describe('AdhocMetricEditPopover', () => {
|
|||
|
||||
it('highlights save if changes are present', () => {
|
||||
const { wrapper } = setup();
|
||||
expect(wrapper.find(Button).find({ bsStyle: 'primary' })).not.toExist();
|
||||
expect(wrapper.find(Button).find({ buttonStyle: 'primary' })).not.toExist();
|
||||
wrapper.instance().onColumnChange({ column: columns[1] });
|
||||
expect(wrapper.find(Button).find({ bsStyle: 'primary' })).toExist();
|
||||
expect(wrapper.find(Button).find({ buttonStyle: 'primary' })).toExist();
|
||||
});
|
||||
|
||||
it('will initiate a drag when clicked', () => {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
/* eslint-disable no-unused-expressions */
|
||||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
import { shallow } from 'enzyme';
|
||||
import { styledShallow as shallow } from 'spec/helpers/theming';
|
||||
import { OverlayTrigger } from 'react-bootstrap';
|
||||
|
||||
import Label from 'src/components/Label';
|
||||
|
@ -46,7 +46,7 @@ function setup(overrides) {
|
|||
columns,
|
||||
...overrides,
|
||||
};
|
||||
const wrapper = shallow(<AdhocMetricOption {...props} />);
|
||||
const wrapper = shallow(<AdhocMetricOption {...props} />).dive();
|
||||
return { wrapper, onMetricEdit };
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
import { styledMount as mount } from 'spec/helpers/theming';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
|
||||
import Label from 'src/components/Label';
|
||||
import DateFilterControl from 'src/explore/components/controls/DateFilterControl';
|
||||
|
|
|
@ -54,7 +54,7 @@ describe('QueryAndSaveButtons', () => {
|
|||
});
|
||||
|
||||
it('calls onQuery when query button is clicked', () => {
|
||||
const queryButton = wrapper.find('.query');
|
||||
const queryButton = wrapper.find('[data-test="run-query-button"]');
|
||||
queryButton.simulate('click');
|
||||
expect(defaultProps.onQuery.called).toBe(true);
|
||||
});
|
||||
|
|
|
@ -21,8 +21,10 @@ import configureStore from 'redux-mock-store';
|
|||
import thunk from 'redux-thunk';
|
||||
import { bindActionCreators } from 'redux';
|
||||
|
||||
import { shallow, mount } from 'enzyme';
|
||||
import { FormControl, Modal, Button, Radio } from 'react-bootstrap';
|
||||
import { shallow } from 'enzyme';
|
||||
import { styledMount as mount } from 'spec/helpers/theming';
|
||||
import { FormControl, Modal, Radio } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import sinon from 'sinon';
|
||||
import fetchMock from 'fetch-mock';
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import { shallow } from 'enzyme';
|
||||
import sinon from 'sinon';
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ describe('SouthPane', () => {
|
|||
const getWrapper = () =>
|
||||
shallow(<SouthPaneContainer {...mockedProps} />, {
|
||||
context: { store },
|
||||
}).dive();
|
||||
});
|
||||
|
||||
let wrapper;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import React, { ReactNode } from 'react';
|
||||
import shortid from 'shortid';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import Button from '../components/Button';
|
||||
import Button from 'src/components/Button';
|
||||
import Fieldset from './Fieldset';
|
||||
import { recurseReactClone } from './utils';
|
||||
import './crud.less';
|
||||
|
@ -167,7 +167,7 @@ export default class CRUDCollection extends React.PureComponent<
|
|||
{allowDeletes && !allowAddItem && <th className="tiny-cell" />}
|
||||
{allowAddItem && (
|
||||
<th>
|
||||
<Button bsStyle="primary" onClick={this.onAddItem}>
|
||||
<Button buttonStyle="primary" onClick={this.onAddItem}>
|
||||
<i className="fa fa-plus" /> {t('Add Item')}
|
||||
</Button>
|
||||
</th>
|
||||
|
|
|
@ -22,7 +22,7 @@ import { Table } from 'reactable-arc';
|
|||
import { Alert } from 'react-bootstrap';
|
||||
import { t } from '@superset-ui/translation';
|
||||
|
||||
import Button from '../../components/Button';
|
||||
import Button from 'src/components/Button';
|
||||
import Loading from '../../components/Loading';
|
||||
import ModalTrigger from '../../components/ModalTrigger';
|
||||
|
||||
|
@ -85,8 +85,8 @@ class EstimateQueryCostButton extends React.PureComponent {
|
|||
modalBody={this.renderModalBody()}
|
||||
triggerNode={
|
||||
<Button
|
||||
bsStyle="warning"
|
||||
bsSize="small"
|
||||
buttonStyle="warning"
|
||||
buttonSize="small"
|
||||
onClick={this.onClick}
|
||||
key="query-estimate-btn"
|
||||
tooltip={tooltip}
|
||||
|
|
|
@ -24,9 +24,9 @@ import Dialog from 'react-bootstrap-dialog';
|
|||
import { t } from '@superset-ui/translation';
|
||||
import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
|
||||
|
||||
import Button from 'src/components/Button';
|
||||
import { exploreChart } from '../../explore/exploreUtils';
|
||||
import * as actions from '../actions/sqlLab';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
const propTypes = {
|
||||
actions: PropTypes.object.isRequired,
|
||||
|
@ -89,7 +89,7 @@ class ExploreCtasResultsButton extends React.PureComponent {
|
|||
return (
|
||||
<>
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
onClick={this.onClick}
|
||||
tooltip={t('Explore the result set in the data exploration view')}
|
||||
>
|
||||
|
|
|
@ -25,11 +25,11 @@ import { Alert } from 'react-bootstrap';
|
|||
import Dialog from 'react-bootstrap-dialog';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
|
||||
|
||||
import shortid from 'shortid';
|
||||
|
||||
import Button from 'src/components/Button';
|
||||
import { exploreChart } from '../../explore/exploreUtils';
|
||||
import * as actions from '../actions/sqlLab';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
const propTypes = {
|
||||
actions: PropTypes.object.isRequired,
|
||||
|
@ -213,7 +213,7 @@ class ExploreResultsButton extends React.PureComponent {
|
|||
return (
|
||||
<>
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
onClick={this.onClick}
|
||||
disabled={!allowsSubquery}
|
||||
tooltip={t('Explore the result set in the data exploration view')}
|
||||
|
|
|
@ -17,13 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import {
|
||||
Button,
|
||||
FormGroup,
|
||||
FormControl,
|
||||
Overlay,
|
||||
Popover,
|
||||
} from 'react-bootstrap';
|
||||
import { FormGroup, FormControl, Overlay, Popover } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import styled from '@superset-ui/style';
|
||||
|
||||
|
@ -119,8 +114,8 @@ export default class LimitControl extends React.PureComponent<
|
|||
</FormGroup>
|
||||
<div className="clearfix">
|
||||
<Button
|
||||
bsSize="small"
|
||||
bsStyle="primary"
|
||||
buttonSize="small"
|
||||
buttonStyle="primary"
|
||||
className="float-right ok m-l-5"
|
||||
disabled={!isValid}
|
||||
onClick={this.submitAndClose}
|
||||
|
@ -128,7 +123,7 @@ export default class LimitControl extends React.PureComponent<
|
|||
{t('Ok')}
|
||||
</Button>
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
className="float-right reset"
|
||||
onClick={this.setValueAndClose.bind(
|
||||
this,
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import Select from 'src/components/Select';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import { SupersetClient } from '@superset-ui/connection';
|
||||
|
@ -273,8 +273,8 @@ class QuerySearch extends React.PureComponent {
|
|||
/>
|
||||
|
||||
<Button
|
||||
bsSize="small"
|
||||
bsStyle="success"
|
||||
buttonSize="small"
|
||||
buttonStyle="success"
|
||||
onClick={this.refreshQueries}
|
||||
>
|
||||
{t('Search')}
|
||||
|
|
|
@ -24,6 +24,7 @@ import { ProgressBar, Well } from 'react-bootstrap';
|
|||
import Label from 'src/components/Label';
|
||||
import { t } from '@superset-ui/translation';
|
||||
|
||||
import Button from 'src/components/Button';
|
||||
import Link from '../../components/Link';
|
||||
import ResultSet from './ResultSet';
|
||||
import ModalTrigger from '../../components/ModalTrigger';
|
||||
|
@ -99,31 +100,34 @@ class QueryTable extends React.PureComponent {
|
|||
</div>
|
||||
);
|
||||
q.user = (
|
||||
<button
|
||||
className="btn btn-link btn-xs"
|
||||
<Button
|
||||
buttonSize="small"
|
||||
buttonStyle="link"
|
||||
onClick={this.props.onUserClicked.bind(this, q.userId)}
|
||||
>
|
||||
{q.user}
|
||||
</button>
|
||||
</Button>
|
||||
);
|
||||
q.db = (
|
||||
<button
|
||||
className="btn btn-link btn-xs"
|
||||
<Button
|
||||
buttonSize="small"
|
||||
buttonStyle="link"
|
||||
onClick={this.props.onDbClicked.bind(this, q.dbId)}
|
||||
>
|
||||
{q.db}
|
||||
</button>
|
||||
</Button>
|
||||
);
|
||||
q.started = moment(q.startDttm).format('HH:mm:ss');
|
||||
q.querylink = (
|
||||
<div style={{ width: '100px' }}>
|
||||
<button
|
||||
className="btn btn-link btn-xs"
|
||||
<Button
|
||||
buttonSize="small"
|
||||
buttonStyle="link"
|
||||
onClick={this.openQuery.bind(this, q.queryId)}
|
||||
>
|
||||
<i className="fa fa-external-link m-r-3" />
|
||||
{t('Edit')}
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
q.sql = (
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
import React, { CSSProperties } from 'react';
|
||||
import { Alert, Button, ButtonGroup, ProgressBar } from 'react-bootstrap';
|
||||
import { Alert, ButtonGroup, ProgressBar } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import shortid from 'shortid';
|
||||
import { t } from '@superset-ui/translation';
|
||||
|
||||
|
@ -166,7 +167,7 @@ export default class ResultSet extends React.PureComponent<
|
|||
)}
|
||||
{this.props.csv && (
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
href={`/superset/csv/${this.props.query.id}`}
|
||||
>
|
||||
<i className="fa fa-file-text-o" /> {t('.CSV')}
|
||||
|
@ -177,7 +178,7 @@ export default class ResultSet extends React.PureComponent<
|
|||
text={prepareCopyToClipboardTabularData(data)}
|
||||
wrapped={false}
|
||||
copyNode={
|
||||
<Button bsSize="small">
|
||||
<Button buttonSize="small">
|
||||
<i className="fa fa-clipboard" /> {t('Clipboard')}
|
||||
</Button>
|
||||
}
|
||||
|
@ -243,7 +244,7 @@ export default class ResultSet extends React.PureComponent<
|
|||
] {t('was created')}
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
className="m-r-5"
|
||||
onClick={() => this.popSelectStar(tempSchema, tempTable)}
|
||||
>
|
||||
|
@ -296,9 +297,9 @@ export default class ResultSet extends React.PureComponent<
|
|||
if (query.isDataPreview) {
|
||||
return (
|
||||
<Button
|
||||
bsSize="sm"
|
||||
buttonSize="sm"
|
||||
className="fetch"
|
||||
bsStyle="primary"
|
||||
buttonStyle="primary"
|
||||
onClick={() =>
|
||||
this.reFetchQueryResults({
|
||||
...query,
|
||||
|
@ -312,9 +313,9 @@ export default class ResultSet extends React.PureComponent<
|
|||
} else if (query.resultsKey) {
|
||||
return (
|
||||
<Button
|
||||
bsSize="sm"
|
||||
buttonSize="sm"
|
||||
className="fetch"
|
||||
bsStyle="primary"
|
||||
buttonStyle="primary"
|
||||
onClick={() => this.fetchResults(query)}
|
||||
>
|
||||
{t('Refetch Results')}
|
||||
|
@ -336,7 +337,7 @@ export default class ResultSet extends React.PureComponent<
|
|||
if (query.trackingUrl) {
|
||||
trackingUrl = (
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
onClick={() => query.trackingUrl && window.open(query.trackingUrl)}
|
||||
>
|
||||
{t('Track Job')}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import React from 'react';
|
||||
import { t } from '@superset-ui/translation';
|
||||
|
||||
import Button, { ButtonProps } from '../../components/Button';
|
||||
import Button, { ButtonProps } from 'src/components/Button';
|
||||
|
||||
const NO_OP = () => undefined;
|
||||
|
||||
|
@ -32,9 +32,6 @@ interface Props {
|
|||
stopQuery: () => void;
|
||||
sql: string;
|
||||
}
|
||||
const commonBtnStyle = {
|
||||
width: '140px',
|
||||
};
|
||||
|
||||
const RunQueryActionButton = ({
|
||||
allowAsync = false,
|
||||
|
@ -51,15 +48,14 @@ const RunQueryActionButton = ({
|
|||
!!queryState && ['running', 'pending'].indexOf(queryState) > -1;
|
||||
|
||||
const commonBtnProps: ButtonProps = {
|
||||
bsSize: 'small',
|
||||
bsStyle: btnStyle,
|
||||
buttonSize: 'small',
|
||||
buttonStyle: btnStyle,
|
||||
disabled: !dbId,
|
||||
style: commonBtnStyle,
|
||||
};
|
||||
|
||||
if (shouldShowStopBtn) {
|
||||
return (
|
||||
<Button {...commonBtnProps} onClick={stopQuery}>
|
||||
<Button {...commonBtnProps} cta onClick={stopQuery}>
|
||||
<i className="fa fa-stop" /> {t('Stop')}
|
||||
</Button>
|
||||
);
|
||||
|
@ -67,6 +63,7 @@ const RunQueryActionButton = ({
|
|||
return (
|
||||
<Button
|
||||
{...commonBtnProps}
|
||||
cta
|
||||
onClick={() => runQuery(true)}
|
||||
key="run-async-btn"
|
||||
tooltip={t('Run query asynchronously (Ctrl + ↵)')}
|
||||
|
@ -79,6 +76,7 @@ const RunQueryActionButton = ({
|
|||
return (
|
||||
<Button
|
||||
{...commonBtnProps}
|
||||
cta
|
||||
onClick={() => runQuery(false)}
|
||||
key="run-btn"
|
||||
tooltip={t('Run query synchronously (Ctrl + ↵)')}
|
||||
|
|
|
@ -135,7 +135,7 @@ class SaveQuery extends React.PureComponent {
|
|||
<Col md={12}>
|
||||
{isSaved && (
|
||||
<Button
|
||||
bsStyle="primary"
|
||||
buttonStyle="primary"
|
||||
onClick={this.onUpdate}
|
||||
className="m-r-3"
|
||||
>
|
||||
|
@ -143,7 +143,7 @@ class SaveQuery extends React.PureComponent {
|
|||
</Button>
|
||||
)}
|
||||
<Button
|
||||
bsStyle={isSaved ? undefined : 'primary'}
|
||||
buttonStyle={isSaved ? undefined : 'primary'}
|
||||
onClick={this.onSave}
|
||||
className="m-r-3"
|
||||
>
|
||||
|
@ -169,7 +169,7 @@ class SaveQuery extends React.PureComponent {
|
|||
backdrop="static"
|
||||
triggerNode={
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
className="toggleSave"
|
||||
onClick={this.toggleSave}
|
||||
>
|
||||
|
|
|
@ -192,7 +192,7 @@ class ScheduleQueryButton extends React.PureComponent {
|
|||
modalBody={this.renderModalBody()}
|
||||
triggerNode={
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
className="toggleSchedule"
|
||||
onClick={this.toggleSchedule}
|
||||
disabled={this.props.disabled}
|
||||
|
|
|
@ -22,7 +22,7 @@ import { Popover, OverlayTrigger } from 'react-bootstrap';
|
|||
import { t } from '@superset-ui/translation';
|
||||
import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
|
||||
|
||||
import Button from '../../components/Button';
|
||||
import Button from 'src/components/Button';
|
||||
import CopyToClipboard from '../../components/CopyToClipboard';
|
||||
import { storeQuery } from '../../utils/common';
|
||||
import getClientErrorObject from '../../utils/getClientErrorObject';
|
||||
|
@ -110,7 +110,7 @@ class ShareSqlLabQuery extends React.Component {
|
|||
shouldUpdatePosition
|
||||
overlay={this.renderPopover()}
|
||||
>
|
||||
<Button bsSize="small" className="toggleSave">
|
||||
<Button buttonSize="small" className="toggleSave">
|
||||
<i className="fa fa-share" /> {t('Share')}
|
||||
</Button>
|
||||
</OverlayTrigger>
|
||||
|
|
|
@ -398,7 +398,7 @@ class SqlEditor extends React.PureComponent {
|
|||
<InputGroup.Button>
|
||||
{this.props.database.allow_ctas && (
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
disabled={this.state.ctas.length === 0}
|
||||
onClick={this.createTableAs.bind(this)}
|
||||
tooltip={ctasToolTip}
|
||||
|
@ -408,7 +408,7 @@ class SqlEditor extends React.PureComponent {
|
|||
)}
|
||||
{this.props.database.allow_cvas && (
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
disabled={this.state.ctas.length === 0}
|
||||
onClick={this.createViewAs.bind(this)}
|
||||
tooltip={cvasToolTip}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import TableElement from './TableElement';
|
||||
import TableSelector from '../../components/TableSelector';
|
||||
|
@ -140,7 +140,11 @@ export default class SqlEditorLeftBar extends React.PureComponent {
|
|||
</div>
|
||||
</div>
|
||||
{shouldShowReset && (
|
||||
<Button bsSize="small" bsStyle="danger" onClick={this.resetState}>
|
||||
<Button
|
||||
buttonSize="small"
|
||||
buttonStyle="danger"
|
||||
onClick={this.resetState}
|
||||
>
|
||||
<i className="fa fa-bomb" /> {t('Reset State')}
|
||||
</Button>
|
||||
)}
|
||||
|
|
|
@ -29,8 +29,8 @@ import 'brace/theme/textmate';
|
|||
import { t } from '@superset-ui/translation';
|
||||
import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
|
||||
|
||||
import Button from 'src/components/Button';
|
||||
import ModalTrigger from '../../components/ModalTrigger';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
const propTypes = {
|
||||
onChange: PropTypes.func,
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { Button, Panel } from 'react-bootstrap';
|
||||
import { Panel } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import Select from 'src/components/Select';
|
||||
import { t } from '@superset-ui/translation';
|
||||
|
||||
|
@ -142,7 +143,7 @@ export default class AddSliceContainer extends React.PureComponent<
|
|||
<br />
|
||||
<hr />
|
||||
<Button
|
||||
bsStyle="primary"
|
||||
buttonStyle="primary"
|
||||
disabled={this.isBtnDisabled()}
|
||||
onClick={this.gotoSlice}
|
||||
>
|
||||
|
|
|
@ -20,7 +20,7 @@ import React from 'react';
|
|||
import styled from '@superset-ui/style';
|
||||
import { Modal as BaseModal } from 'src/common/components';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import Button from 'src/views/CRUD/data/dataset/Button';
|
||||
import Button from 'src/components/Button';
|
||||
|
||||
interface ModalProps {
|
||||
className?: string;
|
||||
|
|
|
@ -25,13 +25,16 @@ export default {
|
|||
title: 'Button',
|
||||
component: Button,
|
||||
decorators: [withKnobs],
|
||||
excludeStories: /.*Knob$/,
|
||||
};
|
||||
|
||||
const bsStyleKnob = {
|
||||
export const buttonStyleKnob = {
|
||||
label: 'Types',
|
||||
options: {
|
||||
Primary: 'primary',
|
||||
Secondary: 'secondary',
|
||||
Tertiary: 'tertiary',
|
||||
Dashed: 'dashed',
|
||||
Danger: 'danger',
|
||||
Warning: 'warning',
|
||||
Success: 'success',
|
||||
|
@ -42,17 +45,18 @@ const bsStyleKnob = {
|
|||
defaultValue: null,
|
||||
// groupId: 'ButtonType',
|
||||
};
|
||||
const bsSizeKnob = {
|
||||
|
||||
export const buttonSizeKnob = {
|
||||
label: 'Sizes',
|
||||
options: {
|
||||
XS: 'xsmall',
|
||||
S: 'small',
|
||||
M: 'medium',
|
||||
Default: null,
|
||||
L: 'large',
|
||||
None: null,
|
||||
},
|
||||
defaultValue: null,
|
||||
};
|
||||
|
||||
// TODO remove the use of these in the codebase where they're not necessary
|
||||
// const classKnob = {
|
||||
// label: 'Known Classes',
|
||||
|
@ -62,7 +66,6 @@ const bsSizeKnob = {
|
|||
// Reset: 'reset',
|
||||
// Fetch: 'fetch',
|
||||
// Query: 'query',
|
||||
// saveBtn: 'save-btn',
|
||||
// MR3: 'm-r-3',
|
||||
// cancelQuery: 'cancelQuery',
|
||||
// toggleSave: 'toggleSave',
|
||||
|
@ -101,43 +104,43 @@ const hrefKnob = {
|
|||
|
||||
export const ButtonGallery = () => (
|
||||
<>
|
||||
{Object.values(bsSizeKnob.options)
|
||||
.filter(a => a)
|
||||
.map(size => (
|
||||
<div>
|
||||
<h4>{size}</h4>
|
||||
{Object.values(bsStyleKnob.options)
|
||||
.filter(o => o)
|
||||
.map(style => (
|
||||
<Button
|
||||
disabled={boolean('Disabled', false)}
|
||||
bsStyle={style}
|
||||
bsSize={size}
|
||||
onClick={action('clicked')}
|
||||
style={{ marginRight: 5 }}
|
||||
>
|
||||
{style}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
{Object.entries(buttonSizeKnob.options).map(([name, size]) => (
|
||||
<div key={size}>
|
||||
<h4>{name}</h4>
|
||||
{Object.values(buttonStyleKnob.options)
|
||||
.filter(o => o)
|
||||
.map(style => (
|
||||
<Button
|
||||
disabled={boolean('Disabled', false)}
|
||||
cta={boolean('CTA', false)}
|
||||
buttonStyle={style}
|
||||
buttonSize={size}
|
||||
onClick={action('clicked')}
|
||||
key={`${style}_${size}`}
|
||||
>
|
||||
{style}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
|
||||
export const InteractiveButton = () => (
|
||||
<Button
|
||||
disabled={boolean('Disabled', false)}
|
||||
bsStyle={select(
|
||||
bsStyleKnob.label,
|
||||
bsStyleKnob.options,
|
||||
bsStyleKnob.defaultValue,
|
||||
bsStyleKnob.groupId,
|
||||
cta={boolean('CTA', false)}
|
||||
buttonStyle={select(
|
||||
buttonStyleKnob.label,
|
||||
buttonStyleKnob.options,
|
||||
buttonStyleKnob.defaultValue,
|
||||
buttonStyleKnob.groupId,
|
||||
)}
|
||||
bsSize={select(
|
||||
bsSizeKnob.label,
|
||||
bsSizeKnob.options,
|
||||
bsSizeKnob.defaultValue,
|
||||
bsSizeKnob.groupId,
|
||||
size={select(
|
||||
buttonSizeKnob.label,
|
||||
buttonSizeKnob.options,
|
||||
buttonSizeKnob.defaultValue,
|
||||
buttonSizeKnob.groupId,
|
||||
)}
|
||||
onClick={action('clicked')}
|
||||
type={select(
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* 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';
|
||||
import { ReactWrapper } from 'enzyme';
|
||||
import { styledMount as mount } from 'spec/helpers/theming';
|
||||
import Button from '.';
|
||||
import {
|
||||
ButtonGallery,
|
||||
buttonSizeKnob,
|
||||
buttonStyleKnob,
|
||||
} from './Button.stories';
|
||||
|
||||
describe('Button', () => {
|
||||
let wrapper: ReactWrapper;
|
||||
|
||||
// test the basic component
|
||||
it('renders the base component', () => {
|
||||
expect(React.isValidElement(<Button />)).toBe(true);
|
||||
});
|
||||
|
||||
it('works with an onClick handler', () => {
|
||||
const mockAction = jest.fn();
|
||||
wrapper = mount(<Button onClick={mockAction} />);
|
||||
wrapper.find('Button').first().simulate('click');
|
||||
expect(mockAction).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not handle onClicks when disabled', () => {
|
||||
const mockAction = jest.fn();
|
||||
wrapper = mount(<Button onClick={mockAction} disabled />);
|
||||
wrapper.find('Button').first().simulate('click');
|
||||
expect(mockAction).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
// test stories from the storybook!
|
||||
it('All the sorybook gallery variants mount', () => {
|
||||
wrapper = mount(<ButtonGallery />);
|
||||
|
||||
const permutationCount =
|
||||
Object.values(buttonStyleKnob.options).filter(o => o).length *
|
||||
Object.values(buttonSizeKnob.options).length;
|
||||
|
||||
expect(wrapper.find(Button).length).toEqual(permutationCount);
|
||||
});
|
||||
|
||||
// test things NOT in the storybook!
|
||||
it('renders custom button styles without melting', () => {
|
||||
wrapper = mount(<Button buttonStyle="foobar" />);
|
||||
expect(wrapper.find('Button.btn-foobar')).toHaveLength(1);
|
||||
});
|
||||
});
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { kebabCase } from 'lodash';
|
||||
import { mix } from 'polished';
|
||||
import cx from 'classnames';
|
||||
import {
|
||||
Button as BootstrapButton,
|
||||
Tooltip,
|
||||
|
@ -40,52 +42,201 @@ export interface ButtonProps {
|
|||
placement?: string;
|
||||
onClick?: OnClickHandler;
|
||||
disabled?: boolean;
|
||||
bsStyle?: string;
|
||||
buttonStyle?: string;
|
||||
btnStyles?: string;
|
||||
bsSize?: BootstrapButton.ButtonProps['bsSize'];
|
||||
buttonSize?: BootstrapButton.ButtonProps['bsSize'];
|
||||
style?: BootstrapButton.ButtonProps['style'];
|
||||
children?: React.ReactNode;
|
||||
dropdownItems?: DropdownItemProps[];
|
||||
href?: string; // React-Bootstrap creates a link when this is passed in.
|
||||
target?: string; // React-Bootstrap creates a link when this is passed in.
|
||||
type?: string; // React-Bootstrap supports this when rendering an HTML button element
|
||||
cta?: boolean;
|
||||
}
|
||||
|
||||
const BUTTON_WRAPPER_STYLE = { display: 'inline-block', cursor: 'not-allowed' };
|
||||
|
||||
const SupersetButton = styled(BootstrapButton)`
|
||||
&.supersetButton {
|
||||
border-radius: ${({ theme }) => theme.borderRadius}px;
|
||||
border: none;
|
||||
color: ${({ theme }) => theme.colors.secondary.light5};
|
||||
font-size: ${({ theme }) => theme.typography.sizes.s}px;
|
||||
font-weight: ${({ theme }) => theme.typography.weights.bold};
|
||||
&:focus,
|
||||
&:active,
|
||||
&:focus:active {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
transition: all ${({ theme }) => theme.transitionTiming}s;
|
||||
border-radius: ${({ theme }) => theme.borderRadius}px;
|
||||
border: none;
|
||||
font-size: ${({ theme }) => theme.typography.sizes.s}px;
|
||||
font-weight: ${({ theme }) => theme.typography.weights.bold};
|
||||
margin-left: ${({ theme }) => theme.gridUnit * 4}px;
|
||||
&:first-of-type {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
i {
|
||||
padding: 0 ${({ theme }) => theme.gridUnit * 2}px 0 0;
|
||||
}
|
||||
|
||||
/* SIP 34 colors! */
|
||||
&.btn {
|
||||
border: 1px solid transparent; /* this just makes sure the height is the same as tertiary/dashed buttons */
|
||||
&:hover,
|
||||
&:active {
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
&-default,
|
||||
&-secondary {
|
||||
background-color: ${({ theme }) => theme.colors.primary.light4};
|
||||
color: ${({ theme }) => theme.colors.primary.dark1};
|
||||
&:hover {
|
||||
background-color: ${({ theme }) =>
|
||||
mix(0.1, theme.colors.grayscale.light5, theme.colors.primary.light4)};
|
||||
color: ${({ theme }) => theme.colors.primary.dark1};
|
||||
}
|
||||
&:active {
|
||||
background-color: ${({ theme }) =>
|
||||
mix(0.25, theme.colors.primary.base, theme.colors.primary.light4)};
|
||||
color: ${({ theme }) => theme.colors.primary.dark1};
|
||||
}
|
||||
}
|
||||
&-tertiary,
|
||||
&-dashed {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
background-color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
color: ${({ theme }) => theme.colors.primary.dark1};
|
||||
border-color: ${({ theme }) => theme.colors.primary.dark1};
|
||||
&:hover {
|
||||
background-color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
color: ${({ theme }) => theme.colors.primary.dark1};
|
||||
border-color: ${({ theme }) => theme.colors.primary.light1};
|
||||
}
|
||||
&:active {
|
||||
background-color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
color: ${({ theme }) => theme.colors.primary.dark1};
|
||||
border-color: ${({ theme }) => theme.colors.primary.dark1};
|
||||
}
|
||||
&[disabled],
|
||||
&[disabled]:hover {
|
||||
background-color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
color: ${({ theme }) => theme.colors.grayscale.base};
|
||||
border-color: ${({ theme }) => theme.colors.grayscale.light2};
|
||||
}
|
||||
}
|
||||
&-dashed {
|
||||
border-style: dashed;
|
||||
&:hover,
|
||||
&:active {
|
||||
border-style: dashed;
|
||||
}
|
||||
}
|
||||
&-link {
|
||||
background: none;
|
||||
text-decoration: none;
|
||||
color: ${({ theme }) => theme.colors.primary.dark1};
|
||||
&:hover {
|
||||
background: none;
|
||||
color: ${({ theme }) => theme.colors.primary.base};
|
||||
}
|
||||
&:active {
|
||||
background: none;
|
||||
color: ${({ theme }) => theme.colors.primary.dark1};
|
||||
}
|
||||
&[disabled],
|
||||
&[disabled]:hover {
|
||||
background: none;
|
||||
color: ${({ theme }) => theme.colors.grayscale.base};
|
||||
}
|
||||
}
|
||||
&-primary {
|
||||
background-color: ${({ theme }) => theme.colors.primary.dark1};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
&:hover {
|
||||
background-color: ${({ theme }) =>
|
||||
mix(0.1, theme.colors.grayscale.light5, theme.colors.primary.dark1)};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
}
|
||||
&:active {
|
||||
background-color: ${({ theme }) =>
|
||||
mix(0.2, theme.colors.grayscale.dark2, theme.colors.primary.dark1)};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
}
|
||||
}
|
||||
&-danger {
|
||||
background-color: ${({ theme }) => theme.colors.error.base};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
&:hover {
|
||||
background-color: ${({ theme }) =>
|
||||
mix(0.1, theme.colors.grayscale.light5, theme.colors.error.base)};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
}
|
||||
&:active {
|
||||
background-color: ${({ theme }) =>
|
||||
mix(0.2, theme.colors.grayscale.dark2, theme.colors.error.base)};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
}
|
||||
}
|
||||
&-success {
|
||||
background-color: ${({ theme }) => theme.colors.success.base};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
&:hover {
|
||||
background-color: ${({ theme }) =>
|
||||
mix(0.1, theme.colors.grayscale.light5, theme.colors.success.base)};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
}
|
||||
&:active {
|
||||
background-color: ${({ theme }) =>
|
||||
mix(0.2, theme.colors.grayscale.dark2, theme.colors.success.base)};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
}
|
||||
}
|
||||
&-warning {
|
||||
background-color: ${({ theme }) => theme.colors.warning.base};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
&:hover {
|
||||
background-color: ${({ theme }) =>
|
||||
mix(0.1, theme.colors.grayscale.light5, theme.colors.warning.base)};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
}
|
||||
&:active {
|
||||
background-color: ${({ theme }) =>
|
||||
mix(0.2, theme.colors.grayscale.dark2, theme.colors.warning.base)};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
}
|
||||
}
|
||||
&-info {
|
||||
background-color: ${({ theme }) => theme.colors.info.dark1};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
&:hover {
|
||||
background-color: ${({ theme }) =>
|
||||
mix(0.1, theme.colors.grayscale.light5, theme.colors.info.dark1)};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
}
|
||||
&:active {
|
||||
background-color: ${({ theme }) =>
|
||||
mix(0.2, theme.colors.grayscale.dark2, theme.colors.info.dark1)};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
}
|
||||
}
|
||||
&[disabled],
|
||||
&[disabled]:hover {
|
||||
background-color: ${({ theme }) => theme.colors.grayscale.light2};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light1};
|
||||
}
|
||||
}
|
||||
|
||||
/* big Call to Action buttons */
|
||||
&.cta {
|
||||
min-width: ${({ theme }) => theme.gridUnit * 36}px;
|
||||
min-height: ${({ theme }) => theme.gridUnit * 8}px;
|
||||
text-transform: uppercase;
|
||||
margin-left: ${({ theme }) => theme.gridUnit * 4}px;
|
||||
&:first-of-type {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
i {
|
||||
padding: 0 ${({ theme }) => theme.gridUnit * 2}px 0 0;
|
||||
}
|
||||
|
||||
&.primary {
|
||||
background-color: ${({ theme }) => theme.colors.primary.base};
|
||||
}
|
||||
&.secondary {
|
||||
color: ${({ theme }) => theme.colors.primary.base};
|
||||
background-color: ${({ theme }) => theme.colors.primary.light4};
|
||||
}
|
||||
&.danger {
|
||||
background-color: ${({ theme }) => theme.colors.error.base};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default function Button(props: ButtonProps) {
|
||||
const buttonProps = {
|
||||
...props,
|
||||
bsSize: props.bsSize || 'sm',
|
||||
bsSize: props.buttonSize,
|
||||
placement: props.placement || 'top',
|
||||
};
|
||||
const tooltip = props.tooltip;
|
||||
|
@ -100,17 +251,40 @@ export default function Button(props: ButtonProps) {
|
|||
buttonProps.style = { pointerEvents: 'none' };
|
||||
}
|
||||
|
||||
let button = (
|
||||
<SupersetButton {...buttonProps}>{props.children}</SupersetButton>
|
||||
);
|
||||
const officialBootstrapStyles = [
|
||||
'success',
|
||||
'warning',
|
||||
'danger',
|
||||
'info',
|
||||
'default',
|
||||
'primary',
|
||||
];
|
||||
|
||||
const whittledProps = { ...buttonProps };
|
||||
delete whittledProps.dropdownItems;
|
||||
const transformedProps = {
|
||||
...buttonProps,
|
||||
bsStyle: officialBootstrapStyles.includes(props.buttonStyle || '')
|
||||
? props.buttonStyle
|
||||
: 'default',
|
||||
className: cx(props.className, {
|
||||
cta: !!buttonProps.cta,
|
||||
[`btn-${props.buttonStyle}`]: !officialBootstrapStyles.includes(
|
||||
props.buttonStyle || '',
|
||||
),
|
||||
}),
|
||||
};
|
||||
delete transformedProps.dropdownItems;
|
||||
delete transformedProps.buttonSize;
|
||||
delete transformedProps.buttonStyle;
|
||||
delete transformedProps.cta;
|
||||
|
||||
let button = (
|
||||
<SupersetButton {...transformedProps}>{props.children}</SupersetButton>
|
||||
);
|
||||
|
||||
if (dropdownItems) {
|
||||
button = (
|
||||
<div style={BUTTON_WRAPPER_STYLE}>
|
||||
<SupersetButton {...whittledProps} data-toggle="dropdown">
|
||||
<SupersetButton {...transformedProps} data-toggle="dropdown">
|
||||
{props.children}
|
||||
</SupersetButton>
|
||||
<ul className="dropdown-menu">
|
||||
|
|
|
@ -21,7 +21,7 @@ import { Modal } from 'react-bootstrap';
|
|||
import { styled, supersetTheme } from '@superset-ui/style';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import { noOp } from 'src/utils/common';
|
||||
import Button from 'src/views/CRUD/data/dataset/Button';
|
||||
import Button from 'src/components/Button';
|
||||
|
||||
import Icon from '../Icon';
|
||||
import { ErrorLevel, ErrorSource } from './types';
|
||||
|
@ -190,7 +190,11 @@ export default function ErrorAlert({
|
|||
copyNode={<Button onClick={noOp}>{t('Copy Message')}</Button>}
|
||||
/>
|
||||
)}
|
||||
<Button bsStyle="primary" onClick={() => setIsModalOpen(false)}>
|
||||
<Button
|
||||
cta
|
||||
buttonStyle="primary"
|
||||
onClick={() => setIsModalOpen(false)}
|
||||
>
|
||||
{t('Close')}
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
|
|
|
@ -39,12 +39,12 @@ export default function ExpandableList({ items, display = 3 }: Props) {
|
|||
const showMoreAction = items.length > display;
|
||||
|
||||
const lessAction = (
|
||||
<Button bsStyle="link" bsSize="xsmall" onClick={toggleShowingAll}>
|
||||
<Button buttonStyle="link" buttonSize="xsmall" onClick={toggleShowingAll}>
|
||||
less
|
||||
</Button>
|
||||
);
|
||||
const moreAction = (
|
||||
<Button bsStyle="link" bsSize="xsmall" onClick={toggleShowingAll}>
|
||||
<Button buttonStyle="link" buttonSize="xsmall" onClick={toggleShowingAll}>
|
||||
{items.length - itemsToDisplay.length} more
|
||||
</Button>
|
||||
);
|
||||
|
|
|
@ -25,7 +25,7 @@ export default {
|
|||
title: 'Label',
|
||||
component: Label,
|
||||
decorators: [withKnobs],
|
||||
excludeStories: ['bsStyleKnob'],
|
||||
excludeStories: /.*Knob$/,
|
||||
};
|
||||
|
||||
export const bsStyleKnob = {
|
||||
|
|
|
@ -311,11 +311,12 @@ function ListView<T extends object = any>({
|
|||
<Button
|
||||
data-test="bulk-select-action"
|
||||
key={action.key}
|
||||
className={cx('supersetButton', {
|
||||
className={cx({
|
||||
danger: action.type === 'danger',
|
||||
primary: action.type === 'primary',
|
||||
secondary: action.type === 'secondary',
|
||||
})}
|
||||
cta
|
||||
onClick={() =>
|
||||
action.onSelect(selectedFlatRows.map(r => r.original))
|
||||
}
|
||||
|
|
|
@ -129,6 +129,14 @@ const StyledHeader = styled.header`
|
|||
margin-bottom: 8px;
|
||||
border-bottom: 1px solid ${({ theme }) => theme.colors.grayscale.light2};
|
||||
}
|
||||
.navbar-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.dropdown:first-of-type {
|
||||
/* this is the "+ NEW" button. Sweep this up when it's replaced */
|
||||
margin-right: ${({ theme }) => theme.gridUnit * 2}px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export function Menu({
|
||||
|
|
|
@ -17,15 +17,9 @@
|
|||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import styled from '@superset-ui/style';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import Button, { DropdownItemProps } from '../Button';
|
||||
|
||||
const StyledButton = styled(Button)`
|
||||
margin-top: 12px;
|
||||
margin-right: 30px;
|
||||
`;
|
||||
|
||||
const dropdownItems: DropdownItemProps[] = [
|
||||
{
|
||||
label: t('SQL Query'),
|
||||
|
@ -47,12 +41,9 @@ const dropdownItems: DropdownItemProps[] = [
|
|||
export default function NewMenu() {
|
||||
return (
|
||||
<li className="dropdown">
|
||||
<StyledButton
|
||||
className="dropdown-toggle btn btn-sm btn-primary"
|
||||
dropdownItems={dropdownItems}
|
||||
>
|
||||
<Button buttonStyle="primary" dropdownItems={dropdownItems}>
|
||||
<i className="fa fa-plus" /> New
|
||||
</StyledButton>
|
||||
</Button>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -26,12 +26,8 @@ const StyledHeader = styled.header`
|
|||
font-weight: ${({ theme }) => theme.typography.weights.bold};
|
||||
}
|
||||
.navbar-right {
|
||||
.supersetButton {
|
||||
margin: ${({ theme }) =>
|
||||
`${theme.gridUnit * 2}px ${theme.gridUnit * 4}px ${
|
||||
theme.gridUnit * 2
|
||||
}px 0`};
|
||||
}
|
||||
padding: 8px 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
.navbar-nav {
|
||||
li {
|
||||
|
@ -94,16 +90,18 @@ const SubMenu: React.FunctionComponent<SubMenuProps> = props => {
|
|||
<Nav className="navbar-right">
|
||||
{props.secondaryButton && (
|
||||
<Button
|
||||
className="supersetButton secondary"
|
||||
buttonStyle="secondary"
|
||||
onClick={props.secondaryButton.onClick}
|
||||
cta
|
||||
>
|
||||
{props.secondaryButton.name}
|
||||
</Button>
|
||||
)}
|
||||
{props.primaryButton && (
|
||||
<Button
|
||||
className="supersetButton primary"
|
||||
buttonStyle="primary"
|
||||
onClick={props.primaryButton.onClick}
|
||||
cta
|
||||
>
|
||||
{props.primaryButton.name}
|
||||
</Button>
|
||||
|
|
|
@ -20,7 +20,7 @@ import React from 'react';
|
|||
import styled from '@superset-ui/style';
|
||||
import { Modal as BaseModal } from 'react-bootstrap';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import Button from 'src/views/CRUD/data/dataset/Button';
|
||||
import Button from 'src/components/Button';
|
||||
|
||||
interface ModalProps {
|
||||
children: React.ReactNode;
|
||||
|
@ -54,9 +54,6 @@ const StyledModal = styled(BaseModal)`
|
|||
.modal-footer {
|
||||
border-top: 1px solid ${({ theme }) => theme.colors.grayscale.light2};
|
||||
padding: 16px;
|
||||
.btn + .btn {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -86,11 +83,14 @@ export default function Modal({
|
|||
<BaseModal.Body>{children}</BaseModal.Body>
|
||||
<BaseModal.Footer>
|
||||
<span className="float-right">
|
||||
<Button onClick={onHide}>{t('Cancel')}</Button>
|
||||
<Button onClick={onHide} cta>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
bsStyle={primaryButtonType}
|
||||
buttonStyle={primaryButtonType}
|
||||
disabled={disablePrimaryButton}
|
||||
onClick={onHandledPrimaryAction}
|
||||
cta
|
||||
>
|
||||
{primaryButtonName}
|
||||
</Button>
|
||||
|
|
|
@ -19,9 +19,8 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Modal, MenuItem } from 'react-bootstrap';
|
||||
import cx from 'classnames';
|
||||
|
||||
import Button from './Button';
|
||||
import Button from 'src/components/Button';
|
||||
|
||||
const propTypes = {
|
||||
dialogClassName: PropTypes.string,
|
||||
|
@ -96,9 +95,6 @@ export default class ModalTrigger extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const classNames = cx({
|
||||
'btn btn-default btn-sm': this.props.isButton,
|
||||
});
|
||||
if (this.props.isButton) {
|
||||
return (
|
||||
<>
|
||||
|
@ -123,7 +119,7 @@ export default class ModalTrigger extends React.Component {
|
|||
/* eslint-disable jsx-a11y/interactive-supports-focus */
|
||||
return (
|
||||
<>
|
||||
<span className={classNames} onClick={this.open} role="button">
|
||||
<span onClick={this.open} role="button">
|
||||
{this.props.triggerNode}
|
||||
</span>
|
||||
{this.renderModal()}
|
||||
|
|
|
@ -53,7 +53,7 @@ class RefreshChartOverlay extends React.PureComponent<Props> {
|
|||
<Button
|
||||
className="refresh-btn"
|
||||
onClick={this.props.onQuery}
|
||||
bsStyle="primary"
|
||||
buttonStyle="primary"
|
||||
>
|
||||
{t('Run Query')}
|
||||
</Button>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import { t } from '@superset-ui/translation';
|
||||
|
||||
import ModalTrigger from '../../components/ModalTrigger';
|
||||
|
@ -66,7 +66,7 @@ export default class DeleteComponentModal extends React.PureComponent {
|
|||
</div>
|
||||
<div className="dashboard-modal-actions-container">
|
||||
<Button onClick={this.close}>{t('Cancel')}</Button>
|
||||
<Button bsStyle="primary" onClick={this.deleteTab}>
|
||||
<Button buttonStyle="primary" onClick={this.deleteTab}>
|
||||
{t('Delete')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
@ -26,10 +26,10 @@ import { CategoricalColorNamespace } from '@superset-ui/color';
|
|||
import { t } from '@superset-ui/translation';
|
||||
|
||||
import Icon from 'src/components/Icon';
|
||||
import Button from 'src/components/Button';
|
||||
|
||||
import HeaderActionsDropdown from './HeaderActionsDropdown';
|
||||
import EditableTitle from '../../components/EditableTitle';
|
||||
import Button from '../../components/Button';
|
||||
import FaveStar from '../../components/FaveStar';
|
||||
import PublishedStatus from './PublishedStatus';
|
||||
import UndoRedoKeylisteners from './UndoRedoKeylisteners';
|
||||
|
@ -390,36 +390,40 @@ class Header extends React.PureComponent {
|
|||
<>
|
||||
<ButtonGroup className="m-r-5">
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
onClick={onUndo}
|
||||
disabled={undoLength < 1}
|
||||
bsStyle={this.state.emphasizeUndo ? 'primary' : undefined}
|
||||
buttonStyle={
|
||||
this.state.emphasizeUndo ? 'primary' : undefined
|
||||
}
|
||||
>
|
||||
<i title="Undo" className="undo-action fa fa-reply" />
|
||||
|
||||
</Button>
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
onClick={onRedo}
|
||||
disabled={redoLength < 1}
|
||||
bsStyle={this.state.emphasizeRedo ? 'primary' : undefined}
|
||||
buttonStyle={
|
||||
this.state.emphasizeRedo ? 'primary' : undefined
|
||||
}
|
||||
>
|
||||
|
||||
<i title="Redo" className="redo-action fa fa-share" />
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
className="m-r-5"
|
||||
onClick={this.constructor.discardChanges}
|
||||
bsStyle="default"
|
||||
buttonStyle="default"
|
||||
>
|
||||
{t('Discard Changes')}
|
||||
</Button>
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
disabled={!hasUnsavedChanges}
|
||||
bsStyle="primary"
|
||||
buttonStyle="primary"
|
||||
onClick={this.overwriteDashboard}
|
||||
>
|
||||
{t('Save')}
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Row, Col, Button, Modal, FormControl } from 'react-bootstrap';
|
||||
import { Row, Col, Modal, FormControl } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import Dialog from 'react-bootstrap-dialog';
|
||||
import { AsyncSelect } from 'src/components/Select';
|
||||
import AceEditor from 'react-ace';
|
||||
|
@ -288,11 +289,7 @@ class PropertiesModal extends React.PureComponent {
|
|||
<Row>
|
||||
<Col md={12}>
|
||||
<h3 style={{ marginTop: '1em' }}>
|
||||
<button
|
||||
type="button"
|
||||
className="text-button"
|
||||
onClick={this.toggleAdvanced}
|
||||
>
|
||||
<Button buttonStyle="link" onClick={this.toggleAdvanced}>
|
||||
<i
|
||||
className={`fa fa-angle-${
|
||||
isAdvancedOpen ? 'down' : 'right'
|
||||
|
@ -300,7 +297,7 @@ class PropertiesModal extends React.PureComponent {
|
|||
style={{ minWidth: '1em' }}
|
||||
/>
|
||||
{t('Advanced')}
|
||||
</button>
|
||||
</Button>
|
||||
</h3>
|
||||
{isAdvancedOpen && (
|
||||
<>
|
||||
|
@ -332,14 +329,15 @@ class PropertiesModal extends React.PureComponent {
|
|||
<span className="float-right">
|
||||
<Button
|
||||
type="submit"
|
||||
bsSize="sm"
|
||||
bsStyle="primary"
|
||||
buttonSize="sm"
|
||||
buttonStyle="primary"
|
||||
className="m-r-5"
|
||||
disabled={errors.length > 0}
|
||||
cta
|
||||
>
|
||||
{saveLabel}
|
||||
</Button>
|
||||
<Button type="button" bsSize="sm" onClick={onHide}>
|
||||
<Button type="button" buttonSize="sm" onClick={onHide} cta>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Dialog
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import TooltipWrapper from '../../components/TooltipWrapper';
|
||||
import TooltipWrapper from 'src/components/TooltipWrapper';
|
||||
import Label from 'src/components/Label';
|
||||
|
||||
const propTypes = {
|
||||
dashboardId: PropTypes.number.isRequired,
|
||||
|
@ -43,14 +44,6 @@ const publishedTooltip = t(
|
|||
'This dashboard is published. Click to make it a draft.',
|
||||
);
|
||||
|
||||
const divStyle = {
|
||||
border: '1px dotted black',
|
||||
backgroundColor: '#F9F9F9',
|
||||
padding: '3px 7px 3px 7px',
|
||||
fontFamily: 'Monospace',
|
||||
fontSize: '16px',
|
||||
};
|
||||
|
||||
export default class PublishedStatus extends React.Component {
|
||||
componentDidMount() {
|
||||
this.togglePublished = this.togglePublished.bind(this);
|
||||
|
@ -71,14 +64,13 @@ export default class PublishedStatus extends React.Component {
|
|||
placement="bottom"
|
||||
tooltip={draftButtonTooltip}
|
||||
>
|
||||
<button
|
||||
style={divStyle}
|
||||
<Label
|
||||
onClick={() => {
|
||||
this.togglePublished();
|
||||
}}
|
||||
>
|
||||
Draft
|
||||
</button>
|
||||
</Label>
|
||||
</TooltipWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -88,7 +80,7 @@ export default class PublishedStatus extends React.Component {
|
|||
placement="bottom"
|
||||
tooltip={draftDivTooltip}
|
||||
>
|
||||
<div style={divStyle}>Draft</div>
|
||||
<Label>Draft</Label>
|
||||
</TooltipWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -101,14 +93,13 @@ export default class PublishedStatus extends React.Component {
|
|||
placement="bottom"
|
||||
tooltip={publishedTooltip}
|
||||
>
|
||||
<button
|
||||
style={divStyle}
|
||||
<Label
|
||||
onClick={() => {
|
||||
this.togglePublished();
|
||||
}}
|
||||
>
|
||||
Published
|
||||
</button>
|
||||
</Label>
|
||||
</TooltipWrapper>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import Select from 'src/components/Select';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import { Alert, Button } from 'react-bootstrap';
|
||||
import { Alert } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
|
||||
import ModalTrigger from 'src/components/ModalTrigger';
|
||||
import FormLabel from 'src/components/FormLabel';
|
||||
|
@ -116,10 +117,10 @@ class RefreshIntervalModal extends React.PureComponent {
|
|||
}
|
||||
modalFooter={
|
||||
<>
|
||||
<Button bsStyle="primary" bsSize="sm" onClick={this.onSave}>
|
||||
<Button buttonStyle="primary" buttonSize="sm" onClick={this.onSave}>
|
||||
{editMode ? t('Save') : t('Save for this session')}
|
||||
</Button>
|
||||
<Button onClick={this.onCancel} bsSize="sm">
|
||||
<Button onClick={this.onCancel} buttonSize="sm">
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
</>
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
/* eslint-env browser */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, FormControl, FormGroup, Radio } from 'react-bootstrap';
|
||||
import { FormControl, FormGroup, Radio } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import { CategoricalColorNamespace } from '@superset-ui/color';
|
||||
import { t } from '@superset-ui/translation';
|
||||
|
||||
|
@ -191,7 +192,7 @@ class SaveModal extends React.PureComponent {
|
|||
}
|
||||
modalFooter={
|
||||
<div>
|
||||
<Button bsStyle="primary" onClick={this.saveDashboard}>
|
||||
<Button buttonStyle="primary" onClick={this.saveDashboard}>
|
||||
{t('Save')}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import cx from 'classnames';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import { t } from '@superset-ui/translation';
|
||||
|
||||
import buildFilterScopeTreeEntry from '../../util/buildFilterScopeTreeEntry';
|
||||
|
@ -513,11 +513,11 @@ export default class FilterScopeSelector extends React.PureComponent {
|
|||
</div>
|
||||
|
||||
<div className="dashboard-modal-actions-container">
|
||||
<Button bsSize="sm" onClick={this.onClose}>
|
||||
<Button buttonSize="sm" onClick={this.onClose}>
|
||||
{t('Close')}
|
||||
</Button>
|
||||
{showSelector && (
|
||||
<Button bsSize="sm" bsStyle="primary" onClick={this.onSave}>
|
||||
<Button buttonSize="sm" buttonStyle="primary" onClick={this.onSave}>
|
||||
{t('Save')}
|
||||
</Button>
|
||||
)}
|
||||
|
|
|
@ -41,14 +41,3 @@
|
|||
padding-left: 8px;
|
||||
font-size: @font-size-m;
|
||||
}
|
||||
|
||||
.text-button {
|
||||
outline: none;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: none;
|
||||
text-decoration: none;
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
|
|
@ -784,7 +784,7 @@ export class DatasourceEditor extends React.PureComponent {
|
|||
}
|
||||
/>
|
||||
<Button
|
||||
bsStyle="primary"
|
||||
buttonStyle="primary"
|
||||
onClick={this.syncMetadata}
|
||||
className="sync-from-source"
|
||||
disabled={!!datasource.sql}
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
import React, { FunctionComponent, useState, useRef } from 'react';
|
||||
import { Alert, Button, Modal } from 'react-bootstrap';
|
||||
import { Alert, Modal } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
// @ts-ignore
|
||||
import Dialog from 'react-bootstrap-dialog';
|
||||
import { t } from '@superset-ui/translation';
|
||||
|
@ -158,8 +159,8 @@ const DatasourceModal: FunctionComponent<DatasourceModalProps> = ({
|
|||
<Modal.Footer>
|
||||
<span className="float-left">
|
||||
<Button
|
||||
bsSize="sm"
|
||||
bsStyle="default"
|
||||
buttonSize="sm"
|
||||
buttonStyle="default"
|
||||
target="_blank"
|
||||
href={currentDatasource.edit_url || currentDatasource.url}
|
||||
>
|
||||
|
@ -169,15 +170,16 @@ const DatasourceModal: FunctionComponent<DatasourceModalProps> = ({
|
|||
|
||||
<span className="float-right">
|
||||
<Button
|
||||
bsSize="sm"
|
||||
bsStyle="primary"
|
||||
buttonSize="sm"
|
||||
buttonStyle="primary"
|
||||
className="m-r-5"
|
||||
data-test="datasource-modal-save"
|
||||
onClick={onClickSave}
|
||||
disabled={errors.length > 0}
|
||||
>
|
||||
{t('Save')}
|
||||
</Button>
|
||||
<Button bsSize="sm" onClick={onHide}>
|
||||
<Button buttonSize="sm" onClick={onHide}>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Dialog ref={dialog} />
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, Popover, Tab, Tabs } from 'react-bootstrap';
|
||||
import { Popover, Tab, Tabs } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import { ThemeProvider } from '@superset-ui/style';
|
||||
|
||||
import columnType from '../propTypes/columnType';
|
||||
import adhocMetricType from '../propTypes/adhocMetricType';
|
||||
|
@ -40,6 +42,7 @@ const propTypes = {
|
|||
).isRequired,
|
||||
datasource: PropTypes.object,
|
||||
partitionColumn: PropTypes.string,
|
||||
theme: PropTypes.object,
|
||||
};
|
||||
|
||||
const startingWidth = 300;
|
||||
|
@ -119,6 +122,7 @@ export default class AdhocFilterEditPopover extends React.Component {
|
|||
onResize,
|
||||
datasource,
|
||||
partitionColumn,
|
||||
theme,
|
||||
...popoverProps
|
||||
} = this.props;
|
||||
|
||||
|
@ -129,68 +133,74 @@ export default class AdhocFilterEditPopover extends React.Component {
|
|||
|
||||
return (
|
||||
<Popover id="filter-edit-popover" {...popoverProps}>
|
||||
<Tabs
|
||||
id="adhoc-filter-edit-tabs"
|
||||
defaultActiveKey={adhocFilter.expressionType}
|
||||
className="adhoc-filter-edit-tabs"
|
||||
style={{ height: this.state.height, width: this.state.width }}
|
||||
>
|
||||
<Tab
|
||||
className="adhoc-filter-edit-tab"
|
||||
eventKey={EXPRESSION_TYPES.SIMPLE}
|
||||
title="Simple"
|
||||
<ThemeProvider theme={theme}>
|
||||
<Tabs
|
||||
id="adhoc-filter-edit-tabs"
|
||||
defaultActiveKey={adhocFilter.expressionType}
|
||||
className="adhoc-filter-edit-tabs"
|
||||
style={{ height: this.state.height, width: this.state.width }}
|
||||
>
|
||||
<AdhocFilterEditPopoverSimpleTabContent
|
||||
adhocFilter={this.state.adhocFilter}
|
||||
onChange={this.onAdhocFilterChange}
|
||||
options={options}
|
||||
datasource={datasource}
|
||||
onHeightChange={this.adjustHeight}
|
||||
partitionColumn={partitionColumn}
|
||||
/>
|
||||
</Tab>
|
||||
<Tab
|
||||
className="adhoc-filter-edit-tab"
|
||||
eventKey={EXPRESSION_TYPES.SQL}
|
||||
title="Custom SQL"
|
||||
>
|
||||
{!this.props.datasource ||
|
||||
this.props.datasource.type !== 'druid' ? (
|
||||
<AdhocFilterEditPopoverSqlTabContent
|
||||
<Tab
|
||||
className="adhoc-filter-edit-tab"
|
||||
eventKey={EXPRESSION_TYPES.SIMPLE}
|
||||
title="Simple"
|
||||
>
|
||||
<AdhocFilterEditPopoverSimpleTabContent
|
||||
adhocFilter={this.state.adhocFilter}
|
||||
onChange={this.onAdhocFilterChange}
|
||||
options={this.props.options}
|
||||
height={this.state.height}
|
||||
options={options}
|
||||
datasource={datasource}
|
||||
onHeightChange={this.adjustHeight}
|
||||
partitionColumn={partitionColumn}
|
||||
/>
|
||||
) : (
|
||||
<div className="custom-sql-disabled-message">
|
||||
Custom SQL Filters are not available on druid datasources
|
||||
</div>
|
||||
)}
|
||||
</Tab>
|
||||
</Tabs>
|
||||
<div>
|
||||
<Button
|
||||
disabled={!stateIsValid}
|
||||
bsStyle={hasUnsavedChanges && stateIsValid ? 'primary' : 'default'}
|
||||
bsSize="small"
|
||||
className="m-r-5"
|
||||
onClick={this.onSave}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button bsSize="small" onClick={this.props.onClose}>
|
||||
Close
|
||||
</Button>
|
||||
<i
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onMouseDown={this.onDragDown}
|
||||
className="fa fa-expand edit-popover-resize text-muted"
|
||||
/>
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab
|
||||
className="adhoc-filter-edit-tab"
|
||||
eventKey={EXPRESSION_TYPES.SQL}
|
||||
title="Custom SQL"
|
||||
>
|
||||
{!this.props.datasource ||
|
||||
this.props.datasource.type !== 'druid' ? (
|
||||
<AdhocFilterEditPopoverSqlTabContent
|
||||
adhocFilter={this.state.adhocFilter}
|
||||
onChange={this.onAdhocFilterChange}
|
||||
options={this.props.options}
|
||||
height={this.state.height}
|
||||
/>
|
||||
) : (
|
||||
<div className="custom-sql-disabled-message">
|
||||
Custom SQL Filters are not available on druid datasources
|
||||
</div>
|
||||
)}
|
||||
</Tab>
|
||||
</Tabs>
|
||||
<div>
|
||||
<Button
|
||||
disabled={!stateIsValid}
|
||||
buttonStyle={
|
||||
hasUnsavedChanges && stateIsValid ? 'primary' : 'default'
|
||||
}
|
||||
buttonSize="small"
|
||||
className="m-r-5"
|
||||
onClick={this.onSave}
|
||||
cta
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button buttonSize="small" onClick={this.props.onClose} cta>
|
||||
Close
|
||||
</Button>
|
||||
<i
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onMouseDown={this.onDragDown}
|
||||
className="fa fa-expand edit-popover-resize text-muted"
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AdhocFilterEditPopover.propTypes = propTypes;
|
||||
|
|
|
@ -21,6 +21,7 @@ import PropTypes from 'prop-types';
|
|||
import { OverlayTrigger } from 'react-bootstrap';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
|
||||
import { withTheme } from '@superset-ui/style';
|
||||
|
||||
import Label from 'src/components/Label';
|
||||
import AdhocFilterEditPopover from './AdhocFilterEditPopover';
|
||||
|
@ -41,8 +42,7 @@ const propTypes = {
|
|||
datasource: PropTypes.object,
|
||||
partitionColumn: PropTypes.string,
|
||||
};
|
||||
|
||||
export default class AdhocFilterOption extends React.PureComponent {
|
||||
class AdhocFilterOption extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.closeFilterEditOverlay = this.closeFilterEditOverlay.bind(this);
|
||||
|
@ -73,7 +73,7 @@ export default class AdhocFilterOption extends React.PureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { adhocFilter } = this.props;
|
||||
const { adhocFilter, theme } = this.props;
|
||||
const overlay = (
|
||||
<AdhocFilterEditPopover
|
||||
onResize={this.onPopoverResize}
|
||||
|
@ -83,6 +83,7 @@ export default class AdhocFilterOption extends React.PureComponent {
|
|||
options={this.props.options}
|
||||
datasource={this.props.datasource}
|
||||
partitionColumn={this.props.partitionColumn}
|
||||
theme={theme}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
|
@ -123,4 +124,7 @@ export default class AdhocFilterOption extends React.PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(AdhocFilterOption);
|
||||
|
||||
AdhocFilterOption.propTypes = propTypes;
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, FormGroup, Popover, Tab, Tabs } from 'react-bootstrap';
|
||||
import { FormGroup, Popover, Tab, Tabs } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import Select from 'src/components/Select';
|
||||
import ace from 'brace';
|
||||
import AceEditor from 'react-ace';
|
||||
|
@ -27,6 +28,7 @@ import 'brace/theme/github';
|
|||
import 'brace/ext/language_tools';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import { ColumnOption } from '@superset-ui/chart-controls';
|
||||
import { ThemeProvider } from '@superset-ui/style';
|
||||
|
||||
import FormLabel from 'src/components/FormLabel';
|
||||
|
||||
|
@ -45,6 +47,7 @@ const propTypes = {
|
|||
onResize: PropTypes.func.isRequired,
|
||||
columns: PropTypes.arrayOf(columnType),
|
||||
datasourceType: PropTypes.string,
|
||||
theme: PropTypes.object,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
|
@ -192,6 +195,7 @@ export default class AdhocMetricEditPopover extends React.Component {
|
|||
onClose,
|
||||
onResize,
|
||||
datasourceType,
|
||||
theme,
|
||||
...popoverProps
|
||||
} = this.props;
|
||||
|
||||
|
@ -232,98 +236,104 @@ export default class AdhocMetricEditPopover extends React.Component {
|
|||
const hasUnsavedChanges = !adhocMetric.equals(propsAdhocMetric);
|
||||
return (
|
||||
<Popover id="metrics-edit-popover" title={popoverTitle} {...popoverProps}>
|
||||
<Tabs
|
||||
id="adhoc-metric-edit-tabs"
|
||||
defaultActiveKey={adhocMetric.expressionType}
|
||||
className="adhoc-metric-edit-tabs"
|
||||
style={{ height: this.state.height, width: this.state.width }}
|
||||
onSelect={this.refreshAceEditor}
|
||||
animation={false}
|
||||
>
|
||||
<Tab
|
||||
className="adhoc-metric-edit-tab"
|
||||
eventKey={EXPRESSION_TYPES.SIMPLE}
|
||||
title="Simple"
|
||||
<ThemeProvider theme={theme}>
|
||||
<Tabs
|
||||
id="adhoc-metric-edit-tabs"
|
||||
defaultActiveKey={adhocMetric.expressionType}
|
||||
className="adhoc-metric-edit-tabs"
|
||||
style={{ height: this.state.height, width: this.state.width }}
|
||||
onSelect={this.refreshAceEditor}
|
||||
animation={false}
|
||||
>
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
<strong>column</strong>
|
||||
</FormLabel>
|
||||
<Select
|
||||
name="select-column"
|
||||
{...this.selectProps}
|
||||
{...columnSelectProps}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
<strong>aggregate</strong>
|
||||
</FormLabel>
|
||||
<Select
|
||||
name="select-aggregate"
|
||||
{...this.selectProps}
|
||||
{...aggregateSelectProps}
|
||||
autoFocus
|
||||
/>
|
||||
</FormGroup>
|
||||
</Tab>
|
||||
<Tab
|
||||
className="adhoc-metric-edit-tab"
|
||||
eventKey={EXPRESSION_TYPES.SQL}
|
||||
title="Custom SQL"
|
||||
data-test="adhoc-metric-edit-tab#custom"
|
||||
>
|
||||
{this.props.datasourceType !== 'druid' ? (
|
||||
<Tab
|
||||
className="adhoc-metric-edit-tab"
|
||||
eventKey={EXPRESSION_TYPES.SIMPLE}
|
||||
title="Simple"
|
||||
>
|
||||
<FormGroup>
|
||||
<AceEditor
|
||||
ref={this.handleAceEditorRef}
|
||||
mode="sql"
|
||||
theme="github"
|
||||
height={`${this.state.height - 43}px`}
|
||||
onChange={this.onSqlExpressionChange}
|
||||
width="100%"
|
||||
showGutter={false}
|
||||
value={
|
||||
adhocMetric.sqlExpression || adhocMetric.translateToSql()
|
||||
}
|
||||
editorProps={{ $blockScrolling: true }}
|
||||
enableLiveAutocompletion
|
||||
className="adhoc-filter-sql-editor"
|
||||
wrapEnabled
|
||||
<FormLabel>
|
||||
<strong>column</strong>
|
||||
</FormLabel>
|
||||
<Select
|
||||
name="select-column"
|
||||
{...this.selectProps}
|
||||
{...columnSelectProps}
|
||||
/>
|
||||
</FormGroup>
|
||||
) : (
|
||||
<div className="custom-sql-disabled-message">
|
||||
Custom SQL Metrics are not available on druid datasources
|
||||
</div>
|
||||
)}
|
||||
</Tab>
|
||||
</Tabs>
|
||||
<div>
|
||||
<Button
|
||||
disabled={!stateIsValid}
|
||||
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}
|
||||
data-test="AdhocMetricEdit#cancel"
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
<i
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onMouseDown={this.onDragDown}
|
||||
className="fa fa-expand edit-popover-resize text-muted"
|
||||
/>
|
||||
</div>
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
<strong>aggregate</strong>
|
||||
</FormLabel>
|
||||
<Select
|
||||
name="select-aggregate"
|
||||
{...this.selectProps}
|
||||
{...aggregateSelectProps}
|
||||
autoFocus
|
||||
/>
|
||||
</FormGroup>
|
||||
</Tab>
|
||||
<Tab
|
||||
className="adhoc-metric-edit-tab"
|
||||
eventKey={EXPRESSION_TYPES.SQL}
|
||||
title="Custom SQL"
|
||||
data-test="adhoc-metric-edit-tab#custom"
|
||||
>
|
||||
{this.props.datasourceType !== 'druid' ? (
|
||||
<FormGroup>
|
||||
<AceEditor
|
||||
ref={this.handleAceEditorRef}
|
||||
mode="sql"
|
||||
theme="github"
|
||||
height={`${this.state.height - 43}px`}
|
||||
onChange={this.onSqlExpressionChange}
|
||||
width="100%"
|
||||
showGutter={false}
|
||||
value={
|
||||
adhocMetric.sqlExpression || adhocMetric.translateToSql()
|
||||
}
|
||||
editorProps={{ $blockScrolling: true }}
|
||||
enableLiveAutocompletion
|
||||
className="adhoc-filter-sql-editor"
|
||||
wrapEnabled
|
||||
/>
|
||||
</FormGroup>
|
||||
) : (
|
||||
<div className="custom-sql-disabled-message">
|
||||
Custom SQL Metrics are not available on druid datasources
|
||||
</div>
|
||||
)}
|
||||
</Tab>
|
||||
</Tabs>
|
||||
<div>
|
||||
<Button
|
||||
disabled={!stateIsValid}
|
||||
buttonStyle={
|
||||
hasUnsavedChanges && stateIsValid ? 'primary' : 'default'
|
||||
}
|
||||
buttonSize="small"
|
||||
className="m-r-5"
|
||||
data-test="AdhocMetricEdit#save"
|
||||
onClick={this.onSave}
|
||||
cta
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
buttonSize="small"
|
||||
onClick={this.props.onClose}
|
||||
data-test="AdhocMetricEdit#cancel"
|
||||
cta
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
<i
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onMouseDown={this.onDragDown}
|
||||
className="fa fa-expand edit-popover-resize text-muted"
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { OverlayTrigger } from 'react-bootstrap';
|
||||
import { withTheme } from '@superset-ui/style';
|
||||
|
||||
import Label from 'src/components/Label';
|
||||
import AdhocMetricEditPopover from './AdhocMetricEditPopover';
|
||||
|
@ -33,7 +34,7 @@ const propTypes = {
|
|||
datasourceType: PropTypes.string,
|
||||
};
|
||||
|
||||
export default class AdhocMetricOption extends React.PureComponent {
|
||||
class AdhocMetricOption extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.closeMetricEditOverlay = this.closeMetricEditOverlay.bind(this);
|
||||
|
@ -65,7 +66,7 @@ export default class AdhocMetricOption extends React.PureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { adhocMetric } = this.props;
|
||||
const { adhocMetric, theme } = this.props;
|
||||
const overlayContent = (
|
||||
<AdhocMetricEditPopover
|
||||
onResize={this.onPopoverResize}
|
||||
|
@ -74,6 +75,7 @@ export default class AdhocMetricOption extends React.PureComponent {
|
|||
onClose={this.closeMetricEditOverlay}
|
||||
columns={this.props.columns}
|
||||
datasourceType={this.props.datasourceType}
|
||||
theme={theme}
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -109,4 +111,7 @@ export default class AdhocMetricOption extends React.PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(AdhocMetricOption);
|
||||
|
||||
AdhocMetricOption.propTypes = propTypes;
|
||||
|
|
|
@ -38,13 +38,13 @@ import {
|
|||
import { Table } from 'reactable-arc';
|
||||
import { t } from '@superset-ui/translation';
|
||||
|
||||
import Button from 'src/components/Button';
|
||||
import getClientErrorObject from '../../utils/getClientErrorObject';
|
||||
import CopyToClipboard from './../../components/CopyToClipboard';
|
||||
import { getChartDataRequest } from '../../chart/chartAction';
|
||||
import downloadAsImage from '../../utils/downloadAsImage';
|
||||
import Loading from '../../components/Loading';
|
||||
import ModalTrigger from './../../components/ModalTrigger';
|
||||
import Button from '../../components/Button';
|
||||
import RowCountLabel from './RowCountLabel';
|
||||
import {
|
||||
applyFormattingToTabularData,
|
||||
|
|
|
@ -47,7 +47,7 @@ export default function ExploreActionButtons({
|
|||
slice,
|
||||
}) {
|
||||
const exportToCSVClasses = cx('btn btn-default btn-sm', {
|
||||
'disabled disabledButton': !canDownload,
|
||||
disabled: !canDownload,
|
||||
});
|
||||
const doExportCSV = exportChart.bind(this, {
|
||||
formData: latestQueryFormData,
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import {
|
||||
Button,
|
||||
Modal,
|
||||
Row,
|
||||
Col,
|
||||
|
@ -26,6 +25,7 @@ import {
|
|||
FormGroup,
|
||||
// @ts-ignore
|
||||
} from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
// @ts-ignore
|
||||
import Dialog from 'react-bootstrap-dialog';
|
||||
import { OptionsType } from 'react-select/src/types';
|
||||
|
@ -263,15 +263,15 @@ function PropertiesModal({ slice, onHide, onSave }: InternalProps) {
|
|||
</Row>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button type="button" bsSize="sm" onClick={onHide}>
|
||||
<Button type="button" buttonSize="sm" onClick={onHide} cta>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
bsSize="sm"
|
||||
bsStyle="primary"
|
||||
className="m-r-5"
|
||||
buttonSize="sm"
|
||||
buttonStyle="primary"
|
||||
disabled={!owners || submitting || !name}
|
||||
cta
|
||||
>
|
||||
{t('Save')}
|
||||
</Button>
|
||||
|
|
|
@ -19,11 +19,10 @@
|
|||
import React from 'react';
|
||||
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 Button from 'src/components/Button';
|
||||
import Hotkeys from '../../components/Hotkeys';
|
||||
|
||||
const propTypes = {
|
||||
|
@ -61,7 +60,8 @@ const Styles = styled.div`
|
|||
align-items: center;
|
||||
padding-bottom: ${({ theme }) => 2 * theme.gridUnit}px;
|
||||
|
||||
.save-btn {
|
||||
.btn {
|
||||
/* just to make sure buttons don't jiggle */
|
||||
width: 100px;
|
||||
}
|
||||
`;
|
||||
|
@ -75,12 +75,7 @@ export default function QueryAndSaveBtns({
|
|||
chartIsStale,
|
||||
errorMessage,
|
||||
}) {
|
||||
const saveClasses = classnames({
|
||||
'disabled disabledButton': !canAdd,
|
||||
'save-btn': true,
|
||||
});
|
||||
|
||||
let qryButtonStyle = 'default';
|
||||
let qryButtonStyle = 'secondary';
|
||||
if (errorMessage) {
|
||||
qryButtonStyle = 'danger';
|
||||
} else if (chartIsStale) {
|
||||
|
@ -89,15 +84,21 @@ export default function QueryAndSaveBtns({
|
|||
|
||||
const saveButtonDisabled = errorMessage ? true : loading;
|
||||
const qryOrStopButton = loading ? (
|
||||
<Button onClick={onStop} bsStyle="warning" className="save-btn">
|
||||
<Button
|
||||
onClick={onStop}
|
||||
buttonStyle="warning"
|
||||
buttonSize="small"
|
||||
disabled={!canAdd}
|
||||
>
|
||||
<i className="fa fa-stop-circle-o" /> Stop
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
className="query save-btn"
|
||||
buttonSize="small"
|
||||
onClick={onQuery}
|
||||
bsStyle={qryButtonStyle}
|
||||
buttonStyle={qryButtonStyle}
|
||||
disabled={!!errorMessage}
|
||||
data-test="run-query-button"
|
||||
>
|
||||
<i className="fa fa-bolt" /> {t('Run')}
|
||||
</Button>
|
||||
|
@ -109,7 +110,8 @@ export default function QueryAndSaveBtns({
|
|||
<ButtonGroup className="query-and-save">
|
||||
{qryOrStopButton}
|
||||
<Button
|
||||
className={saveClasses}
|
||||
buttonStyle="secondary"
|
||||
buttonSize="small"
|
||||
data-target="#save_modal"
|
||||
data-toggle="modal"
|
||||
disabled={saveButtonDisabled}
|
||||
|
|
|
@ -20,14 +20,8 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
FormControl,
|
||||
FormGroup,
|
||||
Modal,
|
||||
Radio,
|
||||
} from 'react-bootstrap';
|
||||
import { Alert, FormControl, FormGroup, Modal, Radio } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import FormLabel from 'src/components/FormLabel';
|
||||
import { CreatableSelect } from 'src/components/Select/SupersetStyledSelect';
|
||||
import { t } from '@superset-ui/translation';
|
||||
|
@ -208,18 +202,12 @@ class SaveModal extends React.Component {
|
|||
|
||||
<Modal.Footer>
|
||||
<div className="float-right">
|
||||
<Button
|
||||
type="button"
|
||||
id="btn_cancel"
|
||||
bsSize="sm"
|
||||
onClick={this.props.onHide}
|
||||
>
|
||||
<Button id="btn_cancel" buttonSize="sm" onClick={this.props.onHide}>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
id="btn_modal_save_goto_dash"
|
||||
bsSize="sm"
|
||||
buttonSize="sm"
|
||||
disabled={
|
||||
!this.state.newSliceName || !this.state.newDashboardName
|
||||
}
|
||||
|
@ -228,10 +216,9 @@ class SaveModal extends React.Component {
|
|||
{t('Save & go to dashboard')}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
id="btn_modal_save"
|
||||
bsSize="sm"
|
||||
bsStyle="primary"
|
||||
buttonSize="sm"
|
||||
buttonStyle="primary"
|
||||
onClick={this.saveOrOverwrite.bind(this, false)}
|
||||
disabled={!this.state.newSliceName}
|
||||
>
|
||||
|
|
|
@ -19,13 +19,14 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { CompactPicker } from 'react-color';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import mathjs from 'mathjs';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import { SupersetClient } from '@superset-ui/connection';
|
||||
import { getCategoricalSchemeRegistry } from '@superset-ui/color';
|
||||
import { getChartMetadataRegistry } from '@superset-ui/chart';
|
||||
import { validateNonEmpty } from '@superset-ui/validator';
|
||||
import { ThemeProvider } from '@superset-ui/style';
|
||||
|
||||
import SelectControl from './SelectControl';
|
||||
import TextControl from './TextControl';
|
||||
|
@ -63,6 +64,7 @@ const propTypes = {
|
|||
timeColumn: PropTypes.string,
|
||||
intervalEndColumn: PropTypes.string,
|
||||
vizType: PropTypes.string,
|
||||
theme: PropTypes.object,
|
||||
|
||||
error: PropTypes.string,
|
||||
colorScheme: PropTypes.string,
|
||||
|
@ -619,8 +621,8 @@ export default class AnnotationLayer extends React.PureComponent {
|
|||
/>
|
||||
<Button
|
||||
style={{ marginTop: '0.5rem', marginBottom: '0.5rem' }}
|
||||
bsStyle={color === AUTOMATIC_COLOR ? 'success' : 'default'}
|
||||
bsSize="xsmall"
|
||||
buttonStyle={color === AUTOMATIC_COLOR ? 'success' : 'default'}
|
||||
buttonSize="xsmall"
|
||||
onClick={() => this.setState({ color: AUTOMATIC_COLOR })}
|
||||
>
|
||||
Automatic Color
|
||||
|
@ -661,7 +663,7 @@ export default class AnnotationLayer extends React.PureComponent {
|
|||
render() {
|
||||
const { isNew, name, annotationType, sourceType, show } = this.state;
|
||||
const isValid = this.isValidForm();
|
||||
|
||||
const { theme } = this.props;
|
||||
const metadata = getChartMetadataRegistry().get(this.props.vizType);
|
||||
const supportedAnnotationTypes = metadata
|
||||
? metadata.supportedAnnotationTypes.map(
|
||||
|
@ -671,7 +673,7 @@ export default class AnnotationLayer extends React.PureComponent {
|
|||
const supportedSourceTypes = this.getSupportedSourceTypes(annotationType);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ThemeProvider theme={theme}>
|
||||
{this.props.error && (
|
||||
<span style={{ color: 'red' }}>ERROR: {this.props.error}</span>
|
||||
)}
|
||||
|
@ -724,12 +726,12 @@ export default class AnnotationLayer extends React.PureComponent {
|
|||
{this.renderDisplayConfiguration()}
|
||||
</div>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<Button bsSize="sm" onClick={this.deleteAnnotation}>
|
||||
<Button buttonSize="sm" onClick={this.deleteAnnotation}>
|
||||
{!isNew ? t('Remove') : t('Cancel')}
|
||||
</Button>
|
||||
<div>
|
||||
<Button
|
||||
bsSize="sm"
|
||||
buttonSize="sm"
|
||||
disabled={!isValid}
|
||||
onClick={this.applyAnnotation}
|
||||
>
|
||||
|
@ -737,7 +739,7 @@ export default class AnnotationLayer extends React.PureComponent {
|
|||
</Button>
|
||||
|
||||
<Button
|
||||
bsSize="sm"
|
||||
buttonSize="sm"
|
||||
disabled={!isValid}
|
||||
onClick={this.submitAnnotation}
|
||||
>
|
||||
|
@ -745,7 +747,7 @@ export default class AnnotationLayer extends React.PureComponent {
|
|||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import {
|
|||
} from 'react-bootstrap';
|
||||
import { connect } from 'react-redux';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import { withTheme } from '@superset-ui/style';
|
||||
import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
|
||||
import { getChartKey } from '../../exploreUtils';
|
||||
import { runAnnotationQuery } from '../../../chart/chartAction';
|
||||
|
@ -100,6 +101,7 @@ class AnnotationLayerControl extends React.PureComponent {
|
|||
|
||||
renderPopover(parent, annotation, error) {
|
||||
const id = !annotation ? '_new' : annotation.name;
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<Popover
|
||||
style={{ maxWidth: 'none' }}
|
||||
|
@ -116,6 +118,7 @@ class AnnotationLayerControl extends React.PureComponent {
|
|||
addAnnotationLayer={this.addAnnotationLayer}
|
||||
removeAnnotationLayer={this.removeAnnotationLayer}
|
||||
close={() => this.refs[parent].hide()}
|
||||
theme={theme}
|
||||
/>
|
||||
</Popover>
|
||||
);
|
||||
|
@ -208,7 +211,9 @@ function mapDispatchToProps(dispatch) {
|
|||
};
|
||||
}
|
||||
|
||||
const themedAnnotationLayerControl = withTheme(AnnotationLayerControl);
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
)(AnnotationLayerControl);
|
||||
)(themedAnnotationLayerControl);
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Button,
|
||||
DropdownButton,
|
||||
FormControl,
|
||||
FormGroup,
|
||||
|
@ -32,6 +31,7 @@ import {
|
|||
Tabs,
|
||||
Tooltip,
|
||||
} from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import Datetime from 'react-datetime';
|
||||
import 'react-datetime/css/react-datetime.css';
|
||||
import moment from 'moment';
|
||||
|
@ -365,7 +365,7 @@ class DateFilterControl extends React.Component {
|
|||
onClick={() => {}}
|
||||
/>
|
||||
<InputGroup.Button onClick={() => this.toggleCalendar(key)}>
|
||||
<Button>
|
||||
<Button theme={this.props.theme}>
|
||||
<i className="fa fa-calendar" />
|
||||
</Button>
|
||||
</InputGroup.Button>
|
||||
|
@ -563,10 +563,11 @@ class DateFilterControl extends React.Component {
|
|||
</Tabs>
|
||||
<div className="clearfix">
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
className="float-right ok"
|
||||
bsStyle="primary"
|
||||
buttonStyle="primary"
|
||||
onClick={this.close}
|
||||
theme={this.props.theme}
|
||||
>
|
||||
Ok
|
||||
</Button>
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Row, Col, Button, OverlayTrigger, Popover } from 'react-bootstrap';
|
||||
import { Row, Col, OverlayTrigger, Popover } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import { t } from '@superset-ui/translation';
|
||||
|
||||
import Label from 'src/components/Label';
|
||||
|
@ -204,9 +205,9 @@ export default class SpatialControl extends React.Component {
|
|||
</PopoverSection>
|
||||
<div className="clearfix">
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
className="float-left ok"
|
||||
bsStyle="primary"
|
||||
buttonStyle="primary"
|
||||
onClick={this.close.bind(this)}
|
||||
>
|
||||
Ok
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, FormGroup, FormControl } from 'react-bootstrap';
|
||||
import { FormGroup, FormControl } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
|
||||
import AceEditor from 'react-ace';
|
||||
import 'brace/mode/sql';
|
||||
|
@ -121,7 +122,7 @@ export default class TextAreaControl extends React.Component {
|
|||
bsSize="large"
|
||||
modalTitle={controlHeader}
|
||||
triggerNode={
|
||||
<Button bsSize="small" className="m-t-5">
|
||||
<Button buttonSize="small" className="m-t-5">
|
||||
{t('Edit')} <strong>{this.props.language}</strong>{' '}
|
||||
{t('in modal')}
|
||||
</Button>
|
||||
|
|
|
@ -1,72 +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.
|
||||
*/
|
||||
import React from 'react';
|
||||
import styled from '@superset-ui/style';
|
||||
import BaseButton from 'src/components/Button';
|
||||
|
||||
interface ModalProps {
|
||||
children: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
onClick: () => void;
|
||||
padding?: number;
|
||||
bsStyle?: 'default' | 'primary' | 'danger';
|
||||
width?: number;
|
||||
}
|
||||
|
||||
const StyledButton = styled(BaseButton)`
|
||||
border-radius: ${({ theme }) => theme.borderRadius}px;
|
||||
border: none;
|
||||
padding: ${(props: ModalProps) => props.padding || 8}px;
|
||||
text-transform: uppercase;
|
||||
width: ${(props: ModalProps) => props.width || 160}px;
|
||||
|
||||
&.btn,
|
||||
&.btn:hover {
|
||||
background-color: ${({ theme }) => theme.colors.primary.light4};
|
||||
color: ${({ theme }) => theme.colors.primary.base};
|
||||
}
|
||||
&.btn[disabled],
|
||||
&.btn[disabled]:hover {
|
||||
background-color: ${({ theme }) => theme.colors.grayscale.light2};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light1};
|
||||
}
|
||||
&.btn-primary,
|
||||
&.btn-primary:hover {
|
||||
background-color: ${({ theme }) => theme.colors.primary.base};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
}
|
||||
&.btn-danger,
|
||||
&.btn-danger:hover {
|
||||
background-color: ${({ theme }) => theme.colors.error.base};
|
||||
color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
}
|
||||
`;
|
||||
|
||||
export default function Modal({
|
||||
bsStyle = 'default',
|
||||
disabled,
|
||||
onClick,
|
||||
children,
|
||||
}: ModalProps) {
|
||||
return (
|
||||
<StyledButton disabled={disabled} bsStyle={bsStyle} onClick={onClick}>
|
||||
{children}
|
||||
</StyledButton>
|
||||
);
|
||||
}
|
|
@ -21,7 +21,7 @@ import PropTypes from 'prop-types';
|
|||
import { debounce } from 'lodash';
|
||||
import { max as d3Max } from 'd3-array';
|
||||
import { AsyncCreatableSelect, CreatableSelect } from 'src/components/Select';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import { t } from '@superset-ui/translation';
|
||||
import { SupersetClient } from '@superset-ui/connection';
|
||||
import styled from '@superset-ui/style';
|
||||
|
@ -438,8 +438,8 @@ class FilterBox extends React.Component {
|
|||
{this.renderFilters()}
|
||||
{!instantFiltering && (
|
||||
<Button
|
||||
bsSize="small"
|
||||
bsStyle="primary"
|
||||
buttonSize="small"
|
||||
buttonStyle="primary"
|
||||
onClick={this.clickApply.bind(this)}
|
||||
disabled={!this.state.hasChanged}
|
||||
>
|
||||
|
|
|
@ -196,6 +196,10 @@ table.table-no-hover tr:hover {
|
|||
background-color: initial;
|
||||
}
|
||||
|
||||
.editable-title {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.editable-title input {
|
||||
outline: none;
|
||||
background: transparent;
|
||||
|
|
|
@ -26,7 +26,7 @@ import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
|
|||
|
||||
import { exploreChart } from '../../explore/exploreUtils';
|
||||
import * as actions from '../actions/sqlLab';
|
||||
import Button from '../../components/Button';
|
||||
import Button from 'src/components/Button';
|
||||
|
||||
const propTypes = {
|
||||
actions: PropTypes.object.isRequired,
|
||||
|
@ -88,7 +88,7 @@ class ExploreCtasResultsButton extends React.PureComponent {
|
|||
return (
|
||||
<>
|
||||
<Button
|
||||
bsSize="small"
|
||||
buttonSize="small"
|
||||
onClick={this.onClick}
|
||||
tooltip={t('Explore the result set in the data exploration view')}
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue