Skip to content

Commit

Permalink
feat(workbench): drag-and-drop body updates
Browse files Browse the repository at this point in the history
some leftover things to do here:
* dropping a file _outside_ the drop zone doesn't cancel the drop overlay. I've added a cancel button for now so users aren't stuck
* need to update status indicator
  • Loading branch information
b5 committed Feb 27, 2020
1 parent 6eede95 commit 5de9843
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 10 deletions.
69 changes: 67 additions & 2 deletions app/components/DatasetComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from 'react'
import path from 'path'

import MetadataContainer from '../containers/MetadataContainer'
import MetadataEditor from '../components/MetadataEditor'
Expand All @@ -20,6 +21,8 @@ import { Details } from '../models/details'
import { ApiActionThunk } from '../store/api'
import { Action } from 'redux'
import Dataset from '../models/dataset'
import DropZone from './chrome/DropZone'
import CalloutBlock from './chrome/CalloutBlock'
import Icon from './chrome/Icon'
import StatusDot from './chrome/StatusDot'

Expand Down Expand Up @@ -48,12 +51,60 @@ interface DatasetComponentProps {
}

const DatasetComponent: React.FunctionComponent<DatasetComponentProps> = (props: DatasetComponentProps) => {
const { component: selectedComponent, componentStatus, isLoading, history = false, fsiPath, data, peername, name, stats, bodyPageInfo, details, setDetailsBar, fetchBody, write } = props
const {
component: selectedComponent,
componentStatus,
isLoading,
history = false,
fsiPath,
data,
peername,
name,
stats,
bodyPageInfo,
details,
setDetailsBar,
fetchBody,
write
} = props

const hasParseError = componentStatus.status === 'parse error'
const component = selectedComponent || 'meta'
const { displayName, icon, tooltip } = getComponentDisplayProps(component)

const [dragging, setDragging] = React.useState(false)

const dragHandler = (drag: boolean) => (e: React.DragEvent) => {
if (history) {
return
}
e.preventDefault()
setDragging(drag)
}

const dropHandler = (e: React.DragEvent) => {
setDragging(false)
e.preventDefault()
const ext = path.extname(e.dataTransfer.files[0].path)
// closeToast()
if (!(ext === '.csv' || ext === '.json')) {
// // open toast for 1 second
// openToast(ToastTypes.error, 'drag-drop', 'unsupported file format: only json and csv supported')
// setTimeout(() => closeToast(), 2500)
console.log('can only drop csv & json files')
return
}

// const {
// path: filePath,
// name: fileName,
// size: fileSize
// } = e.dataTransfer.files[0]
// importFile(filePath, fileName, fileSize)
console.log('dropped file')
handleWrite({ bodyPath: e.dataTransfer.files[0].path })
}

const handleWrite = (data: Dataset): ApiActionThunk | void => {
return write(peername, name, data)
}
Expand Down Expand Up @@ -136,7 +187,21 @@ const DatasetComponent: React.FunctionComponent<DatasetComponentProps> = (props:
unmountOnExit
appear={true}
>
<div className='transition-wrap'>
<div className='transition-wrap'
onDragEnter={dragHandler(true)}
>
{dragging && <DropZone
title='Drop a body update'
subtitle='import either csv or json file'
setDragging={setDragging}
onDrop={dropHandler}
/>}
{!history && data.bodyPath && <CalloutBlock
type='info'
text={`body will be replaced with file: ${data.bodyPath} when you commit`}
cancelText='unstage file'
onCancel={() => { handleWrite({ bodyPath: '' }) }}
/>}
<Body
data={data}
pageInfo={bodyPageInfo}
Expand Down
18 changes: 18 additions & 0 deletions app/components/chrome/CalloutBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react'

export interface CalloutBlockProps {
text: string
type: 'info' | 'warning'

cancelText?: string
onCancel?: () => void
}

const CalloutBlock: React.FC<CalloutBlockProps> = ({ text, type, cancelText = 'cancel', onCancel }) => (
<div className={`callout-block ${type}`}>
{onCancel && <a className='cancel' onClick={onCancel}>{cancelText}</a>}
<p className='text'>{text}</p>
</div>
)

export default CalloutBlock
12 changes: 8 additions & 4 deletions app/components/chrome/DropZone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faFileMedical } from '@fortawesome/free-solid-svg-icons'

export interface DropZoneProps {
title: string
subtitle: string

setDragging: (showing: boolean) => void
onDrop: (e: React.SyntheticEvent) => void
}

const DropZone: React.FC<DropZoneProps> = (props) => {
const { onDrop, setDragging } = props
const { title, subtitle, onDrop, setDragging } = props

const setDragStateHandler = (showing: boolean) => {
return (e: React.SyntheticEvent) => {
Expand All @@ -20,15 +23,16 @@ const DropZone: React.FC<DropZoneProps> = (props) => {
return (<div className='drag-drop' id='drag-drop'
onDragEnter={setDragStateHandler(true)}
onDragOver={setDragStateHandler(true)}
onDragLeave={setDragStateHandler(false)}
onDragExit={setDragStateHandler(false)}
onDragEnd={setDragStateHandler(false)}
onDrop={onDrop}
>
<div className="inner">
<div className="icon"><FontAwesomeIcon size="5x" icon={faFileMedical} /></div>
<div className="spacer">Drop to Create a new dataset</div>
<div className="spacer">{title}</div>
<a onClick={setDragStateHandler(false)}>cancel</a>
</div>
<div className="footer">You can import csv and json files</div>
<div className="footer">{subtitle}</div>
</div>)
}

Expand Down
2 changes: 1 addition & 1 deletion app/components/collection/Collection.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react'
import { Action, AnyAction } from 'redux'

import { MyDatasets, WorkingDataset } from '../../models/store'
import { MyDatasets, WorkingDataset, ToastType } from '../../models/store'

import DatasetList from '../DatasetList'
import Layout from '../Layout'
Expand Down
11 changes: 8 additions & 3 deletions app/components/collection/CollectionHome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const CollectionHome: React.FC<CollectionHomeProps> = (props) => {

const [dragging, setDragging] = React.useState(false)

const setDragStateHandler = (prefix: string, dragState: boolean) => {
const setDragStateHandler = (dragState: boolean) => {
return (e: React.SyntheticEvent) => {
e.preventDefault()
setDragging(dragState)
Expand Down Expand Up @@ -52,8 +52,13 @@ const CollectionHome: React.FC<CollectionHomeProps> = (props) => {
}

return (
<div className='main-content-flex' onDragEnter={setDragStateHandler('outer', true)}>
{dragging && <DropZone setDragging={setDragging} onDrop={dropHandler} />}
<div className='main-content-flex' onDragEnter={setDragStateHandler(true)}>
{dragging && <DropZone
title='Drop to create a new dataset'
subtitle='You can import csv and json files'
setDragging={setDragging}
onDrop={dropHandler}
/>}
<div className='main-content-header'>
<HeaderColumnButton
id='create-dataset'
Expand Down
1 change: 1 addition & 0 deletions app/models/dataset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export interface Dataset {
meta?: Meta
structure?: Structure
body?: Body
bodyPath?: string
commit?: Commit
readme?: string
[key: string]: any
Expand Down
23 changes: 23 additions & 0 deletions app/scss/0.4.0/chrome.scss
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,27 @@
bottom: 0;
padding: 10px;
width: 100%;
}

.callout-block {
width: 100%;
padding: 15px 10px 0 10px;

.text {
margin-top: 5px;
}

&.info {
background: #4FC7F3;
border: solid 1px #4FC7F3;
}

.cancel {
float: right;
padding: 3px 8px;
border: 1px solid white;
border-radius: 3px;
color: white;
font-weight: 500;
}
}

0 comments on commit 5de9843

Please sign in to comment.