diff --git a/js/components/ascribe_accordion_list/accordion_list.js b/js/components/ascribe_accordion_list/accordion_list.js new file mode 100644 index 00000000..9eb484b7 --- /dev/null +++ b/js/components/ascribe_accordion_list/accordion_list.js @@ -0,0 +1,26 @@ +import React from 'react'; +import ReactAddons from 'react/addons'; + + +let AccordionList = React.createClass({ + propTypes: { + className: React.PropTypes.string, + children: React.PropTypes.arrayOf(React.PropTypes.element).isRequired + }, + + render() { + if(this.props.itemList && this.props.itemList.length > 0) { + return ( +
+ {this.props.children} +
+ ); + } else { + return ( +

Loading

+ ); + } + } +}); + +export default AccordionList; \ No newline at end of file diff --git a/js/components/ascribe_accordion_list/accordion_list_item.js b/js/components/ascribe_accordion_list/accordion_list_item.js new file mode 100644 index 00000000..cf615820 --- /dev/null +++ b/js/components/ascribe_accordion_list/accordion_list_item.js @@ -0,0 +1,27 @@ +import React from 'react'; + +let AccordionListItem = React.createClass({ + propTypes: { + className: React.PropTypes.string, + content: React.PropTypes.object + }, + + render() { + console.log(this.props.content); + return ( +
+
+
+ +
+
+

{this.props.content.title}

+

by {this.props.content.artist_name}

+
+
+
+ ); + } +}); + +export default AccordionListItem; diff --git a/js/components/ascribe_accordion_list/table_header.js b/js/components/ascribe_accordion_list/table_header.js new file mode 100644 index 00000000..8176ad31 --- /dev/null +++ b/js/components/ascribe_accordion_list/table_header.js @@ -0,0 +1,50 @@ +import React from 'react'; + +import TableColumnMixin from '../../mixins/table_column_mixin'; +import GeneralUtils from '../../utils/general_utils'; +import TableHeaderItem from './table_header_item'; + +import TableColumnContentModel from '../../models/table_column_content_model'; + + +let TableHeader = React.createClass({ + mixins: [TableColumnMixin], + propTypes: { + columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)), + itemList: React.PropTypes.array.isRequired, + changeOrder: React.PropTypes.func, + orderAsc: React.PropTypes.bool, + orderBy: React.PropTypes.string + }, + + render() { + return ( +
+
+ {this.props.columnList.map((val, i) => { + + let columnClasses = this.calcColumnClasses(this.props.columnList, i, 12); + let columnName = this.props.columnList[i].columnName; + let canBeOrdered = this.props.columnList[i].canBeOrdered; + + return ( + + + ); + })} +
+
+ ); + + } +}); + +export default TableHeader; diff --git a/js/components/ascribe_accordion_list/table_header_item.js b/js/components/ascribe_accordion_list/table_header_item.js new file mode 100644 index 00000000..dce2261e --- /dev/null +++ b/js/components/ascribe_accordion_list/table_header_item.js @@ -0,0 +1,52 @@ +import React from 'react'; + +import TableHeaderItemCarret from './table_header_item_carret'; + +let TableHeaderItem = React.createClass({ + + propTypes: { + columnClasses: React.PropTypes.string.isRequired, + displayName: React.PropTypes.string.isRequired, + columnName: React.PropTypes.string.isRequired, + canBeOrdered: React.PropTypes.bool, + changeOrder: React.PropTypes.func, + orderAsc: React.PropTypes.bool, + orderBy: React.PropTypes.string + }, + + changeOrder() { + this.props.changeOrder(this.props.columnName, !this.props.orderAsc); + }, + + render() { + if(this.props.canBeOrdered && this.props.changeOrder && this.props.orderAsc != null && this.props.orderBy) { + if(this.props.columnName === this.props.orderBy) { + return ( +
+ {this.props.displayName} +
+ ); + } else { + return ( +
+ {this.props.displayName} +
+ ); + } + } else { + return ( +
+ + {this.props.displayName} + +
+ ); + } + } +}); + +export default TableHeaderItem; diff --git a/js/components/ascribe_accordion_list/table_header_item_carret.js b/js/components/ascribe_accordion_list/table_header_item_carret.js new file mode 100644 index 00000000..628ead11 --- /dev/null +++ b/js/components/ascribe_accordion_list/table_header_item_carret.js @@ -0,0 +1,24 @@ +import React from 'react'; + +let TableHeaderItemCarret = React.createClass({ + propTypes: { + orderAsc: React.PropTypes.bool.isRequired + }, + + render() { + let carretDirection = 'glyphicon-triangle-'; + + if(this.props.orderAsc) { + carretDirection += 'bottom'; + } else { + carretDirection += 'top'; + } + + return ( + + + ); + } +}); + +export default TableHeaderItemCarret; \ No newline at end of file diff --git a/js/components/ascribe_accordion_list/table_item_acl.js b/js/components/ascribe_accordion_list/table_item_acl.js new file mode 100644 index 00000000..87e14761 --- /dev/null +++ b/js/components/ascribe_accordion_list/table_item_acl.js @@ -0,0 +1,18 @@ +import React from 'react'; + + +let TableItemAcl = React.createClass({ + propTypes: { + content: React.PropTypes.array.isRequired + }, + + render() { + return ( + + {this.props.content.join('/')} + + ); + } +}); + +export default TableItemAcl; diff --git a/js/components/ascribe_accordion_list/table_item_img.js b/js/components/ascribe_accordion_list/table_item_img.js new file mode 100644 index 00000000..c082e85a --- /dev/null +++ b/js/components/ascribe_accordion_list/table_item_img.js @@ -0,0 +1,20 @@ +import React from 'react'; + +/** + * This could be enhanced further by specifying an optional description for example + */ +let TableItemImg = React.createClass({ + propTypes: { + content: React.PropTypes.string.isRequired, + }, + + render() { + return ( + + + + ); + } +}); + +export default TableItemImg; \ No newline at end of file diff --git a/js/components/ascribe_accordion_list/table_item_selectable.js b/js/components/ascribe_accordion_list/table_item_selectable.js new file mode 100644 index 00000000..d62f8d04 --- /dev/null +++ b/js/components/ascribe_accordion_list/table_item_selectable.js @@ -0,0 +1,38 @@ +import React from 'react'; +import classNames from 'classnames'; + +import TableColumnContentModel from '../../models/table_column_content_model'; + +import TableItem from './table_item'; + +// This component is implemented as recommended here: http://stackoverflow.com/a/25723635/1263876 +let TableItemSelectable = React.createClass({ + + propTypes: { + columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)), + columnContent: React.PropTypes.object, + parentId: React.PropTypes.number, + className: React.PropTypes.string + }, + + selectItem() { + this.props.selectItem(this.props.parentId, this.props.columnContent.edition_number); + }, + + render() { + let tableItemClasses = classNames({ + 'ascribe-table-item-selected': this.props.columnContent.selected + }); + + return ( + + + ); + } +}); + +export default TableItemSelectable; diff --git a/js/components/ascribe_accordion_list/table_item_subtable.js b/js/components/ascribe_accordion_list/table_item_subtable.js new file mode 100644 index 00000000..dcd3da0f --- /dev/null +++ b/js/components/ascribe_accordion_list/table_item_subtable.js @@ -0,0 +1,110 @@ +import React from 'react'; + +import TableColumnContentModel from '../../models/table_column_content_model'; + +import EditionListStore from '../../stores/edition_list_store'; +import EditionListActions from '../../actions/edition_list_actions'; + + +import Table from './table'; +import TableItemWrapper from './table_item_wrapper'; +import TableItemText from './table_item_text'; +import TableItemAcl from './table_item_acl'; +import TableItemSelectable from './table_item_selectable'; +import TableItemSubtableButton from './table_item_subtable_button'; + + +let TableItemSubtable = React.createClass({ + propTypes: { + columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)), + columnContent: React.PropTypes.object + }, + + getInitialState() { + return { + 'open': false + }; + }, + + onChange(state) { + this.setState(state); + }, + + componentDidMount() { + EditionListStore.listen(this.onChange); + }, + + loadEditionList() { + if(this.state.open) { + this.setState({ + 'open': false + }); + } else { + + EditionListActions.fetchEditionList(this.props.columnContent.id); + this.setState({ + 'open': true, + 'editionList': EditionListStore.getState() + }); + } + }, + + selectItem(parentId, itemId) { + EditionListActions.selectEdition({ + 'pieceId': parentId, + 'editionId': itemId + }); + }, + + render() { + + let renderEditionListTable = () => { + + let columnList = [ + new TableColumnContentModel('edition_number', 'Number', TableItemText, 2, false), + new TableColumnContentModel('user_registered', 'User', TableItemText, 4, true), + new TableColumnContentModel('acl', 'Actions', TableItemAcl, 4, true) + ]; + + if(this.state.open && this.state.editionList[this.props.columnContent.id] && this.state.editionList[this.props.columnContent.id].length) { + return ( +
+
+ + {this.state.editionList[this.props.columnContent.id].map((edition, i) => { + return ( + + + ); + })} +
+
+
+ ); + } + }; + + return ( +
+
+ + +
+ + +
+
+ {renderEditionListTable()} +
+ ); + } +}); + +export default TableItemSubtable; diff --git a/js/components/ascribe_accordion_list/table_item_subtable_button.js b/js/components/ascribe_accordion_list/table_item_subtable_button.js new file mode 100644 index 00000000..8c5431d8 --- /dev/null +++ b/js/components/ascribe_accordion_list/table_item_subtable_button.js @@ -0,0 +1,21 @@ +import React from 'react'; + +let TableItemSubtableButton = React.createClass({ + + propTypes: { + content: React.PropTypes.string.isRequired, + onClick: React.PropTypes.func.isRequired + }, + + render() { + return ( + + + + ); + } +}); + +export default TableItemSubtableButton; \ No newline at end of file diff --git a/js/components/ascribe_accordion_list/table_item_text.js b/js/components/ascribe_accordion_list/table_item_text.js new file mode 100644 index 00000000..0e90a2d5 --- /dev/null +++ b/js/components/ascribe_accordion_list/table_item_text.js @@ -0,0 +1,21 @@ +import React from 'react'; + + +let TableItemText = React.createClass({ + propTypes: { + content: React.PropTypes.oneOfType([ + React.PropTypes.string, + React.PropTypes.number + ]) + }, + + render() { + return ( + + {this.props.content} + + ); + } +}); + +export default TableItemText; diff --git a/js/components/ascribe_accordion_list/table_item_wrapper.js b/js/components/ascribe_accordion_list/table_item_wrapper.js new file mode 100644 index 00000000..2f9f4c7e --- /dev/null +++ b/js/components/ascribe_accordion_list/table_item_wrapper.js @@ -0,0 +1,34 @@ +import React from 'react'; + +import TableColumnContentModel from '../../models/table_column_content_model'; +import TableColumnMixin from '../../mixins/table_column_mixin'; + +let TableItemWrapper = React.createClass({ + mixins: [TableColumnMixin], + propTypes: { + columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)), + columnContent: React.PropTypes.object, + columnWidth: React.PropTypes.number.isRequired + }, + + render() { + return ( +
+ {this.props.columnList.map((column, i) => { + + let TypeElement = column.displayType; + let columnClass = this.calcColumnClasses(this.props.columnList, i, this.props.columnWidth); + + return ( +
+ +
+ ); + + })} +
+ ); + } +}); + +export default TableItemWrapper; \ No newline at end of file diff --git a/js/components/header.js b/js/components/header.js index f191c04c..20855b1b 100644 --- a/js/components/header.js +++ b/js/components/header.js @@ -24,7 +24,7 @@ let Header = React.createClass({ render() { return ( -