/**
* 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 { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import PropTypes from 'prop-types';
import Icons from 'src/components/Icons';
import { styled, t } from '@superset-ui/core';
import { Tooltip } from 'src/components/Tooltip';
import ReportModal from 'src/components/ReportModal';
import {
fetchUISpecificReport,
toggleActive,
deleteActiveReport,
} from 'src/reports/actions/reports';
import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
import HeaderReportActionsDropdown from 'src/components/ReportModal/HeaderReportActionsDropdown';
import { chartPropShape } from '../../dashboard/util/propShapes';
import ExploreActionButtons from './ExploreActionButtons';
import RowCountLabel from './RowCountLabel';
import EditableTitle from '../../components/EditableTitle';
import AlteredSliceTag from '../../components/AlteredSliceTag';
import FaveStar from '../../components/FaveStar';
import Timer from '../../components/Timer';
import CachedLabel from '../../components/CachedLabel';
import PropertiesModal from './PropertiesModal';
import { sliceUpdated } from '../actions/exploreActions';
const CHART_STATUS_MAP = {
failed: 'danger',
loading: 'warning',
success: 'success',
};
const propTypes = {
actions: PropTypes.object.isRequired,
addHistory: PropTypes.func,
can_overwrite: PropTypes.bool.isRequired,
can_download: PropTypes.bool.isRequired,
isStarred: PropTypes.bool.isRequired,
slice: PropTypes.object,
sliceName: PropTypes.string,
table_name: PropTypes.string,
form_data: PropTypes.object,
ownState: PropTypes.object,
timeout: PropTypes.number,
chart: chartPropShape,
};
const StyledHeader = styled.div`
display: flex;
flex-direction: row;
align-items: center;
flex-wrap: wrap;
justify-content: space-between;
span[role='button'] {
display: flex;
height: 100%;
}
.title-panel {
display: flex;
align-items: center;
}
.right-button-panel {
display: flex;
align-items: center;
> .btn-group {
flex: 0 0 auto;
margin-left: ${({ theme }) => theme.gridUnit}px;
}
}
.action-button {
color: ${({ theme }) => theme.colors.grayscale.base};
margin: 0 ${({ theme }) => theme.gridUnit * 1.5}px 0
${({ theme }) => theme.gridUnit}px;
}
`;
const StyledButtons = styled.span`
display: flex;
align-items: center;
`;
export class ExploreChartHeader extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
isPropertiesModalOpen: false,
showingReportModal: false,
};
this.openPropertiesModal = this.openPropertiesModal.bind(this);
this.closePropertiesModal = this.closePropertiesModal.bind(this);
this.showReportModal = this.showReportModal.bind(this);
this.hideReportModal = this.hideReportModal.bind(this);
this.renderReportModal = this.renderReportModal.bind(this);
}
componentDidMount() {
if (this.canAddReports()) {
const { user, chart } = this.props;
// this is in the case that there is an anonymous user.
this.props.fetchUISpecificReport(
user.userId,
'chart_id',
'charts',
chart.id,
);
}
}
getSliceName() {
return this.props.sliceName || t('%s - untitled', this.props.table_name);
}
postChartFormData() {
this.props.actions.postChartFormData(
this.props.form_data,
true,
this.props.timeout,
this.props.chart.id,
this.props.ownState,
);
}
openPropertiesModal() {
this.setState({
isPropertiesModalOpen: true,
});
}
closePropertiesModal() {
this.setState({
isPropertiesModalOpen: false,
});
}
showReportModal() {
this.setState({ showingReportModal: true });
}
hideReportModal() {
this.setState({ showingReportModal: false });
}
renderReportModal() {
const attachedReportExists = !!Object.keys(this.props.reports).length;
return attachedReportExists ? (
) : (
<>
>
);
}
canAddReports() {
if (!isFeatureEnabled(FeatureFlag.ALERT_REPORTS)) {
return false;
}
const { user } = this.props;
if (!user) {
// this is in the case that there is an anonymous user.
return false;
}
const roles = Object.keys(user.roles || []);
const permissions = roles.map(key =>
user.roles[key].filter(
perms => perms[0] === 'menu_access' && perms[1] === 'Manage',
),
);
return permissions[0].length > 0;
}
render() {
const { user, form_data: formData } = this.props;
const {
chartStatus,
chartUpdateEndTime,
chartUpdateStartTime,
latestQueryFormData,
queriesResponse,
} = this.props.chart;
// TODO: when will get appropriate design for multi queries use all results and not first only
const queryResponse = queriesResponse?.[0];
const chartFinished = ['failed', 'rendered', 'success'].includes(
this.props.chart.chartStatus,
);
return (
);
}
}
ExploreChartHeader.propTypes = propTypes;
function mapDispatchToProps(dispatch) {
return bindActionCreators(
{ sliceUpdated, fetchUISpecificReport, toggleActive, deleteActiveReport },
dispatch,
);
}
export default connect(null, mapDispatchToProps)(ExploreChartHeader);