Skip to content

file download upload #48

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion app/backendAPI/fileAPI.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* @flow weak */
import { request } from '../utils'
import { request, querystring as qs } from '../utils'
import config from '../config'

export function fetchPath (path, other, group) {
Expand All @@ -10,6 +10,27 @@ export function fetchPath (path, other, group) {
})
}

export function downloadFile (path, shouldPacked) {
const packOrRaw = shouldPacked ? 'pack' : 'raw'
let url = `${config.baseURL}/workspaces/${config.spaceKey}/${packOrRaw}`
url += '?' + qs.stringify({
path: path,
inline: false
})
window.open(url, '_blank')
}

export function uploadFile (path, file) {
let formdata = new FormData()
formdata.append('path', path)
formdata.append('files', file, file.name)
fetch(`${config.baseURL}/workspaces/${config.spaceKey}/upload`, {
method: 'POST',
body: formdata,
})
}


export function writeFile (path, content, base64) {
return request({
method: 'PUT',
Expand Down
5 changes: 5 additions & 0 deletions app/commands/commandBindings/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ export default {
}

Modal.dismissModal()
},


'file:download': c => {
api.downloadFile(c.context.path, c.context.isDir)
}
// 'file:unsaved_files_list':
}
6 changes: 5 additions & 1 deletion app/components/ContextMenu/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ const ContextMenu = (props) => {

return (
<div className='context-menu' style={{left: pos.x, top: pos.y}} >
<Menu key={`cm-${pos.x}-${pos.y}`} items={items} deactivate={deactivate} />
<Menu key={`cm-${pos.x}-${pos.y}`}
items={items}
deactivate={deactivate}
context={context}
/>
</div>
)
}
Expand Down
9 changes: 9 additions & 0 deletions app/components/FileTree/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,12 @@ export function initializeFileTree () {
api.fetchPath('/').then(data => dispatch(loadNodeData(data)))
}
}

export const uploadFilesToPath = (files, path) => {
return (dispatch, getState) => {
if (!files.length) return
_(files).forEach(file => {
api.uploadFile(path, file)
})
}
}
14 changes: 14 additions & 0 deletions app/components/FileTree/contextMenuItems.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@ var items = [
name: 'Rename...',
icon: '',
command: 'file:rename'
}, {
name: 'Download',
icon: '',
command: 'file:download'
}, {
name: 'Upload',
icon: '',
command: () => {
// reset the files selected from last round
document.getElementById('filetree-hidden-input-form').reset()
const input = document.getElementById('filetree-hidden-input')
input.dispatchEvent(new MouseEvent('click'))
},
visible: ctx => Boolean(ctx.isDir)
}
]

Expand Down
17 changes: 16 additions & 1 deletion app/components/FileTree/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ import * as FileTreeActions from './actions'
import FileTreeContextMenuItems from './contextMenuItems'
import subscribeToFileChange from './subscribeToFileChange'

const FileUploadInput = ({ node, handleUpload }) => {
return (
<form id='filetree-hidden-input-form' style={{position: 'fixed',top: '-10000px'}}>
<input
id='filetree-hidden-input'
type='file'
name='files'
multiple={true}
onChange={e=>handleUpload(e.target.files, node.path)}
/>
</form>
)
}

class FileTree extends Component {
constructor (props) {
Expand Down Expand Up @@ -90,8 +103,10 @@ class FileTree extends Component {
isActive={isContextMenuActive}
pos={contextMenuPos}
context={this.state.contextNode}
deactivate={this.setState.bind(this, { isContextMenuActive: false })}
deactivate={()=>this.setState({ isContextMenuActive: false })}
/>
<FileUploadInput node={this.state.contextNode}
handleUpload={this.props.uploadFilesToPath} />
</div>
)
}
Expand Down
5 changes: 3 additions & 2 deletions app/components/Menu/Menu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Menu extends Component {
}

render () {
const {items, className, style, deactivate, deactivateTopLevelMenu} = this.props
const {items, className, context, style, deactivate, deactivateTopLevelMenu} = this.props
return (
<ul className={cx('menu', className)}
style={style}
Expand All @@ -35,7 +35,8 @@ class Menu extends Component {
toggleActive={this.activateItemAtIndex}
deactivateTopLevelMenu={deactivate||deactivateTopLevelMenu}
key={`menu-item-${item.name}-${i}`}
state={this.props.state} /> )}
state={this.props.state}
context={this.props.context} /> )}
</ul>
)
}
Expand Down
46 changes: 26 additions & 20 deletions app/components/Menu/MenuItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,44 +19,50 @@ const triangleIcon = (<div
/>)


const handleMenuItemCommand = (item) => {
if (typeof item.command === 'function') {
item.command()
const handleMenuItemCommand = (command) => {
if (typeof command === 'function') {
command()
return true
} else if (typeof item.command === 'string') {
} else {
// ↓ temporary measure to resolve a cyclic dependent conflict
require('../../commands').dispatchCommand(item.command)
require('../../commands').dispatchCommand(command)
return true
}
}

const MenuItem = ({item, index, isActive, toggleActive, deactivateTopLevelMenu, state}) => {
const MenuItem = ({item, index, isActive, toggleActive, deactivateTopLevelMenu, state, context}) => {
if (item.visible && !item.visible(context)) return null
let itemElement = item.element ? React.createElement(item.element, { item }) : null
if (item.name == '-') return <li><hr /></li>
const disabled = item.checkDisable ? item.checkDisable(state) : item.isDisabled

return (
<li className='menu-item'>
<div
className={cx('menu-item-container', {active: isActive, disabled: disabled, padding: '4px 8px' })}
className={cx('menu-item-container', {
active: isActive,
disabled: disabled,
padding: '4px 8px'
})}
onMouseEnter={e => toggleActive(index)}
onClick={e => {
if(disabled)
return
handleMenuItemCommand(item)&&deactivateTopLevelMenu()
}} >
if (disabled) return
handleMenuItemCommand(item.command)&&deactivateTopLevelMenu()
}}
>
<div className={item.icon} style={{ paddingTop: '3px', marginRight: '8px', marginLeft: '-6px' }}></div>
<div className='menu-item-name'>{item.displayName || item.name}</div>
{ item.shortcut?
<div className='menu-item-shortcut'>{item.shortcut}</div>
: null }
{
item.items && item.items.length ?
triangleIcon : null
}
<div className='menu-item-name'>{itemElement || item.displayName || item.name}</div>
{ item.shortcut
? <div className='menu-item-shortcut'>{item.shortcut}</div>
: null }
{ item.items && item.items.length
? triangleIcon
: null }
</div>
{ isActive && item.items && item.items.length ?
<Menu items={item.items} className={cx({active: isActive})}
deactivateTopLevelMenu={deactivateTopLevelMenu} />
: null}
: null }
</li>
)
}
Expand Down
1 change: 1 addition & 0 deletions app/styles/components/Menu.styl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
display: flex;
min-width: 140px;
padding: 4px 20px;
cursor: default;
&.active {
background-color: $menu-background-color-active;
color: #fff;
Expand Down
1 change: 1 addition & 0 deletions app/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export createI18n from './createI18n'
export update from './immutableUpdate'
export Model from './model'
export { getExtensions } from './extensions.js'
export { querystring } from './url-helpers'