mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			161 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
| import { css } from '@emotion/css';
 | |
| import React, { useState } from 'react';
 | |
| import { DropzoneOptions } from 'react-dropzone';
 | |
| 
 | |
| import { DataSourceInstanceSettings, DataSourceRef, GrafanaTheme2 } from '@grafana/data';
 | |
| import {
 | |
|   Modal,
 | |
|   FileDropzone,
 | |
|   FileDropzoneDefaultChildren,
 | |
|   CustomScrollbar,
 | |
|   LinkButton,
 | |
|   useStyles2,
 | |
|   Input,
 | |
|   Icon,
 | |
| } from '@grafana/ui';
 | |
| import * as DFImport from 'app/features/dataframe-import';
 | |
| 
 | |
| import { DataSourceList } from './DataSourceList';
 | |
| 
 | |
| interface DataSourceModalProps {
 | |
|   onChange: (ds: DataSourceInstanceSettings) => void;
 | |
|   current: DataSourceRef | string | null | undefined;
 | |
|   onDismiss: () => void;
 | |
|   datasources: DataSourceInstanceSettings[];
 | |
|   recentlyUsed?: string[];
 | |
|   enableFileUpload?: boolean;
 | |
|   fileUploadOptions?: DropzoneOptions;
 | |
| }
 | |
| 
 | |
| export function DataSourceModal({
 | |
|   enableFileUpload,
 | |
|   fileUploadOptions,
 | |
|   onChange,
 | |
|   current,
 | |
|   onDismiss,
 | |
| }: DataSourceModalProps) {
 | |
|   const styles = useStyles2(getDataSourceModalStyles);
 | |
|   const [search, setSearch] = useState('');
 | |
| 
 | |
|   return (
 | |
|     <Modal
 | |
|       title="Select data source"
 | |
|       closeOnEscape={true}
 | |
|       closeOnBackdropClick={true}
 | |
|       isOpen={true}
 | |
|       className={styles.modal}
 | |
|       onClickBackdrop={onDismiss}
 | |
|       onDismiss={onDismiss}
 | |
|     >
 | |
|       <div className={styles.modalContent}>
 | |
|         <div className={styles.leftColumn}>
 | |
|           <Input
 | |
|             className={styles.searchInput}
 | |
|             value={search}
 | |
|             prefix={<Icon name="search" />}
 | |
|             placeholder="Search data source"
 | |
|             onChange={(e) => setSearch(e.currentTarget.value)}
 | |
|           />
 | |
|           <CustomScrollbar>
 | |
|             <DataSourceList
 | |
|               dashboard={false}
 | |
|               mixed={false}
 | |
|               // FIXME: Filter out the grafana data source in a hacky way
 | |
|               filter={(ds) => ds.name.includes(search) && ds.name !== '-- Grafana --'}
 | |
|               onChange={onChange}
 | |
|               current={current}
 | |
|             />
 | |
|           </CustomScrollbar>
 | |
|         </div>
 | |
|         <div className={styles.rightColumn}>
 | |
|           <div className={styles.builtInDataSources}>
 | |
|             <DataSourceList
 | |
|               className={styles.builtInDataSourceList}
 | |
|               filter={(ds) => !!ds.meta.builtIn}
 | |
|               dashboard
 | |
|               mixed
 | |
|               onChange={onChange}
 | |
|               current={current}
 | |
|             />
 | |
|             {enableFileUpload && (
 | |
|               <FileDropzone
 | |
|                 readAs="readAsArrayBuffer"
 | |
|                 fileListRenderer={() => undefined}
 | |
|                 options={{
 | |
|                   maxSize: DFImport.maxFileSize,
 | |
|                   multiple: false,
 | |
|                   accept: DFImport.acceptedFiles,
 | |
|                   ...fileUploadOptions,
 | |
|                   onDrop: (...args) => {
 | |
|                     fileUploadOptions?.onDrop?.(...args);
 | |
|                     onDismiss();
 | |
|                   },
 | |
|                 }}
 | |
|               >
 | |
|                 <FileDropzoneDefaultChildren />
 | |
|               </FileDropzone>
 | |
|             )}
 | |
|           </div>
 | |
|           <div className={styles.dsCTAs}>
 | |
|             <LinkButton variant="secondary" href={`datasources/new`}>
 | |
|               Configure a new data source
 | |
|             </LinkButton>
 | |
|           </div>
 | |
|         </div>
 | |
|       </div>
 | |
|     </Modal>
 | |
|   );
 | |
| }
 | |
| 
 | |
| function getDataSourceModalStyles(theme: GrafanaTheme2) {
 | |
|   return {
 | |
|     modal: css`
 | |
|       width: 80%;
 | |
|       height: 80%;
 | |
|     `,
 | |
|     modalContent: css`
 | |
|       display: flex;
 | |
|       flex-direction: row;
 | |
|       justify-content: space-between;
 | |
|       align-items: stretch;
 | |
|       height: 100%;
 | |
|     `,
 | |
|     leftColumn: css`
 | |
|       display: flex;
 | |
|       flex-direction: column;
 | |
|       width: 50%;
 | |
|       height: 100%;
 | |
|       padding-right: ${theme.spacing(1)};
 | |
|       border-right: 1px solid ${theme.colors.border.weak};
 | |
|     `,
 | |
|     rightColumn: css`
 | |
|       display: flex;
 | |
|       flex-direction: column;
 | |
|       width: 50%;
 | |
|       height: 100%;
 | |
|       padding: ${theme.spacing(1)};
 | |
|       justify-items: space-evenly;
 | |
|       align-items: stretch;
 | |
|       padding-left: ${theme.spacing(1)};
 | |
|     `,
 | |
|     builtInDataSources: css`
 | |
|       flex: 1;
 | |
|       margin-bottom: ${theme.spacing(4)};
 | |
|     `,
 | |
|     builtInDataSourceList: css`
 | |
|       margin-bottom: ${theme.spacing(4)};
 | |
|     `,
 | |
|     dsCTAs: css`
 | |
|       display: flex;
 | |
|       flex-direction: row;
 | |
|       width: 100%;
 | |
|       justify-content: flex-end;
 | |
|     `,
 | |
|     searchInput: css`
 | |
|       width: 100%;
 | |
|       min-height: 32px;
 | |
|       margin-bottom: ${theme.spacing(1)};
 | |
|     `,
 | |
|   };
 | |
| }
 |