diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 00000000..869e2d3d
--- /dev/null
+++ b/.eslintrc
@@ -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
+ }
+}
\ No newline at end of file
diff --git a/gulpfile.js b/gulpfile.js
index a685ea56..6e5697bb 100644
--- a/gulpfile.js
+++ b/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;
diff --git a/js/actions/edition_actions.js b/js/actions/edition_actions.js
index a39c330a..07fcab1d 100644
--- a/js/actions/edition_actions.js
+++ b/js/actions/edition_actions.js
@@ -1,3 +1,5 @@
+'use strict';
+
import alt from '../alt';
import EditionFetcher from '../fetchers/edition_fetcher';
diff --git a/js/actions/edition_list_actions.js b/js/actions/edition_list_actions.js
index f07d7d18..83b9abfe 100644
--- a/js/actions/edition_list_actions.js
+++ b/js/actions/edition_list_actions.js
@@ -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) => {
diff --git a/js/actions/piece_actions.js b/js/actions/piece_actions.js
index 274ef458..cd78569d 100644
--- a/js/actions/piece_actions.js
+++ b/js/actions/piece_actions.js
@@ -1,3 +1,5 @@
+'use strict';
+
import alt from '../alt';
import PieceFetcher from '../fetchers/piece_fetcher';
diff --git a/js/actions/piece_list_actions.js b/js/actions/piece_list_actions.js
index 0105ff06..938cb195 100644
--- a/js/actions/piece_list_actions.js
+++ b/js/actions/piece_list_actions.js
@@ -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);
diff --git a/js/actions/user_actions.js b/js/actions/user_actions.js
index 34e80f52..90e931b1 100644
--- a/js/actions/user_actions.js
+++ b/js/actions/user_actions.js
@@ -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);
+ console.log(err);
});
}
-};
+}
export default alt.createActions(UserActions);
diff --git a/js/alt.js b/js/alt.js
index ad49b9b5..94786185 100644
--- a/js/alt.js
+++ b/js/alt.js
@@ -1,3 +1,5 @@
+'use strict';
+
import Alt from 'alt';
export default new Alt();
diff --git a/js/app.js b/js/app.js
index d37e1a62..ca2df1c6 100644
--- a/js/app.js
+++ b/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
+
+
+
+*/
+
+var warn = console.warn;
+console.warn = function(warning) {
+ if (/(setState)/.test(warning)) {
+ throw new Error(warning);
+ }
+ warn.apply(console, arguments);
+};
+
+/*
+
+
+ */
fetch.defaults({
urlMap: ApiUrls,
diff --git a/js/components/acl_button.js b/js/components/acl_button.js
index 5f2a0708..9607384b 100644
--- a/js/components/acl_button.js
+++ b/js/components/acl_button.js
@@ -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:
- }
+ };
}
- 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:
- }
+ };
}
- 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: }
+ title: 'Loan artwork',
+ tooltip: 'Loan your artwork for a limited period of time',
+ form:
+ };
}
- else if (this.props.action == 'share'){
+ else if (this.props.action === 'share'){
return {
- title: "Share artwork",
- tooltip: "Share the artwork",
- form: }
+ title: 'Share artwork',
+ tooltip: 'Share the artwork',
+ form:
+ };
}
},
render() {
diff --git a/js/components/ascribe_accordion_list/accordion_list.js b/js/components/ascribe_accordion_list/accordion_list.js
index 9eb484b7..a17aed36 100644
--- a/js/components/ascribe_accordion_list/accordion_list.js
+++ b/js/components/ascribe_accordion_list/accordion_list.js
@@ -1,5 +1,6 @@
+'use strict';
+
import React from 'react';
-import ReactAddons from 'react/addons';
let AccordionList = React.createClass({
diff --git a/js/components/ascribe_accordion_list/accordion_list_item.js b/js/components/ascribe_accordion_list/accordion_list_item.js
index c52f7e55..e822b5c6 100644
--- a/js/components/ascribe_accordion_list/accordion_list_item.js
+++ b/js/components/ascribe_accordion_list/accordion_list_item.js
@@ -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({
-
+
-
+
{this.props.content.title}
{getLangText('by %s', this.props.content.artist_name)}
+ {this.props.content.date_created.split('-')[0]}
diff --git a/js/components/ascribe_accordion_list/accordion_list_item_table.js b/js/components/ascribe_accordion_list/accordion_list_item_table.js
index 82b9a23a..4ead1eeb 100644
--- a/js/components/ascribe_accordion_list/accordion_list_item_table.js
+++ b/js/components/ascribe_accordion_list/accordion_list_item_table.js
@@ -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,17 +25,17 @@ let AccordionListItemTable = React.createClass({
return (
+ className="ascribe-table"
+ columnList={this.props.columnList}
+ itemList={this.props.itemList}
+ changeOrder={this.props.changeOrder}
+ orderBy={this.props.orderBy}
+ orderAsc={this.props.orderAsc}>
{this.props.itemList.map((item, i) => {
return (
-
+ key={i} />
);
})}
diff --git a/js/components/ascribe_accordion_list/accordion_list_item_table_editions.js b/js/components/ascribe_accordion_list/accordion_list_item_table_editions.js
index 70391e2d..c975500e 100644
--- a/js/components/ascribe_accordion_list/accordion_list_item_table_editions.js
+++ b/js/components/ascribe_accordion_list/accordion_list_item_table_editions.js
@@ -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
- }},
+ }; },
'',
{
+ 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(
- (item) => {
+ new ColumnModel(
+ (item) => {
return {
'content': item.acl
- }},
+ }; },
'acl',
getLangText('Actions'),
TableItemAclFiltered,
4,
false,
- {to: 'edition', paramsKey: 'editionId', contentKey: 'bitcoin_id'}
+ transition
)
];
@@ -149,11 +155,11 @@ 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}>
diff --git a/js/components/ascribe_accordion_list/accordion_list_item_table_select_all_editions_toggle.js b/js/components/ascribe_accordion_list/accordion_list_item_table_select_all_editions_toggle.js
index 37af9edb..0fe71c35 100644
--- a/js/components/ascribe_accordion_list/accordion_list_item_table_select_all_editions_toggle.js
+++ b/js/components/ascribe_accordion_list/accordion_list_item_table_select_all_editions_toggle.js
@@ -1,3 +1,5 @@
+'use strict';
+
import React from 'react';
@@ -11,8 +13,8 @@ let AccordionListItemTableSelectAllEditionsToggle = React.createClass({
render() {
return (
-
);
}
diff --git a/js/components/ascribe_accordion_list/accordion_list_item_table_toggle.js b/js/components/ascribe_accordion_list/accordion_list_item_table_toggle.js
index a3431b04..1f05de4b 100644
--- a/js/components/ascribe_accordion_list/accordion_list_item_table_toggle.js
+++ b/js/components/ascribe_accordion_list/accordion_list_item_table_toggle.js
@@ -1,3 +1,5 @@
+'use strict';
+
import React from 'react';
let AccordionListItemTableToggle = React.createClass({
@@ -10,7 +12,7 @@ let AccordionListItemTableToggle = React.createClass({
render() {
return (
-
{this.props.show ? 'Hide all ' + this.props.numOfTableItems + ' Editions' : 'Show all ' + this.props.numOfTableItems + ' Editions'}
diff --git a/js/components/ascribe_app.js b/js/components/ascribe_app.js
index bab7de97..6484976c 100644
--- a/js/components/ascribe_app.js
+++ b/js/components/ascribe_app.js
@@ -1,3 +1,5 @@
+'use strict';
+
import React from 'react';
import Router from 'react-router';
import Header from '../components/header';
@@ -12,7 +14,7 @@ let AscribeApp = React.createClass({
-
+
);
}
});
diff --git a/js/components/ascribe_forms/alert.js b/js/components/ascribe_forms/alert.js
index 482afdfe..4d5bae64 100644
--- a/js/components/ascribe_forms/alert.js
+++ b/js/components/ascribe_forms/alert.js
@@ -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;
diff --git a/js/components/ascribe_forms/button_submit_close.js b/js/components/ascribe_forms/button_submit_close.js
index e811cab5..7430f484 100644
--- a/js/components/ascribe_forms/button_submit_close.js
+++ b/js/components/ascribe_forms/button_submit_close.js
@@ -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({
{this.props.text}
CLOSE
- )
+ );
}
});
diff --git a/js/components/ascribe_forms/form_consign.js b/js/components/ascribe_forms/form_consign.js
index dbb1eee0..85c21467 100644
--- a/js/components/ascribe_forms/form_consign.js
+++ b/js/components/ascribe_forms/form_consign.js
@@ -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,
diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js
index 483d0f0a..3b9dc5e3 100644
--- a/js/components/ascribe_forms/form_loan.js
+++ b/js/components/ascribe_forms/form_loan.js
@@ -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,
- contract_url: res[0].s3Url,
- loaneeHasContract: true});
+ this.setState({
+ contract_key: res[0].s3Key,
+ contract_url: res[0].s3Url,
+ 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 =
;
if (this.state.loaneeHasContract){
- let label =
+ let label = (
;
- contract =
);
+ contract = (
+ />);
}
+
return (
- )
+ );
}
});
diff --git a/js/components/ascribe_modal/modal_share.js b/js/components/ascribe_modal/modal_share.js
index 4ada244c..2cce53ad 100644
--- a/js/components/ascribe_modal/modal_share.js
+++ b/js/components/ascribe_modal/modal_share.js
@@ -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,12 +20,12 @@ let ShareModalButton = React.createClass({
- )
+ );
}
});
let ShareModal = React.createClass({
- mixins : [ModalMixin],
+ mixins: [ModalMixin],
render() {
return (
@@ -36,7 +36,7 @@ let ShareModal = React.createClass({
onRequestHide={this.onRequestHide}/>
- )
+ );
}
});
diff --git a/js/components/ascribe_modal/modal_unconsign.js b/js/components/ascribe_modal/modal_unconsign.js
index 1245fc01..9bfb2faf 100644
--- a/js/components/ascribe_modal/modal_unconsign.js
+++ b/js/components/ascribe_modal/modal_unconsign.js
@@ -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,12 +21,12 @@ let UnConsignModalButton = React.createClass({
- )
+ );
}
});
let UnConsignModal = React.createClass({
- mixins : [ModalMixin],
+ mixins: [ModalMixin],
render() {
return (
@@ -35,7 +37,7 @@ let UnConsignModal = React.createClass({
onRequestHide={this.onRequestHide}/>
- )
+ );
}
});
diff --git a/js/components/ascribe_modal/modal_unconsign_request.js b/js/components/ascribe_modal/modal_unconsign_request.js
index c74e637b..fa0cd19f 100644
--- a/js/components/ascribe_modal/modal_unconsign_request.js
+++ b/js/components/ascribe_modal/modal_unconsign_request.js
@@ -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,12 +21,12 @@ let UnConsignRequestModalButton = React.createClass({
- )
+ );
}
});
let UnConsignRequestModal = React.createClass({
- mixins : [ModalMixin],
+ mixins: [ModalMixin],
render() {
return (
@@ -35,7 +37,7 @@ let UnConsignRequestModal = React.createClass({
onRequestHide={this.onRequestHide}/>
- )
+ );
}
});
diff --git a/js/components/ascribe_modal/modal_wrapper.js b/js/components/ascribe_modal/modal_wrapper.js
index a5d20389..43aecbe0 100644
--- a/js/components/ascribe_modal/modal_wrapper.js
+++ b/js/components/ascribe_modal/modal_wrapper.js
@@ -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}
- )
+ );
}
});
//
let ModalBody = React.createClass({
- mixins : [ModalMixin],
+
+ 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 (
@@ -56,7 +61,7 @@ let ModalBody = React.createClass({
{this.renderChildren()}
- )
+ );
}
});
diff --git a/js/components/ascribe_pagination/pagination.js b/js/components/ascribe_pagination/pagination.js
index e99f8e4e..6b55f119 100644
--- a/js/components/ascribe_pagination/pagination.js
+++ b/js/components/ascribe_pagination/pagination.js
@@ -1,3 +1,5 @@
+'use strict';
+
import React from 'react';
import PaginationButton from './pagination_button';
@@ -7,25 +9,23 @@ let Pagination = React.createClass({
goToPage: React.PropTypes.func.isRequired,
currentPage: React.PropTypes.number.isRequired,
totalPages: React.PropTypes.number.isRequired
- //itemListCount: React.PropTypes.number.isRequired
+ //itemListCount: React.PropTypes.number.isRequired
},
render() {
- return(
+ return (
-
-
-
+
-
+ totalPages={this.props.totalPages} />
);
diff --git a/js/components/ascribe_pagination/pagination_button.js b/js/components/ascribe_pagination/pagination_button.js
index bbb2a789..3adf0b50 100644
--- a/js/components/ascribe_pagination/pagination_button.js
+++ b/js/components/ascribe_pagination/pagination_button.js
@@ -1,3 +1,5 @@
+'use strict';
+
import React from 'react';
import Router from 'react-router';
diff --git a/js/components/ascribe_piece_list_bulk_modal/piece_list_bulk_modal.js b/js/components/ascribe_piece_list_bulk_modal/piece_list_bulk_modal.js
index 896882df..039d6aad 100644
--- a/js/components/ascribe_piece_list_bulk_modal/piece_list_bulk_modal.js
+++ b/js/components/ascribe_piece_list_bulk_modal/piece_list_bulk_modal.js
@@ -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);
});
@@ -73,8 +86,13 @@ let PieceListBulkModal = React.createClass({
EditionListActions.clearAllEditionSelections();
},
- handleSuccess(){
+ handleSuccess() {
+ this.fetchSelectedPieceEditionList()
+ .forEach((pieceId) => {
+ EditionListActions.fetchEditionList(pieceId, this.state.orderBy, this.state.orderAsc);
+ });
+ EditionListActions.clearAllEditionSelections();
},
render() {
@@ -92,7 +110,7 @@ let PieceListBulkModal = React.createClass({
- clear all
@@ -132,7 +150,7 @@ let PieceListBulkModal = React.createClass({
);
} else {
return null;
- }
+ }
}
});
diff --git a/js/components/ascribe_piece_list_bulk_modal/piece_list_bulk_modal_selected_editions_widget.js b/js/components/ascribe_piece_list_bulk_modal/piece_list_bulk_modal_selected_editions_widget.js
index 22b35a4a..99ede112 100644
--- a/js/components/ascribe_piece_list_bulk_modal/piece_list_bulk_modal_selected_editions_widget.js
+++ b/js/components/ascribe_piece_list_bulk_modal/piece_list_bulk_modal_selected_editions_widget.js
@@ -1,3 +1,5 @@
+'use strict';
+
import React from 'react';
let PieceListBulkModalSelectedEditionsWidget = React.createClass({
diff --git a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js
index ce9150b1..a3c8c219 100644
--- a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js
+++ b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js
@@ -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);
diff --git a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js
index 7aaf9dd8..d9d2b172 100644
--- a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js
+++ b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js
@@ -1,3 +1,5 @@
+'use strict';
+
import React from 'react';
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
diff --git a/js/components/ascribe_table/models/table_models.js b/js/components/ascribe_table/models/table_models.js
new file mode 100644
index 00000000..e5fad805
--- /dev/null
+++ b/js/components/ascribe_table/models/table_models.js
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/js/components/ascribe_table/table.js b/js/components/ascribe_table/table.js
index 9339a00a..44ba5d61 100644
--- a/js/components/ascribe_table/table.js
+++ b/js/components/ascribe_table/table.js
@@ -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 (
-
-
+
-
+
{this.renderChildren()}
-
-
+
+
);
}
});
diff --git a/js/components/ascribe_table/table_header.js b/js/components/ascribe_table/table_header.js
index 44594394..ccf0f31f 100644
--- a/js/components/ascribe_table/table_header.js
+++ b/js/components/ascribe_table/table_header.js
@@ -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 (
-
-
+
+
{this.props.columnList.map((val, i) => {
let columnClasses = this.calcColumnClasses(this.props.columnList, i, 12);
@@ -29,20 +32,18 @@ let TableHeader = React.createClass({
return (
-
+ changeOrder={this.props.changeOrder} />
);
})}
-
-
+
+
);
-
}
});
diff --git a/js/components/ascribe_table/table_header_item.js b/js/components/ascribe_table/table_header_item.js
index 598edada..56b5c16c 100644
--- a/js/components/ascribe_table/table_header_item.js
+++ b/js/components/ascribe_table/table_header_item.js
@@ -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 (
-
{this.props.displayName}
-
+
);
} else {
return (
-
{this.props.displayName}
-
+
);
}
} else {
return (
-
+
{this.props.displayName}
-
+
);
}
}
diff --git a/js/components/ascribe_table/table_header_item_carret.js b/js/components/ascribe_table/table_header_item_carret.js
index 628ead11..d597e8c5 100644
--- a/js/components/ascribe_table/table_header_item_carret.js
+++ b/js/components/ascribe_table/table_header_item_carret.js
@@ -1,3 +1,5 @@
+'use strict';
+
import React from 'react';
let TableHeaderItemCarret = React.createClass({
diff --git a/js/components/ascribe_table/table_item.js b/js/components/ascribe_table/table_item.js
index dffb7fa9..a0e6e852 100644
--- a/js/components/ascribe_table/table_item.js
+++ b/js/components/ascribe_table/table_item.js
@@ -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 (
-
+
);
}
});
diff --git a/js/components/ascribe_table/table_item_acl.js b/js/components/ascribe_table/table_item_acl.js
index 87e14761..1f66fd81 100644
--- a/js/components/ascribe_table/table_item_acl.js
+++ b/js/components/ascribe_table/table_item_acl.js
@@ -1,3 +1,5 @@
+'use strict';
+
import React from 'react';
diff --git a/js/components/ascribe_table/table_item_acl_filtered.js b/js/components/ascribe_table/table_item_acl_filtered.js
index 6fd8e9fe..10a419f0 100644
--- a/js/components/ascribe_table/table_item_acl_filtered.js
+++ b/js/components/ascribe_table/table_item_acl_filtered.js
@@ -1,3 +1,5 @@
+'use strict';
+
import React from 'react';
diff --git a/js/components/ascribe_table/table_item_checkbox.js b/js/components/ascribe_table/table_item_checkbox.js
index 02357fa3..131f7427 100644
--- a/js/components/ascribe_table/table_item_checkbox.js
+++ b/js/components/ascribe_table/table_item_checkbox.js
@@ -1,3 +1,5 @@
+'use strict';
+
import React from 'react';
diff --git a/js/components/ascribe_table/table_item_img.js b/js/components/ascribe_table/table_item_img.js
index c082e85a..d7670524 100644
--- a/js/components/ascribe_table/table_item_img.js
+++ b/js/components/ascribe_table/table_item_img.js
@@ -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() {
diff --git a/js/components/ascribe_table/table_item_selectable.js b/js/components/ascribe_table/table_item_selectable.js
index 711e42b6..cc53c5f0 100644
--- a/js/components/ascribe_table/table_item_selectable.js
+++ b/js/components/ascribe_table/table_item_selectable.js
@@ -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() {
@@ -25,12 +28,11 @@ let TableItemSelectable = React.createClass({
});
return (
-
-
+ onClick={this.selectItem} />
);
}
diff --git a/js/components/ascribe_table/table_item_subtable.js b/js/components/ascribe_table/table_item_subtable.js
index dcd3da0f..56b22fa0 100644
--- a/js/components/ascribe_table/table_item_subtable.js
+++ b/js/components/ascribe_table/table_item_subtable.js
@@ -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,10 +83,9 @@ let TableItemSubtable = React.createClass({
className="ascribe-table-item-selectable"
selectItem={this.selectItem}
parentId={this.props.columnContent.id}
- key={i}>
-
+ key={i} />
);
- })}
+ })}
@@ -94,15 +99,13 @@ let TableItemSubtable = React.createClass({
-
+ columnWidth={12} />
{renderEditionListTable()}
-
+
);
}
});
diff --git a/js/components/ascribe_table/table_item_subtable_button.js b/js/components/ascribe_table/table_item_subtable_button.js
index 8c5431d8..75aeba7f 100644
--- a/js/components/ascribe_table/table_item_subtable_button.js
+++ b/js/components/ascribe_table/table_item_subtable_button.js
@@ -1,3 +1,5 @@
+'use strict';
+
import React from 'react';
let TableItemSubtableButton = React.createClass({
diff --git a/js/components/ascribe_table/table_item_text.js b/js/components/ascribe_table/table_item_text.js
index 0e90a2d5..96dd1f16 100644
--- a/js/components/ascribe_table/table_item_text.js
+++ b/js/components/ascribe_table/table_item_text.js
@@ -1,3 +1,5 @@
+'use strict';
+
import React from 'react';
diff --git a/js/components/ascribe_table/table_item_wrapper.js b/js/components/ascribe_table/table_item_wrapper.js
index a6ffa36b..9e1696f4 100644
--- a/js/components/ascribe_table/table_item_wrapper.js
+++ b/js/components/ascribe_table/table_item_wrapper.js
@@ -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 (
-
+
{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);
-
- return (
-
-
-
- );
+ if(!column.transition) {
+ return (
+
+
+
+ );
+ } 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 (
+
+
+
+
+
+ );
+ }
})}
-
+
);
}
});
diff --git a/js/components/edition.js b/js/components/edition.js
index 6d3d08f8..9bfe8f41 100644
--- a/js/components/edition.js
+++ b/js/components/edition.js
@@ -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,13 +52,17 @@ let Edition = React.createClass({
});
let EditionHeader = React.createClass({
+ propTypes: {
+ edition: React.PropTypes.object
+ },
+
render() {
- var title_html =
{this.props.edition.title}
;
+ var titleHtml =
{this.props.edition.title}
;
return (
-
+
-
+
);
@@ -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 (
+ value={this.props.edition.edition_number + ' of ' + this.props.edition.num_editions} />
diff --git a/js/components/edition_container.js b/js/components/edition_container.js
index 2377ea3e..af2ccfa6 100644
--- a/js/components/edition_container.js
+++ b/js/components/edition_container.js
@@ -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 (
Loading
);
}
-
-
}
});
diff --git a/js/components/fatal_error.js b/js/components/fatal_error.js
deleted file mode 100644
index e69de29b..00000000
diff --git a/js/components/header.js b/js/components/header.js
index b7a412e0..e26553a3 100644
--- a/js/components/header.js
+++ b/js/components/header.js
@@ -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);
},
diff --git a/js/components/piece_list.js b/js/components/piece_list.js
index e6735a27..479b9c3f 100644
--- a/js/components/piece_list.js
+++ b/js/components/piece_list.js
@@ -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,7 +16,10 @@ 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,8 +51,8 @@ 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 (
@@ -64,12 +68,12 @@ let PieceList = React.createClass({
pageSize={this.state.pageSize}>
{this.state.pieceList.map((item, i) => {
return (
-
-
@@ -80,8 +84,7 @@ let PieceList = React.createClass({
-
+ goToPage={this.paginationGoToPage} />
);
}
diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js
index db846a72..7d466561 100644
--- a/js/constants/api_urls.js
+++ b/js/constants/api_urls.js
@@ -1,17 +1,19 @@
+'use strict';
+
import AppConstants from './application_constants';
let apiUrls = {
- 'ownership_shares_mail' : AppConstants.baseUrl + 'ownership/shares/mail/',
- 'ownership_transfers' : AppConstants.baseUrl + 'ownership/transfers/',
+ 'ownership_shares_mail': AppConstants.baseUrl + 'ownership/shares/mail/',
+ 'ownership_transfers': AppConstants.baseUrl + 'ownership/transfers/',
'user': AppConstants.baseUrl + 'users/',
'pieces_list': AppConstants.baseUrl + 'pieces/',
'piece': AppConstants.baseUrl + 'pieces/${piece_id}',
'edition': AppConstants.baseUrl + 'editions/${bitcoin_id}/',
'editions_list': AppConstants.baseUrl + 'pieces/${piece_id}/editions/',
- 'ownership_loans' : AppConstants.baseUrl + 'ownership/loans/',
- 'ownership_consigns' : AppConstants.baseUrl + 'ownership/consigns/',
- 'ownership_unconsigns' : AppConstants.baseUrl + 'ownership/unconsigns/',
- 'ownership_unconsigns_request' : AppConstants.baseUrl + 'ownership/unconsigns/request/'
+ 'ownership_loans': AppConstants.baseUrl + 'ownership/loans/',
+ 'ownership_consigns': AppConstants.baseUrl + 'ownership/consigns/',
+ 'ownership_unconsigns': AppConstants.baseUrl + 'ownership/unconsigns/',
+ 'ownership_unconsigns_request': AppConstants.baseUrl + 'ownership/unconsigns/request/'
};
export default apiUrls;
diff --git a/js/constants/application_constants.js b/js/constants/application_constants.js
index b235d1d4..25486919 100644
--- a/js/constants/application_constants.js
+++ b/js/constants/application_constants.js
@@ -1,3 +1,5 @@
+'use strict';
+
let constants = {
//'baseUrl': 'http://localhost:8000/api/',
'baseUrl': 'http://staging.ascribe.io/api/',
diff --git a/js/constants/languages.js b/js/constants/languages.js
index 47e29ee0..f673083d 100644
--- a/js/constants/languages.js
+++ b/js/constants/languages.js
@@ -1,3 +1,5 @@
+'use strict';
+
const languages = {
'en-US': {
'Bitcoin Address': 'Bitcoin Address',
diff --git a/js/fetchers/edition_fetcher.js b/js/fetchers/edition_fetcher.js
index 46cdf1b7..bb995523 100644
--- a/js/fetchers/edition_fetcher.js
+++ b/js/fetchers/edition_fetcher.js
@@ -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});
diff --git a/js/fetchers/edition_list_fetcher.js b/js/fetchers/edition_list_fetcher.js
index 2cec37a7..21ebee58 100644
--- a/js/fetchers/edition_list_fetcher.js
+++ b/js/fetchers/edition_list_fetcher.js
@@ -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 = {
/**
diff --git a/js/fetchers/ownership_fetcher.js b/js/fetchers/ownership_fetcher.js
index 94050860..57cef4b9 100644
--- a/js/fetchers/ownership_fetcher.js
+++ b/js/fetchers/ownership_fetcher.js
@@ -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, {
diff --git a/js/fetchers/piece_fetcher.js b/js/fetchers/piece_fetcher.js
index cf37c4d3..a5317e5f 100644
--- a/js/fetchers/piece_fetcher.js
+++ b/js/fetchers/piece_fetcher.js
@@ -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');
}
};
diff --git a/js/fetchers/piece_list_fetcher.js b/js/fetchers/piece_list_fetcher.js
index ed867253..2f706e15 100644
--- a/js/fetchers/piece_list_fetcher.js
+++ b/js/fetchers/piece_list_fetcher.js
@@ -1,4 +1,5 @@
-import AppConstants from '../constants/application_constants';
+'use strict';
+
import { generateOrderingQueryParams } from '../utils/fetch_api_utils';
import fetch from '../utils/fetch';
diff --git a/js/fetchers/user_fetcher.js b/js/fetchers/user_fetcher.js
index df3e887e..c57c93d9 100644
--- a/js/fetchers/user_fetcher.js
+++ b/js/fetchers/user_fetcher.js
@@ -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');
diff --git a/js/mixins/alert_mixin.js b/js/mixins/alert_mixin.js
index f52890c7..2b9b5158 100644
--- a/js/mixins/alert_mixin.js
+++ b/js/mixins/alert_mixin.js
@@ -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) {
- return ;
- }.bind(this)
- );
+ let alerts = errors.map((error) => {
+ return ;
+ });
+
this.setState({alerts: alerts});
},
+
clearAlerts(){
this.setState({alerts: null});
}
diff --git a/js/mixins/form_mixin.js b/js/mixins/form_mixin.js
index 4e2c7045..fa398390 100644
--- a/js/mixins/form_mixin.js
+++ b/js/mixins/form_mixin.js
@@ -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) {
- return ;
- }.bind(this)
- );
+ alert = this.state.errors.map((error) => {
+ return ;
+ });
}
return (
{alert}
{this.renderForm()}
- )
+ );
}
};
diff --git a/js/mixins/inject_in_head_mixin.js b/js/mixins/inject_in_head_mixin.js
index 00841726..a336c25f 100644
--- a/js/mixins/inject_in_head_mixin.js
+++ b/js/mixins/inject_in_head_mixin.js
@@ -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);
}
diff --git a/js/mixins/modal_mixin.js b/js/mixins/modal_mixin.js
index 7dee243b..6087f32c 100644
--- a/js/mixins/modal_mixin.js
+++ b/js/mixins/modal_mixin.js
@@ -1,9 +1,10 @@
-import React from 'react';
+'use strict';
let ModalMixin = {
onRequestHide(e){
- if (e)
+ if (e) {
e.preventDefault();
+ }
this.props.onRequestHide();
}
};
diff --git a/js/mixins/table_column_mixin.js b/js/mixins/table_column_mixin.js
index eac266b6..b8813433 100644
--- a/js/mixins/table_column_mixin.js
+++ b/js/mixins/table_column_mixin.js
@@ -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];
}
diff --git a/js/models/table_column_content_model.js b/js/models/table_column_content_model.js
deleted file mode 100644
index ecaa0748..00000000
--- a/js/models/table_column_content_model.js
+++ /dev/null
@@ -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;
\ No newline at end of file
diff --git a/js/routes.js b/js/routes.js
index ab515462..eeadc564 100644
--- a/js/routes.js
+++ b/js/routes.js
@@ -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 = (
-
-
-
-
-
+
+
);
diff --git a/js/stores/edition_list_store.js b/js/stores/edition_list_store.js
index 4c93fd5c..67993ff9 100644
--- a/js/stores/edition_list_store.js
+++ b/js/stores/edition_list_store.js
@@ -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);
\ No newline at end of file
diff --git a/js/stores/edition_store.js b/js/stores/edition_store.js
index b33e248f..7579c8d8 100644
--- a/js/stores/edition_store.js
+++ b/js/stores/edition_store.js
@@ -1,3 +1,5 @@
+'use strict';
+
import alt from '../alt';
import EditionActions from '../actions/edition_actions';
diff --git a/js/stores/piece_list_store.js b/js/stores/piece_list_store.js
index 3b3fd94e..d61d6c07 100644
--- a/js/stores/piece_list_store.js
+++ b/js/stores/piece_list_store.js
@@ -1,11 +1,14 @@
+'use strict';
+
import alt from '../alt';
+
import PieceListActions from '../actions/piece_list_actions';
class PieceListStore {
constructor() {
/**
- * The store manages the state that is introduced by fetching
+ * The store manages the state that is introduced by fetching
* the resource with certain parameters.
*
* This means that pieceList for example only contains pageSize-many items.
@@ -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);
}
@@ -36,6 +39,13 @@ class PieceListStore {
}
});
}
+
+ onCloseAllEditionLists() {
+ this.pieceList
+ .forEach((piece) => {
+ piece.show = false;
+ });
+ }
onUpdatePieceList({ page, pageSize, search, pieceList, orderBy, orderAsc, pieceListCount }) {
this.page = page;
@@ -46,21 +56,24 @@ 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
+ * Once a new page is requested, this.pieceList will be overwritten, which means that the
* open/close state of a specific list item will be thrown away.
*
- * This means that when opening an editionListTable on a piece, and continuing
+ * This means that when opening an editionListTable on a piece, and continuing
* clicking next or back in the pagination, the editionListTable will return to its
* default value, which is "close".
*
* 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);
diff --git a/js/stores/piece_store.js b/js/stores/piece_store.js
index 35e8c229..f9693564 100644
--- a/js/stores/piece_store.js
+++ b/js/stores/piece_store.js
@@ -1,3 +1,5 @@
+'use strict';
+
import alt from '../alt';
import PieceAction from '../actions/piece_actions';
diff --git a/js/stores/user_store.js b/js/stores/user_store.js
index 6ae631c9..e1b4dd29 100644
--- a/js/stores/user_store.js
+++ b/js/stores/user_store.js
@@ -1,3 +1,5 @@
+'use strict';
+
import alt from '../alt';
import UserAction from '../actions/user_actions';
diff --git a/js/utils/fetch.js b/js/utils/fetch.js
index f7e12f43..ec674935 100644
--- a/js/utils/fetch.js
+++ b/js/utils/fetch.js
@@ -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 });
}
diff --git a/js/utils/fetch_api_utils.js b/js/utils/fetch_api_utils.js
index bf66a45c..272e29f3 100644
--- a/js/utils/fetch_api_utils.js
+++ b/js/utils/fetch_api_utils.js
@@ -1,3 +1,5 @@
+'use strict';
+
import { sanitize } from './general_utils';
// TODO: Create Unittests that test all functions
@@ -16,7 +18,7 @@ import { sanitize } from './general_utils';
* ?page=1&page_size=10
*
* CamelCase gets converted to snake_case!
- *
+ *
*/
export function argsToQueryParams(obj) {
@@ -38,10 +40,10 @@ export function argsToQueryParams(obj) {
return s + snakeCaseKey + '=' + encodeURIComponent(obj[key]);
})
.join('');
-};
+}
/**
- * Takes a string and a boolean and generates a string query parameter for
+ * Takes a string and a boolean and generates a string query parameter for
* an API call.
*/
export function generateOrderingQueryParams(orderBy, orderAsc) {
@@ -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());
+}
diff --git a/js/utils/general_utils.js b/js/utils/general_utils.js
index 96f56c1e..4caf3d15 100644
--- a/js/utils/general_utils.js
+++ b/js/utils/general_utils.js
@@ -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;
+}
diff --git a/js/utils/lang_utils.js b/js/utils/lang_utils.js
index d1ea5fd5..bf842efa 100644
--- a/js/utils/lang_utils.js
+++ b/js/utils/lang_utils.js
@@ -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) {
}
}
-};
+}
diff --git a/package.json b/package.json
index d822c614..2e9d596b 100644
--- a/package.json
+++ b/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",
diff --git a/sass/ascribe_accordion_list.scss b/sass/ascribe_accordion_list.scss
index 43b77fa9..21236488 100644
--- a/sass/ascribe_accordion_list.scss
+++ b/sass/ascribe_accordion_list.scss
@@ -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,29 +21,20 @@ $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 {
- font-size: 2.25em;
- }
- h3 {
- font-size: 1.1em;
- margin: .7em 0 0 0;
- }
+ h1 {
+ margin-top: .3em;
+ font-size: 2.25em;
+ }
+ h3 {
+ font-size: 1.1em;
+ margin: .7em 0 0 0;
}
}
}
diff --git a/sass/ascribe_piece_list_bulk_modal.scss b/sass/ascribe_piece_list_bulk_modal.scss
index 4a6b98d7..d2c72113 100644
--- a/sass/ascribe_piece_list_bulk_modal.scss
+++ b/sass/ascribe_piece_list_bulk_modal.scss
@@ -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 {
diff --git a/sass/main.scss b/sass/main.scss
index b5b0d7d7..cc9e3203 100644
--- a/sass/main.scss
+++ b/sass/main.scss
@@ -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 {