blob: 7837eb04ae9f0f3336d28f629a3b907a0492e1dc [file] [log] [blame]
/**
* 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, { useCallback, useState } from 'react';
import PropTypes from 'prop-types';
import { t, getChartMetadataRegistry, styled } from '@superset-ui/core';
import { usePluginContext } from 'src/components/DynamicPlugins';
import Modal from 'src/components/Modal';
import { Tooltip } from 'src/components/Tooltip';
import Label, { Type } from 'src/components/Label';
import ControlHeader from 'src/explore/components/ControlHeader';
import VizTypeGallery, {
MAX_ADVISABLE_VIZ_GALLERY_WIDTH,
} from './VizTypeGallery';
const propTypes = {
description: PropTypes.string,
label: PropTypes.string,
name: PropTypes.string.isRequired,
onChange: PropTypes.func,
value: PropTypes.string.isRequired,
labelType: PropTypes.string,
};
interface VizTypeControlProps {
description?: string;
label?: string;
name: string;
onChange: (vizType: string | null) => void;
value: string | null;
labelType?: Type;
isModalOpenInit?: boolean;
}
const defaultProps = {
onChange: () => {},
labelType: 'default',
};
const metadataRegistry = getChartMetadataRegistry();
export const VIZ_TYPE_CONTROL_TEST_ID = 'viz-type-control';
function VizSupportValidation({ vizType }: { vizType: string }) {
const state = usePluginContext();
if (state.loading || metadataRegistry.has(vizType)) {
return null;
}
return (
<div className="text-danger">
<i className="fa fa-exclamation-circle text-danger" />{' '}
<small>{t('This visualization type is not supported.')}</small>
</div>
);
}
const UnpaddedModal = styled(Modal)`
.ant-modal-body {
padding: 0;
}
`;
/** Manages the viz type and the viz picker modal */
const VizTypeControl = (props: VizTypeControlProps) => {
const { value: initialValue, onChange, isModalOpenInit, labelType } = props;
const { mountedPluginMetadata } = usePluginContext();
const [showModal, setShowModal] = useState(!!isModalOpenInit);
// a trick to force re-initialization of the gallery each time the modal opens,
// ensuring that the modal always opens to the correct category.
const [modalKey, setModalKey] = useState(0);
const [selectedViz, setSelectedViz] = useState<string | null>(initialValue);
const openModal = useCallback(() => {
setShowModal(true);
}, []);
const onSubmit = useCallback(() => {
onChange(selectedViz);
setShowModal(false);
}, [selectedViz, onChange]);
const onCancel = useCallback(() => {
setShowModal(false);
setModalKey(key => key + 1);
// make sure the modal re-opens to the last submitted viz
setSelectedViz(initialValue);
}, [initialValue]);
const labelContent = initialValue
? mountedPluginMetadata[initialValue]?.name || `${initialValue}`
: t('Select Viz Type');
return (
<div>
<ControlHeader {...props} />
<Tooltip
id="error-tooltip"
placement="right"
title={t('Click to change visualization type')}
>
<>
<Label
onClick={openModal}
type={labelType}
data-test="visualization-type"
>
{labelContent}
</Label>
{initialValue && <VizSupportValidation vizType={initialValue} />}
</>
</Tooltip>
<UnpaddedModal
show={showModal}
onHide={onCancel}
title={t('Select a visualization type')}
primaryButtonName={t('Select')}
disablePrimaryButton={!selectedViz}
onHandledPrimaryAction={onSubmit}
maxWidth={`${MAX_ADVISABLE_VIZ_GALLERY_WIDTH}px`}
responsive
>
{/* When the key increments, it forces react to re-init the gallery component */}
<VizTypeGallery
key={modalKey}
selectedViz={selectedViz}
onChange={setSelectedViz}
/>
</UnpaddedModal>
</div>
);
};
VizTypeControl.propTypes = propTypes;
VizTypeControl.defaultProps = defaultProps;
export default VizTypeControl;