From ac1b43d24ba8c2bc08615a83d5c18913c1fc9854 Mon Sep 17 00:00:00 2001 From: Brett Sun Date: Mon, 26 Oct 2015 19:17:06 +0100 Subject: [PATCH] Set the consignee email by using the server's white label settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consignee email is available through the white label settings we get from the server, so we don’t need to hardcode them into the constants. Separated out AclButtonList from PieceListbulkModal to make the modal more flexible and separated in concerns. --- js/components/ascribe_buttons/acl_button.js | 10 +- js/components/ascribe_forms/form_consign.js | 11 +-- .../piece_list_bulk_modal.js | 68 +++----------- js/components/piece_list.js | 61 ++++++++++++- .../lumenus_acl_button_list.js | 39 ++++++++ .../lumenus_buttons/lumenus_submit_button.js | 91 +++++++++++++++++++ .../components/lumenus/lumenus_piece_list.js | 4 + .../lumenus/lumenus_register_piece.js | 7 -- js/constants/application_constants.js | 6 -- js/utils/acl_utils.js | 13 ++- js/utils/form_utils.js | 21 +++-- 11 files changed, 230 insertions(+), 101 deletions(-) create mode 100644 js/components/whitelabel/wallet/components/lumenus/lumenus_buttons/lumenus_acl_button_list.js create mode 100644 js/components/whitelabel/wallet/components/lumenus/lumenus_buttons/lumenus_submit_button.js diff --git a/js/components/ascribe_buttons/acl_button.js b/js/components/ascribe_buttons/acl_button.js index ee337149..7eec36f1 100644 --- a/js/components/ascribe_buttons/acl_button.js +++ b/js/components/ascribe_buttons/acl_button.js @@ -16,7 +16,7 @@ import GlobalNotificationActions from '../../actions/global_notification_actions import ApiUrls from '../../constants/api_urls'; -import { getAclFormMessage } from '../../utils/form_utils'; +import { getAclFormMessage, getAclFormDataId } from '../../utils/form_utils'; import { getLangText } from '../../utils/lang_utils'; let AclButton = React.createClass({ @@ -134,13 +134,7 @@ let AclButton = React.createClass({ }, getFormDataId(){ - 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()}; - } + return getAclFormDataId(this.isPiece(), this.props.pieceOrEditions); }, // Removes the acl_ prefix and converts to upper case diff --git a/js/components/ascribe_forms/form_consign.js b/js/components/ascribe_forms/form_consign.js index 7e3233e8..9617acd4 100644 --- a/js/components/ascribe_forms/form_consign.js +++ b/js/components/ascribe_forms/form_consign.js @@ -11,12 +11,11 @@ import InputTextAreaToggable from './input_textarea_toggable'; import AscribeSpinner from '../ascribe_spinner'; import { getLangText } from '../../utils/lang_utils.js'; -import { getSubdomainFormSettings } from '../../utils/form_utils'; - let ConsignForm = React.createClass({ propTypes: { url: React.PropTypes.string, id: React.PropTypes.object, + email: React.PropTypes.string, message: React.PropTypes.string, handleSuccess: React.PropTypes.func }, @@ -26,8 +25,6 @@ let ConsignForm = React.createClass({ }, render() { - let envSettings = getSubdomainFormSettings('consign'); - return (
+ editable={!this.props.email} + overrideForm={!!this.props.email}> { - return this.state.editionList[pieceId] - .filter((edition) => edition.selected).length > 0; - }); - return filteredPieceIdList; - }, - - fetchSelectedEditionList() { - let selectedEditionList = []; - - Object - .keys(this.state.editionList) - .forEach((pieceId) => { - let filteredEditionsForPiece = this.state.editionList[pieceId].filter((edition) => edition.selected); - selectedEditionList = selectedEditionList.concat(filteredEditionsForPiece); - }); - - return selectedEditionList; - }, - clearAllSelections() { EditionListActions.clearAllEditionSelections(); EditionListActions.closeAllEditionLists(); }, - handleSuccess() { - PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search, - this.state.orderBy, this.state.orderAsc, this.state.filterBy); - - this.fetchSelectedPieceEditionList() - .forEach((pieceId) => { - EditionListActions.refreshEditionList({pieceId, filterBy: {}}); - }); - EditionListActions.clearAllEditionSelections(); - }, - render() { - let selectedEditions = this.fetchSelectedEditionList(); - let availableAcls = getAvailableAcls(selectedEditions, (aclName) => aclName !== 'acl_view'); - - if(Object.keys(availableAcls).length > 0) { + if (Object.keys(this.props.availableAcls).length > 0) { return (
@@ -104,7 +70,7 @@ let PieceListBulkModal = React.createClass({
+ numberOfSelectedEditions={this.props.selectedEditions.length} />          

- - - + {this.props.children}
diff --git a/js/components/piece_list.js b/js/components/piece_list.js index c427a911..528ee409 100644 --- a/js/components/piece_list.js +++ b/js/components/piece_list.js @@ -13,6 +13,9 @@ import AccordionList from './ascribe_accordion_list/accordion_list'; import AccordionListItemWallet from './ascribe_accordion_list/accordion_list_item_wallet'; import AccordionListItemTableEditions from './ascribe_accordion_list/accordion_list_item_table_editions'; +import AclButtonList from './ascribe_buttons/acl_button_list.js'; +import DeleteButton from './ascribe_buttons/delete_button'; + import Pagination from './ascribe_pagination/pagination'; import PieceListFilterDisplay from './piece_list_filter_display'; @@ -24,6 +27,7 @@ import AscribeSpinner from './ascribe_spinner'; import AppConstants from '../constants/application_constants'; +import { getAvailableAcls } from '../utils/acl_utils'; import { mergeOptions } from '../utils/general_utils'; import { getLangText } from '../utils/lang_utils'; import { setDocumentTitle } from '../utils/dom_utils'; @@ -32,6 +36,7 @@ import { setDocumentTitle } from '../utils/dom_utils'; let PieceList = React.createClass({ propTypes: { accordionListItemType: React.PropTypes.func, + bulkModalButtonListType: React.PropTypes.func, redirectTo: React.PropTypes.string, customSubmitButton: React.PropTypes.element, filterParams: React.PropTypes.array, @@ -45,6 +50,7 @@ let PieceList = React.createClass({ getDefaultProps() { return { accordionListItemType: AccordionListItemWallet, + bulkModalButtonListType: AclButtonList, orderParams: ['artist_name', 'title'], filterParams: [{ label: getLangText('Show works I can'), @@ -152,9 +158,46 @@ let PieceList = React.createClass({ orderBy, this.state.orderAsc, this.state.filterBy); }, + fetchSelectedPieceEditionList() { + let filteredPieceIdList = Object.keys(this.state.editionList) + .filter((pieceId) => { + return this.state.editionList[pieceId] + .filter((edition) => edition.selected).length > 0; + }); + return filteredPieceIdList; + }, + + fetchSelectedEditionList() { + let selectedEditionList = []; + + Object + .keys(this.state.editionList) + .forEach((pieceId) => { + let filteredEditionsForPiece = this.state.editionList[pieceId].filter((edition) => edition.selected); + selectedEditionList = selectedEditionList.concat(filteredEditionsForPiece); + }); + + return selectedEditionList; + }, + + handleAclSuccess() { + PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search, + this.state.orderBy, this.state.orderAsc, this.state.filterBy); + + this.fetchSelectedPieceEditionList() + .forEach((pieceId) => { + EditionListActions.refreshEditionList({pieceId, filterBy: {}}); + }); + EditionListActions.clearAllEditionSelections(); + }, + render() { - let loadingElement = ; - let AccordionListItemType = this.props.accordionListItemType; + const loadingElement = ; + const AccordionListItemType = this.props.accordionListItemType; + const BulkModalButtonListType = this.props.bulkModalButtonListType; + + const selectedEditions = this.fetchSelectedEditionList(); + const availableAcls = getAvailableAcls(selectedEditions, (aclName) => aclName !== 'acl_view'); setDocumentTitle(getLangText('Collection')); @@ -178,7 +221,19 @@ let PieceList = React.createClass({ } + availableAcls={availableAcls} + selectedEditions={selectedEditions} + className="ascribe-piece-list-bulk-modal"> + + + + diff --git a/js/components/whitelabel/wallet/components/lumenus/lumenus_buttons/lumenus_acl_button_list.js b/js/components/whitelabel/wallet/components/lumenus/lumenus_buttons/lumenus_acl_button_list.js new file mode 100644 index 00000000..6c1aa0ae --- /dev/null +++ b/js/components/whitelabel/wallet/components/lumenus/lumenus_buttons/lumenus_acl_button_list.js @@ -0,0 +1,39 @@ +'use strict'; + +import React from 'react'; + +import LumenusSubmitButton from './lumenus_submit_button'; + +import AclProxy from '../../../../../acl_proxy'; + +import DeleteButton from '../../../../../ascribe_buttons/delete_button'; + +let LumenusAclButtonList = React.createClass({ + propTypes: { + availableAcls: React.PropTypes.object.isRequired, + className: React.PropTypes.string, + editions: React.PropTypes.array, + handleSuccess: React.PropTypes.func, + children: React.PropTypes.oneOfType([ + React.PropTypes.arrayOf(React.PropTypes.element), + React.PropTypes.element + ]) + }, + + render() { + return ( +
+ + + + {this.props.children} +
+ ); + } +}); + +export default LumenusAclButtonList; diff --git a/js/components/whitelabel/wallet/components/lumenus/lumenus_buttons/lumenus_submit_button.js b/js/components/whitelabel/wallet/components/lumenus/lumenus_buttons/lumenus_submit_button.js new file mode 100644 index 00000000..13483502 --- /dev/null +++ b/js/components/whitelabel/wallet/components/lumenus/lumenus_buttons/lumenus_submit_button.js @@ -0,0 +1,91 @@ +'use strict'; + +import React from 'react'; +import classNames from 'classnames'; + + +import GlobalNotificationModel from '../../../../../../models/global_notification_model'; +import GlobalNotificationActions from '../../../../../../actions/global_notification_actions'; +import UserActions from '../../../../../../actions/user_actions'; +import UserStore from '../../../../../../stores/user_store'; +import WhitelabelActions from '../../../../../../actions/whitelabel_actions'; +import WhitelabelStore from '../../../../../../stores/whitelabel_store'; + +import ConsignForm from '../../../../../ascribe_forms/form_consign'; + +import ModalWrapper from '../../../../../ascribe_modal/modal_wrapper'; + +import ApiUrls from '../../../../../../constants/api_urls'; + +import { getAclFormMessage, getAclFormDataId } from '../../../../../../utils/form_utils'; +import { mergeOptions } from '../../../../../../utils/general_utils'; +import { getLangText } from '../../../../../../utils/lang_utils'; + +let LumenusSubmitButton = React.createClass({ + propTypes: { + className: React.PropTypes.string, + editions: React.PropTypes.array, + handleSuccess: React.PropTypes.func, + }, + + getInitialState() { + return mergeOptions( + UserStore.getState(), + WhitelabelStore.getState() + ); + }, + + componentDidMount() { + UserStore.listen(this.onChange); + UserActions.fetchCurrentUser(); + WhitelabelStore.listen(this.onChange); + WhitelabelActions.fetchWhitelabel(); + }, + + componentWillUnmount() { + UserStore.unlisten(this.onChange); + WhitelabelStore.unlisten(this.onChange); + }, + + onChange(state) { + this.setState(state); + }, + + showNotification(response) { + this.props.handleSuccess(); + if (response.notification) { + let notification = new GlobalNotificationModel(response.notification, 'success'); + GlobalNotificationActions.appendGlobalNotification(notification); + } + }, + + render() { + const { className, editions, handleSuccess } = this.props; + const title = getLangText('Consign to Lumenus'); + const message = getAclFormMessage({ + aclName: 'acl_consign', + entities: editions, + isPiece: false, + senderName: this.state.currentUser.username + }); + + return ( + + {title} + + } + handleSuccess={this.showNotification} + title={title}> + + + ); + } +}); + +export default LumenusSubmitButton; diff --git a/js/components/whitelabel/wallet/components/lumenus/lumenus_piece_list.js b/js/components/whitelabel/wallet/components/lumenus/lumenus_piece_list.js index c3f01374..403e226b 100644 --- a/js/components/whitelabel/wallet/components/lumenus/lumenus_piece_list.js +++ b/js/components/whitelabel/wallet/components/lumenus/lumenus_piece_list.js @@ -1,6 +1,9 @@ 'use strict'; import React from 'react'; + +import LumenusAclButtonList from './lumenus_buttons/lumenus_acl_button_list'; + import PieceList from '../../../../piece_list'; import UserActions from '../../../../../actions/user_actions'; @@ -39,6 +42,7 @@ let LumenusPieceList = React.createClass({
= 1) { + if (editionsCopy.length >= 1) { availableAcls = editionsCopy[0].acl; - } - if(editionsCopy.length >= 2) { - for(let i = 1; i < editionsCopy.length; i++) { + } else if (editionsCopy.length >= 2) { + for (let i = 1; i < editionsCopy.length; i++) { availableAcls = intersectAcls(availableAcls, editionsCopy[i].acl); } } // convert acls back to key-value object let availableAclsObj = {}; - for(let i = 0; i < availableAcls.length; i++) { + for (let i = 0; i < availableAcls.length; i++) { availableAclsObj[availableAcls[i]] = true; } return availableAclsObj; -} \ No newline at end of file +} diff --git a/js/utils/form_utils.js b/js/utils/form_utils.js index a98d956f..d2d2cd29 100644 --- a/js/utils/form_utils.js +++ b/js/utils/form_utils.js @@ -5,15 +5,19 @@ import { getLangText } from './lang_utils'; import AppConstants from '../constants/application_constants'; /** - * Gets a dictionary of settings for a form based on the environment - * (ie. if on a whitelabel) - * @param {string} formName Name of the form - * @return {object} Settings key-val dictionary + * Get the data ids of the given piece or editions. + * @param {boolean} isPiece Is the given entities parameter a piece? (False: array of editions) + * @param {(object|object[])} pieceOrEditions Piece or array of editions + * @return {(object|object[])} Data IDs of the pieceOrEditions for the form */ -export function getSubdomainFormSettings(formName) { - let subdomainFormSettings = AppConstants.whitelabel.formSettings || {}; - - return subdomainFormSettings[formName] || {}; +export function getAclFormDataId(isPiece, pieceOrEditions) { + if (isPiece) { + return {piece_id: pieceOrEditions.id}; + } else { + return {bitcoin_id: pieceOrEditions.map(function(edition){ + return edition.bitcoin_id; + }).join()}; + } } /** @@ -21,6 +25,7 @@ export function getSubdomainFormSettings(formName) { * @param {object} options Options object for creating the message: * @param {string} options.aclName Enum name of an acl * @param {(object|object[])} options.entities Piece or array of Editions + * @param {boolean} options.isPiece Is the given entities parameter a piece? (False: array of editions) * @param {string} [options.senderName] Name of the sender * @return {string} Completed message */