diff --git a/index.html b/index.html index 8b61e4b0..b61794b4 100644 --- a/index.html +++ b/index.html @@ -9,7 +9,7 @@ -
+
diff --git a/js/actions/piece_list_actions.js b/js/actions/piece_list_actions.js index 4ec237ca..3bcb6917 100644 --- a/js/actions/piece_list_actions.js +++ b/js/actions/piece_list_actions.js @@ -6,7 +6,8 @@ import PieceListFetcher from '../fetchers/piece_list_fetcher'; class PieceListActions { constructor() { this.generateActions( - 'updatePieceList' + 'updatePieceList', + 'showEditionList' ); } diff --git a/js/components/ascribe_accordion_list/accordion_list_item_table.js b/js/components/ascribe_accordion_list/accordion_list_item_table.js index 9ddb3308..2cbb54d7 100644 --- a/js/components/ascribe_accordion_list/accordion_list_item_table.js +++ b/js/components/ascribe_accordion_list/accordion_list_item_table.js @@ -6,30 +6,17 @@ import TableItem from '../ascribe_table/table_item'; import TableColumnContentModel from '../../models/table_column_content_model'; let AccordionListItemTable = React.createClass({ - getInitialState() { - return { - 'show': false - }; - }, - propTypes: { className: React.PropTypes.string, parentId: React.PropTypes.number, - fetchData: React.PropTypes.func, itemList: React.PropTypes.array, columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)), - numOfTableItems: React.PropTypes.number - }, - - toggleTable() { - this.props.fetchData(); - this.setState({ - 'show': !this.state.show - }); + numOfTableItems: React.PropTypes.number, + show: React.PropTypes.bool }, render() { - if(this.props.itemList && this.state.show) { + if(this.props.show && this.props.itemList) { return (
- + {this.props.children} ); } else { return (
- + {this.props.children}
); } } }); -let AccordionListItemTableToggle = React.createClass({ - propTypes: { - className: React.PropTypes.string, - onClick: React.PropTypes.func, - show: React.PropTypes.bool, - numOfTableItems: React.PropTypes.number - }, - - render() { - return ( - - {this.props.show ? 'Hide all ' + this.props.numOfTableItems + ' Editions' : 'Show all ' + this.props.numOfTableItems + ' Editions'} - - ); - } -}); - export default AccordionListItemTable; \ No newline at end of file diff --git a/js/components/ascribe_accordion_list/accordion_list_item_table_editions.js b/js/components/ascribe_accordion_list/accordion_list_item_table_editions.js index 2b3bd5c0..e5789528 100644 --- a/js/components/ascribe_accordion_list/accordion_list_item_table_editions.js +++ b/js/components/ascribe_accordion_list/accordion_list_item_table_editions.js @@ -2,8 +2,11 @@ import React from 'react'; import EditionListStore from '../../stores/edition_list_store'; import EditionListActions from '../../actions/edition_list_actions'; +import PieceListStore from '../../stores/piece_list_store'; +import PieceListActions from '../../actions/piece_list_actions'; import AccordionListItemTable from './accordion_list_item_table'; +import AccordionListItemTableToggle from './accordion_list_item_table_toggle'; import TableColumnContentModel from '../../models/table_column_content_model'; @@ -17,7 +20,8 @@ let AccordionListItemTableEditions = React.createClass({ propTypes: { className: React.PropTypes.string, parentId: React.PropTypes.number, - numOfEditions: React.PropTypes.number + numOfEditions: React.PropTypes.number, + show: React.PropTypes.bool }, getInitialState() { @@ -36,14 +40,15 @@ let AccordionListItemTableEditions = React.createClass({ EditionListStore.unlisten(this.onChange); }, - getEditionList() { - EditionListActions.fetchEditionList(this.props.parentId); - }, - selectItem(pieceId, editionId) { EditionListActions.selectEdition({pieceId, editionId}); }, + toggleTable() { + PieceListActions.showEditionList(this.props.parentId); + EditionListActions.fetchEditionList(this.props.parentId); + }, + render() { let columnList = [ new TableColumnContentModel((item) => { return { 'editionId': item.id, 'pieceId': this.props.parentId, 'selectItem': this.selectItem, 'selected': item.selected }}, '', '', TableItemCheckbox, 1, false), @@ -53,13 +58,22 @@ let AccordionListItemTableEditions = React.createClass({ ]; return ( - +
+ + + + +
); } }); diff --git a/js/components/ascribe_accordion_list/accordion_list_item_table_toggle.js b/js/components/ascribe_accordion_list/accordion_list_item_table_toggle.js new file mode 100644 index 00000000..a3431b04 --- /dev/null +++ b/js/components/ascribe_accordion_list/accordion_list_item_table_toggle.js @@ -0,0 +1,22 @@ +import React from 'react'; + +let AccordionListItemTableToggle = React.createClass({ + propTypes: { + className: React.PropTypes.string, + onClick: React.PropTypes.func, + show: React.PropTypes.bool, + numOfTableItems: React.PropTypes.number + }, + + render() { + return ( + + {this.props.show ? 'Hide all ' + this.props.numOfTableItems + ' Editions' : 'Show all ' + this.props.numOfTableItems + ' Editions'} + + ); + } +}); + +export default AccordionListItemTableToggle; \ No newline at end of file diff --git a/js/components/ascribe_piece_list_bulk_modal/piece_list_bulk_modal.js b/js/components/ascribe_piece_list_bulk_modal/piece_list_bulk_modal.js new file mode 100644 index 00000000..43330538 --- /dev/null +++ b/js/components/ascribe_piece_list_bulk_modal/piece_list_bulk_modal.js @@ -0,0 +1,117 @@ +import React from 'react'; + +import EditionListStore from '../../stores/edition_list_store'; +import EditionListActions from '../../actions/edition_list_actions'; + +import AclButton from '../acl_button'; +import PieceListBulkModalSelectedEditionsWidget from './piece_list_bulk_modal_selected_editions_widget'; + +let PieceListBulkModal = React.createClass({ + propTypes: { + className: React.PropTypes.string + }, + + getInitialState() { + return EditionListStore.getState(); + }, + + onChange(state) { + this.setState(state); + }, + + componentDidMount() { + EditionListStore.listen(this.onChange) + }, + + componentDidUnmount() { + EditionListStore.unlisten(this.onChange) + }, + + filterForSelected(edition) { + return edition.selected; + }, + + fetchSelectedEditionList() { + let selectedEditionList = []; + + Object + .keys(this.state.editionList) + .forEach((key) => { + let filteredEditionsForPiece = this.state.editionList[key].filter(this.filterForSelected); + selectedEditionList = selectedEditionList.concat(filteredEditionsForPiece); + }); + + return selectedEditionList; + }, + + intersectAcls(a, b) { + return a.filter((val) => b.indexOf(val) > -1); + }, + + bulk(action) { + console.log(action); + }, + + getAvailableAcls() { + let availableAcls = []; + let selectedEditionList = this.fetchSelectedEditionList(); + + // If no edition has been selected, availableActions is empty + // If only one edition has been selected, their actions are available + // If more than one editions have been selected, their acl properties are intersected + if(selectedEditionList.length >= 1) { + availableAcls = selectedEditionList[0].acl; + } + if(selectedEditionList.length >= 2) { + for(let i = 1; i < selectedEditionList.length; i++) { + availableAcls = this.intersectAcls(availableAcls, selectedEditionList[i].acl); + } + } + + return availableAcls; + }, + + clearAllSelections() { + EditionListActions.clearAllEditionSelections(); + }, + + render() { + let availableAcls = this.getAvailableAcls(); + + if(availableAcls.length > 0) { + return ( +
+
+
+

+
+
+ +           + clear all +
+
+

+
+
+ + + + +
+
+
+
+
+ ); + } else { + return null; + } + + } +}); + +export default PieceListBulkModal; \ No newline at end of file diff --git a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_selected_editions_widget.js b/js/components/ascribe_piece_list_bulk_modal/piece_list_bulk_modal_selected_editions_widget.js similarity index 74% rename from js/components/ascribe_piece_list_toolbar/piece_list_toolbar_selected_editions_widget.js rename to js/components/ascribe_piece_list_bulk_modal/piece_list_bulk_modal_selected_editions_widget.js index 5c020d45..22b35a4a 100644 --- a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_selected_editions_widget.js +++ b/js/components/ascribe_piece_list_bulk_modal/piece_list_bulk_modal_selected_editions_widget.js @@ -1,6 +1,6 @@ import React from 'react'; -let PieceListToolbarSelectedEditionsWidget = React.createClass({ +let PieceListBulkModalSelectedEditionsWidget = React.createClass({ propTypes: { numberOfSelectedEditions: React.PropTypes.number.isRequired }, @@ -14,4 +14,4 @@ let PieceListToolbarSelectedEditionsWidget = React.createClass({ } }); -export default PieceListToolbarSelectedEditionsWidget; \ No newline at end of file +export default PieceListBulkModalSelectedEditionsWidget; \ No newline at end of file diff --git a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js index f7b04cc6..ce9150b1 100644 --- a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js +++ b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js @@ -1,18 +1,17 @@ import React from 'react'; -import EditionListStore from '../../stores/edition_list_store'; -import EditionListActions from '../../actions/edition_list_actions'; +import PieceListStore from '../../stores/piece_list_store'; +import PieceListActions from '../../actions/piece_list_actions'; -import AclButton from '../acl_button'; -import PieceListToolbarSelectedEditionsWidget from './piece_list_toolbar_selected_editions_widget'; +import Input from 'react-bootstrap/lib/Input'; +import Glyphicon from 'react-bootstrap/lib/Glyphicon'; + +import PieceListToolbarFilterWidgetFilter from './piece_list_toolbar_filter_widget'; let PieceListToolbar = React.createClass({ - propTypes: { - className: React.PropTypes.string - }, getInitialState() { - return EditionListStore.getState(); + return PieceListStore.getState(); }, onChange(state) { @@ -20,97 +19,38 @@ let PieceListToolbar = React.createClass({ }, componentDidMount() { - EditionListStore.listen(this.onChange) + PieceListStore.listen(this.onChange); }, componentDidUnmount() { - EditionListStore.unlisten(this.onChange) + PieceListStore.unlisten(this.onChange); }, - filterForSelected(edition) { - return edition.selected; - }, - - fetchSelectedEditionList() { - let selectedEditionList = []; - - Object - .keys(this.state.editionList) - .forEach((key) => { - let filteredEditionsForPiece = this.state.editionList[key].filter(this.filterForSelected); - selectedEditionList = selectedEditionList.concat(filteredEditionsForPiece); - }); - - return selectedEditionList; - }, - - intersectAcls(a, b) { - return a.filter((val) => b.indexOf(val) > -1); - }, - - bulk(action) { - console.log(action); - }, - - getAvailableAcls() { - let availableAcls = []; - let selectedEditionList = this.fetchSelectedEditionList(); - - // If no edition has been selected, availableActions is empty - // If only one edition has been selected, their actions are available - // If more than one editions have been selected, their acl properties are intersected - if(selectedEditionList.length >= 1) { - availableAcls = selectedEditionList[0].acl; - } - if(selectedEditionList.length >= 2) { - for(let i = 1; i < selectedEditionList.length; i++) { - availableAcls = this.intersectAcls(availableAcls, selectedEditionList[i].acl); - } - } - - return availableAcls; - }, - - clearAllSelections() { - EditionListActions.clearAllEditionSelections(); + searchFor() { + let searchTerm = this.refs.search.getInputDOMNode().value; + PieceListActions.fetchPieceList(this.state.page, this.pageSize, searchTerm, this.state.orderBy, this.state.orderAsc); }, render() { - let availableAcls = this.getAvailableAcls(); + let searchIcon = ; - if(availableAcls.length > 0) { - return ( -
-
-
-

-
-
- -           - clear all -
-
-

-
-
- - - - + return ( +
+
+
+
+
+
+ +    + {/**/}
- ); - } else { - return null; - } - +
+ ); } }); diff --git a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js new file mode 100644 index 00000000..7aaf9dd8 --- /dev/null +++ b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js @@ -0,0 +1,31 @@ +import React from 'react'; + +import Glyphicon from 'react-bootstrap/lib/Glyphicon'; +import DropdownButton from 'react-bootstrap/lib/DropdownButton'; +import MenuItem from 'react-bootstrap/lib/MenuItem'; + +let PieceListToolbarFilterWidgetFilter = React.createClass({ + render() { + let filterIcon = ; + + return ( + +
  • + Show Pieces that: +
  • + +
    + I can transfer +
    +
    + +
    + I can consign +
    +
    +
    + ); + } +}); + +export default PieceListToolbarFilterWidgetFilter; \ No newline at end of file diff --git a/js/components/piece_list.js b/js/components/piece_list.js index 9580ffb1..e6735a27 100644 --- a/js/components/piece_list.js +++ b/js/components/piece_list.js @@ -10,6 +10,7 @@ import AccordionListItemTableEditions from './ascribe_accordion_list/accordion_l import Pagination from './ascribe_pagination/pagination'; +import PieceListBulkModal from './ascribe_piece_list_bulk_modal/piece_list_bulk_modal'; import PieceListToolbar from './ascribe_piece_list_toolbar/piece_list_toolbar'; @@ -51,6 +52,7 @@ let PieceList = React.createClass({ return (
    + ); diff --git a/js/stores/piece_list_store.js b/js/stores/piece_list_store.js index 97e3f4a4..7ca96c87 100644 --- a/js/stores/piece_list_store.js +++ b/js/stores/piece_list_store.js @@ -24,6 +24,19 @@ class PieceListStore { this.bindActions(PieceListActions); } + onShowEditionList(pieceId) { + this.pieceList + .forEach((piece) => { + if(piece.id === pieceId) { + if(piece.show) { + piece.show = false; + } else { + piece.show = true; + } + } + }); + } + onUpdatePieceList({ page, pageSize, search, pieceList, orderBy, orderAsc, pieceListCount }) { this.page = page; this.pageSize = pageSize; diff --git a/sass/ascribe-accordion_list.scss b/sass/ascribe_accordion_list.scss similarity index 100% rename from sass/ascribe-accordion_list.scss rename to sass/ascribe_accordion_list.scss diff --git a/sass/ascribe-piece-list-toolbar.scss b/sass/ascribe_piece_list_bulk_modal.scss similarity index 85% rename from sass/ascribe-piece-list-toolbar.scss rename to sass/ascribe_piece_list_bulk_modal.scss index 6093aed9..4a6b98d7 100644 --- a/sass/ascribe-piece-list-toolbar.scss +++ b/sass/ascribe_piece_list_bulk_modal.scss @@ -1,4 +1,4 @@ -.ascribe-piece-list-toolbar { +.ascribe-piece-list-bulk-modal { position: fixed; top:0; width:1170px; @@ -14,7 +14,7 @@ z-index:9999; } -.piece-list-toolbar-clear-all { +.piece-list-bulk-modal-clear-all { text-decoration: underline; cursor:pointer; } \ No newline at end of file diff --git a/sass/ascribe_piece_list_toolbar.scss b/sass/ascribe_piece_list_toolbar.scss new file mode 100644 index 00000000..73c0bc94 --- /dev/null +++ b/sass/ascribe_piece_list_toolbar.scss @@ -0,0 +1,3 @@ +.ascribe-piece-list-toolbar { + margin-bottom: 1.5em; +} \ No newline at end of file diff --git a/sass/ascribe-variables.scss b/sass/ascribe_variables.scss similarity index 100% rename from sass/ascribe-variables.scss rename to sass/ascribe_variables.scss diff --git a/sass/main.scss b/sass/main.scss index 471a6124..5327032e 100644 --- a/sass/main.scss +++ b/sass/main.scss @@ -1,12 +1,14 @@ // If you import a new .scss file, make sure to restart gulp // otherwise it will not be included @import 'variables'; -@import 'ascribe-variables'; +@import 'ascribe_variables'; @import '../node_modules/bootstrap-sass/assets/stylesheets/bootstrap'; @import './ascribe-fonts/style'; @import './ascribe-fonts/ascribe-fonts'; -@import 'ascribe-accordion_list'; -@import 'ascribe-piece-list-toolbar'; +@import 'ascribe_accordion_list'; +@import 'ascribe_piece_list_bulk_modal'; +@import 'ascribe_piece_list_toolbar'; +@import 'offset_right'; .hidden { display: none; @@ -15,10 +17,10 @@ .navbar-default { border-left:0; border-right:0; - margin-bottom: 3em; + margin-bottom: 1.5em; } -.clear-margins-and-paddings { +.clear-paddings { padding-left:0; padding-right:0; } diff --git a/sass/offset_right.scss b/sass/offset_right.scss new file mode 100644 index 00000000..f844ce20 --- /dev/null +++ b/sass/offset_right.scss @@ -0,0 +1,164 @@ +/* Taken from: http://stackoverflow.com/a/27501063/1263876 */ + +.col-xs-offset-right-12 { + margin-right: 100%; +} +.col-xs-offset-right-11 { + margin-right: 91.66666667%; +} +.col-xs-offset-right-10 { + margin-right: 83.33333333%; +} +.col-xs-offset-right-9 { + margin-right: 75%; +} +.col-xs-offset-right-8 { + margin-right: 66.66666667%; +} +.col-xs-offset-right-7 { + margin-right: 58.33333333%; +} +.col-xs-offset-right-6 { + margin-right: 50%; +} +.col-xs-offset-right-5 { + margin-right: 41.66666667%; +} +.col-xs-offset-right-4 { + margin-right: 33.33333333%; +} +.col-xs-offset-right-3 { + margin-right: 25%; +} +.col-xs-offset-right-2 { + margin-right: 16.66666667%; +} +.col-xs-offset-right-1 { + margin-right: 8.33333333%; +} +.col-xs-offset-right-0 { + margin-right: 0; +} +@media (min-width: 768px) { + .col-sm-offset-right-12 { + margin-right: 100%; + } + .col-sm-offset-right-11 { + margin-right: 91.66666667%; + } + .col-sm-offset-right-10 { + margin-right: 83.33333333%; + } + .col-sm-offset-right-9 { + margin-right: 75%; + } + .col-sm-offset-right-8 { + margin-right: 66.66666667%; + } + .col-sm-offset-right-7 { + margin-right: 58.33333333%; + } + .col-sm-offset-right-6 { + margin-right: 50%; + } + .col-sm-offset-right-5 { + margin-right: 41.66666667%; + } + .col-sm-offset-right-4 { + margin-right: 33.33333333%; + } + .col-sm-offset-right-3 { + margin-right: 25%; + } + .col-sm-offset-right-2 { + margin-right: 16.66666667%; + } + .col-sm-offset-right-1 { + margin-right: 8.33333333%; + } + .col-sm-offset-right-0 { + margin-right: 0; + } +} +@media (min-width: 992px) { + .col-md-offset-right-12 { + margin-right: 100%; + } + .col-md-offset-right-11 { + margin-right: 91.66666667%; + } + .col-md-offset-right-10 { + margin-right: 83.33333333%; + } + .col-md-offset-right-9 { + margin-right: 75%; + } + .col-md-offset-right-8 { + margin-right: 66.66666667%; + } + .col-md-offset-right-7 { + margin-right: 58.33333333%; + } + .col-md-offset-right-6 { + margin-right: 50%; + } + .col-md-offset-right-5 { + margin-right: 41.66666667%; + } + .col-md-offset-right-4 { + margin-right: 33.33333333%; + } + .col-md-offset-right-3 { + margin-right: 25%; + } + .col-md-offset-right-2 { + margin-right: 16.66666667%; + } + .col-md-offset-right-1 { + margin-right: 8.33333333%; + } + .col-md-offset-right-0 { + margin-right: 0; + } +} +@media (min-width: 1200px) { + .col-lg-offset-right-12 { + margin-right: 100%; + } + .col-lg-offset-right-11 { + margin-right: 91.66666667%; + } + .col-lg-offset-right-10 { + margin-right: 83.33333333%; + } + .col-lg-offset-right-9 { + margin-right: 75%; + } + .col-lg-offset-right-8 { + margin-right: 66.66666667%; + } + .col-lg-offset-right-7 { + margin-right: 58.33333333%; + } + .col-lg-offset-right-6 { + margin-right: 50%; + } + .col-lg-offset-right-5 { + margin-right: 41.66666667%; + } + .col-lg-offset-right-4 { + margin-right: 33.33333333%; + } + .col-lg-offset-right-3 { + margin-right: 25%; + } + .col-lg-offset-right-2 { + margin-right: 16.66666667%; + } + .col-lg-offset-right-1 { + margin-right: 8.33333333%; + } + .col-lg-offset-right-0 { + margin-right: 0; + } +} \ No newline at end of file