mirror of
https://github.com/ascribe/onion.git
synced 2024-12-22 17:33:14 +01:00
merge table branch
This commit is contained in:
commit
b8ffac4275
2
.gitignore
vendored
2
.gitignore
vendored
@ -15,3 +15,5 @@ node_modules
|
|||||||
npm-debug.log
|
npm-debug.log
|
||||||
|
|
||||||
build/app.js
|
build/app.js
|
||||||
|
|
||||||
|
.DS_Store
|
@ -18,9 +18,7 @@ Install some nice extensions for Chrom(e|ium):
|
|||||||
git clone git@bitbucket.org:ascribe/onion.git
|
git clone git@bitbucket.org:ascribe/onion.git
|
||||||
cd onion
|
cd onion
|
||||||
npm install
|
npm install
|
||||||
npm run watch
|
gulp serve
|
||||||
|
|
||||||
python -mSimpleHTTPServer
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
24
css/main.css
24
css/main.css
@ -12,11 +12,13 @@
|
|||||||
.ascribe-table-header-row {
|
.ascribe-table-header-row {
|
||||||
border-bottom: 2px solid rgba(2, 182, 163, 0.5);
|
border-bottom: 2px solid rgba(2, 182, 163, 0.5);
|
||||||
border-top: 2px solid rgba(2, 182, 163, 0.5);
|
border-top: 2px solid rgba(2, 182, 163, 0.5);
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ascribe-table-header-column {
|
.ascribe-table-header-column {
|
||||||
display: table;
|
display: table;
|
||||||
height: 4em;
|
height:3em;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ascribe-table-header-column > span {
|
.ascribe-table-header-column > span {
|
||||||
@ -31,10 +33,10 @@
|
|||||||
.ascribe-table-header-column > span > .glyphicon {
|
.ascribe-table-header-column > span > .glyphicon {
|
||||||
font-size: .5em;
|
font-size: .5em;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
.ascribe-table-item:nth-child(even) {
|
.ascribe-table-item:nth-child(even) {
|
||||||
background-color: #F5F5F5;
|
background-color: #F5F5F5;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/*.ascribe-table-item:hover {
|
/*.ascribe-table-item:hover {
|
||||||
background-color: #EEEEEE;
|
background-color: #EEEEEE;
|
||||||
@ -44,7 +46,7 @@
|
|||||||
display: table;
|
display: table;
|
||||||
font-family: 'Source Sans Pro';
|
font-family: 'Source Sans Pro';
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
height: 4em;
|
height:3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ascribe-table-item-column > * {
|
.ascribe-table-item-column > * {
|
||||||
@ -52,6 +54,7 @@
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ascribe-table-item-selected {
|
||||||
/*.btn-ascribe, .btn-ascribe:hover, .btn-ascribe:active, .btn-ascribe:focus {*/
|
/*.btn-ascribe, .btn-ascribe:hover, .btn-ascribe:active, .btn-ascribe:focus {*/
|
||||||
/*background-color: rgba(2, 182, 163, 0.5);*/
|
/*background-color: rgba(2, 182, 163, 0.5);*/
|
||||||
/*border-color: rgba(2, 182, 163, 0.5);*/
|
/*border-color: rgba(2, 182, 163, 0.5);*/
|
||||||
@ -109,6 +112,19 @@
|
|||||||
background-color: rgba(2, 182, 163, 0.5);
|
background-color: rgba(2, 182, 163, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ascribe-table-item-selectable {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.piece-list-toolbar {
|
||||||
|
height:3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-margin {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.ascribe-detail-header {
|
.ascribe-detail-header {
|
||||||
margin-top: 2em;
|
margin-top: 2em;
|
||||||
}
|
}
|
||||||
|
67
gulpfile.js
Normal file
67
gulpfile.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
var gulp = require('gulp');
|
||||||
|
var gulpif = require('gulp-if');
|
||||||
|
var sourcemaps = require('gulp-sourcemaps');
|
||||||
|
var util = require('gulp-util');
|
||||||
|
var source = require('vinyl-source-stream');
|
||||||
|
var buffer = require('vinyl-buffer');
|
||||||
|
var watchify = require('watchify');
|
||||||
|
var browserify = require('browserify');
|
||||||
|
var browserSync = require('browser-sync');
|
||||||
|
var babelify = require('babelify');
|
||||||
|
var notify = require('gulp-notify');
|
||||||
|
var _ = require('lodash');
|
||||||
|
|
||||||
|
gulp.task('build', function() {
|
||||||
|
bundle(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('serve', ['browser-sync'], function() {
|
||||||
|
bundle(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('browser-sync', function() {
|
||||||
|
browserSync({
|
||||||
|
server: {
|
||||||
|
baseDir: "."
|
||||||
|
},
|
||||||
|
port: process.env.PORT || 3000
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function bundle(watch) {
|
||||||
|
var bro;
|
||||||
|
|
||||||
|
if (watch) {
|
||||||
|
bro = watchify(browserify('./js/app.js',
|
||||||
|
// Assigning debug to have sourcemaps
|
||||||
|
_.assign(watchify.args, {
|
||||||
|
debug: true
|
||||||
|
})));
|
||||||
|
bro.on('update', function() {
|
||||||
|
rebundle(bro, true);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
bro = browserify('./js/app.js', {
|
||||||
|
debug: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bro.transform(babelify.configure({
|
||||||
|
compact: false
|
||||||
|
}));
|
||||||
|
|
||||||
|
function rebundle(bundler, watch) {
|
||||||
|
return bundler.bundle()
|
||||||
|
.on('error', notify.onError('Error: <%= error.message %>'))
|
||||||
|
.pipe(source('app.js'))
|
||||||
|
.pipe(buffer())
|
||||||
|
.pipe(sourcemaps.init({
|
||||||
|
loadMaps: true
|
||||||
|
})) // loads map from browserify file
|
||||||
|
.pipe(sourcemaps.write()) // writes .map file
|
||||||
|
.pipe(gulp.dest('./build'))
|
||||||
|
.pipe(browserSync.stream());
|
||||||
|
}
|
||||||
|
|
||||||
|
return rebundle(bro);
|
||||||
|
}
|
@ -5,7 +5,8 @@ import EditionListFetcher from '../fetchers/edition_list_fetcher.js';
|
|||||||
class EditionListActions {
|
class EditionListActions {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.generateActions(
|
this.generateActions(
|
||||||
'updateEditionList'
|
'updateEditionList',
|
||||||
|
'selectEdition'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ class EditionListActions {
|
|||||||
.fetch(pieceId)
|
.fetch(pieceId)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.actions.updateEditionList({
|
this.actions.updateEditionList({
|
||||||
'editionList': res.editions,
|
'editionListOfPiece': res.editions,
|
||||||
pieceId
|
pieceId
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
32
js/components/acl_button.js
Normal file
32
js/components/acl_button.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import AppConstants from '../constants/application_constants';
|
||||||
|
|
||||||
|
let AclButton = React.createClass({
|
||||||
|
propTypes: {
|
||||||
|
action: React.PropTypes.oneOf(AppConstants.aclList).isRequired,
|
||||||
|
availableAcls: React.PropTypes.array.isRequired
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let shouldDisplay = this.props.availableAcls.indexOf(this.props.action) > -1;
|
||||||
|
let styles = {};
|
||||||
|
|
||||||
|
if(shouldDisplay) {
|
||||||
|
styles.display = 'inline-block';
|
||||||
|
} else {
|
||||||
|
styles.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
style={styles}
|
||||||
|
type="button"
|
||||||
|
className="btn btn-default btn-sm">
|
||||||
|
{this.props.action.toUpperCase()}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default AclButton;
|
@ -0,0 +1,82 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import EditionListStore from '../../stores/edition_list_store';
|
||||||
|
|
||||||
|
import AclButton from '../acl_button';
|
||||||
|
|
||||||
|
let PieceListToolbar = React.createClass({
|
||||||
|
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);
|
||||||
|
},
|
||||||
|
|
||||||
|
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;
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let availableAcls = this.getAvailableAcls();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="row no-margin">
|
||||||
|
<div className="col-xs-12 col-sm-12 col-md-12 col-lg-12 piece-list-toolbar">
|
||||||
|
<div className="pull-right">
|
||||||
|
<AclButton availableAcls={availableAcls} action="transfer" />
|
||||||
|
<AclButton availableAcls={availableAcls} action="consign" />
|
||||||
|
<AclButton availableAcls={availableAcls} action="share" />
|
||||||
|
<AclButton availableAcls={availableAcls} action="loan" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default PieceListToolbar;
|
@ -27,7 +27,13 @@ let Table = React.createClass({
|
|||||||
if(this.props.itemList && this.props.itemList.length > 0) {
|
if(this.props.itemList && this.props.itemList.length > 0) {
|
||||||
return (
|
return (
|
||||||
<div className="ascribe-table">
|
<div className="ascribe-table">
|
||||||
<TableHeader columnList={this.props.columnList} itemList={this.props.itemList} fetchList={this.props.fetchList} changeOrder={this.props.changeOrder} orderAsc={this.props.orderAsc} orderBy={this.props.orderBy} />
|
<TableHeader
|
||||||
|
columnList={this.props.columnList}
|
||||||
|
itemList={this.props.itemList}
|
||||||
|
fetchList={this.props.fetchList}
|
||||||
|
changeOrder={this.props.changeOrder}
|
||||||
|
orderAsc={this.props.orderAsc}
|
||||||
|
orderBy={this.props.orderBy} />
|
||||||
{this.renderChildren()}
|
{this.renderChildren()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -12,9 +12,9 @@ let TableHeader = React.createClass({
|
|||||||
propTypes: {
|
propTypes: {
|
||||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)),
|
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)),
|
||||||
itemList: React.PropTypes.array.isRequired,
|
itemList: React.PropTypes.array.isRequired,
|
||||||
changeOrder: React.PropTypes.func.isRequired,
|
changeOrder: React.PropTypes.func,
|
||||||
orderAsc: React.PropTypes.bool.isRequired,
|
orderAsc: React.PropTypes.bool,
|
||||||
orderBy: React.PropTypes.string.isRequired
|
orderBy: React.PropTypes.string
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -23,7 +23,7 @@ let TableHeader = React.createClass({
|
|||||||
<div className="row">
|
<div className="row">
|
||||||
{this.props.columnList.map((val, i) => {
|
{this.props.columnList.map((val, i) => {
|
||||||
|
|
||||||
let columnClasses = this.calcColumnClasses(this.props.columnList, i);
|
let columnClasses = this.calcColumnClasses(this.props.columnList, i, 12);
|
||||||
let columnName = this.props.columnList[i].columnName;
|
let columnName = this.props.columnList[i].columnName;
|
||||||
let canBeOrdered = this.props.columnList[i].canBeOrdered;
|
let canBeOrdered = this.props.columnList[i].canBeOrdered;
|
||||||
|
|
||||||
|
@ -8,10 +8,10 @@ let TableHeaderItem = React.createClass({
|
|||||||
columnClasses: React.PropTypes.string.isRequired,
|
columnClasses: React.PropTypes.string.isRequired,
|
||||||
displayName: React.PropTypes.string.isRequired,
|
displayName: React.PropTypes.string.isRequired,
|
||||||
columnName: React.PropTypes.string.isRequired,
|
columnName: React.PropTypes.string.isRequired,
|
||||||
canBeOrdered: React.PropTypes.bool.isRequired,
|
canBeOrdered: React.PropTypes.bool,
|
||||||
changeOrder: React.PropTypes.func.isRequired,
|
changeOrder: React.PropTypes.func,
|
||||||
orderAsc: React.PropTypes.bool.isRequired,
|
orderAsc: React.PropTypes.bool,
|
||||||
orderBy: React.PropTypes.string.isRequired
|
orderBy: React.PropTypes.string
|
||||||
},
|
},
|
||||||
|
|
||||||
changeOrder() {
|
changeOrder() {
|
||||||
@ -19,7 +19,7 @@ let TableHeaderItem = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if(this.props.canBeOrdered) {
|
if(this.props.canBeOrdered && this.props.changeOrder && this.props.orderAsc != null && this.props.orderBy) {
|
||||||
if(this.props.columnName === this.props.orderBy) {
|
if(this.props.columnName === this.props.orderBy) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -1,38 +1,30 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import TableColumnMixin from '../../mixins/table_column_mixin';
|
|
||||||
|
|
||||||
import TableColumnContentModel from '../../models/table_column_content_model';
|
import TableColumnContentModel from '../../models/table_column_content_model';
|
||||||
|
|
||||||
|
import TableItemWrapper from './table_item_wrapper';
|
||||||
|
|
||||||
|
|
||||||
let TableItem = React.createClass({
|
let TableItem = React.createClass({
|
||||||
mixins: [TableColumnMixin],
|
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)),
|
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)),
|
||||||
columnContent: React.PropTypes.object
|
columnContent: React.PropTypes.object,
|
||||||
|
onClick: React.PropTypes.func, // See: https://facebook.github.io/react/tips/expose-component-functions.html
|
||||||
|
classNames: React.PropTypes.string
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let calcColumnElementContent = () => {
|
|
||||||
return this.props.columnList.map((column, i) => {
|
|
||||||
|
|
||||||
let TypeElement = column.displayType;
|
|
||||||
let columnClass = this.calcColumnClasses(this.props.columnList, i);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={columnClass + ' ascribe-table-item-column'} key={i}>
|
|
||||||
<TypeElement content={this.props.columnContent[column.columnName]} width="50" />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="col-xs-12 col-sm-12 col-md-12 col-lg-12 ascribe-table-item">
|
<div
|
||||||
|
className={this.props.classNames + ' col-xs-12 col-sm-12 col-md-12 col-lg-12 ascribe-table-item'}
|
||||||
|
onClick={this.props.onClick}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
{calcColumnElementContent()}
|
<TableItemWrapper
|
||||||
|
columnList={this.props.columnList}
|
||||||
|
columnContent={this.props.columnContent}
|
||||||
|
columnWidth={12}>
|
||||||
|
</TableItemWrapper>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
18
js/components/ascribe_table/table_item_acl.js
Normal file
18
js/components/ascribe_table/table_item_acl.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
|
||||||
|
let TableItemAcl = React.createClass({
|
||||||
|
propTypes: {
|
||||||
|
content: React.PropTypes.array.isRequired
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{this.props.content.join('/')}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default TableItemAcl;
|
38
js/components/ascribe_table/table_item_selectable.js
Normal file
38
js/components/ascribe_table/table_item_selectable.js
Normal file
@ -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 (
|
||||||
|
<TableItem
|
||||||
|
classNames={tableItemClasses + ' ' + this.props.className}
|
||||||
|
columnList={this.props.columnList}
|
||||||
|
columnContent={this.props.columnContent}
|
||||||
|
onClick={this.selectItem}>
|
||||||
|
</TableItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default TableItemSelectable;
|
@ -5,12 +5,12 @@ import TableColumnContentModel from '../../models/table_column_content_model';
|
|||||||
import EditionListStore from '../../stores/edition_list_store';
|
import EditionListStore from '../../stores/edition_list_store';
|
||||||
import EditionListActions from '../../actions/edition_list_actions';
|
import EditionListActions from '../../actions/edition_list_actions';
|
||||||
|
|
||||||
// ToDo: Create Table-specific Utils to not lock it to projects utilities
|
|
||||||
import GeneralUtils from '../../utils/general_utils';
|
|
||||||
|
|
||||||
import Table from './table';
|
import Table from './table';
|
||||||
import TableItem from './table_item';
|
import TableItemWrapper from './table_item_wrapper';
|
||||||
import TableItemText from './table_item_text';
|
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';
|
import TableItemSubtableButton from './table_item_subtable_button';
|
||||||
|
|
||||||
|
|
||||||
@ -40,6 +40,7 @@ let TableItemSubtable = React.createClass({
|
|||||||
'open': false
|
'open': false
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
EditionListActions.fetchEditionList(this.props.columnContent.id);
|
EditionListActions.fetchEditionList(this.props.columnContent.id);
|
||||||
this.setState({
|
this.setState({
|
||||||
'open': true,
|
'open': true,
|
||||||
@ -48,43 +49,21 @@ let TableItemSubtable = React.createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
calcColumnClasses(list, i) {
|
selectItem(parentId, itemId) {
|
||||||
let bootstrapClasses = ['col-xs-', 'col-sm-', 'col-md-', 'col-lg-'];
|
EditionListActions.selectEdition({
|
||||||
|
'pieceId': parentId,
|
||||||
let listOfRowValues = list.map((column) => column.rowWidth );
|
'editionId': itemId
|
||||||
let numOfColumns = GeneralUtils.sumNumList(listOfRowValues);
|
});
|
||||||
|
|
||||||
if(numOfColumns > 10) {
|
|
||||||
throw new Error('Bootstrap has only 12 columns to assign. You defined ' + numOfColumns + '. Change this in the columnMap you\'re passing to the table.')
|
|
||||||
} else {
|
|
||||||
return bootstrapClasses.join( listOfRowValues[i] + ' ') + listOfRowValues[i];
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
let calcColumnElementContent = () => {
|
|
||||||
return this.props.columnList.map((column, i) => {
|
|
||||||
|
|
||||||
let TypeElement = column.displayType;
|
|
||||||
let columnClass = this.calcColumnClasses(this.props.columnList, i);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={columnClass + ' ascribe-table-item-column'} key={i}>
|
|
||||||
<TypeElement content={this.props.columnContent[column.columnName]} width="50" />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
let renderEditionListTable = () => {
|
let renderEditionListTable = () => {
|
||||||
|
|
||||||
let columnList = [
|
let columnList = [
|
||||||
new TableColumnContentModel('edition_number', 'Edition Number', TableItemText, 2, false),
|
new TableColumnContentModel('edition_number', 'Edition Number', TableItemText, 2, false),
|
||||||
new TableColumnContentModel('user_registered', 'User', TableItemText, 4, true),
|
new TableColumnContentModel('user_registered', 'User', TableItemText, 4, true),
|
||||||
new TableColumnContentModel('bitcoin_id', 'Bitcoin Address', 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) {
|
if(this.state.open && this.state.editionList[this.props.columnContent.id] && this.state.editionList[this.props.columnContent.id].length) {
|
||||||
@ -94,9 +73,12 @@ let TableItemSubtable = React.createClass({
|
|||||||
<Table itemList={this.state.editionList[this.props.columnContent.id]} columnList={columnList}>
|
<Table itemList={this.state.editionList[this.props.columnContent.id]} columnList={columnList}>
|
||||||
{this.state.editionList[this.props.columnContent.id].map((edition, i) => {
|
{this.state.editionList[this.props.columnContent.id].map((edition, i) => {
|
||||||
return (
|
return (
|
||||||
<TableItem
|
<TableItemSelectable
|
||||||
|
className="ascribe-table-item-selectable"
|
||||||
|
selectItem={this.selectItem}
|
||||||
|
parentId={this.props.columnContent.id}
|
||||||
key={i}>
|
key={i}>
|
||||||
</TableItem>
|
</TableItemSelectable>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</Table>
|
</Table>
|
||||||
@ -109,9 +91,13 @@ let TableItemSubtable = React.createClass({
|
|||||||
return (
|
return (
|
||||||
<div className="col-xs-12 col-sm-12 col-md-12 col-lg-12 ascribe-table-item">
|
<div className="col-xs-12 col-sm-12 col-md-12 col-lg-12 ascribe-table-item">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
{calcColumnElementContent()}
|
<TableItemWrapper
|
||||||
<div className="col-xs-2 col-sm-2 col-md-2 col-lg-2 ascribe-table-item-column">
|
columnList={this.props.columnList}
|
||||||
<TableItemSubtableButton content="Editions" onClick={this.loadEditionList}>
|
columnContent={this.props.columnContent}
|
||||||
|
columnWidth={12}>
|
||||||
|
</TableItemWrapper>
|
||||||
|
<div className="col-xs-1 col-sm-1 col-md-1 col-lg-1 ascribe-table-item-column">
|
||||||
|
<TableItemSubtableButton content="+" onClick={this.loadEditionList}>
|
||||||
</TableItemSubtableButton>
|
</TableItemSubtableButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,7 +10,7 @@ let TableItemSubtableButton = React.createClass({
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
<button type="button" className="btn btn-ascribe btn-primary btn-sm" onClick={this.props.onClick}>
|
<button type="button" className="btn btn-default btn-sm ascribe-table-expand-button" onClick={this.props.onClick}>
|
||||||
{this.props.content}
|
{this.props.content}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
|
34
js/components/ascribe_table/table_item_wrapper.js
Normal file
34
js/components/ascribe_table/table_item_wrapper.js
Normal file
@ -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 (
|
||||||
|
<div>
|
||||||
|
{this.props.columnList.map((column, i) => {
|
||||||
|
|
||||||
|
let TypeElement = column.displayType;
|
||||||
|
let columnClass = this.calcColumnClasses(this.props.columnList, i, this.props.columnWidth);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={columnClass + ' ascribe-table-item-column'} key={i}>
|
||||||
|
<TypeElement content={this.props.columnContent[column.columnName]} width="50" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default TableItemWrapper;
|
@ -15,6 +15,8 @@ import TableColumnContentModel from '../models/table_column_content_model';
|
|||||||
|
|
||||||
import Pagination from './ascribe_pagination/pagination';
|
import Pagination from './ascribe_pagination/pagination';
|
||||||
|
|
||||||
|
import PieceListToolbar from './ascribe_piece_list_toolbar/piece_list_toolbar';
|
||||||
|
|
||||||
|
|
||||||
let PieceList = React.createClass({
|
let PieceList = React.createClass({
|
||||||
|
|
||||||
@ -62,6 +64,7 @@ let PieceList = React.createClass({
|
|||||||
if(this.state.pieceList && this.state.pieceList.length > 0) {
|
if(this.state.pieceList && this.state.pieceList.length > 0) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<PieceListToolbar />
|
||||||
<Table
|
<Table
|
||||||
columnList={columnList}
|
columnList={columnList}
|
||||||
changeOrder={this.tableChangeOrder}
|
changeOrder={this.tableChangeOrder}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
let constants = {
|
let constants = {
|
||||||
'baseUrl': 'http://localhost:8000/api/',
|
'baseUrl': 'http://localhost:8000/api/',
|
||||||
//'baseUrl': 'http://staging.ascribe.io/api/',
|
'debugCredentialBase64': 'ZGltaUBtYWlsaW5hdG9yLmNvbTowMDAwMDAwMDAw', // dimi@mailinator:0000000000
|
||||||
'debugCredentialBase64': 'ZGltaUBtYWlsaW5hdG9yLmNvbTowMDAwMDAwMDAw' // dimi@mailinator:0000000000
|
'aclList': ['edit', 'consign', 'transfer', 'loan', 'share', 'download', 'view', 'delete', 'del_from_collection', 'add_to_collection']
|
||||||
|
|
||||||
};
|
};
|
||||||
export default constants;
|
|
||||||
|
|
||||||
|
export default constants;
|
@ -7,14 +7,14 @@ let TableColumnMixin = {
|
|||||||
* Generates the bootstrap grid column declarations automatically using
|
* Generates the bootstrap grid column declarations automatically using
|
||||||
* the columnMap.
|
* the columnMap.
|
||||||
*/
|
*/
|
||||||
calcColumnClasses(list, i) {
|
calcColumnClasses(list, i, numOfColumns) {
|
||||||
let bootstrapClasses = ['col-xs-', 'col-sm-', 'col-md-', 'col-lg-'];
|
let bootstrapClasses = ['col-xs-', 'col-sm-', 'col-md-', 'col-lg-'];
|
||||||
|
|
||||||
let listOfRowValues = list.map((column) => column.rowWidth );
|
let listOfRowValues = list.map((column) => column.rowWidth );
|
||||||
let numOfColumns = GeneralUtils.sumNumList(listOfRowValues);
|
let numOfUsedColumns = GeneralUtils.sumNumList(listOfRowValues);
|
||||||
|
|
||||||
if(numOfColumns > 12) {
|
if(numOfUsedColumns > numOfColumns) {
|
||||||
throw new Error('Bootstrap has only 12 columns to assign. You defined ' + numOfColumns + '. Change this in the columnMap you\'re passing to the table.')
|
throw new Error('This table has only ' + numOfColumns + ' columns to assign. You defined ' + numOfUsedColumns + '. Change this in the columnMap you\'re passing to the table.')
|
||||||
} else {
|
} else {
|
||||||
return bootstrapClasses.join( listOfRowValues[i] + ' ') + listOfRowValues[i];
|
return bootstrapClasses.join( listOfRowValues[i] + ' ') + listOfRowValues[i];
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
import alt from '../alt';
|
import alt from '../alt';
|
||||||
import EditionsListActions from '../actions/edition_list_actions';
|
import EditionsListActions from '../actions/edition_list_actions';
|
||||||
|
|
||||||
@ -7,8 +9,29 @@ class EditionListStore {
|
|||||||
this.bindActions(EditionsListActions);
|
this.bindActions(EditionsListActions);
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpdateEditionList({pieceId, editionList}) {
|
onUpdateEditionList({pieceId, editionListOfPiece}) {
|
||||||
this.editionList[pieceId] = editionList;
|
if(this.editionList[pieceId]) {
|
||||||
|
this.editionList[pieceId].forEach((edition, i) => {
|
||||||
|
// This uses the index of the new editionList for determining the edition.
|
||||||
|
// If the list of editions can be sorted in the future, this needs to be changed!
|
||||||
|
editionListOfPiece[i] = React.addons.update(edition, {$merge: editionListOfPiece[i]});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.editionList[pieceId] = editionListOfPiece;
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelectEdition({pieceId, editionId}) {
|
||||||
|
|
||||||
|
this.editionList[pieceId].forEach((edition) => {
|
||||||
|
if(edition.edition_number === editionId) {
|
||||||
|
if(edition.selected) {
|
||||||
|
edition.selected = false;
|
||||||
|
} else {
|
||||||
|
edition.selected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
22
package.json
22
package.json
@ -3,26 +3,24 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "Das neue web client for Ascribe",
|
"description": "Das neue web client for Ascribe",
|
||||||
"main": "js/app.js",
|
"main": "js/app.js",
|
||||||
"scripts": {
|
|
||||||
"watch": "watchify -o build/app.js -v -d js/app.js",
|
|
||||||
"build": "browserify . -t [envify --NODE_ENV production] | uglifyjs -cm > build/app.js",
|
|
||||||
"test": "jest"
|
|
||||||
},
|
|
||||||
"author": "Ascribe",
|
"author": "Ascribe",
|
||||||
"license": "Copyright",
|
"license": "Copyright",
|
||||||
"browserify": {
|
|
||||||
"transform": [
|
|
||||||
"babelify",
|
|
||||||
"envify"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-jest": "^4.0.0",
|
"babel-jest": "^4.0.0",
|
||||||
"babelify": "^6.0.2",
|
"babelify": "^6.1.2",
|
||||||
|
"browser-sync": "^2.7.5",
|
||||||
"browserify": "^9.0.8",
|
"browserify": "^9.0.8",
|
||||||
"envify": "^3.4.0",
|
"envify": "^3.4.0",
|
||||||
|
"gulp": "^3.8.11",
|
||||||
|
"gulp-if": "^1.2.5",
|
||||||
|
"gulp-notify": "^2.2.0",
|
||||||
|
"gulp-sourcemaps": "^1.5.2",
|
||||||
|
"gulp-util": "^3.0.4",
|
||||||
"jest-cli": "^0.4.0",
|
"jest-cli": "^0.4.0",
|
||||||
|
"lodash": "^3.9.3",
|
||||||
"reactify": "^1.1.0",
|
"reactify": "^1.1.0",
|
||||||
|
"vinyl-buffer": "^1.0.0",
|
||||||
|
"vinyl-source-stream": "^1.1.0",
|
||||||
"watchify": "^3.1.2"
|
"watchify": "^3.1.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
Loading…
Reference in New Issue
Block a user