diff --git a/docs/refactor-todo.md b/docs/refactor-todo.md
index 8554f001..f7a5917b 100644
--- a/docs/refactor-todo.md
+++ b/docs/refactor-todo.md
@@ -2,16 +2,18 @@
*This should be a living document. So if you have any ideas for refactoring stuff, then feel free to add them to this document*
-- Get rid of all Mixins. (making good progress there :))
- Make all standalone components independent from things like global utilities (GeneralUtils is maybe used in table for example)
-- Check if all polyfills are appropriately initialized and available: Compare to this
- Extract all standalone components to their own folder structure and write application independent tests (+ figure out how to do that in a productive way) (fetch lib especially)
-- Refactor forms to generic-declarative form component
- Check for mobile compatibility: Is site responsive anywhere?
queryParams of the piece_list_store should all be reflected in the url and not a single component each should manipulate the URL bar (refactor pagination, use actions and state)
- Refactor string-templating for api_urls
- Use classNames plugin instead of if-conditional-classes
+# Refactor DONE
+- Refactor forms to generic-declarative form component ✓
+- Get rid of all Mixins (inject head is fine) ✓
+- Check if all polyfills are appropriately initialized and available: Compare to this ✓
+
## React-S3-Fineuploader
- implementation should enable to define all important methods outside
- and: maybe create a utility class for all methods to avoid code duplication
diff --git a/js/components/ascribe_buttons/acl_button.js b/js/components/ascribe_buttons/acl_button.js
index d9423889..2f5bb7b0 100644
--- a/js/components/ascribe_buttons/acl_button.js
+++ b/js/components/ascribe_buttons/acl_button.js
@@ -13,8 +13,10 @@ import AppConstants from '../../constants/application_constants';
import GlobalNotificationModel from '../../models/global_notification_model';
import GlobalNotificationActions from '../../actions/global_notification_actions';
-import { getLangText } from '../../utils/lang_utils.js';
-import apiUrls from '../../constants/api_urls';
+import ApiUrls from '../../constants/api_urls';
+
+import { getAclFormMessage } from '../../utils/form_utils';
+import { getLangText } from '../../utils/lang_utils';
let AclButton = React.createClass({
propTypes: {
@@ -34,15 +36,18 @@ let AclButton = React.createClass({
},
actionProperties(){
+
+ let message = getAclFormMessage(this.props.action, this.getTitlesString(), this.props.currentUser.username);
+
if (this.props.action === 'acl_consign'){
return {
title: getLangText('Consign artwork'),
tooltip: getLangText('Have someone else sell the artwork'),
form: (
+ url={ApiUrls.ownership_consigns}/>
),
handleSuccess: this.showNotification
};
@@ -53,9 +58,9 @@ let AclButton = React.createClass({
tooltip: getLangText('Have the owner manage his sales again'),
form: (
+ url={ApiUrls.ownership_unconsigns}/>
),
handleSuccess: this.showNotification
};
@@ -65,9 +70,9 @@ let AclButton = React.createClass({
tooltip: getLangText('Transfer the ownership of the artwork'),
form: (
+ url={ApiUrls.ownership_transfers}/>
),
handleSuccess: this.showNotification
};
@@ -77,9 +82,9 @@ let AclButton = React.createClass({
title: getLangText('Loan artwork'),
tooltip: getLangText('Loan your artwork for a limited period of time'),
form: (
+ url={this.isPiece() ? ApiUrls.ownership_loans_pieces : ApiUrls.ownership_loans_editions}/>
),
handleSuccess: this.showNotification
};
@@ -90,9 +95,9 @@ let AclButton = React.createClass({
tooltip: getLangText('Share the artwork'),
form: (
+ url={this.isPiece() ? ApiUrls.ownership_shares_pieces : ApiUrls.ownership_shares_editions }/>
),
handleSuccess: this.showNotification
};
@@ -133,76 +138,6 @@ let AclButton = React.createClass({
}
},
-// plz move to transfer form
- getTransferMessage(){
- return (
- `${getLangText('Hi')},
-
-${getLangText('I transfer ownership of')}:
-${this.getTitlesString()} ${getLangText('to you')}.
-
-${getLangText('Truly yours')},
-${this.props.currentUser.username}
- `
- );
- },
-
- // plz move to transfer form
- getLoanMessage(){
- return (
- `${getLangText('Hi')},
-
-${getLangText('I loan')}:
-${this.getTitlesString()} ${getLangText('to you')}.
-
-${getLangText('Truly yours')},
-${this.props.currentUser.username}
- `
- );
- },
-
- // plz move to consign form
- getConsignMessage(){
- return (
- `${getLangText('Hi')},
-
-${getLangText('I consign')}:
-${this.getTitlesString()} ${getLangText('to you')}.
-
-${getLangText('Truly yours')},
-${this.props.currentUser.username}
- `
- );
- },
-
- // plz move to consign form
- getUnConsignMessage(){
- return (
- `${getLangText('Hi')},
-
-${getLangText('I un-consign')}:
-${this.getTitlesString()} ${getLangText('from you')}.
-
-${getLangText('Truly yours')},
-${this.props.currentUser.username}
- `
- );
- },
-
-// plz move to share form
- getShareMessage(){
- return (
- `${getLangText('Hi')},
-
-${getLangText('I am sharing')}:
-${this.getTitlesString()} ${getLangText('with you')}.
-
-${getLangText('Truly yours')},
-${this.props.currentUser.username}
- `
- );
- },
-
// Removes the acl_ prefix and converts to upper case
sanitizeAction() {
return this.props.action.split('acl_')[1].toUpperCase();
@@ -214,14 +149,13 @@ ${this.props.currentUser.username}
return (
{this.sanitizeAction()}
}
handleSuccess={aclProps.handleSuccess}
- title={aclProps.title}
- tooltip={aclProps.tooltip}>
+ title={aclProps.title}>
{aclProps.form}
);
diff --git a/js/components/ascribe_buttons/delete_button.js b/js/components/ascribe_buttons/delete_button.js
index a60344df..b0b64427 100644
--- a/js/components/ascribe_buttons/delete_button.js
+++ b/js/components/ascribe_buttons/delete_button.js
@@ -26,7 +26,7 @@ let DeleteButton = React.createClass({
mixins: [Router.Navigation],
- render: function () {
+ render() {
let availableAcls;
let btnDelete;
let content;
@@ -61,13 +61,14 @@ let DeleteButton = React.createClass({
}
btnDelete = {getLangText('REMOVE FROM COLLECTION')} ;
- }
- else {
+
+ } else {
return null;
}
+
return (
{content}
@@ -77,4 +78,3 @@ let DeleteButton = React.createClass({
});
export default DeleteButton;
-
diff --git a/js/components/ascribe_buttons/unconsign_request_button.js b/js/components/ascribe_buttons/unconsign_request_button.js
index 11cbfa51..e5e1c661 100644
--- a/js/components/ascribe_buttons/unconsign_request_button.js
+++ b/js/components/ascribe_buttons/unconsign_request_button.js
@@ -8,7 +8,7 @@ import ModalWrapper from '../ascribe_modal/modal_wrapper';
import UnConsignRequestForm from './../ascribe_forms/form_unconsign_request';
import { getLangText } from '../../utils/lang_utils.js';
-import apiUrls from '../../constants/api_urls';
+import ApiUrls from '../../constants/api_urls';
let UnConsignRequestButton = React.createClass({
@@ -21,16 +21,15 @@ let UnConsignRequestButton = React.createClass({
render: function () {
return (
REQUEST UNCONSIGN
}
handleSuccess={this.props.handleSuccess}
- title='Request to Un-Consign'
- tooltip='Ask the consignee to return the ownership of the work back to you'>
+ title='Request to Un-Consign'>
{text} {this.props.title}
-
+
{this.props.children}
-
+
);
diff --git a/js/components/ascribe_detail/edition.js b/js/components/ascribe_detail/edition.js
index 3aabc9e2..0f1477c0 100644
--- a/js/components/ascribe_detail/edition.js
+++ b/js/components/ascribe_detail/edition.js
@@ -36,7 +36,7 @@ import DeleteButton from '../ascribe_buttons/delete_button';
import GlobalNotificationModel from '../../models/global_notification_model';
import GlobalNotificationActions from '../../actions/global_notification_actions';
-import apiUrls from '../../constants/api_urls';
+import ApiUrls from '../../constants/api_urls';
import AppConstants from '../../constants/application_constants';
import { getLangText } from '../../utils/lang_utils';
@@ -233,10 +233,11 @@ let EditionSummary = React.createClass({
if (this.props.edition.status.length > 0 && this.props.edition.pending_new_owner && this.props.edition.acl.acl_withdraw_transfer) {
withdrawButton = (
}
spinner={
diff --git a/js/components/ascribe_forms/form_delete_edition.js b/js/components/ascribe_forms/form_delete_edition.js
index c05a20bc..9eb721f6 100644
--- a/js/components/ascribe_forms/form_delete_edition.js
+++ b/js/components/ascribe_forms/form_delete_edition.js
@@ -2,33 +2,65 @@
import React from 'react';
-import requests from '../../utils/requests';
+import Form from './form';
+
import ApiUrls from '../../constants/api_urls';
-import FormMixin from '../../mixins/form_mixin';
+import AppConstants from '../../constants/application_constants';
+
import { getLangText } from '../../utils/lang_utils';
+
let EditionDeleteForm = React.createClass({
- mixins: [FormMixin],
+ propTypes: {
+ editions: React.PropTypes.arrayOf(React.PropTypes.object),
- url() {
- return requests.prepareUrl(ApiUrls.edition_delete, {edition_id: this.getBitcoinIds().join()});
- },
- httpVerb(){
- return 'delete';
+ // Propagated by ModalWrapper in most cases
+ handleSuccess: React.PropTypes.func
},
- renderForm () {
+ getBitcoinIds() {
+ return this.props.editions.map(function(edition){
+ return edition.bitcoin_id;
+ });
+ },
+
+ // Since this form can be used for either deleting a single edition or multiple
+ // we need to call getBitcoinIds to get the value of edition_id
+ getFormData() {
+ return {
+ edition_id: this.getBitcoinIds().join(',')
+ };
+ },
+
+ render () {
return (
-
+
+
+
+ {getLangText('YES, DELETE')}
+
+
+
+ }
+ spinner={
+
+
+
+ }>
{getLangText('Are you sure you would like to permanently delete this edition')}?
{getLangText('This is an irrevocable action%s', '.')}
-
- {getLangText('YES, DELETE')}
- {getLangText('CLOSE')}
-
-
+
);
}
});
diff --git a/js/components/ascribe_forms/form_delete_piece.js b/js/components/ascribe_forms/form_delete_piece.js
index 168d9261..552c38c0 100644
--- a/js/components/ascribe_forms/form_delete_piece.js
+++ b/js/components/ascribe_forms/form_delete_piece.js
@@ -2,37 +2,56 @@
import React from 'react';
-import requests from '../../utils/requests';
+import Form from '../ascribe_forms/form';
+
import ApiUrls from '../../constants/api_urls';
-import FormMixin from '../../mixins/form_mixin';
+import AppConstants from '../../constants/application_constants';
+
import { getLangText } from '../../utils/lang_utils';
+
let PieceDeleteForm = React.createClass({
propTypes: {
- pieceId: React.PropTypes.number
+ pieceId: React.PropTypes.number,
+
+ // Propagated by ModalWrapper in most cases
+ handleSuccess: React.PropTypes.func
},
- mixins: [FormMixin],
-
- url() {
- return requests.prepareUrl(ApiUrls.piece, {piece_id: this.props.pieceId});
+ getFormData() {
+ return {
+ piece_id: this.props.pieceId
+ };
},
- httpVerb() {
- return 'delete';
- },
-
- renderForm () {
+ render() {
return (
-
+
+
+
+ {getLangText('YES, DELETE')}
+
+
+
+ }
+ spinner={
+
+
+
+ }>
{getLangText('Are you sure you would like to permanently delete this piece')}?
{getLangText('This is an irrevocable action%s', '.')}
-
- {getLangText('YES, DELETE')}
- {getLangText('CLOSE')}
-
-
+
);
}
});
diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js
index 7aae656a..f319c363 100644
--- a/js/components/ascribe_forms/form_loan.js
+++ b/js/components/ascribe_forms/form_loan.js
@@ -23,7 +23,6 @@ let LoanForm = React.createClass({
url: React.PropTypes.string,
id: React.PropTypes.object,
message: React.PropTypes.string,
- onRequestHide: React.PropTypes.func,
handleSuccess: React.PropTypes.func
},
@@ -101,11 +100,9 @@ let LoanForm = React.createClass({
{getLangText('LOAN')}
- {getLangText('CLOSE')}
+ type="submit">
+ {getLangText('LOAN')}
+
}
spinner={
diff --git a/js/components/ascribe_forms/form_login.js b/js/components/ascribe_forms/form_login.js
index 24b0eb93..a3fd4d33 100644
--- a/js/components/ascribe_forms/form_login.js
+++ b/js/components/ascribe_forms/form_login.js
@@ -11,16 +11,14 @@ import UserActions from '../../actions/user_actions';
import Form from './form';
import Property from './property';
-import FormPropertyHeader from './form_property_header';
-import apiUrls from '../../constants/api_urls';
+import ApiUrls from '../../constants/api_urls';
import AppConstants from '../../constants/application_constants';
import { getLangText } from '../../utils/lang_utils';
let LoginForm = React.createClass({
-
propTypes: {
headerMessage: React.PropTypes.string,
submitMessage: React.PropTypes.string,
@@ -101,7 +99,7 @@ let LoginForm = React.createClass({
}>
-
+
{this.props.headerMessage}
-
+
diff --git a/js/components/ascribe_forms/form_piece_extradata.js b/js/components/ascribe_forms/form_piece_extradata.js
index bbec9dca..293ca09e 100644
--- a/js/components/ascribe_forms/form_piece_extradata.js
+++ b/js/components/ascribe_forms/form_piece_extradata.js
@@ -3,9 +3,9 @@
import React from 'react';
import requests from '../../utils/requests';
-import { getLangText } from '../../utils/lang_utils.js'
+import { getLangText } from '../../utils/lang_utils.js';
-import apiUrls from '../../constants/api_urls';
+import ApiUrls from '../../constants/api_urls';
import Form from './form';
import Property from './property';
@@ -20,7 +20,8 @@ let PieceExtraDataForm = React.createClass({
title: React.PropTypes.string,
editable: React.PropTypes.bool
},
- getFormData(){
+
+ getFormData() {
let extradata = {};
extradata[this.props.name] = this.refs.form.refs[this.props.name].state.value;
return {
@@ -28,12 +29,13 @@ let PieceExtraDataForm = React.createClass({
piece_id: this.props.pieceId
};
},
+
render() {
let defaultValue = this.props.extraData[this.props.name] || '';
if (defaultValue.length === 0 && !this.props.editable){
return null;
}
- let url = requests.prepareUrl(apiUrls.piece_extradata, {piece_id: this.props.pieceId});
+ let url = requests.prepareUrl(ApiUrls.piece_extradata, {piece_id: this.props.pieceId});
return (
- {this.props.children}
-
- );
- }
-});
-
-export default FormPropertyHeader;
\ No newline at end of file
diff --git a/js/components/ascribe_forms/form_register_piece.js b/js/components/ascribe_forms/form_register_piece.js
index 853506f6..156642aa 100644
--- a/js/components/ascribe_forms/form_register_piece.js
+++ b/js/components/ascribe_forms/form_register_piece.js
@@ -7,12 +7,11 @@ import UserActions from '../../actions/user_actions';
import Form from './form';
import Property from './property';
-import FormPropertyHeader from './form_property_header';
import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader';
import AppConstants from '../../constants/application_constants';
-import apiUrls from '../../constants/api_urls';
+import ApiUrls from '../../constants/api_urls';
import { getCookie } from '../../utils/fetch_api_utils';
import { getLangText } from '../../utils/lang_utils';
@@ -96,7 +95,7 @@ let RegisterPieceForm = React.createClass({
}>
-
+
{this.props.headerMessage}
-
+
+
+
+
+ {getLangText('YES, REMOVE')}
+
+
+
+ }
+ spinner={
+
+
+
+ }>
{getLangText('Are you sure you would like to remove these editions from your collection')}?
{getLangText('This is an irrevocable action%s', '.')}
-
- {getLangText('YES, REMOVE')}
- {getLangText('CLOSE')}
-
-
+
);
}
});
diff --git a/js/components/ascribe_forms/form_remove_piece_from_collection.js b/js/components/ascribe_forms/form_remove_piece_from_collection.js
index 905cfcf6..d827c2ee 100644
--- a/js/components/ascribe_forms/form_remove_piece_from_collection.js
+++ b/js/components/ascribe_forms/form_remove_piece_from_collection.js
@@ -2,38 +2,56 @@
import React from 'react';
-import { getLangText } from '../../utils/lang_utils.js';
-import requests from '../../utils/requests';
-import apiUrls from '../../constants/api_urls';
-import FormMixin from '../../mixins/form_mixin';
+import Form from './form';
+
+import ApiUrls from '../../constants/api_urls';
+import AppConstants from '../../constants/application_constants';
+
+import { getLangText } from '../../utils/lang_utils';
+
let PieceRemoveFromCollectionForm = React.createClass({
-
propTypes: {
- pieceId: React.PropTypes.number
+ pieceId: React.PropTypes.number,
+
+ // Propagated by ModalWrapper in most cases
+ handleSuccess: React.PropTypes.func
},
- mixins: [FormMixin],
-
- url() {
- return requests.prepareUrl(apiUrls.piece_remove_from_collection, {piece_id: this.props.pieceId});
- },
-
- httpVerb(){
- return 'delete';
+ getFormData() {
+ return {
+ piece_id: this.props.pieceId
+ };
},
- renderForm () {
+ render () {
return (
-
+
+
+
+ {getLangText('YES, REMOVE')}
+
+
+
+ }
+ spinner={
+
+
+
+ }>
{getLangText('Are you sure you would like to remove this piece from your collection')}?
{getLangText('This is an irrevocable action%s', '.')}
-
- {getLangText('YES, REMOVE')}
- {getLangText('CLOSE')}
-
-
+
);
}
});
diff --git a/js/components/ascribe_forms/form_request_action.js b/js/components/ascribe_forms/form_request_action.js
index 622aa02f..cc4ad88a 100644
--- a/js/components/ascribe_forms/form_request_action.js
+++ b/js/components/ascribe_forms/form_request_action.js
@@ -2,48 +2,48 @@
import React from 'react';
-import Alert from 'react-bootstrap/lib/Alert';
-
-import apiUrls from '../../constants/api_urls';
-import FormMixin from '../../mixins/form_mixin';
-
import AclButton from './../ascribe_buttons/acl_button';
+import ActionPanel from '../ascribe_panel/action_panel';
+import Form from './form';
+
+import GlobalNotificationModel from '../../models/global_notification_model';
+import GlobalNotificationActions from '../../actions/global_notification_actions';
+
+import ApiUrls from '../../constants/api_urls';
-import AppConstants from '../../constants/application_constants';
import { getLangText } from '../../utils/lang_utils.js';
-let RequestActionForm = React.createClass({
- mixins: [FormMixin],
- url(e){
- let edition = this.props.editions[0];
- if (e.target.id === 'request_accept'){
- if (edition.request_action === 'consign'){
- return apiUrls.ownership_consigns_confirm;
- }
- else if (edition.request_action === 'unconsign'){
- return apiUrls.ownership_unconsigns;
- }
- else if (edition.request_action === 'loan'){
- return apiUrls.ownership_loans_confirm;
- }
- }
- else if(e.target.id === 'request_deny'){
- if (edition.request_action === 'consign') {
- return apiUrls.ownership_consigns_deny;
- }
- else if (edition.request_action === 'unconsign') {
- return apiUrls.ownership_unconsigns_deny;
- }
- else if (edition.request_action === 'loan') {
- return apiUrls.ownership_loans_deny;
- }
- }
+let RequestActionForm = React.createClass({
+ propTypes: {
+ editions: React.PropTypes.arrayOf(React.PropTypes.object),
+ currentUser: React.PropTypes.object,
+ handleSuccess: React.PropTypes.func
},
- handleRequest: function(e){
- e.preventDefault();
- this.submit(e);
+ getUrls() {
+ let edition = this.props.editions[0];
+ let urls = {};
+
+
+ if (edition.request_action === 'consign'){
+ urls.accept = ApiUrls.ownership_consigns_confirm;
+ urls.deny = ApiUrls.ownership_consigns_deny;
+ } else if (edition.request_action === 'unconsign'){
+ urls.accept = ApiUrls.ownership_unconsigns;
+ urls.deny = ApiUrls.ownership_unconsigns_deny;
+ } else if (edition.request_action === 'loan'){
+ urls.accept = ApiUrls.ownership_loans_confirm;
+ urls.deny = ApiUrls.ownership_loans_deny;
+ }
+
+ return urls;
+ },
+
+ getBitcoinIds(){
+ return this.props.editions.map(function(edition){
+ return edition.bitcoin_id;
+ });
},
getFormData() {
@@ -52,16 +52,35 @@ let RequestActionForm = React.createClass({
};
},
- renderForm() {
+ showNotification(option, action, owner) {
+ return () => {
+ let message = getLangText('You have successfully') + ' ' + option + ' the ' + action + ' request ' + getLangText('from') + ' ' + owner;
+
+ let notification = new GlobalNotificationModel(message, 'success');
+ GlobalNotificationActions.appendGlobalNotification(notification);
+
+ if(this.props.handleSuccess) {
+ this.props.handleSuccess();
+ }
+ };
+ },
+
+ getContent() {
let edition = this.props.editions[0];
- let buttonAccept = (
- {getLangText('ACCEPT')}
-
);
- if (edition.request_action === 'unconsign'){
- console.log(this.props)
- buttonAccept = (
+ let message = edition.owner + ' ' + getLangText('requests you') + ' ' + edition.request_action + ' ' + getLangText('this edition%s', '.');
+
+ return (
+
+ {message}
+
+ );
+ },
+
+ getAcceptButtonForm(urls) {
+ let edition = this.props.editions[0];
+
+ if(edition.request_action === 'unconsign') {
+ return (
);
- }
- let buttons = (
-
-
- {buttonAccept}
-
-
- {getLangText('REJECT')}
-
-
- );
- if (this.state.submitted){
- buttons = (
-
-
-
+ } else {
+ return (
+
+
+ {getLangText('ACCEPT')}
+
+
);
}
+ },
+
+ getButtonForm() {
+ let edition = this.props.editions[0];
+
+ let urls = this.getUrls();
+ let acceptButtonForm = this.getAcceptButtonForm(urls);
+
return (
-
-
-
{ edition.owner } {getLangText('requests you')} { edition.request_action } {getLangText('this edition%s', '.')}
- {buttons}
-
-
+
+
+
+ {getLangText('REJECT')}
+
+
+ {acceptButtonForm}
+
+ );
+ },
+
+ render() {
+ return (
+
);
}
});
diff --git a/js/components/ascribe_forms/form_share_email.js b/js/components/ascribe_forms/form_share_email.js
index 881c9683..89884886 100644
--- a/js/components/ascribe_forms/form_share_email.js
+++ b/js/components/ascribe_forms/form_share_email.js
@@ -2,14 +2,14 @@
import React from 'react';
-
-
import Form from './form';
import Property from './property';
import InputTextAreaToggable from './input_textarea_toggable';
+
import Button from 'react-bootstrap/lib/Button';
import AppConstants from '../../constants/application_constants';
+
import { getLangText } from '../../utils/lang_utils.js';
@@ -20,7 +20,6 @@ let ShareForm = React.createClass({
message: React.PropTypes.string,
editions: React.PropTypes.array,
currentUser: React.PropTypes.object,
- onRequestHide: React.PropTypes.func,
handleSuccess: React.PropTypes.func
},
@@ -41,11 +40,9 @@ let ShareForm = React.createClass({
SHARE
- CLOSE
+ type="submit">
+ SHARE
+
}
spinner={
diff --git a/js/components/ascribe_forms/form_signup.js b/js/components/ascribe_forms/form_signup.js
index 55aff4b8..67097b42 100644
--- a/js/components/ascribe_forms/form_signup.js
+++ b/js/components/ascribe_forms/form_signup.js
@@ -12,10 +12,9 @@ import GlobalNotificationActions from '../../actions/global_notification_actions
import Form from './form';
import Property from './property';
-import FormPropertyHeader from './form_property_header';
import InputCheckbox from './input_checkbox';
-import apiUrls from '../../constants/api_urls';
+import ApiUrls from '../../constants/api_urls';
let SignupForm = React.createClass({
@@ -56,10 +55,6 @@ let SignupForm = React.createClass({
}
},
- getFormData() {
- return this.getQuery();
- },
-
handleSuccess(response){
if (response.user) {
let notification = new GlobalNotificationModel(getLangText('Sign up successful'), 'success', 50000);
@@ -80,8 +75,8 @@ let SignupForm = React.createClass({
@@ -92,9 +87,9 @@ let SignupForm = React.createClass({
}>
-
+
{this.props.headerMessage}
-
+
diff --git a/js/components/ascribe_forms/form_submit_to_prize.js b/js/components/ascribe_forms/form_submit_to_prize.js
index 7f991af3..ff853c01 100644
--- a/js/components/ascribe_forms/form_submit_to_prize.js
+++ b/js/components/ascribe_forms/form_submit_to_prize.js
@@ -19,10 +19,7 @@ import requests from '../../utils/requests';
let PieceSubmitToPrizeForm = React.createClass({
propTypes: {
piece: React.PropTypes.object,
- handleSuccess: React.PropTypes.func,
-
- // this is set by ModalWrapper automatically
- onRequestHide: React.PropTypes.func
+ handleSuccess: React.PropTypes.func
},
render() {
@@ -36,7 +33,9 @@ let PieceSubmitToPrizeForm = React.createClass({
{getLangText('SUBMIT TO PRIZE')}
+ type="submit">
+ {getLangText('SUBMIT TO PRIZE')}
+
}
spinner={
@@ -80,7 +79,6 @@ let PieceSubmitToPrizeForm = React.createClass({
{getLangText('Are you sure you want to submit to the prize?')}
{getLangText('This is an irrevocable action%s', '.')}
-
);
}
diff --git a/js/components/ascribe_forms/form_transfer.js b/js/components/ascribe_forms/form_transfer.js
index 07821475..6ec73d38 100644
--- a/js/components/ascribe_forms/form_transfer.js
+++ b/js/components/ascribe_forms/form_transfer.js
@@ -21,7 +21,6 @@ let TransferForm = React.createClass({
message: React.PropTypes.string,
editions: React.PropTypes.array,
currentUser: React.PropTypes.object,
- onRequestHide: React.PropTypes.func,
handleSuccess: React.PropTypes.func
},
@@ -42,11 +41,9 @@ let TransferForm = React.createClass({
{getLangText('TRANSFER')}
- {getLangText('CLOSE')}
+ type="submit">
+ {getLangText('TRANSFER')}
+
}
spinner={
diff --git a/js/components/ascribe_forms/form_unconsign.js b/js/components/ascribe_forms/form_unconsign.js
index d33ccedf..9bc5b4bd 100644
--- a/js/components/ascribe_forms/form_unconsign.js
+++ b/js/components/ascribe_forms/form_unconsign.js
@@ -18,7 +18,6 @@ let UnConsignForm = React.createClass({
id: React.PropTypes.object,
message: React.PropTypes.string,
editions: React.PropTypes.array,
- onRequestHide: React.PropTypes.func,
handleSuccess: React.PropTypes.func
},
@@ -39,11 +38,9 @@ let UnConsignForm = React.createClass({
{getLangText('UNCONSIGN')}
- {getLangText('CLOSE')}
+ type="submit">
+ {getLangText('UNCONSIGN')}
+
}
spinner={
diff --git a/js/components/ascribe_forms/form_unconsign_request.js b/js/components/ascribe_forms/form_unconsign_request.js
index 1978e151..c47b5411 100644
--- a/js/components/ascribe_forms/form_unconsign_request.js
+++ b/js/components/ascribe_forms/form_unconsign_request.js
@@ -3,7 +3,6 @@
import React from 'react';
import Button from 'react-bootstrap/lib/Button';
-import Alert from 'react-bootstrap/lib/Alert';
import Form from './form';
import Property from './property';
@@ -19,7 +18,6 @@ let UnConsignRequestForm = React.createClass({
url: React.PropTypes.string,
id: React.PropTypes.object,
message: React.PropTypes.string,
- onRequestHide: React.PropTypes.func,
handleSuccess: React.PropTypes.func
},
@@ -40,11 +38,9 @@ let UnConsignRequestForm = React.createClass({
{getLangText('REQUEST UNCONSIGN')}
- {getLangText('CLOSE')}
+ type="submit">
+ {getLangText('REQUEST UNCONSIGN')}
+
}
spinner={
diff --git a/js/components/ascribe_forms/input_date.js b/js/components/ascribe_forms/input_date.js
index 32ffb5eb..e77f70b7 100644
--- a/js/components/ascribe_forms/input_date.js
+++ b/js/components/ascribe_forms/input_date.js
@@ -7,7 +7,8 @@ import DatePicker from 'react-datepicker/dist/react-datepicker';
let InputDate = React.createClass({
propTypes: {
submitted: React.PropTypes.bool,
- placeholderText: React.PropTypes.string
+ placeholderText: React.PropTypes.string,
+ onChange: React.PropTypes.func
},
getInitialState() {
diff --git a/js/components/ascribe_forms/input_textarea_toggable.js b/js/components/ascribe_forms/input_textarea_toggable.js
index fe372bdd..bc70c530 100644
--- a/js/components/ascribe_forms/input_textarea_toggable.js
+++ b/js/components/ascribe_forms/input_textarea_toggable.js
@@ -5,7 +5,6 @@ import React from 'react';
import TextareaAutosize from 'react-textarea-autosize';
let InputTextAreaToggable = React.createClass({
-
propTypes: {
editable: React.PropTypes.bool.isRequired,
rows: React.PropTypes.number.isRequired,
diff --git a/js/components/ascribe_forms/property_collapsible.js b/js/components/ascribe_forms/property_collapsible.js
index ba6c0a1e..03ec404d 100644
--- a/js/components/ascribe_forms/property_collapsible.js
+++ b/js/components/ascribe_forms/property_collapsible.js
@@ -3,11 +3,9 @@
import React from 'react';
import ReactAddons from 'react/addons';
-import CollapsibleMixin from 'react-bootstrap/lib/CollapsibleMixin';
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
import Tooltip from 'react-bootstrap/lib/Tooltip';
-
-import classNames from 'classnames';
+import Panel from 'react-bootstrap/lib/Panel';
let PropertyCollapsile = React.createClass({
@@ -17,22 +15,12 @@ let PropertyCollapsile = React.createClass({
tooltip: React.PropTypes.string
},
- mixins: [CollapsibleMixin],
-
getInitialState() {
return {
show: false
};
},
- getCollapsibleDOMNode(){
- return React.findDOMNode(this.refs.panel);
- },
-
- getCollapsibleDimensionValue(){
- return React.findDOMNode(this.refs.panel).scrollHeight;
- },
-
handleFocus() {
this.refs.checkboxCollapsible.getDOMNode().checked = !this.refs.checkboxCollapsible.getDOMNode().checked;
this.setState({
@@ -85,11 +73,14 @@ let PropertyCollapsile = React.createClass({
{this.props.checkboxLabel}
-
+
+
{this.renderChildren()}
-
+
+
);
}
diff --git a/js/components/ascribe_modal/modal_password_request_reset.js b/js/components/ascribe_modal/modal_password_request_reset.js
index fffcb3d7..d941bcce 100644
--- a/js/components/ascribe_modal/modal_password_request_reset.js
+++ b/js/components/ascribe_modal/modal_password_request_reset.js
@@ -7,9 +7,13 @@ import PasswordResetRequestForm from '../ascribe_forms/form_password_reset_reque
import GlobalNotificationModel from '../../models/global_notification_model';
import GlobalNotificationActions from '../../actions/global_notification_actions';
-import { getLangText } from '../../utils/lang_utils.js'
+import { getLangText } from '../../utils/lang_utils.js';
let PasswordResetRequestModal = React.createClass({
+ propTypes: {
+ button: React.PropTypes.element
+ },
+
handleResetSuccess(){
let notificationText = getLangText('Request successfully sent, check your email');
let notification = new GlobalNotificationModel(notificationText, 'success', 50000);
@@ -18,10 +22,9 @@ let PasswordResetRequestModal = React.createClass({
render() {
return (
+ handleSuccess={this.handleResetSuccess}>
);
diff --git a/js/components/ascribe_modal/modal_wrapper.js b/js/components/ascribe_modal/modal_wrapper.js
index a8f7b182..f00eee9e 100644
--- a/js/components/ascribe_modal/modal_wrapper.js
+++ b/js/components/ascribe_modal/modal_wrapper.js
@@ -4,92 +4,74 @@ import React from 'react';
import ReactAddons from 'react/addons';
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';
let ModalWrapper = React.createClass({
propTypes: {
- title: React.PropTypes.string.isRequired,
- onRequestHide: React.PropTypes.func,
+ trigger: React.PropTypes.element.isRequired,
+ title: React.PropTypes.oneOfType([
+ React.PropTypes.arrayOf(React.PropTypes.element),
+ React.PropTypes.element,
+ React.PropTypes.string
+ ]).isRequired,
handleSuccess: React.PropTypes.func.isRequired,
- button: React.PropTypes.object.isRequired,
- children: React.PropTypes.object,
- tooltip: React.PropTypes.string
+ children: React.PropTypes.oneOfType([
+ React.PropTypes.arrayOf(React.PropTypes.element),
+ React.PropTypes.element
+ ])
},
- getModalTrigger() {
- return (
-
- {this.props.children}
-
- }>
- {this.props.button}
-
- );
+ getInitialState() {
+ return {
+ showModal: false
+ };
},
- render() {
- if(this.props.tooltip) {
- return (
- {this.props.tooltip}}>
- {this.getModalTrigger()}
-
- );
- } else {
- return (
-
- {/* This needs to be some kind of inline-block */}
- {this.getModalTrigger()}
-
- );
- }
- }
-});
-
-
-let ModalBody = React.createClass({
- propTypes: {
- onRequestHide: React.PropTypes.func,
- handleSuccess: React.PropTypes.func,
- children: React.PropTypes.object,
- title: React.PropTypes.string.isRequired
+ show() {
+ this.setState({
+ showModal: true
+ });
},
- mixins: [ModalMixin],
+ hide() {
+ this.setState({
+ showModal: false
+ });
+ },
handleSuccess(response){
this.props.handleSuccess(response);
- this.props.onRequestHide();
+ this.hide();
},
renderChildren() {
return ReactAddons.Children.map(this.props.children, (child) => {
return ReactAddons.addons.cloneWithProps(child, {
- onRequestHide: this.props.onRequestHide,
handleSuccess: this.handleSuccess
});
});
},
render() {
+ // this adds the onClick method show of modal_wrapper to the trigger component
+ // which is in most cases a button.
+ let trigger = React.cloneElement(this.props.trigger, {onClick: this.show});
+
return (
-
-
- {this.renderChildren()}
-
-
+
+ {trigger}
+
+
+
+ {this.props.title}
+
+
+
+ {this.renderChildren()}
+
+
+
);
}
});
-
export default ModalWrapper;
diff --git a/js/components/ascribe_panel/action_panel.js b/js/components/ascribe_panel/action_panel.js
index 1aaef6f7..148ea03d 100644
--- a/js/components/ascribe_panel/action_panel.js
+++ b/js/components/ascribe_panel/action_panel.js
@@ -1,12 +1,15 @@
'use strict';
import React from 'react';
-
+import classnames from 'classnames';
let ActionPanel = React.createClass({
propTypes: {
title: React.PropTypes.string,
- content: React.PropTypes.string,
+ content: React.PropTypes.oneOfType([
+ React.PropTypes.string,
+ React.PropTypes.element
+ ]),
buttons: React.PropTypes.element,
onClick: React.PropTypes.func,
ignoreFocus: React.PropTypes.bool
@@ -37,33 +40,17 @@ let ActionPanel = React.createClass({
});
},
- getClassName() {
- if(this.state.isFocused) {
- return 'is-focused';
- } else {
- return '';
- }
- },
-
render() {
-
return (
-
-
-
-
-
- {this.props.title}
-
-
- {this.props.content}
-
-
+
+
+
+ {this.props.content}
-
-
- {this.props.buttons}
-
+
+
diff --git a/js/components/coa_verify_container.js b/js/components/coa_verify_container.js
index 8c2f2e77..96987323 100644
--- a/js/components/coa_verify_container.js
+++ b/js/components/coa_verify_container.js
@@ -10,7 +10,7 @@ import Form from './ascribe_forms/form';
import Property from './ascribe_forms/property';
import InputTextAreaToggable from './ascribe_forms/input_textarea_toggable';
-import apiUrls from '../constants/api_urls';
+import ApiUrls from '../constants/api_urls';
import { getLangText } from '../utils/lang_utils';
@@ -59,7 +59,7 @@ let CoaVerifyForm = React.createClass({
return (
;
- }
-
- return (
-
-
- This modal is controlled by our custom trigger component.
-
-
- {getLangText('Close')}
-
-
- );
- }
-});
-
-export default LoginModalHandler;
\ No newline at end of file
diff --git a/js/components/password_reset_container.js b/js/components/password_reset_container.js
index 20851632..80a42a62 100644
--- a/js/components/password_reset_container.js
+++ b/js/components/password_reset_container.js
@@ -5,8 +5,7 @@ import Router from 'react-router';
import Form from './ascribe_forms/form';
import Property from './ascribe_forms/property';
-import FormPropertyHeader from './ascribe_forms/form_property_header';
-import apiUrls from '../constants/api_urls';
+import ApiUrls from '../constants/api_urls';
import GlobalNotificationModel from '../models/global_notification_model';
import GlobalNotificationActions from '../actions/global_notification_actions';
@@ -15,12 +14,15 @@ import { getLangText } from '../utils/lang_utils';
let PasswordResetContainer = React.createClass({
mixins: [Router.Navigation],
+
getInitialState() {
return {isRequested: false};
},
- handleRequestSuccess(email){
+
+ handleRequestSuccess(email) {
this.setState({isRequested: email});
},
+
render() {
if (this.props.query.email && this.props.query.token) {
return (
@@ -57,17 +59,22 @@ let PasswordResetContainer = React.createClass({
});
let PasswordRequestResetForm = React.createClass({
+ propTypes: {
+ handleRequestSuccess: React.PropTypes.func
+ },
+
handleSuccess() {
let notificationText = getLangText('If your email address exists in our database, you will receive a password recovery link in a few minutes.');
let notification = new GlobalNotificationModel(notificationText, 'success', 50000);
GlobalNotificationActions.appendGlobalNotification(notification);
this.props.handleRequestSuccess(this.refs.form.refs.email.state.value);
},
+
render() {
return (
}>
-
+
{getLangText('Reset your password')}
-
+
@@ -99,24 +106,31 @@ let PasswordRequestResetForm = React.createClass({
});
let PasswordResetForm = React.createClass({
+ propTypes: {
+ email: React.PropTypes.string,
+ token: React.PropTypes.string
+ },
+
mixins: [Router.Navigation],
- getFormData(){
+ getFormData() {
return {
email: this.props.email,
token: this.props.token
};
},
+
handleSuccess() {
this.transitionTo('pieces');
let notification = new GlobalNotificationModel(getLangText('password successfully updated'), 'success', 10000);
GlobalNotificationActions.appendGlobalNotification(notification);
},
+
render() {
return (
}>
-
+
{getLangText('Reset the password for')} {this.props.email}
-
+
diff --git a/js/components/react_flow_type/react_flow_type.js b/js/components/react_flow_type/react_flow_type.js
deleted file mode 100644
index 063eaf1c..00000000
--- a/js/components/react_flow_type/react_flow_type.js
+++ /dev/null
@@ -1,92 +0,0 @@
-'use strict';
-/**
- * This component is essentially a port of https://github.com/simplefocus/FlowType.JS
- * to Reactjs in order to not being forced to use jQuery
- *
- * Author: Tim Daubenschütz
- *
- * Thanks to the guys at Simple Focus http://simplefocus.com/
- */
-
-import React from 'react';
-import ReactAddons from 'react/addons';
-
-let FlowType = React.createClass({
- propTypes: {
-
- // standard FlowTypes.JS options
- maximum: React.PropTypes.number,
- minimum: React.PropTypes.number,
- maxFont: React.PropTypes.number,
- minFont: React.PropTypes.number,
- fontRatio: React.PropTypes.number,
-
- // react specific options
- children: React.PropTypes.element.isRequired // only supporting one child element at once right now
- },
-
- getDefaultProps() {
- return {
- maximum: 9999,
- minimum: 1,
- maxFont: 9999,
- minFont: 1,
- fontRatio: 35
- };
- },
-
- getInitialState() {
- return {
- // 32 because that's the default font display size
- // doesn't really matter though
- fontSize: 0
- };
- },
-
- componentDidMount() {
- // Make changes upon resize, calculate changes and rerender
- this.handleResize();
- window.addEventListener('resize', this.handleResize);
- },
-
- componentWillUnmount() {
- // stop listening to window once the component was unmounted
- window.removeEventListener('resize', this.handleResize);
- },
-
- handleResize() {
- let elemWidth = this.refs.flowTypeElement.getDOMNode().offsetWidth;
- let width = elemWidth > this.props.maximum ? this.props.maximum : elemWidth < this.props.minimum ? this.props.minimum : elemWidth;
- let fontBase = width / this.props.fontRatio;
- let fontSize = fontBase > this.props.maxFont ? this.props.maxFont : fontBase < this.props.minFont ? this.props.minFont : fontBase;
-
- this.setState({ fontSize });
- },
-
- // The child the user passes to this component needs to have it's
- // style.fontSize property to be updated
- renderChildren() {
- return ReactAddons.Children.map(this.props.children, (child) => {
- return ReactAddons.addons.cloneWithProps(child, {
- ref: 'flowTypeFontElement',
-
- });
- });
- },
-
- render() {
- return (
-
- {this.props.children}
-
- );
- }
-});
-
-export default FlowType;
\ No newline at end of file
diff --git a/js/components/register_piece.js b/js/components/register_piece.js
index f46ab99c..94ce4d33 100644
--- a/js/components/register_piece.js
+++ b/js/components/register_piece.js
@@ -23,7 +23,6 @@ import GlobalNotificationActions from '../actions/global_notification_actions';
import Property from './ascribe_forms/property';
import PropertyCollapsible from './ascribe_forms/property_collapsible';
import RegisterPieceForm from './ascribe_forms/form_register_piece';
-//import FormPropertyHeader from './ascribe_forms/form_property_header';
import LoginContainer from './login_container';
import SlidesContainer from './ascribe_slides_container/slides_container';
@@ -40,7 +39,9 @@ let RegisterPiece = React.createClass( {
submitMessage: React.PropTypes.string,
children: React.PropTypes.oneOfType([
React.PropTypes.arrayOf(React.PropTypes.element),
- React.PropTypes.element])
+ React.PropTypes.element,
+ React.PropTypes.string
+ ])
},
mixins: [Router.Navigation],
diff --git a/js/components/settings_container.js b/js/components/settings_container.js
index 76a6cf2c..f26e6472 100644
--- a/js/components/settings_container.js
+++ b/js/components/settings_container.js
@@ -24,10 +24,10 @@ import InputCheckbox from './ascribe_forms/input_checkbox';
import ActionPanel from './ascribe_panel/action_panel';
-import apiUrls from '../constants/api_urls';
+import ApiUrls from '../constants/api_urls';
import AppConstants from '../constants/application_constants';
-import { getLangText } from '../utils/lang_utils';
+import { getLangText } from '../utils/lang_utils';
import { getCookie } from '../utils/fetch_api_utils';
let SettingsContainer = React.createClass({
@@ -90,7 +90,7 @@ let AccountSettings = React.createClass({
if (this.state.currentUser.username) {
content = (
+
+ {app.name}
+
+
+ {'Bearer ' + app.bearer_token.token}
+
+
+ }
buttons={
-
- {getLangText('REFRESH')}
-
+
+
+ {getLangText('REFRESH')}
+
+
}/>
);
@@ -366,15 +376,15 @@ let APISettings = React.createClass({
}
return content;
},
+
render() {
-
return (
This is the submission page for Sluice_screens ↄc Prize 2015.
-
+
Sign up to submit
diff --git a/js/components/whitelabel/prize/components/settings_container.js b/js/components/whitelabel/prize/components/settings_container.js
index affae8f2..d2f24f0d 100644
--- a/js/components/whitelabel/prize/components/settings_container.js
+++ b/js/components/whitelabel/prize/components/settings_container.js
@@ -14,7 +14,6 @@ import CollapsibleParagraph from '../../../ascribe_collapsible/collapsible_parag
import Form from '../../../ascribe_forms/form';
import Property from '../../../ascribe_forms/property';
-import FormPropertyHeader from '../../../ascribe_forms/form_property_header';
import ActionPanel from '../../../ascribe_panel/action_panel';
@@ -22,7 +21,7 @@ import GlobalNotificationModel from '../../../../models/global_notification_mode
import GlobalNotificationActions from '../../../../actions/global_notification_actions';
import AppConstants from '../../../../constants/application_constants';
-import apiUrls from '../../../../constants/api_urls';
+import ApiUrls from '../../../../constants/api_urls';
import { getLangText } from '../../../../utils/lang_utils';
@@ -170,8 +169,16 @@ let PrizeJurySettings = React.createClass({
+
+ {member.email}
+
+
+ {member.status}
+
+
+ }
buttons={
-
- {getLangText('REVOKE')}
-
+ content={
+
+
+ {member.email}
+
+
+ {member.status}
+
+ }
+ buttons={
+
+ {getLangText('REVOKE')}
+
}/>
);
@@ -219,17 +232,23 @@ let PrizeJurySettings = React.createClass({
-
- {getLangText('ACTIVATE')}
-
+ content={
+
+
+ {member.email}
+
+
+ {member.status}
+
+ }
+ buttons={
+
+ {getLangText('ACTIVATE')}
+
}/>
);
@@ -270,13 +289,13 @@ let PrizeJurySettings = React.createClass({
return (
-
+
Jury Members
-
+
diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js
index b4f7d926..c11a5df2 100644
--- a/js/constants/api_urls.js
+++ b/js/constants/api_urls.js
@@ -5,7 +5,7 @@ import getPrizeApiUrls from '../components/whitelabel/prize/constants/api_urls';
import { update } from '../utils/general_utils';
-let apiUrls = {
+let ApiUrls = {
'applications': AppConstants.apiEndpoint + 'applications/',
'application_token_refresh': AppConstants.apiEndpoint + 'applications/refresh_token/',
'blob_digitalworks': AppConstants.apiEndpoint + 'blob/digitalworks/',
@@ -63,7 +63,7 @@ export function updateApiUrls(type, subdomain) {
if (type === 'prize') {
newUrls = getPrizeApiUrls(subdomain);
}
- update(apiUrls, newUrls);
+ update(ApiUrls, newUrls);
}
-export default apiUrls;
+export default ApiUrls;
diff --git a/js/fetchers/user_fetcher.js b/js/fetchers/user_fetcher.js
index a175c644..eca7494d 100644
--- a/js/fetchers/user_fetcher.js
+++ b/js/fetchers/user_fetcher.js
@@ -1,7 +1,7 @@
'use strict';
import requests from '../utils/requests';
-import apiUrls from '../constants/api_urls';
+import ApiUrls from '../constants/api_urls';
let UserFetcher = {
/**
@@ -13,7 +13,7 @@ let UserFetcher = {
},
logout() {
- return requests.get(apiUrls.users_logout);
+ return requests.get(ApiUrls.users_logout);
}
};
diff --git a/js/mixins/alert_mixin.js b/js/mixins/alert_mixin.js
deleted file mode 100644
index 2b9b5158..00000000
--- a/js/mixins/alert_mixin.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict';
-
-import React from 'react';
-import AlertDismissable from '../components/ascribe_forms/alert';
-
-let AlertMixin = {
- setAlerts(errors){
- let alerts = errors.map((error) => {
- return ;
- });
-
- this.setState({alerts: alerts});
- },
-
- clearAlerts(){
- this.setState({alerts: null});
- }
-
-};
-
-export default AlertMixin;
\ No newline at end of file
diff --git a/js/mixins/form_mixin.js b/js/mixins/form_mixin.js
deleted file mode 100644
index c04f52ed..00000000
--- a/js/mixins/form_mixin.js
+++ /dev/null
@@ -1,108 +0,0 @@
-'use strict';
-
-import requests from '../utils/requests';
-import React from 'react';
-
-import AlertDismissable from '../components/ascribe_forms/alert';
-import { getLangText } from '../utils/lang_utils.js';
-
-export const FormMixin = {
- propTypes: {
- editions: React.PropTypes.array,
- currentUser: React.PropTypes.object
- },
-
- getInitialState() {
- return {
- submitted: false,
- errors: []
- };
- },
-
- submit(e) {
- if (e) {
- e.preventDefault();
- }
- this.setState({submitted: true});
- this.clearErrors();
- let action = (this.httpVerb && this.httpVerb()) || 'post';
- this[action](e);
- },
-
- post(e){
- requests
- .post(this.url(e), { body: this.getFormData() })
- .then(this.handleSuccess)
- .catch(this.handleError);
- },
-
- delete(e){
- requests
- .delete(this.url(e))
- .then(this.handleSuccess)
- .catch(this.handleError);
- },
-
- clearErrors(){
- for (var ref in this.refs){
- if ('clearAlerts' in this.refs[ref]){
- this.refs[ref].clearAlerts();
- }
-
- }
- this.setState({errors: []});
- },
- handleSuccess(response){
- if ('handleSuccess' in this.props){
- this.props.handleSuccess(response);
- }
-
- },
- handleError(err){
- if (err.json) {
- for (var input in err.json.errors){
- if (this.refs && this.refs[input] && this.refs[input].state) {
- this.refs[input].setAlerts( err.json.errors[input]);
- } else {
- this.setState({errors: this.state.errors.concat(err.json.errors[input])});
- }
- }
- }
- else {
- // TODO translate?
- this.setState({errors: ['Something went wrong, please try again later']});
- }
- this.setState({submitted: false});
- },
-
- getBitcoinIds(){
- return this.props.editions.map(function(edition){
- return edition.bitcoin_id;
- });
- },
-
- getTitlesString(){
- return this.props.editions.map(function(edition){
- return '- \"' + edition.title + ', ' + getLangText('edition') + ' ' + edition.edition_number + '\"\n';
- });
- },
-
- render(){
- let alert = null;
- if (this.state.errors.length > 0){
- alert = this.state.errors.map((error) => {
- return ;
- });
- }
-
- return (
-
- {alert}
- {this.renderForm()}
-
- );
- }
-};
-
-export default FormMixin;
-
diff --git a/js/mixins/modal_mixin.js b/js/mixins/modal_mixin.js
deleted file mode 100644
index 6087f32c..00000000
--- a/js/mixins/modal_mixin.js
+++ /dev/null
@@ -1,12 +0,0 @@
-'use strict';
-
-let ModalMixin = {
- onRequestHide(e){
- if (e) {
- e.preventDefault();
- }
- this.props.onRequestHide();
- }
-};
-
-export default ModalMixin;
\ No newline at end of file
diff --git a/js/utils/form_utils.js b/js/utils/form_utils.js
new file mode 100644
index 00000000..3a8861cc
--- /dev/null
+++ b/js/utils/form_utils.js
@@ -0,0 +1,51 @@
+'use strict';
+
+import { getLangText } from './lang_utils';
+
+/**
+ * Generates a message for submitting a form
+ * @param {string} aclName Enum name of a acl
+ * @param {string} entities Already computed name of entities
+ * @param {string} senderName Name of the sender
+ * @return {string} Completed message
+ */
+export function getAclFormMessage(aclName, entities, senderName) {
+ let message = '';
+
+ message += getLangText('Hi');
+ message += ',\n\n';
+
+ if(aclName === 'acl_transfer') {
+ message += getLangText('I transfer ownership of');
+ } else if(aclName === 'acl_consign') {
+ message += getLangText('I consign');
+ } else if(aclName === 'acl_unconsign') {
+ message += getLangText('I un-consign');
+ } else if(aclName === 'acl_loan') {
+ message += getLangText('I loan');
+ } else if(aclName === 'acl_share') {
+ message += getLangText('I share');
+ } else {
+ throw new Error('Your specified aclName did not match a an acl class.');
+ }
+
+ message += ':\n';
+ message += entities;
+
+ if(aclName === 'acl_transfer' || aclName === 'acl_loan' || aclName === 'acl_consign') {
+ message += getLangText('to you');
+ } else if(aclName === 'acl_unconsign') {
+ message += getLangText('from you');
+ } else if(aclName === 'acl_share') {
+ message += getLangText('with you');
+ } else {
+ throw new Error('Your specified aclName did not match a an acl class.');
+ }
+
+ message += '\n\n';
+ message += getLangText('Truly yours,');
+ message += '\n';
+ message += senderName;
+
+ return message;
+}
\ No newline at end of file
diff --git a/js/utils/requests.js b/js/utils/requests.js
index 8705bc0f..793e1f21 100644
--- a/js/utils/requests.js
+++ b/js/utils/requests.js
@@ -91,7 +91,7 @@ class Requests {
} catch(err) {
throw err;
}
-
+
newUrl = newUrl.replace(re, (match, key) => {
let val = params[key];
if (!val) {
diff --git a/package.json b/package.json
index 4fdf87fb..0fc9844f 100644
--- a/package.json
+++ b/package.json
@@ -71,7 +71,7 @@
"q": "^1.4.1",
"raven-js": "^1.1.19",
"react": "^0.13.2",
- "react-bootstrap": "~0.22.6",
+ "react-bootstrap": "^0.24.3",
"react-datepicker": "~0.8.0",
"react-progressbar": "^1.1.0",
"react-router": "^0.13.3",
diff --git a/sass/ascribe_edition.scss b/sass/ascribe_edition.scss
index ee082a04..fe647e2d 100644
--- a/sass/ascribe_edition.scss
+++ b/sass/ascribe_edition.scss
@@ -16,33 +16,35 @@
margin-top: 20px;
}
.ascribe-edition-collapsible-wrapper > div > span {
- font-size: 1.2em;
- margin-right: .5em;
+ font-size: 1.2em;
+ margin-right: .5em;
}
.ascribe-edition-collapsible-wrapper > div > span:nth-child(2) {
- font-size: 0.9em;
+ font-size: 0.9em;
}
-.ascribe-edition-collapible-content {
- width:100%;
+.ascribe-edition-collapsible-content {
+ width:100%;
+ background: none;
+ border: none;
}
-.coa-file-wrapper{
- display: table;
- height: 200px;
- overflow: hidden;
- margin: 0 auto;
- width: 100%;
- padding: 1em;
+.coa-file-wrapper {
+ display: table;
+ height: 200px;
+ overflow: hidden;
+ margin: 0 auto;
+ width: 100%;
+ padding: 1em;
}
.coa-file {
- display: table-cell;
- vertical-align: middle;
- border: 1px solid #CCC;
- background-color: #F8F8F8;
+ display: table-cell;
+ vertical-align: middle;
+ border: 1px solid #CCC;
+ background-color: #F8F8F8;
}
.ascribe-button-list {
- margin-top: 1em;
+ margin-top: 1em;
}
\ No newline at end of file
diff --git a/sass/ascribe_panel.scss b/sass/ascribe_panel.scss
index 8ad4249c..73fe572e 100644
--- a/sass/ascribe_panel.scss
+++ b/sass/ascribe_panel.scss
@@ -1,18 +1,94 @@
.ascribe-panel-wrapper {
border: 1px solid #DDD;
- padding: 1.4em;
- margin: 1em 0 1em 0;
+ min-height: 5em;
+ height: 5em;
+
+ margin-top: 1em;
+
+ > div {
+ height: 100%;
+ float: left;
+
+ &:first-child {
+ width: 60%;
+ }
+
+ &:nth-child(2) {
+ width: 40%;
+ }
+ }
}
-.ascribe-panel-title {
- margin-bottom: 0.5em;
+.ascribe-panel-table {
+ display:table;
+
+ > .ascribe-panel-content {
+ display: table-cell;
+ vertical-align: middle;
+ }
+
+ @media(max-width:767px) {
+ &:first-child {
+ > div {
+ padding-left: 1em;
+ }
+
+ }
+
+ &:nth-child(2) {
+ > div {
+ padding-right: 1em;
+
+ > button {
+ float:right;
+ }
+ }
+ }
+
+ }
+
+ @media(min-width:768px) {
+ &:first-child {
+ > div {
+ padding-left: 2em;
+ }
+
+ }
+
+ &:nth-child(2) {
+ > div {
+ padding-right: 2em;
+
+ > button {
+ float:right;
+ }
+ }
+ }
+ }
}
-.ascribe-panel-content {
- font-size: 0.9em;
- color: rgba(0,0,0,0.5);
+@media(max-width:767px) {
+ .ascribe-panel-title {
+ font-size: .9em;
+ }
+
+ .ascribe-panel-subtitle {
+ font-size: .7em;
+ color: rgba(0,0,0,0.5);
+ }
+
}
-.ascribe-panel-buttons {
- margin-top: 0.5em;
-}
\ No newline at end of file
+@media(min-width:768px) {
+ .ascribe-panel-title {
+ font-size: 1.1em;
+ }
+
+ .ascribe-panel-subtitle {
+ font-size: .9em;
+ color: rgba(0,0,0,0.5);
+ }
+}
+
+
+
diff --git a/sass/ascribe_theme.scss b/sass/ascribe_theme.scss
index 9eb92a30..e02b97c6 100644
--- a/sass/ascribe_theme.scss
+++ b/sass/ascribe_theme.scss
@@ -2,4 +2,14 @@
.pager li a {
color: white;
+}
+
+.panel-default {
+ border: none;
+ box-shadow: none;
+ margin-bottom: 0;
+}
+
+.panel-body {
+ padding:0;
}
\ No newline at end of file