Move WriteData to ts
parent
c1ae106c24
commit
eb024b928e
|
@ -1,105 +0,0 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import WriteDataFooter from 'src/data_explorer/components/WriteDataFooter'
|
||||
|
||||
const WriteDataBody = ({
|
||||
handleKeyUp,
|
||||
handleCancelFile,
|
||||
handleFile,
|
||||
handleEdit,
|
||||
handleSubmit,
|
||||
inputContent,
|
||||
uploadContent,
|
||||
fileName,
|
||||
isManual,
|
||||
fileInput,
|
||||
handleFileOpen,
|
||||
isUploading,
|
||||
}) => (
|
||||
<div className="write-data-form--body">
|
||||
{isManual ? (
|
||||
<textarea
|
||||
className="form-control write-data-form--input"
|
||||
autoComplete="off"
|
||||
spellCheck="false"
|
||||
placeholder="<measurement>,<tag_key>=<tag_value> <field_key>=<field_value>"
|
||||
onKeyUp={handleKeyUp}
|
||||
onChange={handleEdit}
|
||||
autoFocus={true}
|
||||
data-test="manual-entry-field"
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className={
|
||||
uploadContent
|
||||
? 'write-data-form--file'
|
||||
: 'write-data-form--file write-data-form--file_active'
|
||||
}
|
||||
onClick={handleFileOpen}
|
||||
>
|
||||
{uploadContent ? (
|
||||
<h3 className="write-data-form--filepath_selected">{fileName}</h3>
|
||||
) : (
|
||||
<h3 className="write-data-form--filepath_empty">
|
||||
Drop a file here or click to upload
|
||||
</h3>
|
||||
)}
|
||||
<div
|
||||
className={
|
||||
uploadContent
|
||||
? 'write-data-form--graphic write-data-form--graphic_success'
|
||||
: 'write-data-form--graphic'
|
||||
}
|
||||
/>
|
||||
<input
|
||||
type="file"
|
||||
onChange={handleFile(false)}
|
||||
className="write-data-form--upload"
|
||||
ref={fileInput}
|
||||
accept="text/*, application/gzip"
|
||||
/>
|
||||
{uploadContent && (
|
||||
<span className="write-data-form--file-submit">
|
||||
<button className="btn btn-md btn-success" onClick={handleSubmit}>
|
||||
Write this File
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-md btn-default"
|
||||
onClick={handleCancelFile}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{isManual && (
|
||||
<WriteDataFooter
|
||||
isUploading={isUploading}
|
||||
isManual={isManual}
|
||||
inputContent={inputContent}
|
||||
handleSubmit={handleSubmit}
|
||||
uploadContent={uploadContent}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
const {func, string, bool} = PropTypes
|
||||
|
||||
WriteDataBody.propTypes = {
|
||||
handleKeyUp: func.isRequired,
|
||||
handleEdit: func.isRequired,
|
||||
handleCancelFile: func.isRequired,
|
||||
handleFile: func.isRequired,
|
||||
handleSubmit: func.isRequired,
|
||||
inputContent: string,
|
||||
uploadContent: string,
|
||||
fileName: string,
|
||||
isManual: bool,
|
||||
fileInput: func.isRequired,
|
||||
handleFileOpen: func.isRequired,
|
||||
isUploading: bool.isRequired,
|
||||
}
|
||||
|
||||
export default WriteDataBody
|
|
@ -0,0 +1,162 @@
|
|||
import React, {
|
||||
PureComponent,
|
||||
ChangeEvent,
|
||||
KeyboardEvent,
|
||||
MouseEvent,
|
||||
DragEvent,
|
||||
ReactElement,
|
||||
} from 'react'
|
||||
import WriteDataFooter from 'src/data_explorer/components/WriteDataFooter'
|
||||
|
||||
interface Props {
|
||||
handleCancelFile: (e: MouseEvent<HTMLButtonElement>) => void
|
||||
handleEdit: (e: ChangeEvent<HTMLTextAreaElement>) => void
|
||||
handleKeyUp: (e: KeyboardEvent<HTMLTextAreaElement>) => void
|
||||
handleFile: (drop: boolean) => (e: DragEvent<HTMLInputElement>) => void
|
||||
handleSubmit: (e: MouseEvent<HTMLButtonElement>) => void
|
||||
inputContent: string
|
||||
uploadContent: string
|
||||
fileName: string
|
||||
isManual: boolean
|
||||
fileInput: (ref: any) => any
|
||||
handleFileOpen: () => void
|
||||
isUploading: boolean
|
||||
}
|
||||
|
||||
class WriteDataBody extends PureComponent<Props> {
|
||||
public render() {
|
||||
return (
|
||||
<div className="write-data-form--body">
|
||||
{this.input}
|
||||
{this.footer}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private handleFile = (e: any): void => {
|
||||
this.props.handleFile(false)(e)
|
||||
}
|
||||
|
||||
private get input(): JSX.Element {
|
||||
const {isManual} = this.props
|
||||
if (isManual) {
|
||||
return this.textarea
|
||||
}
|
||||
|
||||
return this.dragArea
|
||||
}
|
||||
|
||||
private get textarea(): ReactElement<HTMLTextAreaElement> {
|
||||
const {handleKeyUp, handleEdit} = this.props
|
||||
return (
|
||||
<textarea
|
||||
spellCheck={false}
|
||||
autoFocus={true}
|
||||
autoComplete="off"
|
||||
onKeyUp={handleKeyUp}
|
||||
onChange={handleEdit}
|
||||
data-test="manual-entry-field"
|
||||
className="form-control write-data-form--input"
|
||||
placeholder="<measurement>,<tag_key>=<tag_value> <field_key>=<field_value>"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
private get dragArea(): ReactElement<HTMLDivElement> {
|
||||
const {fileInput, handleFileOpen} = this.props
|
||||
|
||||
return (
|
||||
<div className={this.dragAreaClass} onClick={handleFileOpen}>
|
||||
{this.dragAreaHeader}
|
||||
<div className={this.infoClass} />
|
||||
<input
|
||||
type="file"
|
||||
ref={fileInput}
|
||||
className="write-data-form--upload"
|
||||
accept="text/*, application/gzip"
|
||||
onChange={this.handleFile}
|
||||
/>
|
||||
{this.buttons}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private get dragAreaHeader(): ReactElement<HTMLHeadElement> {
|
||||
const {uploadContent, fileName} = this.props
|
||||
|
||||
if (uploadContent) {
|
||||
return <h3 className="write-data-form--filepath_selected">{fileName}</h3>
|
||||
}
|
||||
|
||||
return (
|
||||
<h3 className="write-data-form--filepath_empty">
|
||||
Drop a file here or click to upload
|
||||
</h3>
|
||||
)
|
||||
}
|
||||
|
||||
private get infoClass(): string {
|
||||
const {uploadContent} = this.props
|
||||
|
||||
if (uploadContent) {
|
||||
return 'write-data-form--graphic write-data-form--graphic_success'
|
||||
}
|
||||
|
||||
return 'write-data-form--graphic'
|
||||
}
|
||||
|
||||
private get buttons(): ReactElement<HTMLSpanElement> | null {
|
||||
const {uploadContent, handleSubmit, handleCancelFile} = this.props
|
||||
|
||||
if (!uploadContent) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<span className="write-data-form--file-submit">
|
||||
<button className="btn btn-md btn-success" onClick={handleSubmit}>
|
||||
Write this File
|
||||
</button>
|
||||
<button className="btn btn-md btn-default" onClick={handleCancelFile}>
|
||||
Cancel
|
||||
</button>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
private get dragAreaClass(): string {
|
||||
const {uploadContent} = this.props
|
||||
|
||||
if (uploadContent) {
|
||||
return 'write-data-form--file'
|
||||
}
|
||||
|
||||
return 'write-data-form--file write-data-form--file_active'
|
||||
}
|
||||
|
||||
private get footer(): JSX.Element | null {
|
||||
const {
|
||||
isUploading,
|
||||
isManual,
|
||||
inputContent,
|
||||
handleSubmit,
|
||||
uploadContent,
|
||||
} = this.props
|
||||
|
||||
if (!isManual) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<WriteDataFooter
|
||||
isUploading={isUploading}
|
||||
isManual={isManual}
|
||||
inputContent={inputContent}
|
||||
handleSubmit={handleSubmit}
|
||||
uploadContent={uploadContent}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default WriteDataBody
|
|
@ -1,17 +1,43 @@
|
|||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import React, {
|
||||
PureComponent,
|
||||
DragEvent,
|
||||
ChangeEvent,
|
||||
KeyboardEvent,
|
||||
} from 'react'
|
||||
import classnames from 'classnames'
|
||||
|
||||
import OnClickOutside from 'shared/components/OnClickOutside'
|
||||
import OnClickOutside from 'src/shared/components/OnClickOutside'
|
||||
import WriteDataBody from 'src/data_explorer/components/WriteDataBody'
|
||||
import WriteDataHeader from 'src/data_explorer/components/WriteDataHeader'
|
||||
|
||||
import {OVERLAY_TECHNOLOGY} from 'shared/constants/classNames'
|
||||
import {OVERLAY_TECHNOLOGY} from 'src/shared/constants/classNames'
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
import {Source, DropdownItem} from 'src/types'
|
||||
let dragCounter = 0
|
||||
|
||||
interface Props {
|
||||
source: Source
|
||||
selectedDatabase: string
|
||||
onClose: () => void
|
||||
errorThrown: () => void
|
||||
writeLineProtocol: (source: Source, database: string, content: string) => void
|
||||
}
|
||||
|
||||
interface State {
|
||||
selectedDatabase: string
|
||||
inputContent: string | null
|
||||
uploadContent: string
|
||||
fileName: string
|
||||
progress: string
|
||||
isManual: boolean
|
||||
dragClass: string
|
||||
isUploading: boolean
|
||||
}
|
||||
|
||||
@ErrorHandling
|
||||
class WriteDataForm extends Component {
|
||||
class WriteDataForm extends PureComponent<Props, State> {
|
||||
private fileInput: HTMLInputElement
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
|
@ -26,23 +52,52 @@ class WriteDataForm extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
toggleWriteView = isManual => () => {
|
||||
public render() {
|
||||
const {onClose, errorThrown, source} = this.props
|
||||
const {dragClass} = this.state
|
||||
|
||||
return (
|
||||
<div
|
||||
onDrop={this.handleFile(true)}
|
||||
onDragOver={this.handleDragOver}
|
||||
onDragEnter={this.handleDragEnter}
|
||||
onDragExit={this.handleDragLeave}
|
||||
onDragLeave={this.handleDragLeave}
|
||||
className={classnames(OVERLAY_TECHNOLOGY, dragClass)}
|
||||
>
|
||||
<div className="write-data-form">
|
||||
<WriteDataHeader
|
||||
{...this.state}
|
||||
source={source}
|
||||
onClose={onClose}
|
||||
errorThrown={errorThrown}
|
||||
toggleWriteView={this.toggleWriteView}
|
||||
handleSelectDatabase={this.handleSelectDatabase}
|
||||
/>
|
||||
<WriteDataBody
|
||||
{...this.state}
|
||||
fileInput={this.handleFileInputRef}
|
||||
handleEdit={this.handleEdit}
|
||||
handleFile={this.handleFile}
|
||||
handleKeyUp={this.handleKeyUp}
|
||||
handleSubmit={this.handleSubmit}
|
||||
handleFileOpen={this.handleFileOpen}
|
||||
handleCancelFile={this.handleCancelFile}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private toggleWriteView = (isManual: boolean) => {
|
||||
this.setState({isManual})
|
||||
}
|
||||
|
||||
handleSelectDatabase = item => {
|
||||
private handleSelectDatabase = (item: DropdownItem): void => {
|
||||
this.setState({selectedDatabase: item.text})
|
||||
}
|
||||
|
||||
handleClickOutside = e => {
|
||||
// guard against clicking to close error notification
|
||||
if (e.target.className === OVERLAY_TECHNOLOGY) {
|
||||
const {onClose} = this.props
|
||||
onClose()
|
||||
}
|
||||
}
|
||||
|
||||
handleKeyUp = e => {
|
||||
private handleKeyUp = (e: KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
e.stopPropagation()
|
||||
if (e.key === 'Escape') {
|
||||
const {onClose} = this.props
|
||||
|
@ -50,7 +105,7 @@ class WriteDataForm extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
handleSubmit = async () => {
|
||||
private handleSubmit = async () => {
|
||||
const {onClose, source, writeLineProtocol} = this.props
|
||||
const {inputContent, uploadContent, selectedDatabase, isManual} = this.state
|
||||
const content = isManual ? inputContent : uploadContent
|
||||
|
@ -67,11 +122,11 @@ class WriteDataForm extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
handleEdit = e => {
|
||||
private handleEdit = (e: ChangeEvent<HTMLTextAreaElement>): void => {
|
||||
this.setState({inputContent: e.target.value.trim()})
|
||||
}
|
||||
|
||||
handleFile = drop => e => {
|
||||
private handleFile = (drop: boolean) => (e: any): void => {
|
||||
let file
|
||||
if (drop) {
|
||||
file = e.dataTransfer.files[0]
|
||||
|
@ -79,7 +134,7 @@ class WriteDataForm extends Component {
|
|||
dragClass: 'drag-none',
|
||||
})
|
||||
} else {
|
||||
file = e.target.files[0]
|
||||
file = e.currentTarget.files[0]
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
|
@ -99,23 +154,23 @@ class WriteDataForm extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
handleCancelFile = () => {
|
||||
private handleCancelFile = (): void => {
|
||||
this.setState({uploadContent: ''})
|
||||
this.fileInput.value = ''
|
||||
}
|
||||
|
||||
handleDragOver = e => {
|
||||
private handleDragOver = e => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
handleDragEnter = e => {
|
||||
private handleDragEnter = (e: DragEvent<HTMLDivElement>): void => {
|
||||
dragCounter += 1
|
||||
e.preventDefault()
|
||||
this.setState({dragClass: 'drag-over'})
|
||||
}
|
||||
|
||||
handleDragLeave = e => {
|
||||
private handleDragLeave = (e: DragEvent<HTMLDivElement>): void => {
|
||||
dragCounter -= 1
|
||||
e.preventDefault()
|
||||
if (dragCounter === 0) {
|
||||
|
@ -123,67 +178,14 @@ class WriteDataForm extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
handleFileOpen = () => {
|
||||
private handleFileOpen = (): void => {
|
||||
const {uploadContent} = this.state
|
||||
if (uploadContent === '') {
|
||||
this.fileInput.click()
|
||||
}
|
||||
}
|
||||
|
||||
handleFileInputRef = el => (this.fileInput = el)
|
||||
|
||||
render() {
|
||||
const {onClose, errorThrown, source} = this.props
|
||||
const {dragClass} = this.state
|
||||
|
||||
return (
|
||||
<div
|
||||
onDrop={this.handleFile(true)}
|
||||
onDragOver={this.handleDragOver}
|
||||
onDragEnter={this.handleDragEnter}
|
||||
onDragExit={this.handleDragLeave}
|
||||
onDragLeave={this.handleDragLeave}
|
||||
className={classnames(OVERLAY_TECHNOLOGY, dragClass)}
|
||||
>
|
||||
<div className="write-data-form">
|
||||
<WriteDataHeader
|
||||
{...this.state}
|
||||
source={source}
|
||||
handleSelectDatabase={this.handleSelectDatabase}
|
||||
errorThrown={errorThrown}
|
||||
toggleWriteView={this.toggleWriteView}
|
||||
onClose={onClose}
|
||||
/>
|
||||
<WriteDataBody
|
||||
{...this.state}
|
||||
fileInput={this.handleFileInputRef}
|
||||
handleEdit={this.handleEdit}
|
||||
handleFile={this.handleFile}
|
||||
handleKeyUp={this.handleKeyUp}
|
||||
handleSubmit={this.handleSubmit}
|
||||
handleFileOpen={this.handleFileOpen}
|
||||
handleCancelFile={this.handleCancelFile}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const {func, shape, string} = PropTypes
|
||||
|
||||
WriteDataForm.propTypes = {
|
||||
source: shape({
|
||||
links: shape({
|
||||
proxy: string.isRequired,
|
||||
self: string.isRequired,
|
||||
queries: string.isRequired,
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
onClose: func.isRequired,
|
||||
writeLineProtocol: func.isRequired,
|
||||
errorThrown: func.isRequired,
|
||||
selectedDatabase: string,
|
||||
private handleFileInputRef = r => (this.fileInput = r)
|
||||
}
|
||||
|
||||
export default OnClickOutside(WriteDataForm)
|
|
@ -1,10 +1,10 @@
|
|||
import React, {PureComponent} from 'react'
|
||||
import DatabaseDropdown from 'src/shared/components/DatabaseDropdown'
|
||||
import {Source} from 'src/types'
|
||||
import {Source, DropdownItem} from 'src/types'
|
||||
|
||||
interface Props {
|
||||
handleSelectDatabase: () => void
|
||||
selectedDatabase: () => void
|
||||
handleSelectDatabase: (item: DropdownItem) => void
|
||||
selectedDatabase: string
|
||||
toggleWriteView: (isWriteViewToggled: boolean) => void
|
||||
errorThrown: () => void
|
||||
onClose: () => void
|
||||
|
|
|
@ -30,7 +30,9 @@ class DatabaseDropdown extends Component {
|
|||
|
||||
return (
|
||||
<Dropdown
|
||||
items={databases.map(text => ({text}))}
|
||||
items={databases.map(text => ({
|
||||
text,
|
||||
}))}
|
||||
selected={database || 'Loading...'}
|
||||
onChoose={onSelectDatabase}
|
||||
onClick={onStartEdit ? onStartEdit : null}
|
||||
|
@ -50,11 +52,15 @@ class DatabaseDropdown extends Component {
|
|||
|
||||
const nonSystemDatabases = databases.filter(name => name !== '_internal')
|
||||
|
||||
this.setState({databases: nonSystemDatabases})
|
||||
this.setState({
|
||||
databases: nonSystemDatabases,
|
||||
})
|
||||
const selectedDatabaseText = nonSystemDatabases.includes(database)
|
||||
? database
|
||||
: nonSystemDatabases[0] || 'No databases'
|
||||
onSelectDatabase({text: selectedDatabaseText})
|
||||
onSelectDatabase({
|
||||
text: selectedDatabaseText,
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
onErrorThrown(error)
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import {ReactNode} from 'react'
|
||||
|
||||
export type DropdownItem =
|
||||
| {
|
||||
text: string
|
||||
}
|
||||
| string
|
||||
export interface DropdownItem {
|
||||
text: string
|
||||
}
|
||||
|
||||
export interface DropdownAction {
|
||||
icon: string
|
||||
|
|
Loading…
Reference in New Issue