blob: 99bad3e48f6fd549f038ab8af3d93679ea15b665 [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.
*/
/* eslint-env browser */
import { useRef, useState } from 'react';
import { Radio, RadioChangeEvent } from '@superset-ui/core/components/Radio';
import {
Button,
Checkbox,
Form,
Input,
Divider,
Flex,
} from '@superset-ui/core/components';
import { t, useTheme } from '@superset-ui/core';
import {
ModalTrigger,
ModalTriggerRef,
} from '@superset-ui/core/components/ModalTrigger';
import {
SAVE_TYPE_OVERWRITE,
SAVE_TYPE_NEWDASHBOARD,
} from 'src/dashboard/util/constants';
type SaveType = typeof SAVE_TYPE_OVERWRITE | typeof SAVE_TYPE_NEWDASHBOARD;
type SaveModalProps = {
addSuccessToast: (arg: string) => void;
addDangerToast: (arg: string) => void;
dashboardId: number;
dashboardTitle: string;
dashboardInfo: Record<string, any>;
expandedSlices: Record<string, any>;
layout: Record<string, any>;
saveType: SaveType;
triggerNode: JSX.Element;
customCss: string;
colorNamespace?: string;
colorScheme?: string;
onSave: (data: any, id: number | string, saveType: SaveType) => void;
canOverwrite: boolean;
shouldPersistRefreshFrequency: boolean;
refreshFrequency: number;
lastModifiedTime: number;
};
// Removed SaveModalState - now using useState hooks
function SaveModal({
saveType: initialSaveType = SAVE_TYPE_OVERWRITE,
colorNamespace,
colorScheme,
shouldPersistRefreshFrequency = false,
dashboardTitle,
onSave,
triggerNode,
canOverwrite,
addSuccessToast,
addDangerToast,
dashboardId,
dashboardInfo,
expandedSlices,
layout,
customCss,
refreshFrequency,
lastModifiedTime,
}: SaveModalProps) {
const theme = useTheme();
const modal = useRef() as ModalTriggerRef;
const [saveType, setSaveType] = useState<SaveType>(initialSaveType);
const [newDashName, setNewDashName] = useState(
`${dashboardTitle} ${t('[copy]')}`,
);
const [duplicateSlices, setDuplicateSlices] = useState(false);
const toggleDuplicateSlices = () => {
setDuplicateSlices(prev => !prev);
};
const handleSaveTypeChange = (event: RadioChangeEvent) => {
setSaveType((event.target as HTMLInputElement).value as SaveType);
};
const handleNameChange = (name: string) => {
setNewDashName(name);
setSaveType(SAVE_TYPE_NEWDASHBOARD);
};
const saveDashboard = () => {
// check refresh frequency is for current session or persist
const refreshFrequencyToUse = shouldPersistRefreshFrequency
? refreshFrequency
: dashboardInfo.metadata?.refresh_frequency; // eslint-disable camelcase
const data = {
certified_by: dashboardInfo.certified_by,
certification_details: dashboardInfo.certification_details,
css: customCss,
dashboard_title:
saveType === SAVE_TYPE_NEWDASHBOARD ? newDashName : dashboardTitle,
duplicate_slices: duplicateSlices,
last_modified_time: lastModifiedTime,
owners: dashboardInfo.owners,
roles: dashboardInfo.roles,
metadata: {
...dashboardInfo?.metadata,
positions: layout,
refresh_frequency: refreshFrequencyToUse,
},
};
if (saveType === SAVE_TYPE_NEWDASHBOARD && !newDashName) {
addDangerToast(t('You must pick a name for the new dashboard'));
} else {
onSave(data, dashboardId, saveType);
modal?.current?.close?.();
}
};
return (
<ModalTrigger
ref={modal}
triggerNode={triggerNode}
modalTitle={t('Save dashboard')}
modalBody={
<Form layout="vertical">
<Form.Item>
<Radio
value={SAVE_TYPE_OVERWRITE}
onChange={handleSaveTypeChange}
checked={saveType === SAVE_TYPE_OVERWRITE}
disabled={!canOverwrite}
>
{t('Overwrite Dashboard [%s]', dashboardTitle)}
</Radio>
</Form.Item>
<Divider />
<Form.Item style={{ marginBottom: theme.sizeUnit }}>
<Radio
value={SAVE_TYPE_NEWDASHBOARD}
onChange={handleSaveTypeChange}
checked={saveType === SAVE_TYPE_NEWDASHBOARD}
>
{t('Save as:')}
</Radio>
</Form.Item>
<Form.Item style={{ marginBottom: theme.sizeUnit }}>
<Input
placeholder={t('[dashboard name]')}
value={newDashName}
onFocus={e => handleNameChange(e.target.value)}
onChange={e => handleNameChange(e.target.value)}
/>
</Form.Item>
<Form.Item>
<Checkbox
checked={duplicateSlices}
onChange={() => toggleDuplicateSlices()}
>
{t('also copy (duplicate) charts')}
</Checkbox>
</Form.Item>
</Form>
}
modalFooter={
<Flex justify="flex-end" gap={theme.sizeUnit}>
<Button
buttonStyle="secondary"
onClick={() => modal?.current?.close?.()}
>
{t('Cancel')}
</Button>
<Button
type="primary"
data-test="modal-save-dashboard-button"
onClick={saveDashboard}
>
{t('Save')}
</Button>
</Flex>
}
/>
);
}
export default SaveModal;