From dcee2819cd17fde7ae96993adf823ab5d03d92e9 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Mon, 25 Jan 2016 00:28:16 +0100 Subject: [PATCH 1/2] Start working on the files browser for 0.4 --- app/scripts/components/files-explorer.js | 65 ++++ app/scripts/pages/files.js | 420 ++++++++++++---------- app/styles/app.less | 2 + app/styles/base.less | 11 - app/styles/components/files-explorer.less | 40 +++ package.json | 5 +- 6 files changed, 337 insertions(+), 206 deletions(-) create mode 100644 app/scripts/components/files-explorer.js create mode 100644 app/styles/components/files-explorer.less diff --git a/app/scripts/components/files-explorer.js b/app/scripts/components/files-explorer.js new file mode 100644 index 000000000..55ff5aab3 --- /dev/null +++ b/app/scripts/components/files-explorer.js @@ -0,0 +1,65 @@ +import React, {PropTypes, Component} from 'react' +import {Table} from 'react-bootstrap' +import pretty from 'prettysize' + +import Icon from '../views/icon' + +function renderType (type) { + if (type === 'directory') return + return +} + +function Row ({file, onClick}) { + const click = event => { + onClick(file) + } + + return ( + + + {renderType(file.Type)} + {file.Name} + + + {file.Type === 'directory' ? '-' : pretty(file.Size)} + + + ) +} + +export default class FilesExplorer extends Component { + static propTypes = { + files: PropTypes.array, + onRowClick: PropTypes.func + }; + + static defaultProps = { + files: [], + onRowClick () {} + }; + + state = { + root: '/' + }; + + render () { + const files = this.props.files + .map((file, i) => ( + + )) + + return ( + + + + + + + + + {files} + +
NameSize
+ ) + } +} diff --git a/app/scripts/pages/files.js b/app/scripts/pages/files.js index a25ff2885..3a296fd47 100644 --- a/app/scripts/pages/files.js +++ b/app/scripts/pages/files.js @@ -1,234 +1,266 @@ import React from 'react' -import {Row, Col, Nav, NavItem, Panel} from 'react-bootstrap' -import {LinkContainer} from 'react-router-bootstrap' +import {Row, Col, Modal, Button, Input} from 'react-bootstrap' import debug from 'debug' +import {join} from 'path' +import map from 'map-async' +import _ from 'lodash' +import bl from 'bl' +import Markdown from 'react-remarkable' -import FileList from '../views/filelist' import i18n from '../utils/i18n.js' +import FilesExplorer from '../components/files-explorer' +import Icon from '../views/icon' +import RawData from '../views/object/raw-data' const log = debug('pages:files') +log.error = debug('pages:files:error') -export -default class Files extends React.Component { - state = { - pinned: [], - files: [], - dragging: false - }; +function isDirectory ({Type}) { + return Type === 'directory' +} + +const extensions = { + markdown: ['md', 'markdown'], + image: ['png', 'jpg', 'jpeg', 'gif'] +} + +function getExtension (name) { + name = name.toLowerCase() + + const i = name.lastIndexOf('.') + return name.substring(i + 1) +} + +function getRenderer (ext) { + return _.findKey(extensions, elem => { + return _.includes(elem, ext) + }) +} + +const renderers = { + markdown (name, ext, data) { + return + }, + image (name, ext, data) { + const blob = new Blob([data], {type: `image/${ext}`}) + const urlCreator = window.URL || window.webkitURL + const imageUrl = urlCreator.createObjectURL(blob) + // `data:image;${ext};base64,${data.toString('base64')}` + return ( + + ) + } +} + +function FileRenderer ({name, data}) { + if (!name || !data) return null + + const ext = getExtension(name) + const renderer = getRenderer(ext) + + if (renderers[renderer]) return renderers[renderer](name, ext, data) + return +} + +export default class Files extends React.Component { static displayName = 'Files'; + static propTypes = { - ipfs: React.PropTypes.object, - gateway: React.PropTypes.string, - location: React.PropTypes.object + ipfs: React.PropTypes.object }; - componentDidMount () { - this.getFiles() - } + state = { + files: [], + root: '/', + showModalFolder: false, + showModalFile: false, + file: {} + }; - componentWillUnmount () { - clearInterval(this.pollInterval) - } + onRowClick = file => { + if (isDirectory(file)) { + this.setRoot(join(this.state.root, file.Name)) + } else { + const filePath = join(this.state.root, file.Name) + this.props.ipfs.files.read(filePath, (err, stream) => { + if (err) return log.error(err) - getFiles () { - this.props.ipfs.pin.list((err, pinned) => { - if (err || !pinned) return this.error(err) - this.setState({ - pinned: Object.keys(pinned.Keys).sort() - }) - }) + stream.pipe(bl((err, data) => { + if (err) return log.error(err) - this.props.ipfs.pin.list('recursive', (err, pinned) => { - if (err || !pinned) return this.error(err) - this.setState({ - files: Object.keys(pinned.Keys).sort() + this.setState({ + showModalFile: true, + file: { + ...file, + Data: data + } + }) + })) }) - }) - } - - _onAddFile = event => { - event.preventDefault() - this.refs.fileSelect.click() + } }; - _onDragOver = event => { - event.stopPropagation() - event.preventDefault() - this.setState({ - dragging: true - }) + onParentClick = root => { + this.setRoot(root) }; - _onDragLeave = event => { - event.stopPropagation() - event.preventDefault() - this.setState({ - dragging: false + onFolderAdd = name => { + this.props.ipfs.files.mkdir(name, err => { + if (err) return log.error(err) + this.getFiles() }) }; - _onDrop = event => { - event.stopPropagation() - event.preventDefault() - this.setState({ - dragging: false - }) - this._onFileChange(event) - }; + onModalHide = () => { + this.setState({showModalFolder: false}) + const folderName = this.refs.modalInput.refs.input.value - _onFileChange = event => { - const files = event.target.files || event.dataTransfer.files - if (!files || !files[0]) return - var file = files[0] - log('adding file: ', file) + if (_.isEmpty(folderName)) return log.error('Can not create empty folder') + this.onFolderAdd(join(this.state.root, folderName)) + }; - const add = data => { - this.props.ipfs.add(data, (err, res) => { - if (err || !res) return this.error(err) - res = res[0] + setRoot (newRoot) { + if (newRoot === '.') newRoot = '/' + this.setState({root: newRoot}, () => this.getFiles()) + } - this.setState({ - confirm: res.Name || file.name - }) + getFiles () { + const {ipfs} = this.props + const {root} = this.state - setTimeout(() => this.setState({ - confirm: null - }), 6000) - }) - } + ipfs.files.ls(root, (err, result) => { + if (err || !result) return log.error(err) + const files = _.sortBy(result.Entries, 'Name') || [] - if (file.path) { - add(file.path) - } else { - const reader = new window.FileReader() - reader.onload = () => { - let data = reader.result - data = new Buffer(data.substr(data.indexOf(',') + 1), 'base64') - add(data) - } - // TODO: use array buffers instead of base64 strings - reader.readAsDataURL(file) - } + map( + files, + (file, done) => { + ipfs.files.stat(join(root, file.Name), (err, stats) => { + if (err) return done(err) + done(null, Object.assign({}, file, stats)) + }) + }, + (err, stats) => { + if (err) return log.error(err) + this.setState({ + files: stats + }) + }) + }) + } + componentDidMount () { this.getFiles() - }; - error (err) { - console.error(err) - // TODO + this.setState({fetchIntervall: setInterval(() => this.getFiles(), 5000)}) } - _renderTitle = () => { - switch (this.props.location.pathname) { - case '/files': - return

{i18n.t('All Local Files')}

- case '/files/pinned': - return

{i18n.t('Pinned Files')}

- default: - return '' - } - }; + componentWillUnmount () { + clearInterval(this.state.fetchIntervall) + } - _renderAdder = () => { - return ( -
-
-
-
-
-

- {i18n.t('Drag-and-drop your files here')} -

-

- {i18n.t('or')} -

-

- -

-
-
-

- {i18n.t('Drop your file here to add it to IPFS')} -

-
-
-

- {i18n.t('Added')} {this.state.confirm} -

-
- -
- ) - }; + render () { + const parts = {} + const partsList = _.compact(this.state.root.split('/')) + partsList.map((part, i) => { + if (i === partsList.length - 1) { + parts[part] = null + } else { + parts[part] = '/' + partsList.slice(0, i + 1).join('/') + } + }) - _renderPanel = () => { - switch (this.props.location.pathname) { - case '/files': - return ( - - - - ) - case '/files/pinned': - return ( - - - - ) - default: - return '' - } - }; + const breadcrumbs = _(parts) + .map((root, part) => { + if (!root) { + return [ + , + {part} + ] + } - render () { + return [ + , + + {part} + + ] + }) + .flatten() + .value() + + if (_.isEmpty(partsList)) { + breadcrumbs.unshift( + IPFS + ) + } else { + breadcrumbs.unshift( + + IPFS + + ) + } return ( - - - {this._renderAdder()} - -
- {this._renderTitle()} - {this._renderPanel()} -
- -
+
+ + + + + {breadcrumbs} + + + this.setState({showModalFolder: true})}> + Add Directory + + + + + + + + + + + this.setState({showModalFolder: false})}> + + Add Directory to {this.state.root} + + + + + + + + + this.setState({showModalFile: false})}> + + {this.state.file.Name} + + + + + +
) } } diff --git a/app/styles/app.less b/app/styles/app.less index 2d37a6ac3..9a4ddca36 100644 --- a/app/styles/app.less +++ b/app/styles/app.less @@ -4,3 +4,5 @@ @import "./base"; @import "./typography"; + +@import "./components/files-explorer"; \ No newline at end of file diff --git a/app/styles/base.less b/app/styles/base.less index 9a3218ada..b9d0d7395 100644 --- a/app/styles/base.less +++ b/app/styles/base.less @@ -231,17 +231,6 @@ ul#side li a { color: #78c1c1; } -/* table */ -thead { - border-bottom: 2px solid #eaecf0 !important; -} -.table-striped>tbody>tr:nth-of-type(odd) { - background-color: #fff !important; -} -.table>tbody>tr>td, .table>tbody>tr>th, .table>tfoot>tr>td, .table>tfoot>tr>th { - border-color: transparent !important; -} - /* * Global add-ons */ diff --git a/app/styles/components/files-explorer.less b/app/styles/components/files-explorer.less new file mode 100644 index 000000000..c85b66d6e --- /dev/null +++ b/app/styles/components/files-explorer.less @@ -0,0 +1,40 @@ +.breadcrumbs { + height: 40px; + font-size: 16px; + font-weight: 500; + + .icon { + padding: 0 10px; + font-size: 16px; + } + + a.crumb-link:hover { + cursor: pointer; + } +} + +.actions { + a:hover { + cursor: pointer; + } +} + +tbody { + tr.file-row { + &:hover { + cursor: pointer; + background-color: #F6FBFE; + } + + td { + font-size: 13px; + line-height: 32px; + margin: 9px 0; + } + + .icon { + padding-right: 10px; + font-size: 24px; + } + } +} diff --git a/package.json b/package.json index cdf37d598..72ac573d4 100644 --- a/package.json +++ b/package.json @@ -11,13 +11,16 @@ "i18next-localstorage-cache": "^0.0.4", "i18next-sprintf-postprocessor": "^0.0.6", "i18next-xhr-backend": "^0.3.0", - "ipfs-api": "^2.10.0", + "ipfs-api": "github:ipfs/js-ipfs-api#feat/files-api", "ipfs-geoip": "^1.4.5", "lodash": "^3.10.1", + "map-async": "^0.1.1", + "prettysize": "0.0.3", "react": "^0.14.2", "react-bootstrap": "^0.28.1", "react-dom": "^0.14.2", "react-localstorage": "^0.2.8", + "react-remarkable": "^1.1.1", "react-router": "^2.0.0-rc4", "three": "^0.73.0" }, From c5a7ab7c629ea756ec13aed3febfba9efc189d1b Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Mon, 25 Jan 2016 15:25:47 +0100 Subject: [PATCH 2/2] Start simplifying the layout --- app/scripts/components/navbar.js | 15 ++ app/scripts/pages/files.js | 1 - app/scripts/pages/objects.js | 2 +- app/scripts/views/nav-item.js | 11 +- app/scripts/views/nav.js | 82 ++++---- app/scripts/views/object/link-buttons.js | 2 - app/scripts/views/page.js | 106 +++------- app/scripts/views/peer.js | 38 ++-- app/styles/base.less | 247 ++--------------------- app/styles/typography.less | 16 -- app/styles/variables.less | 4 +- dist/locale/webui-en.json | 10 +- package.json | 1 + 13 files changed, 136 insertions(+), 399 deletions(-) create mode 100644 app/scripts/components/navbar.js diff --git a/app/scripts/components/navbar.js b/app/scripts/components/navbar.js new file mode 100644 index 000000000..7c6a748bd --- /dev/null +++ b/app/scripts/components/navbar.js @@ -0,0 +1,15 @@ +import React from 'react' +import {Link} from 'react-router' + +import i18n from '../utils/i18n.js' + +export default function NavBar () { + return ( +
+ + IPFS + {i18n.t('IPFS')} + +
+ ) +} diff --git a/app/scripts/pages/files.js b/app/scripts/pages/files.js index 3a296fd47..0cb63e1f2 100644 --- a/app/scripts/pages/files.js +++ b/app/scripts/pages/files.js @@ -7,7 +7,6 @@ import _ from 'lodash' import bl from 'bl' import Markdown from 'react-remarkable' -import i18n from '../utils/i18n.js' import FilesExplorer from '../components/files-explorer' import Icon from '../views/icon' import RawData from '../views/object/raw-data' diff --git a/app/scripts/pages/objects.js b/app/scripts/pages/objects.js index b55276da0..5d101147c 100644 --- a/app/scripts/pages/objects.js +++ b/app/scripts/pages/objects.js @@ -120,7 +120,7 @@ default class Objects extends React.Component { placeholder={i18n.t('Enter hash or path: /ipfs/QmBpath...')}/> - diff --git a/app/scripts/views/nav-item.js b/app/scripts/views/nav-item.js index e94a56298..4c0680634 100644 --- a/app/scripts/views/nav-item.js +++ b/app/scripts/views/nav-item.js @@ -1,11 +1,12 @@ import React, {Component} from 'react' -import {Link} from 'react-router' +import {LinkContainer} from 'react-router-bootstrap' +import {NavItem} from 'react-bootstrap' import i18n from '../utils/i18n' import Icon from './icon' export -default class NavItem extends Component { +default class NavigationItem extends Component { static displayName = 'NavItem'; static propTypes = { title: React.PropTypes.string.isRequired, @@ -14,9 +15,11 @@ default class NavItem extends Component { }; render () { return ( - + + {i18n.t(this.props.title)} - + + ) } } diff --git a/app/scripts/views/nav.js b/app/scripts/views/nav.js index c7ba6962a..bb0538a99 100644 --- a/app/scripts/views/nav.js +++ b/app/scripts/views/nav.js @@ -1,8 +1,31 @@ import React, {Component} from 'react' +import {Row, Nav} from 'react-bootstrap' + +import NavBar from '../components/navbar' import NavItem from './nav-item' -export -default class Nav extends Component { +const tabs = [{ + title: 'home', + icon: 'dot-circle-o' +}, { + title: 'connections', + icon: 'globe' +}, { + title: 'files', + icon: 'file' +}, { + title: 'DAG', + url: 'objects', + icon: 'list-alt' +}, { + title: 'config', + icon: 'cog' +}, { + title: 'logs', + icon: 'list' +}] + +export default class Navigation extends Component { static displayName = 'Nav'; static contextTypes: { @@ -10,46 +33,25 @@ default class Nav extends Component { }; render () { - const tabs = [{ - title: 'home', - icon: 'dot-circle-o' - }, { - title: 'connections', - icon: 'globe' - }, { - title: 'files', - icon: 'file' - }, { - title: 'DAG', - url: 'objects', - icon: 'list-alt' - }, { - title: 'config', - icon: 'cog' - }, { - title: 'logs', - icon: 'list' - }] + const items = tabs.map((tab, idx) => { + const url = tab.url ? tab.url : ('/' + tab.title) + const title = tab.title.substring(0, 1).toUpperCase() + tab.title.substring(1) + return ( + + ) + }) return ( -
-
    - { - tabs.map((tab, idx) => { - const url = tab.url ? tab.url : ('/' + tab.title) - const title = tab.title.substring(0, 1).toUpperCase() + tab.title.substring(1) - return ( -
  • - -
  • - ) - }) - } -
-
+ + + + ) } } diff --git a/app/scripts/views/object/link-buttons.js b/app/scripts/views/object/link-buttons.js index 14f66054c..02007e5e6 100644 --- a/app/scripts/views/object/link-buttons.js +++ b/app/scripts/views/object/link-buttons.js @@ -12,14 +12,12 @@ const LinkButtons = ({gateway, path}) => { - + let children = '' + if (this.props.children) { + children = React.cloneElement( + this.props.children, { + ipfs: ipfs, + host: host, + gateway: this.state.gateway + } ) } + return ( -
-
- -
{/* end navbar */} -
-
-
-
-
{/* end row */} -
{/* end navbar collapse */} -
- {update} - {this.props.children && React.cloneElement( - this.props.children, {ipfs: ipfs, host: host, gateway: this.state.gateway} - )} -
+ + +
+ +
-
-
+ + {children} + + + ) } } diff --git a/app/scripts/views/peer.js b/app/scripts/views/peer.js index 39518361b..54223be08 100644 --- a/app/scripts/views/peer.js +++ b/app/scripts/views/peer.js @@ -1,8 +1,7 @@ import React, {Component} from 'react' import i18n from '../utils/i18n.js' -export -default class Peer extends Component { +export default class Peer extends Component { static displayName = 'Peer'; static propTypes = { table: React.PropTypes.object, @@ -13,36 +12,35 @@ default class Peer extends Component { render () { return (
-
+

- {i18n.t('Peer ID:')} {this.props.peer.ID}  + {i18n.t('Peer ID')} {this.props.peer.ID} 


- {i18n.t('Location:')} {this.props.location.formatted || i18n.t('Unknown')} + {i18n.t('Location')} {this.props.location.formatted || i18n.t('Unknown')}

- {i18n.t('Agent Version:')} {this.props.peer.AgentVersion || ''} + {i18n.t('Agent Version')} {this.props.peer.AgentVersion || ''}

- {i18n.t('Protocol Version:')} {this.props.peer.ProtocolVersion || ''} + {i18n.t('Protocol Version')} {this.props.peer.ProtocolVersion || ''}


- {i18n.t('Public Key:')} -
{this.props.peer.PublicKey || ''}
+

{i18n.t('Public Key')}

+
{this.props.peer.PublicKey || ''}
+
+
+
+

{i18n.t('Network Addresses')}

+
+              {(this.props.peer.Addresses || []).map(address => {
+                if (!address) return
+                return address + '\n'
+              })}
+            
-
-

{i18n.t('Network Addresses')}

-
- {(this.props.peer.Addresses || []).map((address, i) => { - if (!address) return - return ( -

- {address}  -

- ) - })}
) diff --git a/app/styles/base.less b/app/styles/base.less index b9d0d7395..aa7bbc1f0 100644 --- a/app/styles/base.less +++ b/app/styles/base.less @@ -1,11 +1,3 @@ -body { - padding-top: 70px; - font-size: 14px; - font-weight: normal !important; - color: #929db1; - font-family: Myriad Pro, "Helvetica Neue", Helvetica, Arial, sans-serif; -} - /* header style */ .page-header { padding-bottom: 9px; @@ -33,32 +25,19 @@ body { /* * navbar */ -.navbar-inverse { - background: #33373f; -} -.navbar { - position: relative; +.branding { + background-color: #24244e; height: 50px; margin-bottom: 20px; - border: 1px solid transparent; -} -.navbar-header { - float: left; - width: 100% !important; } .navbar-brand { - float: left; - height: 50px; - padding: 12px 20px; + padding: 12px 40px; font-size: 18px; line-height: 32px; - text-align: left; - color: #85dede; + text-align: center; margin-left: 0 !important; } -.branding { - background: #2b2e36; -} + .navbar-nav>li>a { padding-top: 14px; padding-bottom: 14px; @@ -76,122 +55,10 @@ li a:hover img.icon { opacity: 1 !important; } -/* - * sidebar - */ -.bottom { - bottom: 0; - position: fixed !important; - background: none !important; - text-align: left; -} -.bottom a:hover { - background: none !important; -} -ul#side li.bottom span { - margin: 0 20px !important; -} -ul#side li span.icon { - margin: 0 5% 0 15%; -} -ul#side li a { - padding: 20px 0; -} -.navbar-inverse .navbar-toggle { - border-color: #5f697d; -} -.navbar-toggle { - position: relative; - float: right; - padding: 9px 10px; - margin-top: 15px; - margin-right: 15px; - margin-bottom: 8px; - background-color: transparent; - background-image: none; - border: none !important; - border-radius: 4px; -} -.navbar-toggle:hover { - background-color: #5f697d !important; -} - /* * buttons */ -/* success */ -.btn-success { - background-color: #81c784; - border-color: #81c784; - border-radius: 3px; - padding: 13px 20px; -} -.btn-success:hover, .btn-success:active, .btn-success:focus { - background-color: #75b678; - border-color: #75b678; -} - -/* primary */ -.btn-primary { - background-color: #85dede; - border-color: #85dede; - border-radius: 3px; - padding: 13px 20px; -} -.btn-primary:hover, .btn-primary:active, .btn-primary:focus { - background-color: #77cccc; - border-color: #77cccc; -} - -/* info */ -.btn-info { - background-color: #cfd8dc; - border-color: #cfd8dc; - border-radius: 3px; - padding: 13px 20px; -} -.btn-info:hover, .btn-info:active, .btn-info:focus { - background-color: #c6ced2; - border-color: #c6ced2; -} - -/* default */ -.btn-default { - border-radius: 3px; - padding: 13px 20px; - color: #B4B4B4; - border-width: 2px !important; - border-color: #dedede; -} -.btn-default:hover, .btn-default:active, .btn-default:focus { - color: #999; - border-color: #B4B4B4; -} - -/* warning */ -.btn-warning { - background-color: #dad785; - border-color: #dad785; - border-radius: 3px; - padding: 13px 20px; -} -.btn-warning:hover, .btn-warning:active, .btn-warning:focus { - background-color: #c1be70; - border-color: #c1be70; -} - -/* danger */ -.btn-danger { - background-color: #e37272; - border-color: #e37272; - border-radius: 3px; - padding: 13px 20px; -} -.btn-danger:hover, .btn-danger:active, .btn-danger:focus { - background-color: #cd6767; - border-color: #cd6767; -} /* Third */ .btn-third { @@ -221,82 +88,34 @@ ul#side li a { color: #fff; } -/* link */ -.btn-link { - color: #85dede; - border-radius: 3px; - padding: 13px 20px; -} -.btn-link:hover, .btn-link:active, .btn-link:focus { - color: #78c1c1; -} - -/* - * Global add-ons - */ -.sub-header { - padding-bottom: 10px; - border-bottom: 1px solid #eee; -} - -/* - * Top navigation - * Hide default border to remove 1px line. - */ -.navbar-fixed-top { - border: 0; -} - /* * Sidebar */ @media (min-width:768px) { .sidebar { position: fixed; - top: 50px; + top: 0; bottom: 0; left: 0; z-index: 1000; display: block; - padding: 0 20px; + padding: 0 25px 20px 25px; overflow-x: hidden; - overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ - background-color: #eaecf0; - border-right: 1px solid #eaecf0; + // Scrollable contents if viewport is shorter than content. + overflow-y: auto; + background-color: #24244e; height: 100%; - } -} -/* Sidebar navigation */ -.nav-sidebar { - margin-right: -21px; /* 20px padding + 1px border */ - margin-bottom: 20px; - margin-left: -20px; -} -.nav-sidebar > li > a { - padding: 15px 20px; - font-size: 16px; - color: #8f939c; - font-weight: 400; -} -.nav-sidebar > li > a:hover { - background: #d9dee6; -} -.nav-sidebar > li > a.active, .nav-sidebar > li > a.active:hover, .nav-sidebar > li > a.active:focus { - color: #fff; - background-color: #85dede; -} -.icon-log { - width: 22px; - height: 22px; - display: inline-block; - background: url(../img/log.png) no-repeat; -} -li a span.icon-log { - background-position: top; -} -li.active a span.icon-log { - background-position: bottom; + .nav { + a { + color: #c3c3f3; + } + } + + .nav-stacked > li + li { + margin-top: 9px; + } + } } /* @@ -405,26 +224,6 @@ p { text-decoration: none; } -.btn:focus { - outline: none !important; -} - -.navbar-left { - - > .form-group { - > input { - width: 350px; - background-color: #555; - color: #ddd; - border: #aaa; - } - } - button { - padding: 7px 16px; - margin-left: 4px; - } -} - .webui-address { font-size: 12px; word-wrap: break-word; @@ -600,11 +399,9 @@ p { position: absolute; right: 0; top: 0; - > a { - color: #fff; - } + > .btn { - margin-left: 5px; + margin-left: 10px; } } .data { diff --git a/app/styles/typography.less b/app/styles/typography.less index fc123f2eb..cf08bb65f 100644 --- a/app/styles/typography.less +++ b/app/styles/typography.less @@ -32,19 +32,3 @@ h5 { h6 { font-size: 12px; } - -a { - color: #85dede; - - &:hover, - &:active, - &:visited, - &:focus { - color: #78c1c1; - } -} - -strong { - color: #7a8394; - font-weight: 600; -} diff --git a/app/styles/variables.less b/app/styles/variables.less index b057ef5bf..049c8748d 100644 --- a/app/styles/variables.less +++ b/app/styles/variables.less @@ -14,7 +14,7 @@ @gray-light: lighten(@gray-base, 46.7%); // #777 @gray-lighter: lighten(@gray-base, 93.5%); // #eee -@brand-primary: darken(#428bca, 6.5%); // #337ab7 +@brand-primary: #55a8fd;//darken(#428bca, 6.5%); // #337ab7 @brand-success: #5cb85c; @brand-info: #5bc0de; @brand-warning: #f0ad4e; @@ -419,7 +419,7 @@ //## //=== Shared nav styles -@nav-link-padding: 10px 15px; +@nav-link-padding: 5px 15px; @nav-link-hover-bg: @gray-lighter; @nav-disabled-link-color: @gray-light; diff --git a/dist/locale/webui-en.json b/dist/locale/webui-en.json index d5a3c4b03..3a36ae7eb 100644 --- a/dist/locale/webui-en.json +++ b/dist/locale/webui-en.json @@ -36,12 +36,12 @@ "Github": "Github", "Report Bugs": "Report Bugs", "Report a bug": "Report a bug", - "Peer ID:": "Peer ID:", - "Location:": "Location:", + "Peer ID": "Peer ID:", + "Location": "Location:", "Unknown": "Unknown", - "Agent Version:": "Agent Version:", - "Protocol Version:": "Protocol Version:", - "Public Key:": "Public Key:", + "Agent Version": "Agent Version:", + "Protocol Version": "Protocol Version:", + "Public Key": "Public Key:", "Network Addresses": "Network Addresses", "Bitswap": "Bitswap", "Wantlist": "Wantlist", diff --git a/package.json b/package.json index 72ac573d4..f965d322d 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "eslint-config-standard-react": "^1.2.1", "eslint-plugin-react": "^3.15.0", "eslint-plugin-standard": "^1.3.1", + "estraverse": "^4.1.1", "file-loader": "^0.8.5", "hjs-webpack": "^7.0.0", "https-browserify": "0.0.1",