diff --git a/js/package.json b/js/package.json
index 54cce18d4ad..6d1eaac299e 100644
--- a/js/package.json
+++ b/js/package.json
@@ -82,8 +82,6 @@
"istanbul": "^1.0.0-alpha.2",
"jsdom": "9.2.1",
"json-loader": "^0.5.4",
- "less": "^2.7.1",
- "less-loader": "^2.2.3",
"mocha": "^3.0.0-1",
"mock-local-storage": "1.0.2",
"mock-socket": "^3.0.1",
@@ -119,6 +117,7 @@
"lodash": "^4.11.1",
"marked": "^0.3.6",
"material-ui": "^0.15.4",
+ "material-ui-chip-input": "^0.8.0",
"moment": "^2.14.1",
"react": "^15.2.1",
"react-addons-css-transition-group": "^15.2.1",
diff --git a/js/src/modals/EditMeta/editMeta.js b/js/src/modals/EditMeta/editMeta.js
index 5822c1a3c9d..103208945e8 100644
--- a/js/src/modals/EditMeta/editMeta.js
+++ b/js/src/modals/EditMeta/editMeta.js
@@ -17,6 +17,8 @@
import React, { Component, PropTypes } from 'react';
import ContentClear from 'material-ui/svg-icons/content/clear';
import ContentSave from 'material-ui/svg-icons/content/save';
+// import ChipInput from 'material-ui-chip-input';
+import ChipInput from 'material-ui-chip-input/src/ChipInput';
import { Button, Form, Input, Modal } from '../../ui';
import { validateName } from '../../util/validation';
@@ -55,6 +57,7 @@ export default class EditMeta extends Component {
error={ nameError }
onSubmit={ this.onNameChange } />
{ this.renderMetaFields() }
+ { this.renderTags() }
);
@@ -96,6 +99,23 @@ export default class EditMeta extends Component {
});
}
+ renderTags () {
+ const { meta } = this.state;
+ const { tags } = meta || [];
+ const onChange = (chips) => this.onMetaChange('tags', chips);
+
+ return (
+
+ );
+ }
+
onNameChange = (name) => {
this.setState(validateName(name));
}
diff --git a/js/src/ui/Actionbar/Search/index.js b/js/src/ui/Actionbar/Search/index.js
new file mode 100644
index 00000000000..f51d38a6fa9
--- /dev/null
+++ b/js/src/ui/Actionbar/Search/index.js
@@ -0,0 +1,17 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+export default from './search';
diff --git a/js/src/ui/Actionbar/Search/search.css b/js/src/ui/Actionbar/Search/search.css
new file mode 100644
index 00000000000..956a9e2e354
--- /dev/null
+++ b/js/src/ui/Actionbar/Search/search.css
@@ -0,0 +1,43 @@
+/* Copyright 2015, 2016 Ethcore (UK) Ltd.
+/* This file is part of Parity.
+/*
+/* Parity is free software: you can redistribute it and/or modify
+/* it under the terms of the GNU General Public License as published by
+/* the Free Software Foundation, either version 3 of the License, or
+/* (at your option) any later version.
+/*
+/* Parity is distributed in the hope that it will be useful,
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+/* GNU General Public License for more details.
+/*
+/* You should have received a copy of the GNU General Public License
+/* along with Parity. If not, see .
+*/
+.searchcontainer {
+ display: flex;
+ overflow: hidden;
+}
+
+.searchButton {
+ min-width: 50px !important;
+}
+
+.input {
+ width: 500px !important;
+}
+
+.inputContainer {
+ transition: width 450ms ease-in-out 0ms, height 0ms ease-in-out 0ms;
+ white-space: nowrap;
+ overflow: hidden;
+ width: 500px;
+ height: 100%;
+ position: relative;
+}
+
+.inputContainerShown {
+ transition: width 450ms ease-in-out 0ms, height 0ms ease-in-out 400ms;
+ width: 0;
+ height: 0;
+}
diff --git a/js/src/ui/Actionbar/Search/search.js b/js/src/ui/Actionbar/Search/search.js
new file mode 100644
index 00000000000..79fabebc878
--- /dev/null
+++ b/js/src/ui/Actionbar/Search/search.js
@@ -0,0 +1,176 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+import React, { Component, PropTypes } from 'react';
+// import ChipInput from 'material-ui-chip-input';
+import ChipInput from 'material-ui-chip-input/src/ChipInput';
+import ActionSearch from 'material-ui/svg-icons/action/search';
+import { uniq } from 'lodash';
+
+import { Button } from '../../';
+
+import styles from './search.css';
+
+export default class ActionbarSearch extends Component {
+ static propTypes = {
+ onChange: PropTypes.func.isRequired,
+ tokens: PropTypes.array
+ };
+
+ state = {
+ showSearch: false,
+ stateChanging: false,
+ inputValue: '',
+ timeoutIds: []
+ }
+
+ componentWillReceiveProps (nextProps) {
+ const { tokens } = nextProps;
+
+ if (tokens.length > 0 && this.props.tokens.length === 0) {
+ this.handleOpenSearch(true, true);
+ }
+ }
+
+ componentWillUnmount () {
+ const { timeoutIds } = this.state;
+
+ if (timeoutIds.length > 0) {
+ timeoutIds.map(id => window.clearTimeout(id));
+ }
+ }
+
+ render () {
+ const { showSearch } = this.state;
+ const { tokens } = this.props;
+
+ const inputContainerClasses = [ styles.inputContainer ];
+
+ if (!showSearch) {
+ inputContainerClasses.push(styles.inputContainerShown);
+ }
+
+ return (
+
+ );
+ }
+
+ handleTokenAdd = (value) => {
+ const { tokens } = this.props;
+
+ const newSearchValues = uniq([].concat(tokens, value));
+
+ this.setState({
+ inputValue: ''
+ });
+
+ this.handleSearchChange(newSearchValues);
+ }
+
+ handleTokenDelete = (value) => {
+ const { tokens } = this.props;
+
+ const newSearchValues = []
+ .concat(tokens)
+ .filter(v => v !== value);
+
+ this.setState({
+ inputValue: ''
+ });
+
+ this.handleSearchChange(newSearchValues);
+ this.refs.searchInput.focus();
+ }
+
+ handleInputChange = (value) => {
+ this.setState({ inputValue: value });
+ }
+
+ handleSearchChange = (searchValues) => {
+ const { onChange } = this.props;
+ const newSearchValues = searchValues.filter(v => v.length > 0);
+
+ onChange(newSearchValues);
+ }
+
+ handleSearchClick = () => {
+ const { showSearch } = this.state;
+
+ this.handleOpenSearch(!showSearch);
+ }
+
+ handleSearchBlur = () => {
+ const timeoutId = window.setTimeout(() => {
+ const { inputValue } = this.state;
+ const { tokens } = this.props;
+
+ if (tokens.length === 0 && inputValue.length === 0) {
+ this.handleOpenSearch(false);
+ }
+ }, 250);
+
+ this.setState({
+ timeoutIds: [].concat(this.state.timeoutIds, timeoutId)
+ });
+ }
+
+ handleOpenSearch = (showSearch, force) => {
+ if (this.state.stateChanging && !force) return false;
+
+ this.setState({
+ showSearch: showSearch,
+ stateChanging: true
+ });
+
+ if (showSearch) {
+ this.refs.searchInput.focus();
+ } else {
+ this.refs.searchInput.getInputNode().blur();
+ }
+
+ const timeoutId = window.setTimeout(() => {
+ this.setState({ stateChanging: false });
+ }, 450);
+
+ this.setState({
+ timeoutIds: [].concat(this.state.timeoutIds, timeoutId)
+ });
+ }
+}
diff --git a/js/src/ui/Actionbar/Sort/index.js b/js/src/ui/Actionbar/Sort/index.js
new file mode 100644
index 00000000000..82855931c74
--- /dev/null
+++ b/js/src/ui/Actionbar/Sort/index.js
@@ -0,0 +1,17 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+export default from './sort';
diff --git a/js/src/ui/Actionbar/Sort/sort.css b/js/src/ui/Actionbar/Sort/sort.css
new file mode 100644
index 00000000000..ff592ca2f3f
--- /dev/null
+++ b/js/src/ui/Actionbar/Sort/sort.css
@@ -0,0 +1,20 @@
+/* Copyright 2015, 2016 Ethcore (UK) Ltd.
+/* This file is part of Parity.
+/*
+/* Parity is free software: you can redistribute it and/or modify
+/* it under the terms of the GNU General Public License as published by
+/* the Free Software Foundation, either version 3 of the License, or
+/* (at your option) any later version.
+/*
+/* Parity is distributed in the hope that it will be useful,
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+/* GNU General Public License for more details.
+/*
+/* You should have received a copy of the GNU General Public License
+/* along with Parity. If not, see .
+*/
+
+.sortButton {
+ min-width: 50px !important;
+}
diff --git a/js/src/ui/Actionbar/Sort/sort.js b/js/src/ui/Actionbar/Sort/sort.js
new file mode 100644
index 00000000000..35c51e5a1dd
--- /dev/null
+++ b/js/src/ui/Actionbar/Sort/sort.js
@@ -0,0 +1,73 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+import React, { Component, PropTypes } from 'react';
+import IconMenu from 'material-ui/IconMenu';
+import MenuItem from 'material-ui/MenuItem';
+
+import SortIcon from 'material-ui/svg-icons/content/sort';
+
+import { Button } from '../../';
+
+import styles from './sort.css';
+
+export default class ActionbarSort extends Component {
+ static propTypes = {
+ onChange: PropTypes.func.isRequired,
+ order: PropTypes.string
+ };
+
+ state = {
+ menuOpen: false
+ }
+
+ render () {
+ return (
+ }
+ onClick={ this.handleMenuOpen }
+ />
+ }
+ open={ this.state.menuOpen }
+ onRequestChange={ this.handleMenuChange }
+ onItemTouchTap={ this.handleSortChange }
+ targetOrigin={ { horizontal: 'right', vertical: 'top' } }
+ anchorOrigin={ { horizontal: 'right', vertical: 'top' } }
+ >
+
+
+
+
+ );
+ }
+
+ handleSortChange = (event, child) => {
+ const order = child.props.value;
+ this.props.onChange(order);
+ }
+
+ handleMenuOpen = () => {
+ this.setState({ menuOpen: true });
+ }
+
+ handleMenuChange = (open) => {
+ this.setState({ menuOpen: open });
+ }
+}
diff --git a/js/src/ui/Container/container.css b/js/src/ui/Container/container.css
index 890f9d93427..14a0179ec8e 100644
--- a/js/src/ui/Container/container.css
+++ b/js/src/ui/Container/container.css
@@ -15,13 +15,15 @@
/* along with Parity. If not, see .
*/
.container {
- padding: 0em
+ padding: 0em;
}
.padded {
padding: 1.5em;
background: rgba(0, 0, 0, 0.8) !important;
border-radius: 0 !important;
+ position: relative;
+ overflow: auto;
}
.light .padded {
diff --git a/js/src/ui/Tags/index.js b/js/src/ui/Tags/index.js
new file mode 100644
index 00000000000..71cd4962429
--- /dev/null
+++ b/js/src/ui/Tags/index.js
@@ -0,0 +1,17 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+export default from './tags';
diff --git a/js/src/ui/Tags/tags.css b/js/src/ui/Tags/tags.css
new file mode 100644
index 00000000000..f17fd1064fa
--- /dev/null
+++ b/js/src/ui/Tags/tags.css
@@ -0,0 +1,36 @@
+/* Copyright 2015, 2016 Ethcore (UK) Ltd.
+/* This file is part of Parity.
+/*
+/* Parity is free software: you can redistribute it and/or modify
+/* it under the terms of the GNU General Public License as published by
+/* the Free Software Foundation, either version 3 of the License, or
+/* (at your option) any later version.
+/*
+/* Parity is distributed in the hope that it will be useful,
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+/* GNU General Public License for more details.
+/*
+/* You should have received a copy of the GNU General Public License
+/* along with Parity. If not, see .
+*/
+
+.tags {
+ display: flex;
+ flex-wrap: wrap;
+ position: absolute;
+ right: 0.25rem;
+ top: 0;
+}
+
+.tag {
+ font-size: 0.75rem;
+ background: rgba(255, 255, 255, 0.07);
+ border-radius: 16px;
+ margin: 0.75em 0.5em 0 0;
+ padding: 0.25em 1em;
+}
+
+.tagClickable:hover {
+ cursor: pointer;
+}
diff --git a/js/src/ui/Tags/tags.js b/js/src/ui/Tags/tags.js
new file mode 100644
index 00000000000..23501b24f10
--- /dev/null
+++ b/js/src/ui/Tags/tags.js
@@ -0,0 +1,56 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+import React, { Component, PropTypes } from 'react';
+
+import styles from './tags.css';
+
+export default class Tags extends Component {
+ static propTypes = {
+ tags: PropTypes.array,
+ handleAddSearchToken: PropTypes.func
+ }
+
+ render () {
+ return (