Merge pull request #3783 from influxdata/refactor/drag-and-drop

Refactor drag and drop to listen for events directly on window.
pull/10616/head
Deniz Kusefoglu 2018-06-27 14:32:14 -07:00 committed by GitHub
commit a817565dd9
2 changed files with 59 additions and 67 deletions

View File

@ -1,6 +1,5 @@
import React, {PureComponent, ReactElement, DragEvent} from 'react' import React, {PureComponent, ReactElement} from 'react'
import classnames from 'classnames' import classnames from 'classnames'
// import {notifyDashboardUploadFailed} from 'src/shared/copy/notifications'
interface Props { interface Props {
fileTypesToAccept?: string fileTypesToAccept?: string
@ -13,7 +12,6 @@ interface State {
inputContent: string | null inputContent: string | null
uploadContent: string uploadContent: string
fileName: string fileName: string
progress: string
dragClass: string dragClass: string
} }
@ -32,41 +30,28 @@ class DragAndDrop extends PureComponent<Props, State> {
inputContent: null, inputContent: null,
uploadContent: '', uploadContent: '',
fileName: '', fileName: '',
progress: '',
dragClass: 'drag-none', dragClass: 'drag-none',
} }
} }
public componentDidMount() {
window.addEventListener('dragover', this.handleWindowDragOver)
window.addEventListener('drop', this.handleFileDrop)
window.addEventListener('dragenter', this.handleDragEnter)
window.addEventListener('dragleave', this.handleDragLeave)
}
public componentWillUnmount() {
window.removeEventListener('dragover', this.handleWindowDragOver)
window.removeEventListener('drop', this.handleFileDrop)
window.removeEventListener('dragenter', this.handleDragEnter)
window.removeEventListener('dragleave', this.handleDragLeave)
}
public render() { public render() {
return ( return (
<div className={this.containerClass}> <div className={this.containerClass}>
{/* (Invisible, covers entire screen) <div className={this.dragAreaClass} onClick={this.handleFileOpen}>
This div handles drag only*/}
<div
onDrop={this.handleFile(true)}
onDragOver={this.handleDragOver}
onDragEnter={this.handleDragEnter}
onDragExit={this.handleDragLeave}
onDragLeave={this.handleDragLeave}
className="drag-and-drop--dropzone"
/>
{/* visible form, handles drag & click */}
{this.dragArea}
</div>
)
}
private get dragArea(): ReactElement<HTMLDivElement> {
return (
<div
className={this.dragAreaClass}
onClick={this.handleFileOpen}
onDrop={this.handleFile(true)}
onDragOver={this.handleDragOver}
onDragEnter={this.handleDragEnter}
onDragExit={this.handleDragLeave}
onDragLeave={this.handleDragLeave}
>
{this.dragAreaHeader} {this.dragAreaHeader}
<div className={this.infoClass} /> <div className={this.infoClass} />
<input <input
@ -74,13 +59,18 @@ class DragAndDrop extends PureComponent<Props, State> {
ref={r => (this.fileInput = r)} ref={r => (this.fileInput = r)}
className="drag-and-drop--input" className="drag-and-drop--input"
accept={this.fileTypesToAccept} accept={this.fileTypesToAccept}
onChange={this.handleFile(false)} onChange={this.handleFileClick}
/> />
{this.buttons} {this.buttons}
</div> </div>
</div>
) )
} }
private handleWindowDragOver = (event: DragEvent) => {
event.preventDefault()
}
private get fileTypesToAccept(): string { private get fileTypesToAccept(): string {
const {fileTypesToAccept} = this.props const {fileTypesToAccept} = this.props
@ -153,16 +143,31 @@ class DragAndDrop extends PureComponent<Props, State> {
handleSubmit(uploadContent, fileName) handleSubmit(uploadContent, fileName)
} }
private handleFile = (drop: boolean) => (e: any): void => { private handleFileClick = (e: any): void => {
let file const file = e.currentTarget.files[0]
if (drop) {
file = e.dataTransfer.files[0] if (!file) {
return
}
e.preventDefault()
e.stopPropagation()
const reader = new FileReader()
reader.readAsText(file)
reader.onload = loadEvent => {
this.setState({
uploadContent: loadEvent.target.result,
fileName: file.name,
})
}
}
private handleFileDrop = (e: any): void => {
const file = e.dataTransfer.files[0]
this.setState({ this.setState({
dragClass: 'drag-none', dragClass: 'drag-none',
}) })
} else {
file = e.currentTarget.files[0]
}
if (!file) { if (!file) {
return return
@ -193,18 +198,13 @@ class DragAndDrop extends PureComponent<Props, State> {
this.fileInput.value = '' this.fileInput.value = ''
} }
private handleDragOver = (e: DragEvent<HTMLDivElement>) => { private handleDragEnter = (e: DragEvent): void => {
e.preventDefault()
e.stopPropagation()
}
private handleDragEnter = (e: DragEvent<HTMLDivElement>): void => {
dragCounter += 1 dragCounter += 1
e.preventDefault() e.preventDefault()
this.setState({dragClass: 'drag-over'}) this.setState({dragClass: 'drag-over'})
} }
private handleDragLeave = (e: DragEvent<HTMLDivElement>): void => { private handleDragLeave = (e: DragEvent): void => {
dragCounter -= 1 dragCounter -= 1
e.preventDefault() e.preventDefault()
if (dragCounter === 0) { if (dragCounter === 0) {

View File

@ -3,16 +3,6 @@
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
*/ */
.drag-and-drop--dropzone {
position: absolute;
top: 50%;
left: 50%;
width: 1000%;
height: 1000%;
transform: translate(-50%, -50%);
z-index: $drag-and-drop--z-dropzone;
}
.drag-and-drop--form { .drag-and-drop--form {
position: relative; position: relative;
z-index: $drag-and-drop--z-form; z-index: $drag-and-drop--z-form;
@ -69,7 +59,9 @@ input[type='file'].drag-and-drop--input {
flex-wrap: nowrap; flex-wrap: nowrap;
margin-top: 18px; margin-top: 18px;
> button.btn {margin: 0 4px;} > button.btn {
margin: 0 4px;
}
} }
/* /*