mirror of
https://github.com/ascribe/onion.git
synced 2025-02-14 21:10:27 +01:00
Merge branch 'master' into AD-412-mediaplayer
Conflicts: js/components/ascribe_media/resource_viewer.js js/components/edition_container.js js/mixins/inject_in_head_mixin.js package.json
This commit is contained in:
commit
e8627cd0a3
54
.eslintrc
Normal file
54
.eslintrc
Normal file
@ -0,0 +1,54 @@
|
||||
{
|
||||
"parser": "babel-eslint",
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true
|
||||
},
|
||||
"rules": {
|
||||
"quotes": [2, "single"],
|
||||
"eol-last": [0],
|
||||
"no-mixed-requires": [0],
|
||||
"no-underscore-dangle": [0],
|
||||
"global-strict": [2, "always"],
|
||||
"no-trailing-spaces": [2, { skipBlankLines: true }],
|
||||
"no-console": 0,
|
||||
"camelcase": [2, {"properties": "never"}],
|
||||
"react/display-name": 0,
|
||||
"react/jsx-boolean-value": 1,
|
||||
"react/jsx-no-undef": 1,
|
||||
"react/jsx-quotes": 1,
|
||||
"react/jsx-sort-prop-types": 0,
|
||||
"react/jsx-sort-props": 0,
|
||||
"react/jsx-uses-react": 1,
|
||||
"react/jsx-uses-vars": 1,
|
||||
"react/no-did-mount-set-state": 1,
|
||||
"react/no-did-update-set-state": 1,
|
||||
"react/no-multi-comp": 0,
|
||||
"react/no-unknown-property": 1,
|
||||
"react/prop-types": 1,
|
||||
"react/react-in-jsx-scope": 1,
|
||||
"react/self-closing-comp": 1,
|
||||
"react/sort-comp": 1,
|
||||
"react/wrap-multilines": 1
|
||||
},
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"ecmaFeatures": {
|
||||
"jsx": 1,
|
||||
"modules": 1,
|
||||
"arrowFunctions",
|
||||
"classes": 1,
|
||||
"blockBindings": 1,
|
||||
"defaultParams": 1,
|
||||
"destructuring": 1,
|
||||
"objectLiteralComputedProperties": 1,
|
||||
"objectLiteralDuplicateProperties": 0,
|
||||
"objectLiteralShorthandMethods": 1,
|
||||
"objectLiteralShorthandProperties": 1,
|
||||
"restParams": 1,
|
||||
"spread": 1,
|
||||
"superInFunctions": 1,
|
||||
"templateStrings": 1
|
||||
}
|
||||
}
|
22
gulpfile.js
22
gulpfile.js
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
var gulp = require('gulp');
|
||||
var gulpif = require('gulp-if');
|
||||
var sourcemaps = require('gulp-sourcemaps');
|
||||
@ -12,6 +14,7 @@ var notify = require('gulp-notify');
|
||||
var sass = require('gulp-sass');
|
||||
var concat = require('gulp-concat');
|
||||
var _ = require('lodash');
|
||||
var eslint = require('gulp-eslint');
|
||||
|
||||
var config = {
|
||||
bootstrapDir: './node_modules/bootstrap-sass'
|
||||
@ -21,7 +24,7 @@ gulp.task('build', function() {
|
||||
bundle(false);
|
||||
});
|
||||
|
||||
gulp.task('serve', ['browser-sync', 'sass', 'sass:watch', 'copy'], function() {
|
||||
gulp.task('serve', ['browser-sync', 'lint:watch', 'sass', 'sass:watch', 'copy'], function() {
|
||||
bundle(true);
|
||||
});
|
||||
|
||||
@ -64,6 +67,23 @@ gulp.task('copy', function () {
|
||||
.pipe(gulp.dest('./build/fonts'));
|
||||
});
|
||||
|
||||
gulp.task('lint', function () {
|
||||
return gulp.src(['js/**/*.js'])
|
||||
// eslint() attaches the lint output to the eslint property
|
||||
// of the file object so it can be used by other modules.
|
||||
.pipe(eslint())
|
||||
// eslint.format() outputs the lint results to the console.
|
||||
// Alternatively use eslint.formatEach() (see Docs).
|
||||
.pipe(eslint.format())
|
||||
// To have the process exit with an error code (1) on
|
||||
// lint error, return the stream and pipe to failOnError last.
|
||||
.pipe(eslint.failOnError());
|
||||
});
|
||||
|
||||
gulp.task('lint:watch', function () {
|
||||
gulp.watch('js/**/*.js', ['lint']);
|
||||
});
|
||||
|
||||
function bundle(watch) {
|
||||
var bro;
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
import EditionFetcher from '../fetchers/edition_fetcher';
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
|
||||
import EditionListFetcher from '../fetchers/edition_list_fetcher.js';
|
||||
@ -12,6 +14,11 @@ class EditionListActions {
|
||||
}
|
||||
|
||||
fetchEditionList(pieceId, orderBy, orderAsc) {
|
||||
if(!orderBy && typeof orderAsc == 'undefined') {
|
||||
orderBy = 'edition_number';
|
||||
orderAsc = true;
|
||||
}
|
||||
|
||||
EditionListFetcher
|
||||
.fetch(pieceId, orderBy, orderAsc)
|
||||
.then((res) => {
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
import PieceFetcher from '../fetchers/piece_fetcher';
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
|
||||
import PieceListFetcher from '../fetchers/piece_list_fetcher';
|
||||
@ -7,7 +9,8 @@ class PieceListActions {
|
||||
constructor() {
|
||||
this.generateActions(
|
||||
'updatePieceList',
|
||||
'showEditionList'
|
||||
'showEditionList',
|
||||
'closeAllEditionLists'
|
||||
);
|
||||
}
|
||||
|
||||
@ -27,6 +30,6 @@ class PieceListActions {
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
export default alt.createActions(PieceListActions);
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
import UserFetcher from '../fetchers/user_fetcher';
|
||||
|
||||
@ -12,12 +14,12 @@ class UserActions {
|
||||
fetchCurrentUser() {
|
||||
UserFetcher.fetchOne()
|
||||
.then((res) => {
|
||||
this.actions.updateCurrentUser(res['users'][0]);
|
||||
this.actions.updateCurrentUser(res.users[0]);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default alt.createActions(UserActions);
|
||||
|
23
js/app.js
23
js/app.js
@ -6,14 +6,31 @@ import promise from 'es6-promise';
|
||||
|
||||
promise.polyfill();
|
||||
|
||||
import AscribeApp from './components/ascribe_app';
|
||||
import AppConstants from './constants/application_constants';
|
||||
import ApiUrls from './constants/api_urls';
|
||||
import routes from './routes';
|
||||
import alt from './alt';
|
||||
import fetch from './utils/fetch';
|
||||
import AlertDismissable from './components/ascribe_forms/alert';
|
||||
|
||||
/*
|
||||
Taken from
|
||||
http://stackoverflow.com/questions/30613447/how-to-debug-reactjss-setstate?noredirect=1#comment49301874_30613447
|
||||
|
||||
<remove this in production>
|
||||
|
||||
*/
|
||||
|
||||
var warn = console.warn;
|
||||
console.warn = function(warning) {
|
||||
if (/(setState)/.test(warning)) {
|
||||
throw new Error(warning);
|
||||
}
|
||||
warn.apply(console, arguments);
|
||||
};
|
||||
|
||||
/*
|
||||
</remove this in production>
|
||||
|
||||
*/
|
||||
|
||||
fetch.defaults({
|
||||
urlMap: ApiUrls,
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import ConsignForm from './ascribe_forms/form_consign';
|
||||
@ -17,31 +19,33 @@ let AclButton = React.createClass({
|
||||
},
|
||||
|
||||
actionProperties(){
|
||||
if (this.props.action == 'consign'){
|
||||
if (this.props.action === 'consign'){
|
||||
return {
|
||||
title: "Consign artwork",
|
||||
tooltip: "Have someone else sell the artwork",
|
||||
title: 'Consign artwork',
|
||||
tooltip: 'Have someone else sell the artwork',
|
||||
form: <ConsignForm />
|
||||
};
|
||||
}
|
||||
}
|
||||
else if (this.props.action == 'transfer') {
|
||||
else if (this.props.action === 'transfer') {
|
||||
return {
|
||||
title: "Transfer artwork",
|
||||
tooltip: "Transfer the ownership of the artwork",
|
||||
title: 'Transfer artwork',
|
||||
tooltip: 'Transfer the ownership of the artwork',
|
||||
form: <TransferForm />
|
||||
};
|
||||
}
|
||||
}
|
||||
else if (this.props.action == 'loan'){
|
||||
else if (this.props.action === 'loan'){
|
||||
return {
|
||||
title: "Loan artwork",
|
||||
tooltip: "Loan your artwork for a limited period of time",
|
||||
form: <LoanForm />}
|
||||
title: 'Loan artwork',
|
||||
tooltip: 'Loan your artwork for a limited period of time',
|
||||
form: <LoanForm />
|
||||
};
|
||||
}
|
||||
else if (this.props.action == 'share'){
|
||||
else if (this.props.action === 'share'){
|
||||
return {
|
||||
title: "Share artwork",
|
||||
tooltip: "Share the artwork",
|
||||
form: <ShareForm />}
|
||||
title: 'Share artwork',
|
||||
tooltip: 'Share the artwork',
|
||||
form: <ShareForm />
|
||||
};
|
||||
}
|
||||
},
|
||||
render() {
|
||||
|
@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import ReactAddons from 'react/addons';
|
||||
|
||||
|
||||
let AccordionList = React.createClass({
|
||||
|
@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
|
||||
import AccordionListItemTable from './accordion_list_item_table';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
let Link = Router.Link;
|
||||
@ -10,7 +10,8 @@ let Link = Router.Link;
|
||||
let AccordionListItem = React.createClass({
|
||||
propTypes: {
|
||||
className: React.PropTypes.string,
|
||||
content: React.PropTypes.object
|
||||
content: React.PropTypes.object,
|
||||
children: React.PropTypes.object
|
||||
},
|
||||
|
||||
render() {
|
||||
@ -18,12 +19,13 @@ let AccordionListItem = React.createClass({
|
||||
<div className="row">
|
||||
<div className={this.props.className}>
|
||||
<div className="wrapper">
|
||||
<div className="thumbnail-wrapper">
|
||||
<div className="col-xs-4 col-sm-4 col-md-4 col-lg-4 thumbnail-wrapper">
|
||||
<img src={this.props.content.thumbnail} />
|
||||
</div>
|
||||
<div className="info-wrapper">
|
||||
<div className="col-xs-8 col-sm-8 col-md-8 col-lg-8">
|
||||
<h1>{this.props.content.title}</h1>
|
||||
<h3>{getLangText('by %s', this.props.content.artist_name)}</h3>
|
||||
<h3>{this.props.content.date_created.split('-')[0]}</h3>
|
||||
</div>
|
||||
<span style={{'clear': 'both'}}></span>
|
||||
</div>
|
||||
|
@ -1,18 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Table from '../ascribe_table/table';
|
||||
import TableItem from '../ascribe_table/table_item';
|
||||
|
||||
import TableColumnContentModel from '../../models/table_column_content_model';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
import { ColumnModel } from '../ascribe_table/models/table_models';
|
||||
|
||||
let AccordionListItemTable = React.createClass({
|
||||
propTypes: {
|
||||
className: React.PropTypes.string,
|
||||
parentId: React.PropTypes.number,
|
||||
itemList: React.PropTypes.array,
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)),
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(ColumnModel)),
|
||||
numOfTableItems: React.PropTypes.number,
|
||||
show: React.PropTypes.bool,
|
||||
changeOrder: React.PropTypes.func,
|
||||
@ -25,6 +25,7 @@ let AccordionListItemTable = React.createClass({
|
||||
return (
|
||||
<div className={this.props.className}>
|
||||
<Table
|
||||
className="ascribe-table"
|
||||
columnList={this.props.columnList}
|
||||
itemList={this.props.itemList}
|
||||
changeOrder={this.props.changeOrder}
|
||||
@ -34,8 +35,7 @@ let AccordionListItemTable = React.createClass({
|
||||
return (
|
||||
<TableItem
|
||||
className="ascribe-table-item-selectable"
|
||||
key={i}>
|
||||
</TableItem>
|
||||
key={i} />
|
||||
);
|
||||
})}
|
||||
</Table>
|
||||
|
@ -1,18 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
|
||||
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 AccordionListItemTableSelectAllEditionsToggle from './accordion_list_item_table_select_all_editions_toggle';
|
||||
|
||||
import TableColumnContentModel from '../../models/table_column_content_model';
|
||||
import { ColumnModel, TransitionModel } from '../ascribe_table/models/table_models';
|
||||
|
||||
import TableItemImg from '../ascribe_table/table_item_img';
|
||||
import TableItemText from '../ascribe_table/table_item_text';
|
||||
import TableItemCheckbox from '../ascribe_table/table_item_checkbox';
|
||||
import TableItemAclFiltered from '../ascribe_table/table_item_acl_filtered';
|
||||
@ -34,18 +34,18 @@ let AccordionListItemTableEditions = React.createClass({
|
||||
return EditionListStore.getState();
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
EditionListStore.listen(this.onChange);
|
||||
},
|
||||
|
||||
componentDidUnmount() {
|
||||
componentWillUnmount() {
|
||||
EditionListStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
},
|
||||
|
||||
selectItem(pieceId, editionId) {
|
||||
EditionListActions.selectEdition({pieceId, editionId});
|
||||
},
|
||||
@ -65,7 +65,7 @@ let AccordionListItemTableEditions = React.createClass({
|
||||
|
||||
toggleTable() {
|
||||
PieceListActions.showEditionList(this.props.parentId);
|
||||
EditionListActions.fetchEditionList(this.props.parentId, this.state.orderBy, this.state.orderAsc);
|
||||
EditionListActions.fetchEditionList(this.props.parentId);
|
||||
},
|
||||
|
||||
changeEditionListOrder(orderBy, orderAsc) {
|
||||
@ -75,6 +75,8 @@ let AccordionListItemTableEditions = React.createClass({
|
||||
render() {
|
||||
let selectedEditionsCount = 0;
|
||||
let allEditionsCount = 0;
|
||||
let orderBy;
|
||||
let orderAsc;
|
||||
|
||||
// here we need to check if all editions of a specific
|
||||
// piece are already defined. Otherwise .length will throw an error and we'll not
|
||||
@ -82,17 +84,21 @@ let AccordionListItemTableEditions = React.createClass({
|
||||
if(this.state.editionList[this.props.parentId]) {
|
||||
selectedEditionsCount = this.filterSelectedEditions().length;
|
||||
allEditionsCount = this.state.editionList[this.props.parentId].length;
|
||||
orderBy = this.state.editionList[this.props.parentId].orderBy;
|
||||
orderAsc = this.state.editionList[this.props.parentId].orderAsc;
|
||||
}
|
||||
|
||||
let transition = new TransitionModel('edition', 'editionId', 'bitcoin_id', PieceListActions.closeAllEditionLists);
|
||||
|
||||
let columnList = [
|
||||
new TableColumnContentModel(
|
||||
new ColumnModel(
|
||||
(item) => {
|
||||
return {
|
||||
'editionId': item.id,
|
||||
'pieceId': this.props.parentId,
|
||||
'selectItem': this.selectItem,
|
||||
'selected': item.selected
|
||||
}},
|
||||
}; },
|
||||
'',
|
||||
<AccordionListItemTableSelectAllEditionsToggle
|
||||
onChange={this.selectAllItems}
|
||||
@ -102,41 +108,41 @@ let AccordionListItemTableEditions = React.createClass({
|
||||
1,
|
||||
false
|
||||
),
|
||||
new TableColumnContentModel(
|
||||
new ColumnModel(
|
||||
(item) => {
|
||||
return {
|
||||
'content': item.edition_number
|
||||
}},
|
||||
}; },
|
||||
'edition_number',
|
||||
'#',
|
||||
TableItemText,
|
||||
1,
|
||||
true,
|
||||
{to: 'edition', paramsKey: 'editionId', contentKey: 'bitcoin_id'}
|
||||
transition
|
||||
),
|
||||
new TableColumnContentModel(
|
||||
new ColumnModel(
|
||||
(item) => {
|
||||
return {
|
||||
'content': item.bitcoin_id
|
||||
}},
|
||||
}; },
|
||||
'bitcoin_id',
|
||||
getLangText('Bitcoin Address'),
|
||||
TableItemText,
|
||||
5,
|
||||
true,
|
||||
{to: 'edition', paramsKey: 'editionId', contentKey: 'bitcoin_id'}
|
||||
transition
|
||||
),
|
||||
new TableColumnContentModel(
|
||||
new ColumnModel(
|
||||
(item) => {
|
||||
return {
|
||||
'content': item.acl
|
||||
}},
|
||||
}; },
|
||||
'acl',
|
||||
getLangText('Actions'),
|
||||
TableItemAclFiltered,
|
||||
4,
|
||||
false,
|
||||
{to: 'edition', paramsKey: 'editionId', contentKey: 'bitcoin_id'}
|
||||
transition
|
||||
)
|
||||
];
|
||||
|
||||
@ -149,8 +155,8 @@ let AccordionListItemTableEditions = React.createClass({
|
||||
columnList={columnList}
|
||||
numOfTableItems={this.props.numOfEditions}
|
||||
show={this.props.show}
|
||||
orderBy={this.state.orderBy}
|
||||
orderAsc={this.state.orderAsc}
|
||||
orderBy={orderBy}
|
||||
orderAsc={orderAsc}
|
||||
changeOrder={this.changeEditionListOrder}>
|
||||
<AccordionListItemTableToggle
|
||||
className="ascribe-accordion-list-table-toggle"
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
let AccordionListItemTableToggle = React.createClass({
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
import Header from '../components/header';
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Alert from 'react-bootstrap/lib/Alert';
|
||||
|
||||
@ -7,12 +9,15 @@ let AlertDismissable = React.createClass({
|
||||
alertVisible: true
|
||||
};
|
||||
},
|
||||
|
||||
show() {
|
||||
this.setState({alertVisible: true});
|
||||
},
|
||||
|
||||
hide() {
|
||||
this.setState({alertVisible: false});
|
||||
},
|
||||
|
||||
render() {
|
||||
if (this.state.alertVisible) {
|
||||
let key = this.props.error;
|
||||
|
@ -1,5 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
|
||||
/*
|
||||
Is this even used somewhere?
|
||||
Deprecate? 5.6.15 - Tim
|
||||
|
||||
*/
|
||||
let ButtonSubmitOrClose = React.createClass({
|
||||
render() {
|
||||
if (this.props.submitted){
|
||||
@ -14,7 +22,7 @@ let ButtonSubmitOrClose = React.createClass({
|
||||
<button type="submit" className="btn btn-ascribe-inv">{this.props.text}</button>
|
||||
<button className="btn btn-ascribe-inv" onClick={this.props.onClose}>CLOSE</button>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import fetch from 'isomorphic-fetch';
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
@ -12,19 +12,20 @@ let ConsignForm = React.createClass({
|
||||
mixins: [FormMixin],
|
||||
|
||||
url() {
|
||||
return ApiUrls.ownership_consigns
|
||||
return ApiUrls.ownership_consigns;
|
||||
},
|
||||
|
||||
getFormData() {
|
||||
return {
|
||||
bitcoin_id: this.getBitcoinIds().join(),
|
||||
consignee: this.refs.consignee.state.value,
|
||||
consign_message: this.refs.consign_message.state.value,
|
||||
password: this.refs.password.state.value
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
renderForm() {
|
||||
let title = this.getTitlesString().join("");
|
||||
let title = this.getTitlesString().join('');
|
||||
let username = this.props.currentUser.username;
|
||||
let message =
|
||||
`Hi,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import fetch from 'isomorphic-fetch';
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
@ -9,39 +9,47 @@ import InputHidden from './input_hidden';
|
||||
import InputCheckbox from './input_checkbox';
|
||||
import InputDate from './input_date';
|
||||
import InputTextArea from './input_textarea';
|
||||
import OwnershipFetcher from '../../fetchers/ownership_fetcher'
|
||||
import OwnershipFetcher from '../../fetchers/ownership_fetcher';
|
||||
import ButtonSubmitOrClose from './button_submit_close';
|
||||
|
||||
let LoanForm = React.createClass({
|
||||
|
||||
getInitialState() {
|
||||
this.setState({
|
||||
contract_key: null,
|
||||
contract_url: null,
|
||||
loaneeHasContract: false
|
||||
});
|
||||
},
|
||||
|
||||
mixins: [FormMixin],
|
||||
|
||||
url() {
|
||||
return ApiUrls.ownership_loans
|
||||
},
|
||||
componentDidMount(){
|
||||
this.setState({contract_key: null,
|
||||
contract_url: null,
|
||||
loaneeHasContract: false});
|
||||
return ApiUrls.ownership_loans;
|
||||
},
|
||||
|
||||
getFormData() {
|
||||
return {
|
||||
bitcoin_id: this.getBitcoinIds().join(),
|
||||
loanee: this.refs.loanee.state.value,
|
||||
gallery_name: this.refs.gallery_name.state.value,
|
||||
startdate: this.refs.startdate.state.value.format("YYYY-MM-DD"),
|
||||
enddate: this.refs.enddate.state.value.format("YYYY-MM-DD"),
|
||||
startdate: this.refs.startdate.state.value.format('YYYY-MM-DD'),
|
||||
enddate: this.refs.enddate.state.value.format('YYYY-MM-DD'),
|
||||
loan_message: this.refs.loan_message.state.value,
|
||||
password: this.refs.password.state.value,
|
||||
terms: this.refs.terms.state.value
|
||||
}
|
||||
};
|
||||
},
|
||||
handleLoanEmailBlur(e){
|
||||
|
||||
handleLoanEmailBlur(){
|
||||
OwnershipFetcher.fetchLoanContract(this.refs.loanee.state.value)
|
||||
.then((res) => {
|
||||
if (res && res.length > 0) {
|
||||
this.setState({contract_key: res[0].s3Key,
|
||||
this.setState({
|
||||
contract_key: res[0].s3Key,
|
||||
contract_url: res[0].s3Url,
|
||||
loaneeHasContract: true});
|
||||
loaneeHasContract: true
|
||||
});
|
||||
}
|
||||
else{
|
||||
this.resetLoanContract();
|
||||
@ -52,14 +60,16 @@ let LoanForm = React.createClass({
|
||||
this.resetLoanContract();
|
||||
});
|
||||
},
|
||||
|
||||
resetLoanContract(){
|
||||
this.setState({contract_key: null,
|
||||
contract_url: null,
|
||||
loaneeHasContract: false
|
||||
});
|
||||
},
|
||||
|
||||
renderForm() {
|
||||
let title = this.getTitlesString().join("");
|
||||
let title = this.getTitlesString().join('');
|
||||
let username = this.props.currentUser.username;
|
||||
let message =
|
||||
`Hi,
|
||||
@ -72,18 +82,19 @@ ${username}`;
|
||||
|
||||
let contract = <InputHidden ref="terms" value="True"/>;
|
||||
if (this.state.loaneeHasContract){
|
||||
let label = <div>
|
||||
let label = (<div>
|
||||
I agree to the
|
||||
<a href={this.state.contract_url} target="_blank">
|
||||
terms of {this.refs.loanee.state.value}
|
||||
</a>
|
||||
</div>;
|
||||
contract = <InputCheckbox
|
||||
</div>);
|
||||
contract = (<InputCheckbox
|
||||
ref="terms"
|
||||
required="required"
|
||||
label={label}
|
||||
/>
|
||||
/>);
|
||||
}
|
||||
|
||||
return (
|
||||
<form id="loan_modal_content" role="form" onSubmit={this.submit}>
|
||||
<input className="invisible" type="email" name="fake_loanee"/>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import fetch from 'isomorphic-fetch';
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
@ -12,17 +12,19 @@ let ShareForm = React.createClass({
|
||||
mixins: [FormMixin],
|
||||
|
||||
url() {
|
||||
return ApiUrls.ownership_shares_mail
|
||||
return ApiUrls.ownership_shares_mail;
|
||||
},
|
||||
|
||||
getFormData() {
|
||||
return {
|
||||
bitcoin_id: this.getBitcoinIds().join(),
|
||||
share_emails: this.refs.share_emails.state.value,
|
||||
share_message: this.refs.share_message.state.value
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
renderForm() {
|
||||
let title = this.getTitlesString().join("");
|
||||
let title = this.getTitlesString().join('');
|
||||
let username = this.props.currentUser.username;
|
||||
let message =
|
||||
`Hi,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import fetch from 'isomorphic-fetch';
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
@ -9,23 +9,24 @@ import InputTextArea from './input_textarea';
|
||||
import ButtonSubmitOrClose from './button_submit_close';
|
||||
|
||||
|
||||
|
||||
let TransferForm = React.createClass({
|
||||
mixins: [FormMixin],
|
||||
|
||||
url() {
|
||||
return ApiUrls.ownership_transfers
|
||||
return ApiUrls.ownership_transfers;
|
||||
},
|
||||
|
||||
getFormData() {
|
||||
return {
|
||||
bitcoin_id: this.getBitcoinIds().join(),
|
||||
transferee: this.refs.transferee.state.value,
|
||||
transfer_message: this.refs.transfer_message.state.value,
|
||||
password: this.refs.password.state.value
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
renderForm() {
|
||||
let title = this.getTitlesString().join("");
|
||||
let title = this.getTitlesString().join('');
|
||||
let username = this.props.currentUser.username;
|
||||
let message =
|
||||
`Hi,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import fetch from 'isomorphic-fetch';
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
@ -12,15 +12,17 @@ let UnConsignForm = React.createClass({
|
||||
mixins: [FormMixin],
|
||||
|
||||
url() {
|
||||
return ApiUrls.ownership_unconsigns
|
||||
return ApiUrls.ownership_unconsigns;
|
||||
},
|
||||
|
||||
getFormData() {
|
||||
return {
|
||||
bitcoin_id: this.props.edition.bitcoin_id,
|
||||
unconsign_message: this.refs.unconsign_message.state.value,
|
||||
password: this.refs.password.state.value
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
renderForm() {
|
||||
let title = this.props.edition.title;
|
||||
let username = this.props.currentUser.username;
|
||||
|
@ -1,10 +1,9 @@
|
||||
import fetch from 'isomorphic-fetch';
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
import FormMixin from '../../mixins/form_mixin';
|
||||
import InputText from './input_text';
|
||||
import InputTextArea from './input_textarea';
|
||||
import ButtonSubmitOrClose from './button_submit_close';
|
||||
|
||||
@ -12,14 +11,16 @@ let UnConsignRequestForm = React.createClass({
|
||||
mixins: [FormMixin],
|
||||
|
||||
url() {
|
||||
return ApiUrls.ownership_unconsigns_request
|
||||
return ApiUrls.ownership_unconsigns_request;
|
||||
},
|
||||
|
||||
getFormData() {
|
||||
return {
|
||||
bitcoin_id: this.props.edition.bitcoin_id,
|
||||
unconsign_request_message: this.refs.unconsign_request_message.state.value
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
renderForm() {
|
||||
let title = this.props.edition.title;
|
||||
let username = this.props.currentUser.username;
|
||||
|
@ -1,19 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import AlertMixin from '../../mixins/alert_mixin'
|
||||
import AlertMixin from '../../mixins/alert_mixin';
|
||||
|
||||
let InputCheckbox = React.createClass({
|
||||
|
||||
mixins: [AlertMixin],
|
||||
|
||||
getInitialState() {
|
||||
return {value: null,
|
||||
return {
|
||||
value: null,
|
||||
alerts: null // needed in AlertMixin
|
||||
};
|
||||
},
|
||||
|
||||
handleChange(event) {
|
||||
this.setState({value: event.target.value});
|
||||
},
|
||||
|
||||
render() {
|
||||
let alerts = (this.props.submitted) ? null : this.state.alerts;
|
||||
return (
|
||||
|
@ -1,14 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import AlertMixin from '../../mixins/alert_mixin'
|
||||
import DatePicker from 'react-datepicker/dist/react-datepicker'
|
||||
import AlertMixin from '../../mixins/alert_mixin';
|
||||
import DatePicker from 'react-datepicker/dist/react-datepicker';
|
||||
|
||||
let InputDate = React.createClass({
|
||||
|
||||
mixins: [AlertMixin],
|
||||
|
||||
getInitialState() {
|
||||
return {value: null,
|
||||
return {
|
||||
value: null,
|
||||
alerts: null // needed in AlertMixin
|
||||
};
|
||||
},
|
||||
@ -18,7 +21,7 @@ let InputDate = React.createClass({
|
||||
},
|
||||
|
||||
render: function () {
|
||||
let className = "form-control input-text-ascribe";
|
||||
let className = 'form-control input-text-ascribe';
|
||||
let alerts = (this.props.submitted) ? null : this.state.alerts;
|
||||
return (
|
||||
<DatePicker
|
||||
@ -29,6 +32,10 @@ let InputDate = React.createClass({
|
||||
placeholderText={this.props.placeholderText}
|
||||
/>
|
||||
);
|
||||
// CAN THIS BE REMOVED???
|
||||
//
|
||||
// - Tim?
|
||||
//
|
||||
//return (
|
||||
// <div className="input-group date"
|
||||
// ref={this.props.name + "_picker"}
|
||||
|
@ -1,6 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import AlertMixin from '../../mixins/alert_mixin'
|
||||
import AlertMixin from '../../mixins/alert_mixin';
|
||||
|
||||
let InputHidden = React.createClass({
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import AlertMixin from '../../mixins/alert_mixin'
|
||||
import AlertMixin from '../../mixins/alert_mixin';
|
||||
|
||||
let InputText = React.createClass({
|
||||
|
||||
@ -11,11 +13,13 @@ let InputText = React.createClass({
|
||||
alerts: null // needed in AlertMixin
|
||||
};
|
||||
},
|
||||
|
||||
handleChange(event) {
|
||||
this.setState({value: event.target.value});
|
||||
},
|
||||
|
||||
render() {
|
||||
let className = "form-control input-text-ascribe";
|
||||
let className = 'form-control input-text-ascribe';
|
||||
let alerts = (this.props.submitted) ? null : this.state.alerts;
|
||||
return (
|
||||
<div className="form-group">
|
||||
|
@ -1,13 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import AlertMixin from '../../mixins/alert_mixin'
|
||||
import AlertMixin from '../../mixins/alert_mixin';
|
||||
|
||||
let InputTextArea = React.createClass({
|
||||
|
||||
mixins: [AlertMixin],
|
||||
|
||||
getInitialState() {
|
||||
return {value: this.props.defaultValue,
|
||||
return {
|
||||
value: this.props.defaultValue,
|
||||
alerts: null // needed in AlertMixin
|
||||
};
|
||||
},
|
||||
@ -15,7 +18,7 @@ let InputTextArea = React.createClass({
|
||||
this.setState({value: event.target.value});
|
||||
},
|
||||
render() {
|
||||
let className = "form-control input-text-ascribe textarea-ascribe-message";
|
||||
let className = 'form-control input-text-ascribe textarea-ascribe-message';
|
||||
|
||||
let alerts = (this.props.submitted) ? null : this.state.alerts;
|
||||
return (
|
||||
|
@ -1,11 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Modal from 'react-bootstrap/lib/Modal';
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
import ModalTrigger from 'react-bootstrap/lib/ModalTrigger';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
|
||||
import LoanForm from '../ascribe_forms/form_loan'
|
||||
import ModalMixin from '../../mixins/modal_mixin'
|
||||
import LoanForm from '../ascribe_forms/form_loan';
|
||||
import ModalMixin from '../../mixins/modal_mixin';
|
||||
|
||||
let LoanModalButton = React.createClass({
|
||||
render() {
|
||||
@ -19,7 +21,7 @@ let LoanModalButton = React.createClass({
|
||||
</div>
|
||||
</ModalTrigger>
|
||||
</OverlayTrigger>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@ -35,7 +37,7 @@ let LoanModal = React.createClass({
|
||||
onRequestHide={this.onRequestHide}/>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Modal from 'react-bootstrap/lib/Modal';
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
import ModalTrigger from 'react-bootstrap/lib/ModalTrigger';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
|
||||
import ModalMixin from '../../mixins/modal_mixin'
|
||||
|
||||
|
||||
import ShareForm from '../ascribe_forms/form_share_email'
|
||||
import ModalMixin from '../../mixins/modal_mixin';
|
||||
import ShareForm from '../ascribe_forms/form_share_email';
|
||||
|
||||
let ShareModalButton = React.createClass({
|
||||
render() {
|
||||
@ -20,7 +20,7 @@ let ShareModalButton = React.createClass({
|
||||
</div>
|
||||
</ModalTrigger>
|
||||
</OverlayTrigger>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@ -36,7 +36,7 @@ let ShareModal = React.createClass({
|
||||
onRequestHide={this.onRequestHide}/>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Modal from 'react-bootstrap/lib/Modal';
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
import ModalTrigger from 'react-bootstrap/lib/ModalTrigger';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
|
||||
import UnConsignForm from '../ascribe_forms/form_unconsign'
|
||||
import ModalMixin from '../../mixins/modal_mixin'
|
||||
import UnConsignForm from '../ascribe_forms/form_unconsign';
|
||||
import ModalMixin from '../../mixins/modal_mixin';
|
||||
|
||||
let UnConsignModalButton = React.createClass({
|
||||
render() {
|
||||
@ -19,7 +21,7 @@ let UnConsignModalButton = React.createClass({
|
||||
</div>
|
||||
</ModalTrigger>
|
||||
</OverlayTrigger>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@ -35,7 +37,7 @@ let UnConsignModal = React.createClass({
|
||||
onRequestHide={this.onRequestHide}/>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Modal from 'react-bootstrap/lib/Modal';
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
import ModalTrigger from 'react-bootstrap/lib/ModalTrigger';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
|
||||
import UnConsignRequestForm from '../ascribe_forms/form_unconsign_request'
|
||||
import ModalMixin from '../../mixins/modal_mixin'
|
||||
import UnConsignRequestForm from '../ascribe_forms/form_unconsign_request';
|
||||
import ModalMixin from '../../mixins/modal_mixin';
|
||||
|
||||
let UnConsignRequestModalButton = React.createClass({
|
||||
render() {
|
||||
@ -19,7 +21,7 @@ let UnConsignRequestModalButton = React.createClass({
|
||||
</div>
|
||||
</ModalTrigger>
|
||||
</OverlayTrigger>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@ -35,7 +37,7 @@ let UnConsignRequestModal = React.createClass({
|
||||
onRequestHide={this.onRequestHide}/>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import ReactAddons from 'react/addons';
|
||||
|
||||
@ -6,7 +8,7 @@ import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
import ModalTrigger from 'react-bootstrap/lib/ModalTrigger';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
|
||||
import ModalMixin from '../../mixins/modal_mixin'
|
||||
import ModalMixin from '../../mixins/modal_mixin';
|
||||
|
||||
let ModalWrapper = React.createClass({
|
||||
|
||||
@ -27,20 +29,22 @@ let ModalWrapper = React.createClass({
|
||||
{this.props.button}
|
||||
</ModalTrigger>
|
||||
</OverlayTrigger>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
let ModalBody = React.createClass({
|
||||
|
||||
mixins: [ModalMixin],
|
||||
|
||||
handleSuccess(){
|
||||
this.props.handleSuccess();
|
||||
this.props.onRequestHide();
|
||||
},
|
||||
|
||||
renderChildren() {
|
||||
return ReactAddons.Children.map(this.props.children, (child, i) => {
|
||||
return ReactAddons.Children.map(this.props.children, (child) => {
|
||||
return ReactAddons.addons.cloneWithProps(child, {
|
||||
editions: this.props.editions,
|
||||
currentUser: this.props.currentUser,
|
||||
@ -49,6 +53,7 @@ let ModalBody = React.createClass({
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal {...this.props} title={this.props.title}>
|
||||
@ -56,7 +61,7 @@ let ModalBody = React.createClass({
|
||||
{this.renderChildren()}
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import PaginationButton from './pagination_button';
|
||||
@ -18,14 +20,12 @@ let Pagination = React.createClass({
|
||||
direction='previous'
|
||||
goToPage={this.props.goToPage}
|
||||
currentPage={this.props.currentPage}
|
||||
totalPages={this.props.totalPages}>
|
||||
</PaginationButton>
|
||||
totalPages={this.props.totalPages} />
|
||||
<PaginationButton
|
||||
direction='next'
|
||||
goToPage={this.props.goToPage}
|
||||
currentPage={this.props.currentPage}
|
||||
totalPages={this.props.totalPages}>
|
||||
</PaginationButton>
|
||||
totalPages={this.props.totalPages} />
|
||||
</ul>
|
||||
</nav>
|
||||
);
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { mergeOptions } from '../../utils/general_utils';
|
||||
|
||||
import EditionListStore from '../../stores/edition_list_store';
|
||||
import EditionListActions from '../../actions/edition_list_actions';
|
||||
|
||||
@ -15,7 +19,7 @@ let PieceListBulkModal = React.createClass({
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return EditionListStore.getState();
|
||||
return mergeOptions(EditionListStore.getState(), UserStore.getState());
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
@ -23,23 +27,32 @@ let PieceListBulkModal = React.createClass({
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
UserActions.fetchCurrentUser();
|
||||
EditionListStore.listen(this.onChange);
|
||||
UserStore.listen(this.onChange);
|
||||
UserActions.fetchCurrentUser();
|
||||
},
|
||||
|
||||
componentDidUnmount() {
|
||||
componentWillUnmount() {
|
||||
EditionListStore.unlisten(this.onChange);
|
||||
UserStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
fetchSelectedPieceEditionList() {
|
||||
let filteredPieceIdList = Object.keys(this.state.editionList)
|
||||
.filter((pieceId) => {
|
||||
return this.state.editions.editionList[pieceId]
|
||||
.filter((edition) => edition.selected).length > 0;
|
||||
});
|
||||
return filteredPieceIdList;
|
||||
},
|
||||
|
||||
fetchSelectedEditionList() {
|
||||
let selectedEditionList = [];
|
||||
|
||||
Object
|
||||
.keys(this.state.editionList)
|
||||
.forEach((key) => {
|
||||
let filteredEditionsForPiece = this.state.editionList[key].filter((edition) => edition.selected);
|
||||
.forEach((pieceId) => {
|
||||
let filteredEditionsForPiece = this.state.editionList[pieceId].filter((edition) => edition.selected);
|
||||
selectedEditionList = selectedEditionList.concat(filteredEditionsForPiece);
|
||||
});
|
||||
|
||||
@ -74,7 +87,12 @@ let PieceListBulkModal = React.createClass({
|
||||
},
|
||||
|
||||
handleSuccess() {
|
||||
this.fetchSelectedPieceEditionList()
|
||||
.forEach((pieceId) => {
|
||||
EditionListActions.fetchEditionList(pieceId, this.state.orderBy, this.state.orderAsc);
|
||||
});
|
||||
|
||||
EditionListActions.clearAllEditionSelections();
|
||||
},
|
||||
|
||||
render() {
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
let PieceListBulkModalSelectedEditionsWidget = React.createClass({
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import PieceListStore from '../../stores/piece_list_store';
|
||||
@ -6,26 +8,28 @@ import PieceListActions from '../../actions/piece_list_actions';
|
||||
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 PieceListStore.getState();
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
PieceListStore.listen(this.onChange);
|
||||
},
|
||||
|
||||
componentDidUnmount() {
|
||||
componentWillUnmount() {
|
||||
PieceListStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
},
|
||||
|
||||
searchFor() {
|
||||
let searchTerm = this.refs.search.getInputDOMNode().value;
|
||||
PieceListActions.fetchPieceList(this.state.page, this.pageSize, searchTerm, this.state.orderBy, this.state.orderAsc);
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
|
||||
|
47
js/components/ascribe_table/models/table_models.js
Normal file
47
js/components/ascribe_table/models/table_models.js
Normal file
@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
|
||||
export class ColumnModel {
|
||||
// ToDo: Add validation for all passed-in parameters
|
||||
constructor(transformFn, columnName, displayName, displayType, rowWidth, canBeOrdered, transition) {
|
||||
this.transformFn = transformFn;
|
||||
this.columnName = columnName;
|
||||
this.displayName = displayName;
|
||||
this.displayType = displayType;
|
||||
this.rowWidth = rowWidth;
|
||||
this.canBeOrdered = canBeOrdered;
|
||||
this.transition = transition;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a user opens an editionList of a piece and clicks on a specific edition to go to the
|
||||
* piece detail page, all previously opened editionLists are still saved as show = true in the
|
||||
* pieceList store.
|
||||
*
|
||||
* So if the user now comes back to this view the old data will still be in this store,
|
||||
* since the browser wasn't able to load the new data (only containing show = undefined = false).
|
||||
*
|
||||
* This means that without closing all pieces after a transition, we'll get this flickering of editionLists.
|
||||
*
|
||||
* Since react-router does not implement a callback function for its transitionTo method, we have to do it
|
||||
* our selfes, using this TransitionModel.
|
||||
*/
|
||||
export class TransitionModel {
|
||||
constructor(to, queryKey, valueKey, callback) {
|
||||
this.to = to;
|
||||
this.queryKey = queryKey;
|
||||
this.valueKey = valueKey;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
toReactRouterLinkProps(queryValue) {
|
||||
let props = {
|
||||
to: this.to,
|
||||
params: {}
|
||||
};
|
||||
|
||||
props.params[this.queryKey] = queryValue;
|
||||
|
||||
return props;
|
||||
}
|
||||
}
|
@ -1,17 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import ReactAddons from 'react/addons';
|
||||
|
||||
import TableHeader from './table_header';
|
||||
import TableColumnContentModel from '../../models/table_column_content_model';
|
||||
import { ColumnModel } from './models/table_models';
|
||||
|
||||
|
||||
let Table = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)),
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(ColumnModel)),
|
||||
changeOrder: React.PropTypes.func,
|
||||
orderBy: React.PropTypes.string,
|
||||
orderAsc: React.PropTypes.bool,
|
||||
className: React.PropTypes.string,
|
||||
children: React.PropTypes.array,
|
||||
itemList: React.PropTypes.array
|
||||
},
|
||||
|
||||
renderChildren() {
|
||||
@ -27,17 +32,17 @@ let Table = React.createClass({
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="ascribe-table">
|
||||
<table className={'table ' + this.props.className}>
|
||||
<TableHeader
|
||||
columnList={this.props.columnList}
|
||||
itemList={this.props.itemList}
|
||||
changeOrder={this.props.changeOrder}
|
||||
orderAsc={this.props.orderAsc}
|
||||
orderBy={this.props.orderBy} />
|
||||
<div className="row">
|
||||
<tbody>
|
||||
{this.renderChildren()}
|
||||
</div>
|
||||
</div>
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -1,25 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import TableColumnMixin from '../../mixins/table_column_mixin';
|
||||
import TableHeaderItem from './table_header_item';
|
||||
|
||||
import TableColumnContentModel from '../../models/table_column_content_model';
|
||||
import { ColumnModel } from './models/table_models';
|
||||
|
||||
|
||||
let TableHeader = React.createClass({
|
||||
mixins: [TableColumnMixin],
|
||||
propTypes: {
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)),
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(ColumnModel)),
|
||||
itemList: React.PropTypes.array.isRequired,
|
||||
changeOrder: React.PropTypes.func,
|
||||
orderAsc: React.PropTypes.bool,
|
||||
orderBy: React.PropTypes.string
|
||||
},
|
||||
|
||||
mixins: [TableColumnMixin],
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="col-xs-12 col-sm-12 col-md-12 col-lg-12 ascribe-table-header-row">
|
||||
<div className="row">
|
||||
<thead>
|
||||
<tr>
|
||||
{this.props.columnList.map((val, i) => {
|
||||
|
||||
let columnClasses = this.calcColumnClasses(this.props.columnList, i, 12);
|
||||
@ -35,14 +38,12 @@ let TableHeader = React.createClass({
|
||||
canBeOrdered={canBeOrdered}
|
||||
orderAsc={this.props.orderAsc}
|
||||
orderBy={this.props.orderBy}
|
||||
changeOrder={this.props.changeOrder}>
|
||||
</TableHeaderItem>
|
||||
changeOrder={this.props.changeOrder} />
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</tr>
|
||||
</thead>
|
||||
);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import TableHeaderItemCarret from './table_header_item_carret';
|
||||
@ -25,28 +27,28 @@ let TableHeaderItem = React.createClass({
|
||||
if(this.props.canBeOrdered && this.props.changeOrder && this.props.orderAsc != null && this.props.orderBy) {
|
||||
if(this.props.columnName === this.props.orderBy) {
|
||||
return (
|
||||
<div
|
||||
className={this.props.columnClasses + ' ascribe-table-header-column'}
|
||||
<th
|
||||
className={'ascribe-table-header-column'}
|
||||
onClick={this.changeOrder}>
|
||||
<span>{this.props.displayName} <TableHeaderItemCarret orderAsc={this.props.orderAsc} /></span>
|
||||
</div>
|
||||
</th>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div
|
||||
className={this.props.columnClasses + ' ascribe-table-header-column'}
|
||||
<th
|
||||
className={'ascribe-table-header-column'}
|
||||
onClick={this.changeOrder}>
|
||||
<span>{this.props.displayName}</span>
|
||||
</div>
|
||||
</th>
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<div className={this.props.columnClasses + ' ascribe-table-header-column'}>
|
||||
<th className={'ascribe-table-header-column'}>
|
||||
<span>
|
||||
{this.props.displayName}
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
let TableHeaderItemCarret = React.createClass({
|
||||
|
@ -1,6 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import TableColumnContentModel from '../../models/table_column_content_model';
|
||||
import { ColumnModel } from './models/table_models';
|
||||
|
||||
import TableItemWrapper from './table_item_wrapper';
|
||||
|
||||
@ -8,24 +10,17 @@ import TableItemWrapper from './table_item_wrapper';
|
||||
let TableItem = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)),
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(ColumnModel)),
|
||||
columnContent: React.PropTypes.object,
|
||||
onClick: React.PropTypes.func, // See: https://facebook.github.io/react/tips/expose-component-functions.html
|
||||
className: React.PropTypes.string
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className={this.props.className + ' col-xs-12 col-sm-12 col-md-12 col-lg-12 ascribe-table-item'}
|
||||
onClick={this.props.onClick}>
|
||||
<div className="row">
|
||||
<TableItemWrapper
|
||||
columnList={this.props.columnList}
|
||||
columnContent={this.props.columnContent}
|
||||
columnWidth={12}>
|
||||
</TableItemWrapper>
|
||||
</div>
|
||||
</div>
|
||||
columnWidth={12} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
/**
|
||||
@ -5,7 +7,7 @@ import React from 'react';
|
||||
*/
|
||||
let TableItemImg = React.createClass({
|
||||
propTypes: {
|
||||
content: React.PropTypes.string.isRequired,
|
||||
content: React.PropTypes.string.isRequired
|
||||
},
|
||||
|
||||
render() {
|
||||
|
@ -1,7 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import TableColumnContentModel from '../../models/table_column_content_model';
|
||||
import { ColumnModel } from './models/table_models';
|
||||
|
||||
import TableItem from './table_item';
|
||||
|
||||
@ -9,10 +11,11 @@ import TableItem from './table_item';
|
||||
let TableItemSelectable = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)),
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(ColumnModel)),
|
||||
columnContent: React.PropTypes.object,
|
||||
parentId: React.PropTypes.number,
|
||||
className: React.PropTypes.string
|
||||
className: React.PropTypes.string,
|
||||
selectItem: React.PropTypes.func
|
||||
},
|
||||
|
||||
selectItem() {
|
||||
@ -29,8 +32,7 @@ let TableItemSelectable = React.createClass({
|
||||
className={tableItemClasses + ' ' + this.props.className}
|
||||
columnList={this.props.columnList}
|
||||
columnContent={this.props.columnContent}
|
||||
onClick={this.selectItem}>
|
||||
</TableItem>
|
||||
onClick={this.selectItem} />
|
||||
);
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import TableColumnContentModel from '../../models/table_column_content_model';
|
||||
import { ColumnModel } from './models/table_models';
|
||||
|
||||
import EditionListStore from '../../stores/edition_list_store';
|
||||
import EditionListActions from '../../actions/edition_list_actions';
|
||||
@ -16,7 +18,7 @@ import TableItemSubtableButton from './table_item_subtable_button';
|
||||
|
||||
let TableItemSubtable = React.createClass({
|
||||
propTypes: {
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)),
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(ColumnModel)),
|
||||
columnContent: React.PropTypes.object
|
||||
},
|
||||
|
||||
@ -26,14 +28,18 @@ let TableItemSubtable = React.createClass({
|
||||
};
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
EditionListStore.listen(this.onChange);
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
EditionListStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
},
|
||||
|
||||
loadEditionList() {
|
||||
if(this.state.open) {
|
||||
this.setState({
|
||||
@ -61,9 +67,9 @@ let TableItemSubtable = React.createClass({
|
||||
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)
|
||||
new ColumnModel('edition_number', 'Number', TableItemText, 2, false),
|
||||
new ColumnModel('user_registered', 'User', TableItemText, 4, true),
|
||||
new ColumnModel('acl', 'Actions', TableItemAcl, 4, true)
|
||||
];
|
||||
|
||||
if(this.state.open && this.state.editionList[this.props.columnContent.id] && this.state.editionList[this.props.columnContent.id].length) {
|
||||
@ -77,8 +83,7 @@ let TableItemSubtable = React.createClass({
|
||||
className="ascribe-table-item-selectable"
|
||||
selectItem={this.selectItem}
|
||||
parentId={this.props.columnContent.id}
|
||||
key={i}>
|
||||
</TableItemSelectable>
|
||||
key={i} />
|
||||
);
|
||||
})}
|
||||
</Table>
|
||||
@ -94,11 +99,9 @@ let TableItemSubtable = React.createClass({
|
||||
<TableItemWrapper
|
||||
columnList={this.props.columnList}
|
||||
columnContent={this.props.columnContent}
|
||||
columnWidth={12}>
|
||||
</TableItemWrapper>
|
||||
columnWidth={12} />
|
||||
<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 content="+" onClick={this.loadEditionList} />
|
||||
</div>
|
||||
</div>
|
||||
{renderEditionListTable()}
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
let TableItemSubtableButton = React.createClass({
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
|
||||
|
@ -1,34 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
|
||||
import TableColumnContentModel from '../../models/table_column_content_model';
|
||||
import { ColumnModel } from './models/table_models';
|
||||
import TableColumnMixin from '../../mixins/table_column_mixin';
|
||||
|
||||
let Link = Router.Link;
|
||||
|
||||
let TableItemWrapper = React.createClass({
|
||||
mixins: [TableColumnMixin, Router.Navigation],
|
||||
propTypes: {
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableColumnContentModel)),
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(ColumnModel)),
|
||||
columnContent: React.PropTypes.object,
|
||||
columnWidth: React.PropTypes.number.isRequired
|
||||
},
|
||||
|
||||
/**
|
||||
* If a link is defined in columnContent, then we can use
|
||||
* Router.Navigation.transitionTo to redirect the user
|
||||
* programmatically
|
||||
*/
|
||||
transition(column) {
|
||||
if(column.link) {
|
||||
let params = {};
|
||||
params[column.link.paramsKey] = this.props.columnContent[column.link.contentKey];
|
||||
|
||||
this.transitionTo(column.link.to, params);
|
||||
}
|
||||
},
|
||||
mixins: [TableColumnMixin, Router.Navigation],
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<tr>
|
||||
{this.props.columnList.map((column, i) => {
|
||||
|
||||
let TypeElement = column.displayType;
|
||||
@ -36,19 +27,35 @@ let TableItemWrapper = React.createClass({
|
||||
|
||||
let columnClass = this.calcColumnClasses(this.props.columnList, i, this.props.columnWidth);
|
||||
|
||||
let transition = this.transition.bind(this, column);
|
||||
|
||||
if(!column.transition) {
|
||||
return (
|
||||
<div
|
||||
className={columnClass + ' ascribe-table-item-column'}
|
||||
key={i}
|
||||
onClick={transition}>
|
||||
<td
|
||||
className={'ascribe-table-item-column'}
|
||||
key={i}>
|
||||
<TypeElement {...typeElementProps} />
|
||||
</div>
|
||||
</td>
|
||||
);
|
||||
} else {
|
||||
|
||||
let linkProps = column.transition.toReactRouterLinkProps(this.props.columnContent[column.transition.valueKey]);
|
||||
/**
|
||||
* If a transition is defined in columnContent, then we can use
|
||||
* Router.Navigation.transitionTo to redirect the user
|
||||
* programmatically
|
||||
*/
|
||||
return (
|
||||
<td key={i}>
|
||||
<Link
|
||||
className={'ascribe-table-item-column'}
|
||||
onClick={column.transition.callback}
|
||||
{...linkProps}>
|
||||
<TypeElement {...typeElementProps} />
|
||||
</Link>
|
||||
</td>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import MediaPlayer from './ascribe_media/media_player';
|
||||
|
||||
@ -6,13 +8,18 @@ import Col from 'react-bootstrap/lib/Col';
|
||||
import Button from 'react-bootstrap/lib/Button';
|
||||
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
|
||||
|
||||
import EditionActions from '../actions/edition_actions'
|
||||
import AclButton from './acl_button'
|
||||
import EditionActions from '../actions/edition_actions';
|
||||
import AclButton from './acl_button';
|
||||
|
||||
/**
|
||||
* This is the component that implements display-specific functionality
|
||||
*/
|
||||
let Edition = React.createClass({
|
||||
propTypes: {
|
||||
edition: React.PropTypes.object,
|
||||
currentUser: React.PropTypes.object
|
||||
},
|
||||
|
||||
render() {
|
||||
let thumbnail = this.props.edition.thumbnail;
|
||||
let mimetype = this.props.edition.digital_work.mime;
|
||||
@ -45,11 +52,15 @@ let Edition = React.createClass({
|
||||
});
|
||||
|
||||
let EditionHeader = React.createClass({
|
||||
propTypes: {
|
||||
edition: React.PropTypes.object
|
||||
},
|
||||
|
||||
render() {
|
||||
var title_html = <div className="ascribe-detail-title">{this.props.edition.title}</div>;
|
||||
var titleHtml = <div className="ascribe-detail-title">{this.props.edition.title}</div>;
|
||||
return (
|
||||
<div className="ascribe-detail-header">
|
||||
<EditionDetailProperty label="title" value={title_html} />
|
||||
<EditionDetailProperty label="title" value={titleHtml} />
|
||||
<EditionDetailProperty label="by" value={this.props.edition.artist_name} />
|
||||
<EditionDetailProperty label="date" value={ this.props.edition.date_created.slice(0, 4) } />
|
||||
<hr/>
|
||||
@ -59,26 +70,32 @@ let EditionHeader = React.createClass({
|
||||
});
|
||||
|
||||
let EditionDetails = React.createClass({
|
||||
propTypes: {
|
||||
edition: React.PropTypes.object,
|
||||
currentUser: React.PropTypes.object
|
||||
},
|
||||
|
||||
handleSuccess(){
|
||||
EditionActions.fetchOne(this.props.edition.id);
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="ascribe-detail-header">
|
||||
<EditionDetailProperty label="edition"
|
||||
value={this.props.edition.edition_number + " of " + this.props.edition.num_editions} />
|
||||
value={this.props.edition.edition_number + ' of ' + this.props.edition.num_editions} />
|
||||
<EditionDetailProperty label="id" value={ this.props.edition.bitcoin_id } />
|
||||
<EditionDetailProperty label="owner" value={ this.props.edition.owner } />
|
||||
<br/>
|
||||
<AclButton
|
||||
availableAcls={["transfer"]}
|
||||
availableAcls={['transfer']}
|
||||
action="transfer"
|
||||
editions={[this.props.edition]}
|
||||
currentUser={this.props.currentUser}
|
||||
handleSuccess={this.handleSuccess}
|
||||
/>
|
||||
<AclButton
|
||||
availableAcls={["consign"]}
|
||||
availableAcls={['consign']}
|
||||
action="consign"
|
||||
editions={[this.props.edition]}
|
||||
currentUser={this.props.currentUser}
|
||||
@ -92,6 +109,14 @@ let EditionDetails = React.createClass({
|
||||
});
|
||||
|
||||
let EditionDetailProperty = React.createClass({
|
||||
propTypes: {
|
||||
label: React.PropTypes.string,
|
||||
value: React.PropTypes.oneOfType([
|
||||
React.PropTypes.string,
|
||||
React.PropTypes.element
|
||||
])
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="row ascribe-detail-property">
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { mergeOptions } from '../utils/general_utils';
|
||||
|
||||
import EditionActions from '../actions/edition_actions';
|
||||
import EditionStore from '../stores/edition_store';
|
||||
import UserActions from '../actions/user_actions';
|
||||
@ -11,10 +15,8 @@ import Edition from './edition';
|
||||
* This is the component that implements resource/data specific functionality
|
||||
*/
|
||||
let EditionContainer = React.createClass({
|
||||
|
||||
getInitialState() {
|
||||
return {'user': UserStore.getState(),
|
||||
'edition': EditionStore.getState()}
|
||||
return mergeOptions(UserStore.getState(), EditionStore.getState());
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
@ -22,18 +24,19 @@ let EditionContainer = React.createClass({
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
EditionActions.fetchOne(this.props.params.editionId);
|
||||
EditionStore.listen(this.onChange);
|
||||
UserActions.fetchCurrentUser();
|
||||
UserStore.listen(this.onChange);
|
||||
|
||||
UserActions.fetchCurrentUser();
|
||||
EditionActions.fetchOne(this.props.params.editionId);
|
||||
},
|
||||
componentDidUnmount() {
|
||||
|
||||
componentWillUnmount() {
|
||||
EditionStore.unlisten(this.onChange);
|
||||
UserStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
render() {
|
||||
|
||||
if('title' in this.state.edition) {
|
||||
return (
|
||||
<Edition edition={this.state.edition}
|
||||
@ -44,8 +47,6 @@ let EditionContainer = React.createClass({
|
||||
<p>Loading</p>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
|
||||
import AltContainer from 'alt/AltContainer';
|
||||
import UserActions from '../actions/user_actions';
|
||||
import UserStore from '../stores/user_store';
|
||||
|
||||
import Nav from 'react-bootstrap/lib/Nav';
|
||||
import Navbar from 'react-bootstrap/lib/Navbar';
|
||||
import NavItem from 'react-bootstrap/lib/NavItem';
|
||||
import DropdownButton from 'react-bootstrap/lib/DropdownButton';
|
||||
import MenuItem from 'react-bootstrap/lib/MenuItem';
|
||||
|
||||
@ -22,10 +22,14 @@ let Header = React.createClass({
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
UserStore.listen(this.onChange)
|
||||
UserStore.listen(this.onChange);
|
||||
UserActions.fetchCurrentUser();
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
UserStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
},
|
||||
|
@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import AltContainer from 'alt/AltContainer';
|
||||
|
||||
import PieceListStore from '../stores/piece_list_store';
|
||||
import PieceListActions from '../actions/piece_list_actions';
|
||||
@ -15,6 +16,9 @@ import PieceListToolbar from './ascribe_piece_list_toolbar/piece_list_toolbar';
|
||||
|
||||
|
||||
let PieceList = React.createClass({
|
||||
propTypes: {
|
||||
query: React.PropTypes.object
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return PieceListStore.getState();
|
||||
@ -35,7 +39,7 @@ let PieceList = React.createClass({
|
||||
},
|
||||
|
||||
paginationGoToPage(page) {
|
||||
return (e) => PieceListActions.fetchPieceList(page, this.state.pageSize,
|
||||
return () => PieceListActions.fetchPieceList(page, this.state.pageSize,
|
||||
this.state.search, this.state.orderBy,
|
||||
this.state.orderAsc);
|
||||
},
|
||||
@ -47,7 +51,7 @@ let PieceList = React.createClass({
|
||||
|
||||
render() {
|
||||
let currentPage = parseInt(this.props.query.page, 10) || 1;
|
||||
let totalPages = Math.ceil(this.state.pieceListCount / this.state.pageSize)
|
||||
let totalPages = Math.ceil(this.state.pieceListCount / this.state.pageSize);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -69,7 +73,7 @@ let PieceList = React.createClass({
|
||||
content={item}
|
||||
key={i}>
|
||||
<AccordionListItemTableEditions
|
||||
className="ascribe-accordion-list-item-table col-xs-6 col-sm-6 col-md-6 col-lg-6 col-xs-offset-3 col-sm-offset-3 col-md-offset-3 col-lg-offset-3"
|
||||
className="ascribe-accordion-list-item-table col-xs-12 col-sm-8 col-md-6 col-lg-6 col-sm-offset-2 col-md-offset-3 col-lg-offset-3"
|
||||
parentId={item.id}
|
||||
show={item.show}
|
||||
numOfEditions={item.num_editions}/>
|
||||
@ -80,8 +84,7 @@ let PieceList = React.createClass({
|
||||
<Pagination
|
||||
currentPage={currentPage}
|
||||
totalPages={totalPages}
|
||||
goToPage={this.paginationGoToPage}>
|
||||
</Pagination>
|
||||
goToPage={this.paginationGoToPage} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import AppConstants from './application_constants';
|
||||
|
||||
let apiUrls = {
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
let constants = {
|
||||
//'baseUrl': 'http://localhost:8000/api/',
|
||||
'baseUrl': 'http://staging.ascribe.io/api/',
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
const languages = {
|
||||
'en-US': {
|
||||
'Bitcoin Address': 'Bitcoin Address',
|
||||
|
@ -1,13 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
import fetch from '../utils/fetch';
|
||||
|
||||
import AppConstants from '../constants/application_constants';
|
||||
|
||||
|
||||
let EditionFetcher = {
|
||||
/**
|
||||
* Fetch one user from the API.
|
||||
* If no arg is supplied, load the current user
|
||||
*
|
||||
*/
|
||||
fetchOne(editionId) {
|
||||
return fetch.get('edition', {'bitcoin_id': editionId});
|
||||
|
@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
import fetch from '../utils/fetch';
|
||||
|
||||
import { generateOrderingQueryParams } from '../utils/fetch_api_utils';
|
||||
|
||||
import AppConstants from '../constants/application_constants';
|
||||
|
||||
|
||||
let EditionListFetcher = {
|
||||
/**
|
||||
|
@ -1,14 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
import fetch from 'isomorphic-fetch';
|
||||
|
||||
import AppConstants from '../constants/application_constants';
|
||||
import FetchApiUtils from '../utils/fetch_api_utils';
|
||||
|
||||
|
||||
let OwnershipFetcher = {
|
||||
/**
|
||||
* Fetch one user from the API.
|
||||
* If no arg is supplied, load the current user
|
||||
*
|
||||
*/
|
||||
fetchLoanContract(email) {
|
||||
return fetch(AppConstants.baseUrl + 'ownership/loans/contract/?loanee=' + email, {
|
||||
|
@ -1,15 +1,14 @@
|
||||
import fetch from '../utils/fetch';
|
||||
'use strict';
|
||||
|
||||
import AppConstants from '../constants/application_constants';
|
||||
import fetch from '../utils/fetch';
|
||||
|
||||
|
||||
let PieceFetcher = {
|
||||
/**
|
||||
* Fetch one user from the API.
|
||||
* If no arg is supplied, load the current user
|
||||
*
|
||||
*/
|
||||
fetchOne(pieceId) {
|
||||
fetchOne() {
|
||||
return fetch.get('piece');
|
||||
}
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
import AppConstants from '../constants/application_constants';
|
||||
'use strict';
|
||||
|
||||
import { generateOrderingQueryParams } from '../utils/fetch_api_utils';
|
||||
import fetch from '../utils/fetch';
|
||||
|
||||
|
@ -1,13 +1,12 @@
|
||||
import fetch from '../utils/fetch';
|
||||
'use strict';
|
||||
|
||||
import AppConstants from '../constants/application_constants';
|
||||
import fetch from '../utils/fetch';
|
||||
|
||||
|
||||
let UserFetcher = {
|
||||
/**
|
||||
* Fetch one user from the API.
|
||||
* If no arg is supplied, load the current user
|
||||
*
|
||||
*/
|
||||
fetchOne() {
|
||||
return fetch.get('user');
|
||||
|
@ -1,15 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import AlertDismissable from '../components/ascribe_forms/alert';
|
||||
|
||||
let AlertMixin = {
|
||||
setAlerts(errors){
|
||||
let alerts = errors.map(
|
||||
function(error) {
|
||||
let alerts = errors.map((error) => {
|
||||
return <AlertDismissable error={error} key={error}/>;
|
||||
}.bind(this)
|
||||
);
|
||||
});
|
||||
|
||||
this.setState({alerts: alerts});
|
||||
},
|
||||
|
||||
clearAlerts(){
|
||||
this.setState({alerts: null});
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
import fetch from '../utils/fetch';
|
||||
import React from 'react';
|
||||
|
||||
import AppConstants from '../constants/application_constants'
|
||||
import AlertDismissable from '../components/ascribe_forms/alert'
|
||||
import AlertDismissable from '../components/ascribe_forms/alert';
|
||||
|
||||
export const FormMixin = {
|
||||
getInitialState() {
|
||||
@ -10,7 +11,7 @@ export const FormMixin = {
|
||||
submitted: false
|
||||
, status: null
|
||||
, errors: []
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
submit(e) {
|
||||
@ -18,7 +19,7 @@ export const FormMixin = {
|
||||
this.setState({submitted: true});
|
||||
fetch
|
||||
.post(this.url(), { body: this.getFormData() })
|
||||
.then(response => { this.props.handleSuccess(); })
|
||||
.then(() => { this.props.handleSuccess(); })
|
||||
.catch(this.handleError);
|
||||
},
|
||||
|
||||
@ -40,31 +41,29 @@ export const FormMixin = {
|
||||
|
||||
getBitcoinIds(){
|
||||
return this.props.editions.map(function(edition){
|
||||
return edition.bitcoin_id
|
||||
})
|
||||
return edition.bitcoin_id;
|
||||
});
|
||||
},
|
||||
|
||||
getTitlesString(){
|
||||
return this.props.editions.map(function(edition){
|
||||
return '- \"' + edition.title + ', edition ' + edition.edition_number + '\"\n'
|
||||
})
|
||||
return '- \"' + edition.title + ', edition ' + edition.edition_number + '\"\n';
|
||||
});
|
||||
},
|
||||
|
||||
render(){
|
||||
let alert = null;
|
||||
if (this.state.errors.length > 0){
|
||||
alert = this.state.errors.map(
|
||||
function(error) {
|
||||
alert = this.state.errors.map((error) => {
|
||||
return <AlertDismissable error={error} key={error}/>;
|
||||
}.bind(this)
|
||||
);
|
||||
});
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
{alert}
|
||||
{this.renderForm()}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
let mapAttr = {
|
||||
link: 'href',
|
||||
script: 'src'
|
||||
}
|
||||
source: 'src'
|
||||
};
|
||||
|
||||
let mapTag = {
|
||||
js: 'script',
|
||||
css: 'link'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
let InjectInHeadMixin = {
|
||||
@ -57,8 +59,9 @@ let InjectInHeadMixin = {
|
||||
inject(src) {
|
||||
let ext = src.split('.').pop();
|
||||
let tag = mapTag[ext];
|
||||
if (!tag)
|
||||
if (!tag) {
|
||||
throw new Error(`Cannot inject ${src} in the DOM, cannot guess the tag name from extension "${ext}". Valid extensions are "js" and "css".`);
|
||||
}
|
||||
|
||||
return InjectInHeadMixin.injectTag(tag, src);
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
import React from 'react';
|
||||
'use strict';
|
||||
|
||||
let ModalMixin = {
|
||||
onRequestHide(e){
|
||||
if (e)
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
this.props.onRequestHide();
|
||||
}
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
'use strict';
|
||||
|
||||
import { sumNumList } from '../utils/general_utils';
|
||||
|
||||
@ -14,7 +14,7 @@ let TableColumnMixin = {
|
||||
let numOfUsedColumns = sumNumList(listOfRowValues);
|
||||
|
||||
if(numOfUsedColumns > numOfColumns) {
|
||||
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.')
|
||||
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 {
|
||||
return bootstrapClasses.join( listOfRowValues[i] + ' ') + listOfRowValues[i];
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
class TableColumnContentModel {
|
||||
// ToDo: Add validation for all passed-in parameters
|
||||
constructor(transformFn, columnName, displayName, displayType, rowWidth, canBeOrdered, link) {
|
||||
this.transformFn = transformFn;
|
||||
this.columnName = columnName;
|
||||
this.displayName = displayName;
|
||||
this.displayType = displayType;
|
||||
this.rowWidth = rowWidth;
|
||||
this.canBeOrdered = canBeOrdered;
|
||||
this.link = link;
|
||||
}
|
||||
}
|
||||
|
||||
export default TableColumnContentModel;
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
|
||||
@ -10,11 +12,8 @@ let Route = Router.Route;
|
||||
|
||||
let routes = (
|
||||
<Route name="app" handler={AscribeApp}>
|
||||
<Route name="pieces" path="/" handler={PieceList}>
|
||||
|
||||
</Route>
|
||||
<Route name="edition" path="/editions/:editionId" handler={EditionContainer}>
|
||||
</Route>
|
||||
<Route name="pieces" path="/" handler={PieceList} />
|
||||
<Route name="edition" path="/editions/:editionId" handler={EditionContainer} />
|
||||
</Route>
|
||||
);
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import alt from '../alt';
|
||||
@ -6,8 +8,6 @@ import EditionsListActions from '../actions/edition_list_actions';
|
||||
class EditionListStore {
|
||||
constructor() {
|
||||
this.editionList = {};
|
||||
this.orderBy = 'edition_number';
|
||||
this.orderAsc = true;
|
||||
this.bindActions(EditionsListActions);
|
||||
}
|
||||
|
||||
@ -17,11 +17,18 @@ class EditionListStore {
|
||||
// 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;
|
||||
this.orderBy = orderBy;
|
||||
this.orderAsc = orderAsc;
|
||||
|
||||
/**
|
||||
* orderBy and orderAsc are specific to a single list of editons
|
||||
* therefore they need to be saved in relation to their parent-piece.
|
||||
*
|
||||
* Default values for both are set in the editon_list-actions.
|
||||
*/
|
||||
this.editionList[pieceId].orderBy = orderBy;
|
||||
this.editionList[pieceId].orderAsc = orderAsc;
|
||||
}
|
||||
|
||||
onSelectEdition({pieceId, editionId}) {
|
||||
@ -50,6 +57,6 @@ class EditionListStore {
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default alt.createStore(EditionListStore);
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
import EditionActions from '../actions/edition_actions';
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
|
||||
import PieceListActions from '../actions/piece_list_actions';
|
||||
|
||||
|
||||
@ -18,8 +21,8 @@ class PieceListStore {
|
||||
this.pieceListCount = 0;
|
||||
this.page = 1;
|
||||
this.pageSize = 10;
|
||||
this.search = "";
|
||||
this.orderBy = "artist_name";
|
||||
this.search = '';
|
||||
this.orderBy = 'artist_name';
|
||||
this.orderAsc = true;
|
||||
this.bindActions(PieceListActions);
|
||||
}
|
||||
@ -37,6 +40,13 @@ class PieceListStore {
|
||||
});
|
||||
}
|
||||
|
||||
onCloseAllEditionLists() {
|
||||
this.pieceList
|
||||
.forEach((piece) => {
|
||||
piece.show = false;
|
||||
});
|
||||
}
|
||||
|
||||
onUpdatePieceList({ page, pageSize, search, pieceList, orderBy, orderAsc, pieceListCount }) {
|
||||
this.page = page;
|
||||
this.pageSize = pageSize;
|
||||
@ -46,6 +56,10 @@ class PieceListStore {
|
||||
this.pieceListCount = pieceListCount;
|
||||
|
||||
/**
|
||||
* Pagination - Known Issue:
|
||||
* #########################
|
||||
*
|
||||
*
|
||||
* The piece list store currently stores the open/close state of a piece list item.
|
||||
*
|
||||
* Once a new page is requested, this.pieceList will be overwritten, which means that the
|
||||
@ -57,10 +71,9 @@ class PieceListStore {
|
||||
*
|
||||
* We did not implement this, as we're going to add pagination to pieceList at some
|
||||
* point anyway. Then, this problem is automatically resolved.
|
||||
*
|
||||
*/
|
||||
this.pieceList = pieceList;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default alt.createStore(PieceListStore);
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
import PieceAction from '../actions/piece_actions';
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import alt from '../alt';
|
||||
import UserAction from '../actions/user_actions';
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
import { default as _fetch } from 'isomorphic-fetch';
|
||||
|
||||
import { argsToQueryParams } from '../utils/fetch_api_utils';
|
||||
|
||||
|
||||
class UrlMapError extends Error {};
|
||||
class ServerError extends Error {};
|
||||
class APIError extends Error {};
|
||||
class UrlMapError extends Error {}
|
||||
class ServerError extends Error {}
|
||||
class APIError extends Error {}
|
||||
|
||||
|
||||
class Fetch {
|
||||
@ -33,7 +35,7 @@ class Fetch {
|
||||
}
|
||||
|
||||
handleAPIError(json) {
|
||||
if (!json['success']) {
|
||||
if (!json.success) {
|
||||
let error = new APIError();
|
||||
error.json = json;
|
||||
throw error;
|
||||
@ -58,7 +60,7 @@ class Fetch {
|
||||
let re = /\${(\w+)}/g;
|
||||
|
||||
newUrl = newUrl.replace(re, (match, key) => {
|
||||
let val = params[key]
|
||||
let val = params[key];
|
||||
if (!val) {
|
||||
throw new Error(`Cannot find param ${key}`);
|
||||
}
|
||||
@ -76,7 +78,7 @@ class Fetch {
|
||||
request(verb, url, options) {
|
||||
options = options || {};
|
||||
let merged = this._merge(this.httpOptions, options);
|
||||
merged['method'] = verb;
|
||||
merged.method = verb;
|
||||
return _fetch(url, merged)
|
||||
.then(this.unpackResponse)
|
||||
.then(JSON.parse)
|
||||
@ -95,8 +97,8 @@ class Fetch {
|
||||
let newUrl = this.prepareUrl(url, params);
|
||||
let body = null;
|
||||
|
||||
if (params['body']) {
|
||||
body = JSON.stringify(params['body'])
|
||||
if (params.body) {
|
||||
body = JSON.stringify(params.body);
|
||||
}
|
||||
return this.request('post', url, { body });
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import { sanitize } from './general_utils';
|
||||
|
||||
// TODO: Create Unittests that test all functions
|
||||
@ -38,7 +40,7 @@ export function argsToQueryParams(obj) {
|
||||
return s + snakeCaseKey + '=' + encodeURIComponent(obj[key]);
|
||||
})
|
||||
.join('');
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a string and a boolean and generates a string query parameter for
|
||||
@ -52,11 +54,11 @@ export function generateOrderingQueryParams(orderBy, orderAsc) {
|
||||
}
|
||||
|
||||
return interpolation + orderBy;
|
||||
};
|
||||
}
|
||||
|
||||
export function status(response) {
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
return response
|
||||
return response;
|
||||
}
|
||||
throw new Error(response.json());
|
||||
}
|
||||
throw new Error(response.json())
|
||||
};
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
// TODO: Create Unittests that test all functions
|
||||
|
||||
export function sanitize(obj) {
|
||||
@ -12,7 +14,7 @@ export function sanitize(obj) {
|
||||
});
|
||||
|
||||
return obj;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the values of an object.
|
||||
@ -21,7 +23,7 @@ export function valuesOfObject(obj) {
|
||||
return Object
|
||||
.keys(obj)
|
||||
.map(key => obj[key]);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sums up a list of numbers. Like a Epsilon-math-kinda-sum...
|
||||
@ -30,11 +32,14 @@ export function sumNumList(l) {
|
||||
let sum = 0;
|
||||
l.forEach((num) => sum += parseFloat(num) || 0);
|
||||
return sum;
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
Taken from http://stackoverflow.com/a/4795914/1263876
|
||||
Behaves like C's format string function
|
||||
|
||||
REFACTOR TO ES6 (let instead of var)
|
||||
|
||||
*/
|
||||
export function formatText() {
|
||||
var args = arguments,
|
||||
@ -60,4 +65,34 @@ export function formatText() {
|
||||
}
|
||||
return val;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a list of object and merges their keys to one object.
|
||||
* Uses mergeOptions for two objects.
|
||||
* @param {[type]} l [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
export function mergeOptions(...l) {
|
||||
let newObj = {};
|
||||
|
||||
for(let i = 1; i < l.length; i++) {
|
||||
newObj = _mergeOptions(newObj, _mergeOptions(l[i - 1], l[i]));
|
||||
}
|
||||
|
||||
return newObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
|
||||
* @param obj1
|
||||
* @param obj2
|
||||
* @returns obj3 a new object based on obj1 and obj2
|
||||
* Taken from: http://stackoverflow.com/a/171256/1263876
|
||||
*/
|
||||
function _mergeOptions(obj1, obj2){
|
||||
let obj3 = {};
|
||||
for (let attrname in obj1) { obj3[attrname] = obj1[attrname]; }
|
||||
for (let attrname in obj2) { obj3[attrname] = obj2[attrname]; }
|
||||
return obj3;
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import languages from '../constants/languages';
|
||||
|
||||
import { formatText } from './general_utils';
|
||||
@ -27,4 +29,4 @@ export function getLangText(s, ...args) {
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
10
package.json
10
package.json
@ -3,18 +3,25 @@
|
||||
"version": "0.0.1",
|
||||
"description": "Das neue web client for Ascribe",
|
||||
"main": "js/app.js",
|
||||
"scripts": {
|
||||
"lint": "eslint ./js"
|
||||
},
|
||||
"author": "Ascribe",
|
||||
"license": "Copyright",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^3.1.11",
|
||||
"babel-jest": "^4.0.0",
|
||||
"babelify": "^6.1.2",
|
||||
"bootstrap-sass": "^3.3.4",
|
||||
"browser-sync": "^2.7.5",
|
||||
"browserify": "^9.0.8",
|
||||
"envify": "^3.4.0",
|
||||
"eslint": "^0.22.1",
|
||||
"eslint-plugin-react": "^2.5.0",
|
||||
"gulp": "^3.8.11",
|
||||
"gulp-concat": "^2.5.2",
|
||||
"gulp-eslint": "^0.13.2",
|
||||
"gulp-if": "^1.2.5",
|
||||
"gulp-notify": "^2.2.0",
|
||||
"gulp-sass": "^2.0.1",
|
||||
@ -38,7 +45,8 @@
|
||||
"react-datepicker": "~0.8.0",
|
||||
"react-router": "^0.13.3",
|
||||
"shmui": "^0.1.0",
|
||||
"uglifyjs": "^2.4.10"
|
||||
"uglifyjs": "^2.4.10",
|
||||
"react-datepicker": "~0.8.0"
|
||||
},
|
||||
"jest": {
|
||||
"scriptPreprocessor": "node_modules/babel-jest",
|
||||
|
@ -1,4 +1,4 @@
|
||||
$ascribe-accordion-list-item-height: 9em;
|
||||
$ascribe-accordion-list-item-height: 8em;
|
||||
$ascribe-accordion-list-font: 'Source Sans Pro';
|
||||
|
||||
.ascribe-accordion-list-item {
|
||||
@ -21,23 +21,15 @@ $ascribe-accordion-list-font: 'Source Sans Pro';
|
||||
height:100%;
|
||||
// ToDo: Include media queries for thumbnail
|
||||
.thumbnail-wrapper {
|
||||
float:left;
|
||||
height:100%;
|
||||
width:$ascribe-accordion-list-item-height;
|
||||
overflow:hidden;
|
||||
margin-left:0;
|
||||
padding-left:0;
|
||||
padding-right:0;
|
||||
|
||||
img {
|
||||
display:block;
|
||||
height: $ascribe-accordion-list-item-height;
|
||||
}
|
||||
}
|
||||
.info-wrapper {
|
||||
float:left;
|
||||
font-family: $ascribe-accordion-list-font;
|
||||
margin-left: 2em;
|
||||
padding-top: .75em;
|
||||
h1 {
|
||||
margin-top: .3em;
|
||||
font-size: 2.25em;
|
||||
}
|
||||
h3 {
|
||||
@ -46,7 +38,6 @@ $ascribe-accordion-list-font: 'Source Sans Pro';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ascribe-accordion-list-item-table {
|
||||
text-align: center;
|
||||
|
@ -11,7 +11,7 @@
|
||||
border-bottom-left-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
border-bottom: 0.2em solid #E0E0E0;
|
||||
z-index:9999;
|
||||
z-index:1000;
|
||||
}
|
||||
|
||||
.piece-list-bulk-modal-clear-all {
|
||||
|
@ -38,15 +38,8 @@
|
||||
float: none;
|
||||
}
|
||||
|
||||
.ascribe-table-header-row {
|
||||
border-bottom: 2px solid #E0E0E0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ascribe-table-header-column {
|
||||
display: table;
|
||||
height:3em;
|
||||
padding: 0;
|
||||
.ascribe-table {
|
||||
margin-bottom:0;
|
||||
}
|
||||
|
||||
.ascribe-table-header-column > span {
|
||||
@ -60,14 +53,6 @@
|
||||
.ascribe-table-header-column > span > .glyphicon {
|
||||
font-size: .5em;
|
||||
}
|
||||
/*
|
||||
.ascribe-table-item:nth-child(even) {
|
||||
background-color: #F5F5F5;
|
||||
}*/
|
||||
|
||||
/*.ascribe-table-item:hover {
|
||||
background-color: #EEEEEE;
|
||||
}*/
|
||||
|
||||
.ascribe-table-item-column {
|
||||
display: table;
|
||||
@ -79,9 +64,9 @@
|
||||
.ascribe-table-item-column > * {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ascribe-table-item-selected {
|
||||
|
Loading…
Reference in New Issue
Block a user