diff --git a/superset-frontend/spec/javascripts/dashboard/components/SliceAdder_spec.jsx b/superset-frontend/spec/javascripts/dashboard/components/SliceAdder_spec.jsx index 6078314bb5..2a0cb55cad 100644 --- a/superset-frontend/spec/javascripts/dashboard/components/SliceAdder_spec.jsx +++ b/superset-frontend/spec/javascripts/dashboard/components/SliceAdder_spec.jsx @@ -155,10 +155,10 @@ describe('SliceAdder', () => { }); it('handleSelect', () => { - const newSortBy = 1; + const newSortBy = { value: 'viz_type' }; wrapper.instance().handleSelect(newSortBy); expect(spy.calledOnce).toBe(true); - expect(spy.lastCall.args[1]).toBe(newSortBy); + expect(spy.lastCall.args[1]).toBe(newSortBy.value); }); it('handleKeyPress', () => { diff --git a/superset-frontend/src/dashboard/components/AddSliceCard.jsx b/superset-frontend/src/dashboard/components/AddSliceCard.jsx index 6163943663..312627e1ee 100644 --- a/superset-frontend/src/dashboard/components/AddSliceCard.jsx +++ b/superset-frontend/src/dashboard/components/AddSliceCard.jsx @@ -19,7 +19,7 @@ import cx from 'classnames'; import React from 'react'; import PropTypes from 'prop-types'; -import { t } from '@superset-ui/core'; +import { t, styled } from '@superset-ui/core'; const propTypes = { datasourceUrl: PropTypes.string, @@ -41,6 +41,69 @@ const defaultProps = { lastModified: null, }; +const Styled = styled.div` + ${({ theme }) => ` + .chart-card { + border: 1px solid ${theme.colors.grayscale.light2}; + border-radius: ${theme.gridUnit}px; + background: ${theme.colors.grayscale.light5}; + font-weight: ${theme.typography.weights.light}; + padding: ${theme.gridUnit * 2}px; + margin: 0 ${theme.gridUnit * 3}px + ${theme.gridUnit * 3}px + ${theme.gridUnit * 3}px; + position: relative; + cursor: move; + white-space: nowrap; + overflow: hidden; + + &:hover { + background: ${theme.colors.grayscale.light4}; + } + } + + .chart-card.is-selected { + cursor: not-allowed; + opacity: 0.4; + } + + .card-title { + margin-right: 60px; + margin-bottom: ${theme.gridUnit * 2}px; + font-weight: ${theme.typography.weights.bold}; + } + + .card-body { + display: flex; + flex-direction: column; + + .item { + span { + word-break: break-all; + + &:first-child { + font-weight: ${theme.typography.weights.normal}; + } + } + } + } + + .is-added-label { + background: ${theme.colors.grayscale.base}; + border-radius: ${theme.gridUnit}px; + color: ${theme.colors.grayscale.light5}; + font-size: ${theme.typography.sizes.s}px; + text-transform: uppercase; + position: absolute; + padding: ${theme.gridUnit}px + ${theme.gridUnit * 2}px; + top: ${theme.gridUnit * 8}px; + right: ${theme.gridUnit * 8}px; + pointer-events: none; + } + `} +`; + function AddSliceCard({ datasourceUrl, datasourceName, @@ -52,7 +115,7 @@ function AddSliceCard({ visType, }) { return ( -
+
{isSelected &&
{t('Added')}
} -
+ ); } diff --git a/superset-frontend/src/dashboard/components/SliceAdder.jsx b/superset-frontend/src/dashboard/components/SliceAdder.jsx index 141ccac14a..12d62c5fdb 100644 --- a/superset-frontend/src/dashboard/components/SliceAdder.jsx +++ b/superset-frontend/src/dashboard/components/SliceAdder.jsx @@ -20,17 +20,23 @@ import React from 'react'; import PropTypes from 'prop-types'; import { List } from 'react-virtualized'; -import SearchInput, { createFilter } from 'react-search-input'; -import { t } from '@superset-ui/core'; - -import { Select } from 'src/common/components'; +import { createFilter } from 'react-search-input'; +import { t, styled } from '@superset-ui/core'; +import { Input } from 'src/common/components'; +import Select from 'src/components/Select'; +import Loading from 'src/components/Loading'; +import { + CHART_TYPE, + NEW_COMPONENT_SOURCE_TYPE, +} from 'src/dashboard/util/componentTypes'; +import { + NEW_CHART_ID, + NEW_COMPONENTS_SOURCE_ID, +} from 'src/dashboard/util/constants'; +import { slicePropShape } from 'src/dashboard/util/propShapes'; import AddSliceCard from './AddSliceCard'; import AddSliceDragPreview from './dnd/AddSliceDragPreview'; import DragDroppable from './dnd/DragDroppable'; -import Loading from '../../components/Loading'; -import { CHART_TYPE, NEW_COMPONENT_SOURCE_TYPE } from '../util/componentTypes'; -import { NEW_CHART_ID, NEW_COMPONENTS_SOURCE_ID } from '../util/constants'; -import { slicePropShape } from '../util/propShapes'; const propTypes = { fetchAllSlices: PropTypes.func.isRequired, @@ -66,6 +72,17 @@ const SIDEPANE_HEADER_HEIGHT = 30; const SLICE_ADDER_CONTROL_HEIGHT = 64; const DEFAULT_CELL_HEIGHT = 112; +const Controls = styled.div` + display: flex; + flex-direction: row; + padding: ${({ theme }) => theme.gridUnit * 3}px; +`; + +const StyledSelect = styled(Select)` + margin-left: ${({ theme }) => theme.gridUnit * 2}px; + min-width: 150px; +`; + class SliceAdder extends React.Component { static sortByComparator(attr) { const desc = attr === 'changed_on' ? -1 : 1; @@ -92,6 +109,7 @@ class SliceAdder extends React.Component { this.rowRenderer = this.rowRenderer.bind(this); this.searchUpdated = this.searchUpdated.bind(this); this.handleKeyPress = this.handleKeyPress.bind(this); + this.handleChange = this.handleChange.bind(this); this.handleSelect = this.handleSelect.bind(this); } @@ -136,6 +154,10 @@ class SliceAdder extends React.Component { } } + handleChange(ev) { + this.searchUpdated(ev.target.value); + } + searchUpdated(searchTerm) { this.setState(prevState => ({ searchTerm, @@ -146,7 +168,8 @@ class SliceAdder extends React.Component { })); } - handleSelect(sortBy) { + handleSelect(object) { + const sortBy = object.value; this.setState(prevState => ({ sortBy, filteredSlices: this.getFilteredSortedSlices( @@ -210,26 +233,25 @@ class SliceAdder extends React.Component { MARGIN_BOTTOM; return (
-
- + - -
+ options={Object.entries(KEYS_TO_SORT).map(([key, label]) => ({ + label: `${t('Sort by')} ${label}`, + value: key, + }))} + placeholder={t('Sort by')} + /> + {this.props.isLoading && } {!this.props.isLoading && this.state.filteredSlices.length > 0 && (