[explore-v2] add fave star and edit button to chart header (#1623)
* add fave star to chart title * add TooltipWrapper, and css for icons * fix linting
This commit is contained in:
parent
267fd5b9bc
commit
506b781f3a
|
|
@ -0,0 +1,44 @@
|
|||
import React, { PropTypes } from 'react';
|
||||
import cx from 'classnames';
|
||||
import TooltipWrapper from './TooltipWrapper';
|
||||
|
||||
const propTypes = {
|
||||
sliceId: PropTypes.string.isRequired,
|
||||
actions: PropTypes.object.isRequired,
|
||||
isStarred: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export default class FaveStar extends React.Component {
|
||||
componentDidMount() {
|
||||
this.props.actions.fetchFaveStar(this.props.sliceId);
|
||||
}
|
||||
|
||||
onClick(e) {
|
||||
e.preventDefault();
|
||||
this.props.actions.saveFaveStar(this.props.sliceId, this.props.isStarred);
|
||||
}
|
||||
|
||||
render() {
|
||||
const iconClassNames = cx('fa', {
|
||||
'fa-star': this.props.isStarred,
|
||||
'fa-star-o': !this.props.isStarred,
|
||||
});
|
||||
|
||||
return (
|
||||
<TooltipWrapper
|
||||
label="fave-unfave"
|
||||
tooltip="Click to favorite/unfavorite"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
onClick={this.onClick.bind(this)}
|
||||
className="fave-unfave-icon"
|
||||
>
|
||||
<i className={iconClassNames} />
|
||||
</a>
|
||||
</TooltipWrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
FaveStar.propTypes = propTypes;
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import React, { PropTypes } from 'react';
|
||||
import { Tooltip, OverlayTrigger } from 'react-bootstrap';
|
||||
import { slugify } from '../modules/utils';
|
||||
|
||||
const propTypes = {
|
||||
label: PropTypes.string.isRequired,
|
||||
tooltip: PropTypes.string.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
placement: PropTypes.string,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
placement: 'top',
|
||||
};
|
||||
|
||||
export default function TooltipWrapper({ label, tooltip, children, placement }) {
|
||||
return (
|
||||
<OverlayTrigger
|
||||
placement={placement}
|
||||
overlay={<Tooltip id={`${slugify(label)}-tooltip`}>{tooltip}</Tooltip>}
|
||||
>
|
||||
{children}
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
|
||||
TooltipWrapper.propTypes = propTypes;
|
||||
TooltipWrapper.defaultProps = defaultProps;
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
/* eslint camelcase: 0 */
|
||||
const $ = window.$ = require('jquery');
|
||||
|
||||
const FAVESTAR_BASE_URL = '/superset/favstar/slice';
|
||||
|
||||
export const SET_FIELD_OPTIONS = 'SET_FIELD_OPTIONS';
|
||||
export function setFieldOptions(options) {
|
||||
return { type: SET_FIELD_OPTIONS, options };
|
||||
|
|
@ -48,6 +51,33 @@ export function fetchFieldOptions(datasourceId, datasourceType) {
|
|||
};
|
||||
}
|
||||
|
||||
export const TOGGLE_FAVE_STAR = 'TOGGLE_FAVE_STAR';
|
||||
export function toggleFaveStar(isStarred) {
|
||||
return { type: TOGGLE_FAVE_STAR, isStarred };
|
||||
}
|
||||
|
||||
export const FETCH_FAVE_STAR = 'FETCH_FAVE_STAR';
|
||||
export function fetchFaveStar(sliceId) {
|
||||
return function (dispatch) {
|
||||
const url = `${FAVESTAR_BASE_URL}/${sliceId}/count`;
|
||||
$.get(url, (data) => {
|
||||
if (data.count > 0) {
|
||||
dispatch(toggleFaveStar(true));
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export const SAVE_FAVE_STAR = 'SAVE_FAVE_STAR';
|
||||
export function saveFaveStar(sliceId, isStarred) {
|
||||
return function (dispatch) {
|
||||
const urlSuffix = isStarred ? 'unselect' : 'select';
|
||||
const url = `${FAVESTAR_BASE_URL}/${sliceId}/${urlSuffix}/`;
|
||||
$.get(url);
|
||||
dispatch(toggleFaveStar(!isStarred));
|
||||
};
|
||||
}
|
||||
|
||||
export const ADD_FILTER = 'ADD_FILTER';
|
||||
export function addFilter(filter) {
|
||||
return { type: ADD_FILTER, filter };
|
||||
|
|
|
|||
|
|
@ -5,9 +5,13 @@ import { Panel } from 'react-bootstrap';
|
|||
import visMap from '../../../visualizations/main';
|
||||
import { d3format } from '../../modules/utils';
|
||||
import ExploreActionButtons from '../../explore/components/ExploreActionButtons';
|
||||
import FaveStar from '../../components/FaveStar';
|
||||
import TooltipWrapper from '../../components/TooltipWrapper';
|
||||
|
||||
const propTypes = {
|
||||
actions: PropTypes.object.isRequired,
|
||||
can_download: PropTypes.bool.isRequired,
|
||||
slice_id: PropTypes.string.isRequired,
|
||||
slice_name: PropTypes.string.isRequired,
|
||||
viz_type: PropTypes.string.isRequired,
|
||||
height: PropTypes.string.isRequired,
|
||||
|
|
@ -19,6 +23,7 @@ const propTypes = {
|
|||
column_formats: PropTypes.object,
|
||||
data: PropTypes.any,
|
||||
isChartLoading: PropTypes.bool,
|
||||
isStarred: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
class ChartContainer extends React.Component {
|
||||
|
|
@ -150,6 +155,25 @@ class ChartContainer extends React.Component {
|
|||
className="panel-title"
|
||||
>
|
||||
{this.props.slice_name}
|
||||
|
||||
<FaveStar
|
||||
sliceId={this.props.slice_id}
|
||||
actions={this.props.actions}
|
||||
isStarred={this.props.isStarred}
|
||||
/>
|
||||
|
||||
<TooltipWrapper
|
||||
label="edit-desc"
|
||||
tooltip="Edit Description"
|
||||
>
|
||||
<a
|
||||
className="edit-desc-icon"
|
||||
href={`/slicemodelview/edit/${this.props.slice_id}`}
|
||||
>
|
||||
<i className="fa fa-edit" />
|
||||
</a>
|
||||
</TooltipWrapper>
|
||||
|
||||
<div className="pull-right">
|
||||
<ExploreActionButtons
|
||||
slice={this.state.mockSlice}
|
||||
|
|
@ -177,6 +201,7 @@ ChartContainer.propTypes = propTypes;
|
|||
function mapStateToProps(state) {
|
||||
return {
|
||||
containerId: `slice-container-${state.viz.form_data.slice_id}`,
|
||||
slice_id: state.viz.form_data.slice_id,
|
||||
slice_name: state.viz.form_data.slice_name,
|
||||
viz_type: state.viz.form_data.viz_type,
|
||||
can_download: state.can_download,
|
||||
|
|
@ -187,6 +212,7 @@ function mapStateToProps(state) {
|
|||
column_formats: state.viz.column_formats,
|
||||
data: state.viz.data,
|
||||
isChartLoading: state.isChartLoading,
|
||||
isStarred: state.isStarred,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ class ExploreViewContainer extends React.Component {
|
|||
</div>
|
||||
<div className="col-sm-8">
|
||||
<ChartContainer
|
||||
actions={this.props.actions}
|
||||
height={this.state.height}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ import { addToArr, removeFromArr, alterInArr } from '../../../utils/reducerUtils
|
|||
|
||||
export const exploreReducer = function (state, action) {
|
||||
const actionHandlers = {
|
||||
[actions.TOGGLE_FAVE_STAR]() {
|
||||
return Object.assign({}, state, { isStarred: action.isStarred });
|
||||
},
|
||||
|
||||
[actions.FETCH_STARTED]() {
|
||||
return Object.assign({}, state, { isDatasourceMetaLoading: true });
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1679,5 +1679,6 @@ export function initialState(vizType = 'table') {
|
|||
datasource_type: null,
|
||||
fields,
|
||||
viz: defaultViz(vizType),
|
||||
isStarred: false,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,3 +15,8 @@
|
|||
margin-right: 0px;
|
||||
margin-bottom: 100px;
|
||||
}
|
||||
|
||||
.fave-unfave-icon, .edit-desc-icon {
|
||||
padding: 0 0 0 .5em;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue