Merge pull request #3783 from influxdata/refactor/drag-and-drop
Refactor drag and drop to listen for events directly on window.pull/10616/head
commit
a817565dd9
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue