From f7259a8ab3784cb74ac2d71e710cd6ef90ee917c Mon Sep 17 00:00:00 2001 From: Brett Sun Date: Tue, 3 Nov 2015 11:13:32 +0100 Subject: [PATCH] Merge with AD-1255 --- js/components/ascribe_buttons/acl_button.js | 174 ------------------ .../ascribe_buttons/acl_button_list.js | 45 +++-- .../ascribe_buttons/acls/acl_button.js | 83 +++++++++ .../ascribe_buttons/acls/consign_button.js | 27 +++ .../ascribe_buttons/acls/loan_button.js | 27 +++ .../acls/loan_request_button.js | 24 +++ .../ascribe_buttons/acls/share_button.js | 24 +++ .../ascribe_buttons/acls/transfer_button.js | 24 +++ .../ascribe_buttons/acls/unconsign_button.js | 24 +++ .../ascribe_detail/edition_action_panel.js | 2 +- .../ascribe_detail/piece_container.js | 2 +- .../ascribe_forms/acl_form_factory.js | 128 +++++++++++++ .../ascribe_forms/form_request_action.js | 70 ++++--- .../ascribe_detail/wallet_action_panel.js | 4 +- js/utils/form_utils.js | 16 ++ js/utils/general_utils.js | 39 +++- js/utils/lang_utils.js | 6 +- js/utils/requests.js | 8 +- 18 files changed, 474 insertions(+), 253 deletions(-) delete mode 100644 js/components/ascribe_buttons/acl_button.js create mode 100644 js/components/ascribe_buttons/acls/acl_button.js create mode 100644 js/components/ascribe_buttons/acls/consign_button.js create mode 100644 js/components/ascribe_buttons/acls/loan_button.js create mode 100644 js/components/ascribe_buttons/acls/loan_request_button.js create mode 100644 js/components/ascribe_buttons/acls/share_button.js create mode 100644 js/components/ascribe_buttons/acls/transfer_button.js create mode 100644 js/components/ascribe_buttons/acls/unconsign_button.js create mode 100644 js/components/ascribe_forms/acl_form_factory.js diff --git a/js/components/ascribe_buttons/acl_button.js b/js/components/ascribe_buttons/acl_button.js deleted file mode 100644 index 5197a744..00000000 --- a/js/components/ascribe_buttons/acl_button.js +++ /dev/null @@ -1,174 +0,0 @@ -'use strict'; - -import React from 'react'; - -import ConsignForm from '../ascribe_forms/form_consign'; -import UnConsignForm from '../ascribe_forms/form_unconsign'; -import TransferForm from '../ascribe_forms/form_transfer'; -import LoanForm from '../ascribe_forms/form_loan'; -import LoanRequestAnswerForm from '../ascribe_forms/form_loan_request_answer'; -import ShareForm from '../ascribe_forms/form_share_email'; -import ModalWrapper from '../ascribe_modal/modal_wrapper'; -import AppConstants from '../../constants/application_constants'; - -import GlobalNotificationModel from '../../models/global_notification_model'; -import GlobalNotificationActions from '../../actions/global_notification_actions'; - -import ApiUrls from '../../constants/api_urls'; - -import { getAclFormMessage, getAclFormDataId } from '../../utils/form_utils'; -import { getLangText } from '../../utils/lang_utils'; - -let AclButton = React.createClass({ - propTypes: { - action: React.PropTypes.oneOf(AppConstants.aclList).isRequired, - availableAcls: React.PropTypes.object.isRequired, - pieceOrEditions: React.PropTypes.oneOfType([ - React.PropTypes.object, - React.PropTypes.array - ]).isRequired, - currentUser: React.PropTypes.object, - buttonAcceptName: React.PropTypes.string, - buttonAcceptClassName: React.PropTypes.string, - email: React.PropTypes.string, - handleSuccess: React.PropTypes.func.isRequired, - className: React.PropTypes.string - }, - - isPiece() { - return this.props.pieceOrEditions.constructor !== Array; - }, - - actionProperties() { - let message = getAclFormMessage({ - aclName: this.props.action, - entities: this.props.pieceOrEditions, - isPiece: this.isPiece(), - senderName: this.props.currentUser.username - }); - - if (this.props.action === 'acl_consign') { - return { - title: getLangText('Consign artwork'), - tooltip: getLangText('Have someone else sell the artwork'), - form: ( - - ), - handleSuccess: this.showNotification - }; - } else if (this.props.action === 'acl_unconsign') { - return { - title: getLangText('Unconsign artwork'), - tooltip: getLangText('Have the owner manage his sales again'), - form: ( - - ), - handleSuccess: this.showNotification - }; - } else if (this.props.action === 'acl_transfer') { - return { - title: getLangText('Transfer artwork'), - tooltip: getLangText('Transfer the ownership of the artwork'), - form: ( - - ), - handleSuccess: this.showNotification - }; - } else if (this.props.action === 'acl_loan') { - return { - title: getLangText('Loan artwork'), - tooltip: getLangText('Loan your artwork for a limited period of time'), - form: ( - - ), - handleSuccess: this.showNotification - }; - } else if (this.props.action === 'acl_loan_request') { - return { - title: getLangText('Loan artwork'), - tooltip: getLangText('Someone requested you to loan your artwork for a limited period of time'), - form: ( - - ), - handleSuccess: this.showNotification - }; - } else if (this.props.action === 'acl_share') { - return { - title: getLangText('Share artwork'), - tooltip: getLangText('Share the artwork'), - form: ( - - ), - handleSuccess: this.showNotification - }; - } else { - throw new Error('Your specified action did not match a form.'); - } - }, - - showNotification(response) { - this.props.handleSuccess(); - if (response.notification) { - let notification = new GlobalNotificationModel(response.notification, 'success'); - GlobalNotificationActions.appendGlobalNotification(notification); - } - }, - - getFormDataId(){ - return getAclFormDataId(this.isPiece(), this.props.pieceOrEditions); - }, - - // Removes the acl_ prefix and converts to upper case - sanitizeAction() { - if (this.props.buttonAcceptName) { - return this.props.buttonAcceptName; - } - return this.props.action.split('acl_')[1].toUpperCase(); - }, - - render() { - if (this.props.availableAcls) { - let shouldDisplay = this.props.availableAcls[this.props.action]; - let aclProps = this.actionProperties(); - let buttonClassName = this.props.buttonAcceptClassName ? this.props.buttonAcceptClassName : ''; - return ( - - {this.sanitizeAction()} - - } - handleSuccess={aclProps.handleSuccess} - title={aclProps.title}> - {aclProps.form} - - ); - } - return null; - } -}); - -export default AclButton; diff --git a/js/components/ascribe_buttons/acl_button_list.js b/js/components/ascribe_buttons/acl_button_list.js index e87a6407..83495363 100644 --- a/js/components/ascribe_buttons/acl_button_list.js +++ b/js/components/ascribe_buttons/acl_button_list.js @@ -5,21 +5,25 @@ import React from 'react/addons'; import UserActions from '../../actions/user_actions'; import UserStore from '../../stores/user_store'; -import AclButton from '../ascribe_buttons/acl_button'; +import ConsignButton from './acls/consign_button'; +import LoanButton from './acls/loan_button'; +import LoanRequestButton from './acls/loan_request_button'; +import ShareButton from './acls/share_button'; +import TransferButton from './acls/transfer_button'; +import UnconsignButton from './acls/unconsign_button'; import { mergeOptions } from '../../utils/general_utils'; - let AclButtonList = React.createClass({ propTypes: { className: React.PropTypes.string, - editions: React.PropTypes.oneOfType([ + pieceOrEditions: React.PropTypes.oneOfType([ React.PropTypes.object, React.PropTypes.array - ]), - availableAcls: React.PropTypes.object, + ]).isRequired, + availableAcls: React.PropTypes.object.isRequired, buttonsStyle: React.PropTypes.object, - handleSuccess: React.PropTypes.func, + handleSuccess: React.PropTypes.func.isRequired, children: React.PropTypes.oneOfType([ React.PropTypes.arrayOf(React.PropTypes.element), React.PropTypes.element @@ -78,7 +82,7 @@ let AclButtonList = React.createClass({ const { className, buttonsStyle, availableAcls, - editions, + pieceOrEditions, handleSuccess } = this.props; const { currentUser } = this.state; @@ -86,34 +90,29 @@ let AclButtonList = React.createClass({ return (
- - - - - {this.renderChildren()} @@ -123,4 +122,4 @@ let AclButtonList = React.createClass({ } }); -export default AclButtonList; \ No newline at end of file +export default AclButtonList; diff --git a/js/components/ascribe_buttons/acls/acl_button.js b/js/components/ascribe_buttons/acls/acl_button.js new file mode 100644 index 00000000..d81a19f4 --- /dev/null +++ b/js/components/ascribe_buttons/acls/acl_button.js @@ -0,0 +1,83 @@ +'use strict'; + +import React from 'react'; +import classNames from 'classnames'; + +import AclProxy from '../../acl_proxy'; + +import AclFormFactory from '../../ascribe_forms/acl_form_factory'; + +import ModalWrapper from '../../ascribe_modal/modal_wrapper'; + +import AppConstants from '../../../constants/application_constants'; + +import GlobalNotificationModel from '../../../models/global_notification_model'; +import GlobalNotificationActions from '../../../actions/global_notification_actions'; + +import ApiUrls from '../../../constants/api_urls'; + +import { getAclFormMessage, getAclFormDataId } from '../../../utils/form_utils'; +import { getLangText } from '../../../utils/lang_utils'; + +let AclButton = React.createClass({ + propTypes: { + action: React.PropTypes.oneOf(AppConstants.aclList).isRequired, + availableAcls: React.PropTypes.object.isRequired, + buttonAcceptName: React.PropTypes.string, + buttonAcceptClassName: React.PropTypes.string, + currentUser: React.PropTypes.object.isRequired, + email: React.PropTypes.string, + pieceOrEditions: React.PropTypes.oneOfType([ + React.PropTypes.object, + React.PropTypes.array + ]).isRequired, + title: React.PropTypes.string, + handleSuccess: React.PropTypes.func.isRequired, + className: React.PropTypes.string + }, + + // Removes the acl_ prefix and converts to upper case + sanitizeAction() { + if (this.props.buttonAcceptName) { + return this.props.buttonAcceptName; + } + return this.props.action.split('acl_')[1].toUpperCase(); + }, + + render() { + const { + action, + availableAcls, + buttonAcceptClassName, + currentUser, + email, + pieceOrEditions, + handleSuccess, + title } = this.props; + + return ( + + + {this.sanitizeAction()} + + } + handleSuccess={handleSuccess} + title={title}> + + + + ); + } +}); + +export default AclButton; diff --git a/js/components/ascribe_buttons/acls/consign_button.js b/js/components/ascribe_buttons/acls/consign_button.js new file mode 100644 index 00000000..6a3759db --- /dev/null +++ b/js/components/ascribe_buttons/acls/consign_button.js @@ -0,0 +1,27 @@ +'use strict'; + +import React from 'react'; + +import AclButton from './acl_button'; + +import { omitFromObject } from '../../../utils/general_utils'; +import { getLangText } from '../../../utils/lang_utils'; + +let ConsignButton = React.createClass({ + propTypes: { + ...omitFromObject(AclButton.propTypes, ['action']), + email: React.PropTypes.string + }, + + render() { + return ( + + ); + } +}); + +export default ConsignButton; diff --git a/js/components/ascribe_buttons/acls/loan_button.js b/js/components/ascribe_buttons/acls/loan_button.js new file mode 100644 index 00000000..283b43eb --- /dev/null +++ b/js/components/ascribe_buttons/acls/loan_button.js @@ -0,0 +1,27 @@ +'use strict'; + +import React from 'react'; + +import AclButton from './acl_button'; + +import { omitFromObject } from '../../../utils/general_utils'; +import { getLangText } from '../../../utils/lang_utils'; + +let LoanButton = React.createClass({ + propTypes: { + ...omitFromObject(AclButton.propTypes, ['action']), + email: React.PropTypes.string + }, + + render() { + return ( + + ); + } +}); + +export default LoanButton; diff --git a/js/components/ascribe_buttons/acls/loan_request_button.js b/js/components/ascribe_buttons/acls/loan_request_button.js new file mode 100644 index 00000000..f4ffe9a4 --- /dev/null +++ b/js/components/ascribe_buttons/acls/loan_request_button.js @@ -0,0 +1,24 @@ +'use strict'; + +import React from 'react'; + +import AclButton from './acl_button'; + +import { omitFromObject } from '../../../utils/general_utils'; +import { getLangText } from '../../../utils/lang_utils'; + +let LoanButton = React.createClass({ + propTypes: omitFromObject(AclButton.propTypes, ['action']), + + render() { + return ( + + ); + } +}); + +export default LoanButton; diff --git a/js/components/ascribe_buttons/acls/share_button.js b/js/components/ascribe_buttons/acls/share_button.js new file mode 100644 index 00000000..4fb914a0 --- /dev/null +++ b/js/components/ascribe_buttons/acls/share_button.js @@ -0,0 +1,24 @@ +'use strict'; + +import React from 'react'; + +import AclButton from './acl_button'; + +import { omitFromObject } from '../../../utils/general_utils'; +import { getLangText } from '../../../utils/lang_utils'; + +let ShareButton = React.createClass({ + propTypes: omitFromObject(AclButton.propTypes, ['action']), + + render() { + return ( + + ); + } +}); + +export default ShareButton; diff --git a/js/components/ascribe_buttons/acls/transfer_button.js b/js/components/ascribe_buttons/acls/transfer_button.js new file mode 100644 index 00000000..e85a81d1 --- /dev/null +++ b/js/components/ascribe_buttons/acls/transfer_button.js @@ -0,0 +1,24 @@ +'use strict'; + +import React from 'react'; + +import AclButton from './acl_button'; + +import { omitFromObject } from '../../../utils/general_utils'; +import { getLangText } from '../../../utils/lang_utils'; + +let TransferButton = React.createClass({ + propTypes: omitFromObject(AclButton.propTypes, ['action']), + + render() { + return ( + + ); + } +}); + +export default TransferButton; diff --git a/js/components/ascribe_buttons/acls/unconsign_button.js b/js/components/ascribe_buttons/acls/unconsign_button.js new file mode 100644 index 00000000..39029c18 --- /dev/null +++ b/js/components/ascribe_buttons/acls/unconsign_button.js @@ -0,0 +1,24 @@ +'use strict'; + +import React from 'react'; + +import AclButton from './acl_button'; + +import { omitFromObject } from '../../../utils/general_utils'; +import { getLangText } from '../../../utils/lang_utils'; + +let UnconsignButton = React.createClass({ + propTypes: omitFromObject(AclButton.propTypes, ['action']), + + render() { + return ( + + ); + } +}); + +export default UnconsignButton; diff --git a/js/components/ascribe_detail/edition_action_panel.js b/js/components/ascribe_detail/edition_action_panel.js index d0f16103..6bd8108d 100644 --- a/js/components/ascribe_detail/edition_action_panel.js +++ b/js/components/ascribe_detail/edition_action_panel.js @@ -115,7 +115,7 @@ let EditionActionPanel = React.createClass({ + ); + } else if (action === 'acl_unconsign') { + return ( + + ); + } else if (action === 'acl_transfer') { + return ( + + ); + } else if (action === 'acl_loan') { + return ( + + ); + } else if (action === 'acl_loan_request') { + return ( + + ); + } else if (action === 'acl_share') { + return ( + + ); + } else { + throw new Error('Your specified action did not match a form.'); + } + } +}); + +export default AclFormFactory; diff --git a/js/components/ascribe_forms/form_request_action.js b/js/components/ascribe_forms/form_request_action.js index b0f3b6c6..d3d1bc71 100644 --- a/js/components/ascribe_forms/form_request_action.js +++ b/js/components/ascribe_forms/form_request_action.js @@ -2,10 +2,13 @@ import React from 'react'; -import AclButton from './../ascribe_buttons/acl_button'; -import ActionPanel from '../ascribe_panel/action_panel'; import Form from './form'; +import LoanRequestButton from '../ascribe_buttons/acls/loan_request_button'; +import UnconsignButton from '../ascribe_buttons/acls/unconsign_button'; + +import ActionPanel from '../ascribe_panel/action_panel'; + import NotificationActions from '../../actions/notification_actions'; import GlobalNotificationModel from '../../models/global_notification_model'; @@ -13,9 +16,9 @@ import GlobalNotificationActions from '../../actions/global_notification_actions import ApiUrls from '../../constants/api_urls'; +import { getAclFormDataId } from '../../utils/form_utils'; import { getLangText } from '../../utils/lang_utils.js'; - let RequestActionForm = React.createClass({ propTypes: { pieceOrEditions: React.PropTypes.oneOfType([ @@ -27,26 +30,26 @@ let RequestActionForm = React.createClass({ handleSuccess: React.PropTypes.func }, - isPiece(){ + isPiece() { return this.props.pieceOrEditions.constructor !== Array; }, getUrls() { let urls = {}; - if (this.props.notifications.action === 'consign'){ + if (this.props.notifications.action === 'consign') { urls.accept = ApiUrls.ownership_consigns_confirm; urls.deny = ApiUrls.ownership_consigns_deny; - } else if (this.props.notifications.action === 'unconsign'){ + } else if (this.props.notifications.action === 'unconsign') { urls.accept = ApiUrls.ownership_unconsigns; urls.deny = ApiUrls.ownership_unconsigns_deny; - } else if (this.props.notifications.action === 'loan' && !this.isPiece()){ + } else if (this.props.notifications.action === 'loan' && !this.isPiece()) { urls.accept = ApiUrls.ownership_loans_confirm; urls.deny = ApiUrls.ownership_loans_deny; - } else if (this.props.notifications.action === 'loan' && this.isPiece()){ + } else if (this.props.notifications.action === 'loan' && this.isPiece()) { urls.accept = ApiUrls.ownership_loans_pieces_confirm; urls.deny = ApiUrls.ownership_loans_pieces_deny; - } else if (this.props.notifications.action === 'loan_request' && this.isPiece()){ + } else if (this.props.notifications.action === 'loan_request' && this.isPiece()) { urls.accept = ApiUrls.ownership_loans_pieces_request_confirm; urls.deny = ApiUrls.ownership_loans_pieces_request_deny; } @@ -54,37 +57,28 @@ let RequestActionForm = React.createClass({ return urls; }, - getFormData(){ - if (this.isPiece()) { - return {piece_id: this.props.pieceOrEditions.id}; - } - else { - return {bitcoin_id: this.props.pieceOrEditions.map(function(edition){ - return edition.bitcoin_id; - }).join()}; - } + getFormData() { + return getAclFormDataId(this.isPiece(), this.props.pieceOrEditions); }, showNotification(option, action, owner) { return () => { - let message = getLangText('You have successfully') + ' ' + option + ' the ' + action + ' request ' + getLangText('from') + ' ' + owner; - - let notifications = new GlobalNotificationModel(message, 'success'); + const message = getLangText('You have successfully %s the %s request from %s', getLangText(option), getLangText(action), owner); + const notifications = new GlobalNotificationModel(message, 'success'); GlobalNotificationActions.appendGlobalNotification(notifications); this.handleSuccess(); - }; }, handleSuccess() { - if (this.isPiece()){ + if (this.isPiece()) { NotificationActions.fetchPieceListNotifications(); - } - else { + } else { NotificationActions.fetchEditionListNotifications(); } - if(this.props.handleSuccess) { + + if (typeof this.props.handleSuccess === 'function') { this.props.handleSuccess(); } }, @@ -98,21 +92,19 @@ let RequestActionForm = React.createClass({ }, getAcceptButtonForm(urls) { - if(this.props.notifications.action === 'unconsign') { + if (this.props.notifications.action === 'unconsign') { return ( - ); - } else if(this.props.notifications.action === 'loan_request') { + } else if (this.props.notifications.action === 'loan_request') { return ( - @@ -140,8 +132,8 @@ let RequestActionForm = React.createClass({ }, getButtonForm() { - let urls = this.getUrls(); - let acceptButtonForm = this.getAcceptButtonForm(urls); + const urls = this.getUrls(); + const acceptButtonForm = this.getAcceptButtonForm(urls); return (
@@ -150,13 +142,13 @@ let RequestActionForm = React.createClass({ isInline={true} getFormData={this.getFormData} handleSuccess={ - this.showNotification(getLangText('denied'), this.props.notifications.action, this.props.notifications.by) + this.showNotification('denied', this.props.notifications.action, this.props.notifications.by) } className='inline pull-right'> {acceptButtonForm} @@ -168,10 +160,10 @@ let RequestActionForm = React.createClass({ return ( + buttons={this.getButtonForm()} /> ); } }); -export default RequestActionForm; \ No newline at end of file +export default RequestActionForm; diff --git a/js/components/whitelabel/wallet/components/ascribe_detail/wallet_action_panel.js b/js/components/whitelabel/wallet/components/ascribe_detail/wallet_action_panel.js index 178be7da..bd240126 100644 --- a/js/components/whitelabel/wallet/components/ascribe_detail/wallet_action_panel.js +++ b/js/components/whitelabel/wallet/components/ascribe_detail/wallet_action_panel.js @@ -47,7 +47,7 @@ let WalletActionPanel = React.createClass({ { + return filter.indexOf(key) >= 0; + }); + } else if (filter && typeof filter === 'function') { + return filterObjOnFn(obj, filter); + } else { + throw new Error('The given filter is not an array or function. Exclude aborted'); + } } /** diff --git a/js/utils/lang_utils.js b/js/utils/lang_utils.js index f2e2fa14..ee2d292c 100644 --- a/js/utils/lang_utils.js +++ b/js/utils/lang_utils.js @@ -22,15 +22,15 @@ export function getLangText(s, ...args) { let lang = getLang(); try { if(lang in languages) { - return formatText(languages[lang][s], args); + return formatText(languages[lang][s], ...args); } else { // just use the english language - return formatText(languages['en-US'][s], args); + return formatText(languages['en-US'][s], ...args); } } catch(err) { //if(!(s in languages[lang])) { //console.warn('Language-string is not in constants file. Add: "' + s + '" to the "' + lang + '" language file. Defaulting to keyname'); - return formatText(s, args); + return formatText(s, ...args); //} else { // console.error(err); //} diff --git a/js/utils/requests.js b/js/utils/requests.js index 7e9c9a58..43c09458 100644 --- a/js/utils/requests.js +++ b/js/utils/requests.js @@ -6,7 +6,7 @@ import { argsToQueryParams, getCookie } from '../utils/fetch_api_utils'; import AppConstants from '../constants/application_constants'; -import {excludePropFromObject} from '../utils/general_utils'; +import { omitFromObject } from '../utils/general_utils'; class Requests { _merge(defaults, options) { @@ -138,9 +138,9 @@ class Requests { return this.request('delete', newUrl); } - _putOrPost(url, paramsAndBody, method){ - let paramsCopy = this._merge(paramsAndBody); - let params = excludePropFromObject(paramsAndBody, ['body']); + _putOrPost(url, paramsAndBody, method) { + let paramsCopy = Object.assign({}, paramsAndBody); + let params = omitFromObject(paramsAndBody, ['body']); let newUrl = this.prepareUrl(url, params); let body = null; if (paramsCopy && paramsCopy.body) {