mirror of
https://github.com/apache/superset.git
synced 2026-06-03 22:59:21 +00:00
191 lines
5.3 KiB
TypeScript
191 lines
5.3 KiB
TypeScript
/**
|
|
* 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, { FunctionComponent, useEffect, useRef, useState } from 'react';
|
|
import { t } from '@superset-ui/core';
|
|
|
|
import Modal from 'src/common/components/Modal';
|
|
import {
|
|
StyledIcon,
|
|
StyledInputContainer,
|
|
} from 'src/views/CRUD/data/database/DatabaseModal';
|
|
import { useImportResource } from 'src/views/CRUD/hooks';
|
|
import { DashboardObject } from 'src/views/CRUD/dashboard/types';
|
|
|
|
export interface ImportDashboardModalProps {
|
|
addDangerToast: (msg: string) => void;
|
|
addSuccessToast: (msg: string) => void;
|
|
onDashboardImport: () => void;
|
|
show: boolean;
|
|
onHide: () => void;
|
|
passwordFields?: string[];
|
|
setPasswordFields?: (passwordFields: string[]) => void;
|
|
}
|
|
|
|
const ImportDashboardModal: FunctionComponent<ImportDashboardModalProps> = ({
|
|
addDangerToast,
|
|
addSuccessToast,
|
|
onDashboardImport,
|
|
show,
|
|
onHide,
|
|
passwordFields = [],
|
|
setPasswordFields = () => {},
|
|
}) => {
|
|
const [uploadFile, setUploadFile] = useState<File | null>(null);
|
|
const [isHidden, setIsHidden] = useState<boolean>(true);
|
|
const [passwords, setPasswords] = useState<Record<string, string>>({});
|
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
|
|
const clearModal = () => {
|
|
setUploadFile(null);
|
|
setPasswordFields([]);
|
|
setPasswords({});
|
|
if (fileInputRef && fileInputRef.current) {
|
|
fileInputRef.current.value = '';
|
|
}
|
|
};
|
|
|
|
const handleErrorMsg = (msg: string) => {
|
|
clearModal();
|
|
addDangerToast(msg);
|
|
};
|
|
|
|
const {
|
|
state: { passwordsNeeded },
|
|
importResource,
|
|
} = useImportResource<DashboardObject>(
|
|
'dashboard',
|
|
t('dashboard'),
|
|
handleErrorMsg,
|
|
);
|
|
|
|
useEffect(() => {
|
|
setPasswordFields(passwordsNeeded);
|
|
}, [passwordsNeeded]);
|
|
|
|
// Functions
|
|
const hide = () => {
|
|
setIsHidden(true);
|
|
onHide();
|
|
};
|
|
|
|
const onUpload = () => {
|
|
if (uploadFile === null) {
|
|
return;
|
|
}
|
|
|
|
importResource(uploadFile, passwords).then(result => {
|
|
if (result) {
|
|
addSuccessToast(t('The dashboards have been imported'));
|
|
clearModal();
|
|
onDashboardImport();
|
|
}
|
|
});
|
|
};
|
|
|
|
const changeFile = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
const { files } = event.target as HTMLInputElement;
|
|
setUploadFile((files && files[0]) || null);
|
|
};
|
|
|
|
const renderPasswordFields = () => {
|
|
if (passwordFields.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<h5>Database passwords</h5>
|
|
<StyledInputContainer>
|
|
<div className="helper">
|
|
{t(
|
|
'The passwords for the databases below are needed in order to ' +
|
|
'import them together with the dashboards. Please note that the ' +
|
|
'"Secure Extra" and "Certificate" sections of ' +
|
|
'the database configuration are not present in export files, and ' +
|
|
'should be added manually after the import if they are needed.',
|
|
)}
|
|
</div>
|
|
</StyledInputContainer>
|
|
{passwordFields.map(fileName => (
|
|
<StyledInputContainer key={`password-for-${fileName}`}>
|
|
<div className="control-label">
|
|
{fileName}
|
|
<span className="required">*</span>
|
|
</div>
|
|
<input
|
|
name={`password-${fileName}`}
|
|
autoComplete="off"
|
|
type="password"
|
|
value={passwords[fileName]}
|
|
onChange={event =>
|
|
setPasswords({ ...passwords, [fileName]: event.target.value })
|
|
}
|
|
/>
|
|
</StyledInputContainer>
|
|
))}
|
|
</>
|
|
);
|
|
};
|
|
|
|
// Show/hide
|
|
if (isHidden && show) {
|
|
setIsHidden(false);
|
|
}
|
|
|
|
return (
|
|
<Modal
|
|
name="dashboard"
|
|
className="dashboard-modal"
|
|
disablePrimaryButton={uploadFile === null}
|
|
onHandledPrimaryAction={onUpload}
|
|
onHide={hide}
|
|
primaryButtonName={t('Import')}
|
|
width="750px"
|
|
show={show}
|
|
title={
|
|
<h4>
|
|
<StyledIcon name="nav-dashboard" />
|
|
{t('Import Dashboard')}
|
|
</h4>
|
|
}
|
|
>
|
|
<StyledInputContainer>
|
|
<div className="control-label">
|
|
<label htmlFor="dashboardFile">
|
|
{t('File')}
|
|
<span className="required">*</span>
|
|
</label>
|
|
</div>
|
|
<input
|
|
ref={fileInputRef}
|
|
data-test="dashboard-file-input"
|
|
name="dashboardFile"
|
|
id="dashboardFile"
|
|
type="file"
|
|
accept=".yaml,.json,.yml,.zip"
|
|
onChange={changeFile}
|
|
/>
|
|
</StyledInputContainer>
|
|
{renderPasswordFields()}
|
|
</Modal>
|
|
);
|
|
};
|
|
|
|
export default ImportDashboardModal;
|