Skip to content
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

Remove jquery #215

Merged
merged 15 commits into from Jan 20, 2016
9 changes: 2 additions & 7 deletions app/scripts/pages/files.js
@@ -1,6 +1,4 @@
import React from 'react'
import ReactDOM from 'react-dom'
import $ from 'jquery'
import {Row, Col, Nav, NavItem, Panel} from 'react-bootstrap'
import {LinkContainer} from 'react-router-bootstrap'
import debug from 'debug'
Expand Down Expand Up @@ -51,29 +49,25 @@ export default React.createClass({

addFile: function (e) {
e.preventDefault()
$(ReactDOM.findDOMNode(this)).find('.file-select').click()
return
this.refs.fileSelect.click()
},

onDragOver: function (e) {
log('dragover')
this.setState({ dragging: true })
$(e.target).addClass('hover')
e.stopPropagation()
e.preventDefault()
},

onDragLeave: function (e) {
log('dragleave')
this.setState({ dragging: false })
$(e.target).removeClass('hover')
e.stopPropagation()
e.preventDefault()
},

onDrop: function (e) {
this.setState({ dragging: false })
$(e.target).removeClass('hover')
e.stopPropagation()
e.preventDefault()
this.onFileChange(e)
Expand Down Expand Up @@ -186,6 +180,7 @@ export default React.createClass({
</div>
<input
type='file'
ref='fileSelect'
className='file-select'
style={{display: 'none'}}
onChange={this.onFileChange}
Expand Down
3 changes: 1 addition & 2 deletions app/scripts/pages/objects.js
@@ -1,5 +1,4 @@
import React from 'react'
import $ from 'jquery'
import ObjectView from '../views/object'
import {parse} from '../utils/path.js'
import i18n from '../utils/i18n.js'
Expand Down Expand Up @@ -64,7 +63,7 @@ export default React.createClass({
},

updatePath: function (e) {
var path = $(e.target).val().trim()
var path = e.target.value.trim()
this.setState({ pathInput: path })
},

Expand Down
13 changes: 13 additions & 0 deletions app/scripts/utils/file-extension.js
@@ -0,0 +1,13 @@
export default function fileExtension (name, defaultExt = '?') {
if (!name) {
return defaultExt
}

const ext = name.split('.').pop()

if (ext === name) {
return defaultExt
} else {
return ext.toUpperCase()
}
}
13 changes: 6 additions & 7 deletions app/scripts/views/config.js
@@ -1,6 +1,4 @@
import React from 'react'
import ReactDOM from 'react-dom'
import $ from 'jquery'
import i18n from '../utils/i18n.js'

export default React.createClass({
Expand All @@ -14,7 +12,8 @@ export default React.createClass({
body: JSON.stringify(this.props.config, null, 2),
error: null,
saving: false,
saved: false
saved: false,
height: 0
}
},

Expand All @@ -30,9 +29,8 @@ export default React.createClass({
},

updateHeight: function () {
var el = $(ReactDOM.findDOMNode(this)).find('textarea')
el.height('1px')
el.height(el.get(0).scrollHeight)
var el = this.refs.textareaConfig
this.setState({height: el.scrollHeight})
},

handleChange: function (e) {
Expand Down Expand Up @@ -113,7 +111,8 @@ export default React.createClass({
{error}
{buttons}
<div className='textarea-panel panel panel-default padded'>
<textarea className='panel-inner' spellCheck='false' onChange={this.handleChange} value={this.state.body} />
<textarea ref='textareaConfig' className='panel-inner' style={{height: this.state.height}}
spellCheck='false' onChange={this.handleChange} value={this.state.body} />
</div>
{error}
{buttons}
Expand Down
30 changes: 30 additions & 0 deletions app/scripts/views/fileitem.js
@@ -0,0 +1,30 @@
import React from 'react'
import i18n from '../utils/i18n.js'
import {Glyphicon, Tooltip, OverlayTrigger} from 'react-bootstrap'
import fileExtension from '../utils/file-extension'

export default ({gatewayPath, dagPath, file, unpin}) => {
var type = fileExtension(file.name)
var tooltip = (
<Tooltip id={file.id}>{i18n.t('Remove')}</Tooltip>
)

return (
<tr className='webui-file' data-type={file.type}>
<td><span className='type'>{type}</span></td>
<td className='filelist-name'><a target='_blank' href={gatewayPath}>{file.name}</a></td>
<td className='id-cell'><code>{file.id}</code></td>
<td className='action-cell'>
<a target='_blank' href={gatewayPath}>{i18n.t('RAW')}</a>
<span className='separator'>|</span>
<a href={dagPath}>{i18n.t('DAG')}</a>
<span className='separator'>|</span>
<a href='#' onClick={unpin}>
<OverlayTrigger placement='right' overlay={tooltip}>
<Glyphicon glyph='remove' />
</OverlayTrigger>
</a>
</td>
</tr>
)
}
99 changes: 40 additions & 59 deletions app/scripts/views/filelist.js
@@ -1,34 +1,49 @@
import React from 'react'
import $ from 'jquery'
import React, { Component } from 'react'
import i18n from '../utils/i18n.js'
import {Table, Tooltip, OverlayTrigger} from 'react-bootstrap'
import {Table} from 'react-bootstrap'
import FileItem from './fileitem'
import debug from 'debug'

export default React.createClass({
displayName: 'FileList',
propTypes: {
const log = debug('views:filelist')
log.error = debug('views:filelist:error')

export default class FileList extends Component {
static propTypes = {
ipfs: React.PropTypes.object,
files: React.PropTypes.array,
namesHidden: React.PropTypes.bool
},
namesHidden: React.PropTypes.bool,
gateway: React.PropTypes.string
};

render () {
const files = this.props.files
let className = 'table-hover filelist'

unpin: function (e) {
e.preventDefault()
e.stopPropagation()
if (this.props.namesHidden) {
className += ' filelist-names-hidden'
}

var el = $(e.target)
var hash = el.attr('data-hash')
if (!hash) hash = el.parent().attr('data-hash')
const createFile = file => {
if (typeof file === 'string') {
file = { id: file }
}

this.props.ipfs.pin.remove(hash, {r: true}, function (err, res) {
if (err) return console.error(err)
})
},
const dagPath = `#/objects/${file.id}`
const gatewayPath = `${this.props.gateway}/ipfs/${file.id}`
const unpin = (e) => {
e.preventDefault()
this.props.ipfs.pin.remove(file.id, {r: true}, (err, res) => {
if (err) {
// TODO Handle error and display to the user
log.error(err)
}
})
}

render: function () {
var t = this
var files = this.props.files
var className = 'table-hover filelist'
if (this.props.namesHidden) className += ' filelist-names-hidden'
return (
<FileItem key={file.id} {...{gatewayPath, dagPath, file, unpin}} />
)
}

return (
<Table responsive className={className}>
Expand All @@ -41,43 +56,9 @@ export default React.createClass({
</tr>
</thead>
<tbody>
{files ? files.map(function (file) {
if (typeof file === 'string') file = { id: file }

var type = '?'
if (file.name) {
var lastDot = file.name.lastIndexOf('.')
if (lastDot !== -1) type = file.name.substr(lastDot + 1, 4).toUpperCase()
}

var gatewayPath = t.props.gateway + '/ipfs/' + file.id
var dagPath = '#/objects/' + file.id

var tooltip = (
<Tooltip id={file.id}>{i18n.t('Remove')}</Tooltip>
)

return (
<tr className='webui-file' data-type={file.type} key={file.id}>
<td><span className='type'>{type}</span></td>
<td className='filelist-name'><a target='_blank' href={gatewayPath}>{file.name}</a></td>
<td className='id-cell'><code>{file.id}</code></td>
<td className='action-cell'>
<a target='_blank' href={gatewayPath}>{i18n.t('RAW')}</a>
<span className='separator'>|</span>
<a href={dagPath}>{i18n.t('DAG')}</a>
<span className='separator'>|</span>
<a href='#' onClick={t.unpin} data-hash={file.id}>
<OverlayTrigger placement='right' overlay={tooltip}>
<i className='fa fa-remove'></i>
</OverlayTrigger>
</a>
</td>
</tr>
)
}) : void 0}
{files ? files.map(createFile) : void 0}
</tbody>
</Table>
)
}
})
}
2 changes: 1 addition & 1 deletion app/scripts/views/globe.js
Expand Up @@ -6,7 +6,7 @@ import _ from 'lodash'
// Displays webgl warning message if not present
require('../include/Detector.js')

const log = debug('globe')
const log = debug('pages:connections')

export default React.createClass({
displayName: 'Globe',
Expand Down
7 changes: 2 additions & 5 deletions app/scripts/views/page.js
@@ -1,9 +1,6 @@
import React from 'react'
import ReactDOM from 'react-dom'
import Nav from './nav'
import {Link} from 'react-router'
import $ from 'jquery'

import i18n from '../utils/i18n.js'
import {parse} from '../utils/path'

Expand Down Expand Up @@ -59,7 +56,7 @@ export default React.createClass({
},

showDAG: function () {
var path = $(ReactDOM.findDOMNode(this)).find('.dag-path').val()
var path = this.refs.dagPath.value
this.context.router.push(`/objects/${parse(path).urlify()}`)
},

Expand Down Expand Up @@ -105,7 +102,7 @@ export default React.createClass({
<div className='col-sm-10'>
<form className='navbar-form navbar-left collapse navbar-collapse col-xs-6'>
<div className='form-group'>
<input type='text' className='form-control dag-path' placeholder={i18n.t('Enter a hash or path')} />
<input type='text' className='form-control' ref='dagPath' placeholder={i18n.t('Enter a hash or path')} />
</div>
<button className='btn btn-third btn-xs' onClick={this.showDAG}>{i18n.t('GO')}</button>
</form>
Expand Down
1 change: 0 additions & 1 deletion package.json
Expand Up @@ -13,7 +13,6 @@
"i18next-xhr-backend": "^0.3.0",
"ipfs-api": "^2.10.0",
"ipfs-geoip": "^1.4.5",
"jquery": "^2.1.4",
"lodash": "^3.10.1",
"react": "^0.14.2",
"react-bootstrap": "^0.28.1",
Expand Down
2 changes: 2 additions & 0 deletions test/views/config.spec.js
Expand Up @@ -10,8 +10,10 @@ describe('ConfigView', () => {

expect(el).to.contain(
<textarea
ref='textareaConfig'
className='panel-inner'
spellCheck='false'
style={{height: 0}}
onChange={() => {}}
value={JSON.stringify(config, null, 2)}
/>
Expand Down