From 6563bf97b0e552e5f6e6a47e4a019a0edb9cd340 Mon Sep 17 00:00:00 2001 From: ddejongh Date: Tue, 9 Jun 2015 13:29:22 +0200 Subject: [PATCH 01/11] toggable textarea --- gulpfile.js | 2 +- .../ascribe_buttons/button_submit_close.js | 2 +- .../ascribe_forms/form_note_personal.js | 43 +++++++++++ .../ascribe_forms/input_textarea_toggable.js | 72 +++++++++++++++++++ js/components/edition.js | 33 ++++----- js/components/edition_container.js | 10 +-- js/constants/api_urls.js | 3 +- js/constants/application_constants.js | 4 +- js/mixins/form_mixin.js | 16 ++++- sass/ascribe_textarea.scss | 21 ++++++ sass/main.scss | 1 + 11 files changed, 179 insertions(+), 28 deletions(-) create mode 100644 js/components/ascribe_forms/form_note_personal.js create mode 100644 js/components/ascribe_forms/input_textarea_toggable.js create mode 100644 sass/ascribe_textarea.scss diff --git a/gulpfile.js b/gulpfile.js index bf9dd46d..424796da 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -45,7 +45,7 @@ gulp.task('build', function() { bundle(false); }); -gulp.task('serve', ['browser-sync', 'lint:watch', 'sass', 'sass:watch', 'copy'], function() { +gulp.task('serve', ['browser-sync', 'sass', 'sass:watch', 'copy'], function() { bundle(true); }); diff --git a/js/components/ascribe_buttons/button_submit_close.js b/js/components/ascribe_buttons/button_submit_close.js index d1939e35..2d70fb03 100644 --- a/js/components/ascribe_buttons/button_submit_close.js +++ b/js/components/ascribe_buttons/button_submit_close.js @@ -14,7 +14,7 @@ let ButtonSubmitOrClose = React.createClass({
- ) + ); } return (
diff --git a/js/components/ascribe_forms/form_note_personal.js b/js/components/ascribe_forms/form_note_personal.js new file mode 100644 index 00000000..282afcdf --- /dev/null +++ b/js/components/ascribe_forms/form_note_personal.js @@ -0,0 +1,43 @@ +'use strict'; + +import React from 'react'; + +import apiUrls from '../../constants/api_urls'; +import FormMixin from '../../mixins/form_mixin'; + +import InputTextAreaToggable from './input_textarea_toggable'; + + +let PersonalNoteForm = React.createClass({ + mixins: [FormMixin], + + url() { + return apiUrls.note_notes; + }, + + getFormData() { + return { + bitcoin_id: this.getBitcoinIds().join(), + note: this.refs.personalNote.state.value + }; + }, + + renderForm() { + + return ( +
+ + + ); + } +}); + +export default PersonalNoteForm; \ No newline at end of file diff --git a/js/components/ascribe_forms/input_textarea_toggable.js b/js/components/ascribe_forms/input_textarea_toggable.js new file mode 100644 index 00000000..e7faea9c --- /dev/null +++ b/js/components/ascribe_forms/input_textarea_toggable.js @@ -0,0 +1,72 @@ +'use strict'; + +import React from 'react'; + +import AlertMixin from '../../mixins/alert_mixin'; +import TextareaAutosize from 'react-textarea-autosize'; +import Button from 'react-bootstrap/lib/Button'; + +let InputTextAreaToggable = React.createClass({ + + mixins: [AlertMixin], + + getInitialState() { + return { + value: this.props.defaultValue, + edited: false, + alerts: null // needed in AlertMixin + }; + }, + handleChange(event) { + this.setState({ + value: event.target.value, + edited: true + }); + }, + reset(){ + this.setState(this.getInitialState()); + }, + submit(){ + this.props.onSubmit(); + this.setState({edited: false}); + }, + render() { + let className = 'form-control ascribe-textarea'; + let buttons = null; + let textarea = null; + if (this.props.editable && this.state.edited){ + buttons = ( +
+ + +
+ ); + + } + if (this.props.editable){ + className = className + ' ascribe-textarea-editable'; + textarea = ( + + ); + } + else{ + textarea =
{this.state.value}
; + } + let alerts = (this.props.submitted) ? null : this.state.alerts; + return ( +
+ {alerts} + {textarea} + {buttons} +
+ ); + } +}); + +export default InputTextAreaToggable; \ No newline at end of file diff --git a/js/components/edition.js b/js/components/edition.js index 20e54990..deb53620 100644 --- a/js/components/edition.js +++ b/js/components/edition.js @@ -8,7 +8,8 @@ import Row from 'react-bootstrap/lib/Row'; import Col from 'react-bootstrap/lib/Col'; import Button from 'react-bootstrap/lib/Button'; import Glyphicon from 'react-bootstrap/lib/Glyphicon'; -import TextareaAutosize from 'react-textarea-autosize'; + +import PersonalNoteForm from './ascribe_forms/form_note_personal'; import EditionActions from '../actions/edition_actions'; import AclButtonList from './ascribe_buttons/acl_button_list'; @@ -23,7 +24,7 @@ let Edition = React.createClass({ edition: React.PropTypes.object, currentUser: React.PropTypes.object, deleteEdition: React.PropTypes.func, - savePersonalNote: React.PropTypes.func + loadEdition: React.PropTypes.func }, render() { @@ -39,10 +40,14 @@ let Edition = React.createClass({ {this.props.edition.bitcoin_id} ); - let hashOfArtwork = ( + let hashOfArtwork = ( {this.props.edition.hash_as_address} ); + let ownerAddress = ( + {this.props.edition.btc_owner_address_noprefix} + ); + return ( @@ -64,8 +69,9 @@ let Edition = React.createClass({ - + + value={ownerAddress} />
-
{ this.props.label }{this.props.separator}
+
{ this.props.label + this.props.separator}
{ this.props.value }
@@ -304,7 +310,7 @@ let EditionDetailHistoryIterator = React.createClass({ let EditionPersonalNote = React.createClass({ propTypes: { - savePersonalNote: React.PropTypes.func + edition: React.PropTypes.object }, prepareSavePersonalNote() { @@ -316,14 +322,9 @@ let EditionPersonalNote = React.createClass({ return ( - - + ); diff --git a/js/components/edition_container.js b/js/components/edition_container.js index 1f2461bd..b2d3bca0 100644 --- a/js/components/edition_container.js +++ b/js/components/edition_container.js @@ -4,6 +4,9 @@ import React from 'react'; import { mergeOptions } from '../utils/general_utils'; +import apiUrls from '../constants/api_urls'; +import fetch from '../utils/fetch'; + import EditionActions from '../actions/edition_actions'; import EditionStore from '../stores/edition_store'; import UserActions from '../actions/user_actions'; @@ -40,9 +43,8 @@ let EditionContainer = React.createClass({ // Delete Edition from server }, - savePersonalNote(note) { - console.log(note); - // Save personalNote to server + loadEdition() { + EditionActions.fetchOne(this.props.params.editionId); }, render() { @@ -52,7 +54,7 @@ let EditionContainer = React.createClass({ edition={this.state.edition} currentUser={this.state.currentUser} deleteEdition={this.deleteEdition} - savePersonalNote={this.savePersonalNote}/> + loadEdition={this.loadEdition}/> ); } else { return ( diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js index 7d466561..fb807cb9 100644 --- a/js/constants/api_urls.js +++ b/js/constants/api_urls.js @@ -13,7 +13,8 @@ let apiUrls = { '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_unconsigns_request': AppConstants.baseUrl + 'ownership/unconsigns/request/', + 'note_notes': AppConstants.baseUrl + 'note/notes/' }; export default apiUrls; diff --git a/js/constants/application_constants.js b/js/constants/application_constants.js index 25486919..778033b4 100644 --- a/js/constants/application_constants.js +++ b/js/constants/application_constants.js @@ -1,8 +1,8 @@ 'use strict'; let constants = { - //'baseUrl': 'http://localhost:8000/api/', - 'baseUrl': 'http://staging.ascribe.io/api/', + 'baseUrl': 'http://localhost:8000/api/', + //'baseUrl': 'http://staging.ascribe.io/api/', 'debugCredentialBase64': 'ZGltaUBtYWlsaW5hdG9yLmNvbTowMDAwMDAwMDAw', // dimi@mailinator:0000000000 'aclList': ['edit', 'consign', 'transfer', 'loan', 'share', 'download', 'view', 'delete', 'del_from_collection', 'add_to_collection'] }; diff --git a/js/mixins/form_mixin.js b/js/mixins/form_mixin.js index 9f5312fe..e0cc39f1 100644 --- a/js/mixins/form_mixin.js +++ b/js/mixins/form_mixin.js @@ -14,22 +14,32 @@ export const FormMixin = { }, submit(e) { - e.preventDefault(); + if (e) { + e.preventDefault(); + } this.setState({submitted: true}); this.clearErrors(); fetch .post(this.url(), { body: this.getFormData() }) - .then(() => this.props.handleSuccess()) + .then(() => this.handleSuccess() ) .catch(this.handleError); }, clearErrors(){ for (var ref in this.refs){ - this.refs[ref].clearAlerts(); + if ('clearAlerts' in this.refs[ref]){ + this.refs[ref].clearAlerts(); + } + } this.setState({errors: []}); }, + handleSuccess(){ + if ('handleSuccess' in this.props){ + this.props.handleSuccess(); + } + }, handleError(err){ if (err.json) { for (var input in err.json.errors){ diff --git a/sass/ascribe_textarea.scss b/sass/ascribe_textarea.scss new file mode 100644 index 00000000..f349628d --- /dev/null +++ b/sass/ascribe_textarea.scss @@ -0,0 +1,21 @@ +.ascribe-textarea { + border: none; + box-shadow: none; + margin-bottom: 1em; +} + +.ascribe-textarea-editable:hover { + border: 1px solid #AAA; +} + +.ascribe-pre{ + word-break: break-word; + /* white-space: pre-wrap; */ + white-space: -moz-pre-wrap; + white-space: -pre-wrap; + white-space: -o-pre-wrap; + /* word-wrap: break-word; */ + font-family: inherit; + text-align: justify; + background-color: white; +} diff --git a/sass/main.scss b/sass/main.scss index 58f43926..061e8a6e 100644 --- a/sass/main.scss +++ b/sass/main.scss @@ -10,6 +10,7 @@ @import 'ascribe_piece_list_bulk_modal'; @import 'ascribe_piece_list_toolbar'; @import 'ascribe_edition'; +@import 'ascribe_textarea'; @import 'ascribe_media_player'; @import 'offset_right'; From 509aa111ab118b52ecad38a6111d1f5655bbe57f Mon Sep 17 00:00:00 2001 From: ddejongh Date: Tue, 9 Jun 2015 16:10:38 +0200 Subject: [PATCH 02/11] Merge remote-tracking branch 'remotes/origin/master' into AD-43-in-piece_detail-add-generic-field- Conflicts: gulpfile.js added notifications cleaned up proptypes --- js/components/ascribe_buttons/acl_button.js | 22 ++++++++++--- .../ascribe_buttons/button_submit_close.js | 11 ++++--- js/components/ascribe_forms/alert.js | 5 ++- js/components/ascribe_forms/form_consign.js | 1 + js/components/ascribe_forms/input_checkbox.js | 5 +++ js/components/ascribe_forms/input_date.js | 25 +++------------ js/components/ascribe_forms/input_hidden.js | 4 +++ js/components/ascribe_forms/input_text.js | 7 +++++ js/components/ascribe_forms/input_textarea.js | 5 +++ .../ascribe_forms/input_textarea_toggable.js | 9 ++++++ js/components/ascribe_modal/modal_wrapper.js | 24 ++++++++++++-- .../piece_list_bulk_modal.js | 1 - js/components/edition.js | 31 ++++++++++++++++--- js/components/piece_list.js | 5 ++- js/mixins/form_mixin.js | 11 +++++-- 15 files changed, 123 insertions(+), 43 deletions(-) diff --git a/js/components/ascribe_buttons/acl_button.js b/js/components/ascribe_buttons/acl_button.js index 518a80d6..18fdf4da 100644 --- a/js/components/ascribe_buttons/acl_button.js +++ b/js/components/ascribe_buttons/acl_button.js @@ -9,6 +9,9 @@ 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'; + let AclButton = React.createClass({ propTypes: { action: React.PropTypes.oneOf(AppConstants.aclList).isRequired, @@ -23,31 +26,40 @@ let AclButton = React.createClass({ return { title: 'Consign artwork', tooltip: 'Have someone else sell the artwork', - form: + form: , + handleSuccess: this.showNotification }; } else if (this.props.action === 'transfer') { return { title: 'Transfer artwork', tooltip: 'Transfer the ownership of the artwork', - form: + form: , + handleSuccess: this.showNotification }; } else if (this.props.action === 'loan'){ return { title: 'Loan artwork', tooltip: 'Loan your artwork for a limited period of time', - form: + form: , + handleSuccess: this.showNotification }; } else if (this.props.action === 'share'){ return { title: 'Share artwork', tooltip: 'Share the artwork', - form: + form: , + handleSuccess: this.showNotification }; } }, + showNotification(response){ + this.props.handleSuccess(); + let notification = new GlobalNotificationModel(response.notification, 'success'); + GlobalNotificationActions.appendGlobalNotification(notification); + }, render() { let shouldDisplay = this.props.availableAcls.indexOf(this.props.action) > -1; let aclProps = this.actionProperties(); @@ -60,7 +72,7 @@ let AclButton = React.createClass({ } currentUser={ this.props.currentUser } editions={ this.props.editions } - handleSuccess={ this.props.handleSuccess } + handleSuccess={ aclProps.handleSuccess } title={ aclProps.title } tooltip={ aclProps.tooltip }> { aclProps.form } diff --git a/js/components/ascribe_buttons/button_submit_close.js b/js/components/ascribe_buttons/button_submit_close.js index 2d70fb03..d5a94f91 100644 --- a/js/components/ascribe_buttons/button_submit_close.js +++ b/js/components/ascribe_buttons/button_submit_close.js @@ -2,12 +2,13 @@ import React from 'react'; -/* - Is this even used somewhere? - Deprecate? 5.6.15 - Tim - - */ let ButtonSubmitOrClose = React.createClass({ + propTypes: { + submitted: React.PropTypes.bool.isRequired, + text: React.PropTypes.string.isRequired, + onClose: React.PropTypes.func.isRequired + }, + render() { if (this.props.submitted){ return ( diff --git a/js/components/ascribe_forms/alert.js b/js/components/ascribe_forms/alert.js index 4d5bae64..21f378ef 100644 --- a/js/components/ascribe_forms/alert.js +++ b/js/components/ascribe_forms/alert.js @@ -4,6 +4,10 @@ import React from 'react'; import Alert from 'react-bootstrap/lib/Alert'; let AlertDismissable = React.createClass({ + propTypes: { + error: React.PropTypes.array.isRequired + }, + getInitialState() { return { alertVisible: true @@ -20,7 +24,6 @@ let AlertDismissable = React.createClass({ render() { if (this.state.alertVisible) { - let key = this.props.error; return ( {this.props.error} diff --git a/js/components/ascribe_forms/form_consign.js b/js/components/ascribe_forms/form_consign.js index 0137e4a0..42f909a8 100644 --- a/js/components/ascribe_forms/form_consign.js +++ b/js/components/ascribe_forms/form_consign.js @@ -11,6 +11,7 @@ import ButtonSubmitOrClose from '../ascribe_buttons/button_submit_close'; let ConsignForm = React.createClass({ mixins: [FormMixin], + url() { return ApiUrls.ownership_consigns; }, diff --git a/js/components/ascribe_forms/input_checkbox.js b/js/components/ascribe_forms/input_checkbox.js index 187a1acf..28f75bc3 100644 --- a/js/components/ascribe_forms/input_checkbox.js +++ b/js/components/ascribe_forms/input_checkbox.js @@ -5,6 +5,11 @@ import React from 'react'; import AlertMixin from '../../mixins/alert_mixin'; let InputCheckbox = React.createClass({ + propTypes: { + submitted: React.PropTypes.bool.isRequired, + required: React.PropTypes.string.isRequired, + label: React.PropTypes.string.isRequired + }, mixins: [AlertMixin], diff --git a/js/components/ascribe_forms/input_date.js b/js/components/ascribe_forms/input_date.js index 5ae1221a..56af046e 100644 --- a/js/components/ascribe_forms/input_date.js +++ b/js/components/ascribe_forms/input_date.js @@ -6,6 +6,10 @@ import AlertMixin from '../../mixins/alert_mixin'; import DatePicker from 'react-datepicker/dist/react-datepicker'; let InputDate = React.createClass({ + propTypes: { + submitted: React.PropTypes.bool, + placeholderText: React.PropTypes.string + }, mixins: [AlertMixin], @@ -20,11 +24,10 @@ let InputDate = React.createClass({ handleChange(date) { this.setState({ value: date, - value_formatted: date.format("YYYY-MM-DD")}); + value_formatted: date.format('YYYY-MM-DD')}); }, render: function () { - let className = 'form-control input-text-ascribe'; let alerts = (this.props.submitted) ? null : this.state.alerts; return (
@@ -37,24 +40,6 @@ let InputDate = React.createClass({ placeholderText={this.props.placeholderText}/>
); - // CAN THIS BE REMOVED??? - // - // - Tim? - // - //return ( - //
- // - // - // - // - //
- //) } }); diff --git a/js/components/ascribe_forms/input_hidden.js b/js/components/ascribe_forms/input_hidden.js index c221372f..b6a8ac46 100644 --- a/js/components/ascribe_forms/input_hidden.js +++ b/js/components/ascribe_forms/input_hidden.js @@ -5,6 +5,10 @@ import React from 'react'; import AlertMixin from '../../mixins/alert_mixin'; let InputHidden = React.createClass({ + propTypes: { + submitted: React.PropTypes.bool, + value: React.PropTypes.string + }, mixins: [AlertMixin], diff --git a/js/components/ascribe_forms/input_text.js b/js/components/ascribe_forms/input_text.js index b35c1ac5..7f0ee5d0 100644 --- a/js/components/ascribe_forms/input_text.js +++ b/js/components/ascribe_forms/input_text.js @@ -5,6 +5,13 @@ import React from 'react'; import AlertMixin from '../../mixins/alert_mixin'; let InputText = React.createClass({ + propTypes: { + submitted: React.PropTypes.bool, + onBlur: React.PropTypes.func, + type: React.PropTypes.string, + required: React.PropTypes.string, + placeHolder: React.PropTypes.string + }, mixins: [AlertMixin], diff --git a/js/components/ascribe_forms/input_textarea.js b/js/components/ascribe_forms/input_textarea.js index 1d7af441..2c5ab40a 100644 --- a/js/components/ascribe_forms/input_textarea.js +++ b/js/components/ascribe_forms/input_textarea.js @@ -5,6 +5,11 @@ import React from 'react'; import AlertMixin from '../../mixins/alert_mixin'; let InputTextArea = React.createClass({ + propTypes: { + submitted: React.PropTypes.bool, + required: React.PropTypes.string, + defaultValue: React.PropTypes.string + }, mixins: [AlertMixin], diff --git a/js/components/ascribe_forms/input_textarea_toggable.js b/js/components/ascribe_forms/input_textarea_toggable.js index e7faea9c..22e95fda 100644 --- a/js/components/ascribe_forms/input_textarea_toggable.js +++ b/js/components/ascribe_forms/input_textarea_toggable.js @@ -8,6 +8,15 @@ import Button from 'react-bootstrap/lib/Button'; let InputTextAreaToggable = React.createClass({ + propTypes: { + editable: React.PropTypes.bool.isRequired, + submitted: React.PropTypes.bool, + rows: React.PropTypes.number.isRequired, + onSubmit: React.PropTypes.func.isRequired, + required: React.PropTypes.string, + defaultValue: React.PropTypes.string + }, + mixins: [AlertMixin], getInitialState() { diff --git a/js/components/ascribe_modal/modal_wrapper.js b/js/components/ascribe_modal/modal_wrapper.js index 0342bfb6..86246419 100644 --- a/js/components/ascribe_modal/modal_wrapper.js +++ b/js/components/ascribe_modal/modal_wrapper.js @@ -11,6 +11,16 @@ import Tooltip from 'react-bootstrap/lib/Tooltip'; import ModalMixin from '../../mixins/modal_mixin'; let ModalWrapper = React.createClass({ + propTypes: { + title: React.PropTypes.string.isRequired, + editions: React.PropTypes.array.isRequired, + currentUser: React.PropTypes.object.isRequired, + onRequestHide: React.PropTypes.func, + handleSuccess: React.PropTypes.func.isRequired, + button: React.PropTypes.object.isRequired, + children: React.PropTypes.object, + tooltip: React.PropTypes.string.isRequired + }, render() { return ( @@ -32,13 +42,21 @@ let ModalWrapper = React.createClass({ } }); -// + let ModalBody = React.createClass({ + propTypes: { + editions: React.PropTypes.array, + currentUser: React.PropTypes.object, + onRequestHide: React.PropTypes.func, + handleSuccess: React.PropTypes.func, + children: React.PropTypes.object, + title: React.PropTypes.string.isRequired + }, mixins: [ModalMixin], - handleSuccess(){ - this.props.handleSuccess(); + handleSuccess(response){ + this.props.handleSuccess(response); this.props.onRequestHide(); }, 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 48c02221..5c9d691b 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 @@ -93,7 +93,6 @@ let PieceListBulkModal = React.createClass({ .forEach((pieceId) => { EditionListActions.fetchEditionList(pieceId, this.state.orderBy, this.state.orderAsc); }); - GlobalNotificationActions.updateGlobalNotification({message: 'Transfer successful'}); EditionListActions.clearAllEditionSelections(); }, diff --git a/js/components/edition.js b/js/components/edition.js index deb53620..31248f99 100644 --- a/js/components/edition.js +++ b/js/components/edition.js @@ -73,6 +73,12 @@ let Edition = React.createClass({ handleSuccess={this.props.loadEdition} edition={this.props.edition}/> + + + + + + + + ); + } +}); + + + +let EditionFurtherDetails = React.createClass({ + propTypes: { + edition: React.PropTypes.object, + handleSuccess: React.PropTypes.func }, render() { diff --git a/js/components/piece_list.js b/js/components/piece_list.js index 479b9c3f..ffe461a5 100644 --- a/js/components/piece_list.js +++ b/js/components/piece_list.js @@ -27,7 +27,10 @@ let PieceList = React.createClass({ componentDidMount() { let page = this.props.query.page || 1; PieceListStore.listen(this.onChange); - PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search, this.state.orderBy, this.state.orderAsc); + if (this.state.pieceList.length === 0){ + PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search, this.state.orderBy, this.state.orderAsc); + } + }, componentWillUnmount() { diff --git a/js/mixins/form_mixin.js b/js/mixins/form_mixin.js index e0cc39f1..35a95bd5 100644 --- a/js/mixins/form_mixin.js +++ b/js/mixins/form_mixin.js @@ -6,6 +6,11 @@ import React from 'react'; import AlertDismissable from '../components/ascribe_forms/alert'; export const FormMixin = { + propTypes: { + editions: React.PropTypes.array, + currentUser: React.PropTypes.object + }, + getInitialState() { return { submitted: false, @@ -21,7 +26,7 @@ export const FormMixin = { this.clearErrors(); fetch .post(this.url(), { body: this.getFormData() }) - .then(() => this.handleSuccess() ) + .then(this.handleSuccess) .catch(this.handleError); }, @@ -34,9 +39,9 @@ export const FormMixin = { } this.setState({errors: []}); }, - handleSuccess(){ + handleSuccess(response){ if ('handleSuccess' in this.props){ - this.props.handleSuccess(); + this.props.handleSuccess(response); } }, From 9241d3e38fedcdde0726de01699912e06736f458 Mon Sep 17 00:00:00 2001 From: ddejongh Date: Tue, 9 Jun 2015 17:24:06 +0200 Subject: [PATCH 03/11] further details functional / unstyled --- .../ascribe_forms/form_piece_extradata.js | 19 +++++++++----- js/components/edition.js | 26 ++++++++++++++++--- js/components/edition_container.js | 3 --- js/constants/api_urls.js | 3 ++- js/utils/fetch.js | 10 +++---- 5 files changed, 42 insertions(+), 19 deletions(-) diff --git a/js/components/ascribe_forms/form_piece_extradata.js b/js/components/ascribe_forms/form_piece_extradata.js index 282afcdf..41828120 100644 --- a/js/components/ascribe_forms/form_piece_extradata.js +++ b/js/components/ascribe_forms/form_piece_extradata.js @@ -2,34 +2,39 @@ import React from 'react'; +import fetch from '../../utils/fetch'; + import apiUrls from '../../constants/api_urls'; import FormMixin from '../../mixins/form_mixin'; import InputTextAreaToggable from './input_textarea_toggable'; -let PersonalNoteForm = React.createClass({ +let PieceExtraDataForm = React.createClass({ mixins: [FormMixin], url() { - return apiUrls.note_notes; + return fetch.prepareUrl(apiUrls.piece_extradata, {piece_id: this.props.editions[0].bitcoin_id}); }, getFormData() { + let extradata = {}; + extradata[this.props.name] = this.refs[this.props.name].state.value; return { bitcoin_id: this.getBitcoinIds().join(), - note: this.refs.personalNote.state.value + extradata: extradata }; }, renderForm() { return ( -
+ +
{this.props.title}
@@ -345,7 +353,19 @@ let EditionFurtherDetails = React.createClass({ return ( - + + diff --git a/js/components/edition_container.js b/js/components/edition_container.js index b2d3bca0..8f8af927 100644 --- a/js/components/edition_container.js +++ b/js/components/edition_container.js @@ -4,9 +4,6 @@ import React from 'react'; import { mergeOptions } from '../utils/general_utils'; -import apiUrls from '../constants/api_urls'; -import fetch from '../utils/fetch'; - import EditionActions from '../actions/edition_actions'; import EditionStore from '../stores/edition_store'; import UserActions from '../actions/user_actions'; diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js index fb807cb9..fd973ffb 100644 --- a/js/constants/api_urls.js +++ b/js/constants/api_urls.js @@ -14,7 +14,8 @@ let apiUrls = { 'ownership_consigns': AppConstants.baseUrl + 'ownership/consigns/', 'ownership_unconsigns': AppConstants.baseUrl + 'ownership/unconsigns/', 'ownership_unconsigns_request': AppConstants.baseUrl + 'ownership/unconsigns/request/', - 'note_notes': AppConstants.baseUrl + 'note/notes/' + 'note_notes': AppConstants.baseUrl + 'note/notes/', + 'piece_extradata': AppConstants.baseUrl + 'pieces/${piece_id}/extradata/' }; export default apiUrls; diff --git a/js/utils/fetch.js b/js/utils/fetch.js index ec674935..96658587 100644 --- a/js/utils/fetch.js +++ b/js/utils/fetch.js @@ -88,19 +88,19 @@ class Fetch { get(url, params) { let paramsCopy = this._merge(params); - let newUrl = this.prepareUrl(url, params, true); + let newUrl = this.prepareUrl(url, paramsCopy, true); return this.request('get', newUrl); } post(url, params) { let paramsCopy = this._merge(params); - let newUrl = this.prepareUrl(url, params); + let newUrl = this.prepareUrl(url, paramsCopy); let body = null; - if (params.body) { - body = JSON.stringify(params.body); + if (paramsCopy && paramsCopy.body) { + body = JSON.stringify(paramsCopy.body); } - return this.request('post', url, { body }); + return this.request('post', newUrl, { body }); } defaults(options) { From af71196dfdefc32395dd4c03ef975ea8433d3d94 Mon Sep 17 00:00:00 2001 From: ddejongh Date: Wed, 10 Jun 2015 15:49:46 +0200 Subject: [PATCH 04/11] delete function for multi editions --- js/components/ascribe_buttons/acl_button.js | 10 ++-- .../ascribe_buttons/delete_button.js | 51 +++++++++++++++++++ .../ascribe_forms/form_delete_edition.js | 35 +++++++++++++ js/components/ascribe_modal/modal_wrapper.js | 10 +--- .../piece_list_bulk_modal.js | 1 - js/components/edition.js | 22 ++++---- js/constants/api_urls.js | 8 +-- js/mixins/form_mixin.js | 12 +++++ js/models/global_notification_model.js | 2 +- js/utils/fetch.js | 6 +++ 10 files changed, 128 insertions(+), 29 deletions(-) create mode 100644 js/components/ascribe_buttons/delete_button.js create mode 100644 js/components/ascribe_forms/form_delete_edition.js diff --git a/js/components/ascribe_buttons/acl_button.js b/js/components/ascribe_buttons/acl_button.js index 18fdf4da..b3930215 100644 --- a/js/components/ascribe_buttons/acl_button.js +++ b/js/components/ascribe_buttons/acl_button.js @@ -26,7 +26,7 @@ let AclButton = React.createClass({ return { title: 'Consign artwork', tooltip: 'Have someone else sell the artwork', - form: , + form: , handleSuccess: this.showNotification }; } @@ -34,7 +34,7 @@ let AclButton = React.createClass({ return { title: 'Transfer artwork', tooltip: 'Transfer the ownership of the artwork', - form: , + form: , handleSuccess: this.showNotification }; } @@ -42,7 +42,7 @@ let AclButton = React.createClass({ return { title: 'Loan artwork', tooltip: 'Loan your artwork for a limited period of time', - form: , + form: , handleSuccess: this.showNotification }; } @@ -50,7 +50,7 @@ let AclButton = React.createClass({ return { title: 'Share artwork', tooltip: 'Share the artwork', - form: , + form: , handleSuccess: this.showNotification }; } @@ -70,8 +70,6 @@ let AclButton = React.createClass({ {this.props.action.toUpperCase()}
} - currentUser={ this.props.currentUser } - editions={ this.props.editions } handleSuccess={ aclProps.handleSuccess } title={ aclProps.title } tooltip={ aclProps.tooltip }> diff --git a/js/components/ascribe_buttons/delete_button.js b/js/components/ascribe_buttons/delete_button.js new file mode 100644 index 00000000..d37546f6 --- /dev/null +++ b/js/components/ascribe_buttons/delete_button.js @@ -0,0 +1,51 @@ +import React from 'react'; +import Router from 'react-router'; + +import Button from 'react-bootstrap/lib/Button'; + +import EditionDeleteForm from '../ascribe_forms/form_delete_edition'; +import ModalWrapper from '../ascribe_modal/modal_wrapper'; + +import GlobalNotificationModel from '../../models/global_notification_model'; +import GlobalNotificationActions from '../../actions/global_notification_actions'; + +let DeleteButton = React.createClass({ + propTypes: { + editions: React.PropTypes.array.isRequired, + }, + + mixins: [Router.Navigation], + + showNotification(response){ + this.transitionTo('pieces'); + let notification = new GlobalNotificationModel(response.notification, 'success'); + GlobalNotificationActions.appendGlobalNotification(notification); + }, + render: function () { + let btnDelete = null; + let content = ; + if (this.props.edition.acl.indexOf('delete') > -1) { + btnDelete = ; + } + else if (this.props.edition.acl.indexOf('del_from_collection') > -1){ + btnDelete = ; + } + else{ + return
; + } + return ( + + { content } + + ); + } +}); + +export default DeleteButton; + diff --git a/js/components/ascribe_forms/form_delete_edition.js b/js/components/ascribe_forms/form_delete_edition.js new file mode 100644 index 00000000..dd7e5b88 --- /dev/null +++ b/js/components/ascribe_forms/form_delete_edition.js @@ -0,0 +1,35 @@ +'use strict'; + +import React from 'react'; + +import fetch from '../../utils/fetch'; +import ApiUrls from '../../constants/api_urls'; +import FormMixin from '../../mixins/form_mixin'; + +let EditionDeleteForm = React.createClass({ + + mixins: [FormMixin], + + url() { + return fetch.prepareUrl(ApiUrls.edition_delete, {edition_id: this.props.editions[0].bitcoin_id}); + }, + httpVerb(){ + return 'delete'; + }, + + renderForm () { + return ( +
+

Are you sure you would like to permanently delete this edition?

+

This is an irrevocable action.

+
+ + +
+
+ ); + } +}); + + +export default EditionDeleteForm; \ No newline at end of file diff --git a/js/components/ascribe_modal/modal_wrapper.js b/js/components/ascribe_modal/modal_wrapper.js index 86246419..e8dcbaa3 100644 --- a/js/components/ascribe_modal/modal_wrapper.js +++ b/js/components/ascribe_modal/modal_wrapper.js @@ -13,8 +13,6 @@ import ModalMixin from '../../mixins/modal_mixin'; let ModalWrapper = React.createClass({ propTypes: { title: React.PropTypes.string.isRequired, - editions: React.PropTypes.array.isRequired, - currentUser: React.PropTypes.object.isRequired, onRequestHide: React.PropTypes.func, handleSuccess: React.PropTypes.func.isRequired, button: React.PropTypes.object.isRequired, @@ -29,8 +27,6 @@ let ModalWrapper = React.createClass({ {this.props.children} @@ -45,8 +41,6 @@ let ModalWrapper = React.createClass({ let ModalBody = React.createClass({ propTypes: { - editions: React.PropTypes.array, - currentUser: React.PropTypes.object, onRequestHide: React.PropTypes.func, handleSuccess: React.PropTypes.func, children: React.PropTypes.object, @@ -63,9 +57,7 @@ let ModalBody = React.createClass({ renderChildren() { return ReactAddons.Children.map(this.props.children, (child) => { return ReactAddons.addons.cloneWithProps(child, { - editions: this.props.editions, - currentUser: this.props.currentUser, - onRequestHide: this.onRequestHide, + onRequestHide: this.props.onRequestHide, handleSuccess: this.handleSuccess }); }); 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 5c9d691b..d557a48d 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 @@ -13,7 +13,6 @@ import UserActions from '../../actions/user_actions'; import PieceListBulkModalSelectedEditionsWidget from './piece_list_bulk_modal_selected_editions_widget'; import AclButtonList from '../ascribe_buttons/acl_button_list'; -import GlobalNotificationActions from '../../actions/global_notification_actions'; let PieceListBulkModal = React.createClass({ propTypes: { diff --git a/js/components/edition.js b/js/components/edition.js index 11e54452..fa721778 100644 --- a/js/components/edition.js +++ b/js/components/edition.js @@ -1,6 +1,7 @@ 'use strict'; import React from 'react'; + import MediaPlayer from './ascribe_media/media_player'; import CollapsibleMixin from 'react-bootstrap/lib/CollapsibleMixin'; @@ -14,6 +15,7 @@ import PieceExtraDataForm from './ascribe_forms/form_piece_extradata'; import EditionActions from '../actions/edition_actions'; import AclButtonList from './ascribe_buttons/acl_button_list'; +import DeleteButton from './ascribe_buttons/delete_button'; import GlobalNotificationModel from '../models/global_notification_model'; import GlobalNotificationActions from '../actions/global_notification_actions'; @@ -113,11 +115,9 @@ let Edition = React.createClass({ - + @@ -348,6 +348,11 @@ let EditionFurtherDetails = React.createClass({ edition: React.PropTypes.object, handleSuccess: React.PropTypes.func }, + showNotification(){ + this.props.handleSuccess(); + let notification = new GlobalNotificationModel('Details updated', 'success'); + GlobalNotificationActions.appendGlobalNotification(notification); + }, render() { return ( @@ -356,17 +361,17 @@ let EditionFurtherDetails = React.createClass({ @@ -374,5 +379,4 @@ let EditionFurtherDetails = React.createClass({ } }); - export default Edition; diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js index fd973ffb..39cf3af4 100644 --- a/js/constants/api_urls.js +++ b/js/constants/api_urls.js @@ -6,16 +6,18 @@ let apiUrls = { '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}', + 'pieces_list': AppConstants.baseUrl + 'pieces/', + 'piece_extradata': AppConstants.baseUrl + 'pieces/${piece_id}/extradata/', 'edition': AppConstants.baseUrl + 'editions/${bitcoin_id}/', 'editions_list': AppConstants.baseUrl + 'pieces/${piece_id}/editions/', + 'edition_delete': AppConstants.baseUrl + 'editions/${edition_id}/', '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/', - 'note_notes': AppConstants.baseUrl + 'note/notes/', - 'piece_extradata': AppConstants.baseUrl + 'pieces/${piece_id}/extradata/' + 'note_notes': AppConstants.baseUrl + 'note/notes/' + }; export default apiUrls; diff --git a/js/mixins/form_mixin.js b/js/mixins/form_mixin.js index 35a95bd5..8404b5b3 100644 --- a/js/mixins/form_mixin.js +++ b/js/mixins/form_mixin.js @@ -24,11 +24,23 @@ export const FormMixin = { } this.setState({submitted: true}); this.clearErrors(); + let action = (this.httpVerb && this.httpVerb()) || 'post'; + this[action](); + }, + + post(){ fetch .post(this.url(), { body: this.getFormData() }) .then(this.handleSuccess) .catch(this.handleError); }, + + delete(){ + fetch + .delete(this.url()) + .then(this.handleSuccess) + .catch(this.handleError); + }, clearErrors(){ for (var ref in this.refs){ diff --git a/js/models/global_notification_model.js b/js/models/global_notification_model.js index 948ba20b..49a82934 100644 --- a/js/models/global_notification_model.js +++ b/js/models/global_notification_model.js @@ -1,7 +1,7 @@ 'use strict'; export default class GlobalNotificationModel { - constructor(message, type = 'info', dismissAfter = 3500) { + constructor(message, type = 'info', dismissAfter = 5000) { if(message) { this.message = message; } else { diff --git a/js/utils/fetch.js b/js/utils/fetch.js index 96658587..74477281 100644 --- a/js/utils/fetch.js +++ b/js/utils/fetch.js @@ -92,6 +92,12 @@ class Fetch { return this.request('get', newUrl); } + delete(url, params) { + let paramsCopy = this._merge(params); + let newUrl = this.prepareUrl(url, paramsCopy, true); + return this.request('delete', newUrl); + } + post(url, params) { let paramsCopy = this._merge(params); let newUrl = this.prepareUrl(url, paramsCopy); From bf0a2aeefb0ea8114561fe78f590cd9fea13f922 Mon Sep 17 00:00:00 2001 From: ddejongh Date: Thu, 11 Jun 2015 15:03:55 +0200 Subject: [PATCH 05/11] consign unconsign requests async emails --- gulpfile.js | 2 +- .../accordion_list_item_table_editions.js | 4 +- js/components/ascribe_buttons/acl_button.js | 10 ++- .../ascribe_buttons/acl_button_list.js | 8 ++ .../ascribe_buttons/delete_button.js | 31 ++++++-- .../ascribe_forms/form_delete_edition.js | 2 +- .../form_remove_editions_from_collection.js | 35 ++++++++ .../ascribe_forms/form_request_action.js | 79 +++++++++++++++++++ js/components/ascribe_forms/form_unconsign.js | 7 +- .../piece_list_bulk_modal.js | 28 +------ js/components/edition.js | 67 ++++++++++------ js/components/edition_container.js | 15 +--- js/constants/api_urls.js | 13 ++- js/constants/application_constants.js | 3 +- js/mixins/form_mixin.js | 10 +-- js/stores/edition_list_store.js | 4 +- js/utils/acl_utils.js | 23 ++++++ 17 files changed, 252 insertions(+), 89 deletions(-) create mode 100644 js/components/ascribe_forms/form_remove_editions_from_collection.js create mode 100644 js/components/ascribe_forms/form_request_action.js create mode 100644 js/utils/acl_utils.js diff --git a/gulpfile.js b/gulpfile.js index 1534c561..80b57550 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -53,7 +53,7 @@ gulp.task('js:build', function() { bundle(false); }); -gulp.task('serve', ['browser-sync', 'run-server', 'lint:watch', 'sass:build', 'sass:watch', 'copy'], function() { +gulp.task('serve', ['browser-sync', 'run-server', 'sass:build', 'sass:watch', 'copy'], function() { bundle(true); }); 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 9b843372..c98e632d 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 @@ -111,10 +111,10 @@ let AccordionListItemTableEditions = React.createClass({ new ColumnModel( (item) => { return { - 'content': item.edition_number + 'content': item.edition_number + ' of ' + item.num_editions }; }, 'edition_number', - '#', + 'Edition', TableItemText, 1, true, diff --git a/js/components/ascribe_buttons/acl_button.js b/js/components/ascribe_buttons/acl_button.js index b3930215..526581c8 100644 --- a/js/components/ascribe_buttons/acl_button.js +++ b/js/components/ascribe_buttons/acl_button.js @@ -3,6 +3,7 @@ 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 ShareForm from '../ascribe_forms/form_share_email'; @@ -30,7 +31,14 @@ let AclButton = React.createClass({ handleSuccess: this.showNotification }; } - else if (this.props.action === 'transfer') { + if (this.props.action === 'unconsign'){ + return { + title: 'Unconsign artwork', + tooltip: 'Have the owner manage his sales again', + form: , + handleSuccess: this.showNotification + }; + }else if (this.props.action === 'transfer') { return { title: 'Transfer artwork', tooltip: 'Transfer the ownership of the artwork', diff --git a/js/components/ascribe_buttons/acl_button_list.js b/js/components/ascribe_buttons/acl_button_list.js index ccabaa48..fca06408 100644 --- a/js/components/ascribe_buttons/acl_button_list.js +++ b/js/components/ascribe_buttons/acl_button_list.js @@ -6,6 +6,7 @@ import UserActions from '../../actions/user_actions'; import UserStore from '../../stores/user_store'; import AclButton from '../ascribe_buttons/acl_button'; +import DeleteButton from '../ascribe_buttons/delete_button'; let AclButtonList = React.createClass({ propTypes: { @@ -47,6 +48,12 @@ let AclButtonList = React.createClass({ editions={this.props.editions} currentUser={this.state.currentUser} handleSuccess={this.props.handleSuccess} /> + +
); } diff --git a/js/components/ascribe_buttons/delete_button.js b/js/components/ascribe_buttons/delete_button.js index d37546f6..0d37a236 100644 --- a/js/components/ascribe_buttons/delete_button.js +++ b/js/components/ascribe_buttons/delete_button.js @@ -1,34 +1,51 @@ +'use strict'; + import React from 'react'; import Router from 'react-router'; import Button from 'react-bootstrap/lib/Button'; import EditionDeleteForm from '../ascribe_forms/form_delete_edition'; +import EditionRemoveFromCollectionForm from '../ascribe_forms/form_remove_editions_from_collection'; import ModalWrapper from '../ascribe_modal/modal_wrapper'; import GlobalNotificationModel from '../../models/global_notification_model'; import GlobalNotificationActions from '../../actions/global_notification_actions'; +import { getAvailableAcls } from '../../utils/acl_utils'; + +import EditionListActions from '../../actions/edition_list_actions'; + let DeleteButton = React.createClass({ propTypes: { - editions: React.PropTypes.array.isRequired, + editions: React.PropTypes.array.isRequired }, mixins: [Router.Navigation], showNotification(response){ + this.props.editions + .forEach((edition) => { + EditionListActions.fetchEditionList(edition.parent); + }); + EditionListActions.clearAllEditionSelections(); this.transitionTo('pieces'); let notification = new GlobalNotificationModel(response.notification, 'success'); GlobalNotificationActions.appendGlobalNotification(notification); }, + render: function () { + let availableAcls = getAvailableAcls(this.props.editions); let btnDelete = null; - let content = ; - if (this.props.edition.acl.indexOf('delete') > -1) { - btnDelete = ; + let content = null; + + if (availableAcls.indexOf('delete') > -1) { + content = ; + btnDelete = ; } - else if (this.props.edition.acl.indexOf('del_from_collection') > -1){ - btnDelete = ; + else if (availableAcls.indexOf('del_from_collection') > -1){ + content = ; + btnDelete = ; } else{ return
; @@ -36,8 +53,6 @@ let DeleteButton = React.createClass({ return ( diff --git a/js/components/ascribe_forms/form_delete_edition.js b/js/components/ascribe_forms/form_delete_edition.js index dd7e5b88..3d81c08c 100644 --- a/js/components/ascribe_forms/form_delete_edition.js +++ b/js/components/ascribe_forms/form_delete_edition.js @@ -11,7 +11,7 @@ let EditionDeleteForm = React.createClass({ mixins: [FormMixin], url() { - return fetch.prepareUrl(ApiUrls.edition_delete, {edition_id: this.props.editions[0].bitcoin_id}); + return fetch.prepareUrl(ApiUrls.edition_delete, {edition_id: this.getBitcoinIds().join()}); }, httpVerb(){ return 'delete'; diff --git a/js/components/ascribe_forms/form_remove_editions_from_collection.js b/js/components/ascribe_forms/form_remove_editions_from_collection.js new file mode 100644 index 00000000..0a268c10 --- /dev/null +++ b/js/components/ascribe_forms/form_remove_editions_from_collection.js @@ -0,0 +1,35 @@ +'use strict'; + +import React from 'react'; + +import fetch from '../../utils/fetch'; +import apiUrls from '../../constants/api_urls'; +import FormMixin from '../../mixins/form_mixin'; + +let EditionRemoveFromCollectionForm = React.createClass({ + + mixins: [FormMixin], + + url() { + return fetch.prepareUrl(apiUrls.edition_remove_from_collection, {edition_id: this.getBitcoinIds().join()}); + }, + httpVerb(){ + return 'delete'; + }, + + renderForm () { + return ( +
+

Are you sure you would like to remove these editions from your collection?

+

This is an irrevocable action.

+
+ + +
+
+ ); + } +}); + + +export default EditionRemoveFromCollectionForm; \ No newline at end of file diff --git a/js/components/ascribe_forms/form_request_action.js b/js/components/ascribe_forms/form_request_action.js new file mode 100644 index 00000000..1bc08361 --- /dev/null +++ b/js/components/ascribe_forms/form_request_action.js @@ -0,0 +1,79 @@ +'use strict'; + +import React from 'react'; + +import Alert from 'react-bootstrap/lib/Alert'; + +import apiUrls from '../../constants/api_urls'; +import FormMixin from '../../mixins/form_mixin'; + +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; + } + } + }, + + handleRequest: function(e){ + e.preventDefault(); + this.submit(e); + }, + + getFormData() { + return { + bitcoin_id: this.getBitcoinIds().join() + }; + }, + + renderForm() { + let edition = this.props.editions[0]; + let buttons = ( + + +
ACCEPT
+
+ +
REJECT
+
+
+ ); + if (this.state.submitted){ + buttons = ( + + + + ); + } + return ( + + { edition.owner } requests you { edition.request_action } this edition.   + {buttons} + + ); + } +}); + + +export default RequestActionForm; \ No newline at end of file diff --git a/js/components/ascribe_forms/form_unconsign.js b/js/components/ascribe_forms/form_unconsign.js index 810c70d8..c7d1cff2 100644 --- a/js/components/ascribe_forms/form_unconsign.js +++ b/js/components/ascribe_forms/form_unconsign.js @@ -17,19 +17,20 @@ let UnConsignForm = React.createClass({ getFormData() { return { - bitcoin_id: this.props.edition.bitcoin_id, + bitcoin_id: this.getBitcoinIds().join(), unconsign_message: this.refs.unconsign_message.state.value, password: this.refs.password.state.value }; }, renderForm() { - let title = this.props.edition.title; + let title = this.getTitlesString().join(''); let username = this.props.currentUser.username; let message = `Hi, -I un-consign \" ${title} \" from you. +I un-consign: +${title}from you. Truly yours, ${username}`; 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 d557a48d..d3e7f127 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 @@ -14,6 +14,9 @@ import PieceListBulkModalSelectedEditionsWidget from './piece_list_bulk_modal_se import AclButtonList from '../ascribe_buttons/acl_button_list'; +import { getAvailableAcls } from '../../utils/acl_utils'; + + let PieceListBulkModal = React.createClass({ propTypes: { className: React.PropTypes.string @@ -60,29 +63,6 @@ let PieceListBulkModal = React.createClass({ return selectedEditionList; }, - intersectAcls(a, b) { - return a.filter((val) => b.indexOf(val) > -1); - }, - - getAvailableAcls() { - let availableAcls = []; - let selectedEditionList = this.fetchSelectedEditionList(); - - // If no edition has been selected, availableActions is empty - // If only one edition has been selected, their actions are available - // If more than one editions have been selected, their acl properties are intersected - if(selectedEditionList.length >= 1) { - availableAcls = selectedEditionList[0].acl; - } - if(selectedEditionList.length >= 2) { - for(let i = 1; i < selectedEditionList.length; i++) { - availableAcls = this.intersectAcls(availableAcls, selectedEditionList[i].acl); - } - } - - return availableAcls; - }, - clearAllSelections() { EditionListActions.clearAllEditionSelections(); }, @@ -96,8 +76,8 @@ let PieceListBulkModal = React.createClass({ }, render() { - let availableAcls = this.getAvailableAcls(); let selectedEditions = this.fetchSelectedEditionList(); + let availableAcls = getAvailableAcls(selectedEditions); if(availableAcls.length > 0) { return ( diff --git a/js/components/edition.js b/js/components/edition.js index fa721778..7d6a66f8 100644 --- a/js/components/edition.js +++ b/js/components/edition.js @@ -12,10 +12,10 @@ import Glyphicon from 'react-bootstrap/lib/Glyphicon'; import PersonalNoteForm from './ascribe_forms/form_note_personal'; import PieceExtraDataForm from './ascribe_forms/form_piece_extradata'; +import RequestActionForm from './ascribe_forms/form_request_action'; import EditionActions from '../actions/edition_actions'; import AclButtonList from './ascribe_buttons/acl_button_list'; -import DeleteButton from './ascribe_buttons/delete_button'; import GlobalNotificationModel from '../models/global_notification_model'; import GlobalNotificationActions from '../actions/global_notification_actions'; @@ -28,8 +28,6 @@ import classNames from 'classnames'; let Edition = React.createClass({ propTypes: { edition: React.PropTypes.object, - currentUser: React.PropTypes.object, - deleteEdition: React.PropTypes.func, loadEdition: React.PropTypes.func }, @@ -70,8 +68,7 @@ let Edition = React.createClass({ + edition={this.props.edition} /> @@ -93,6 +90,13 @@ let Edition = React.createClass({ history={this.props.edition.ownership_history} /> + 0}> + + + 0}> @@ -112,13 +116,6 @@ let Edition = React.createClass({ label="Owned by SPOOL address" value={ownerAddress} /> - - - -
); @@ -146,22 +143,31 @@ let EditionHeader = React.createClass({ let EditionSummary = React.createClass({ propTypes: { - edition: React.PropTypes.object, - currentUser: React.PropTypes.object + edition: React.PropTypes.object }, handleSuccess(){ EditionActions.fetchOne(this.props.edition.id); }, - + showNotification(response){ + this.handleSuccess(); + let notification = new GlobalNotificationModel(response.notification, 'success'); + GlobalNotificationActions.appendGlobalNotification(notification); + }, render() { - return ( -
- - - -
+ let status = null; + if (this.props.edition.status.length > 0){ + status = ; + } + let actions = null; + if (this.props.edition.request_action){ + actions = ( + ); + } + else { + actions = ( - + ); + } + + return ( +
+ + + + {status} +
+ {actions}
); @@ -273,8 +290,8 @@ let EditionDetailProperty = React.createClass({ getDefaultProps() { return { separator: ':', - labelClassName: 'col-xs-5 col-sm-5 col-md-5 col-lg-5', - valueClassName: 'col-xs-7 col-sm-7 col-md-7 col-lg-7' + labelClassName: 'col-xs-5 col-sm-4 col-md-3 col-lg-3', + valueClassName: 'col-xs-7 col-sm-8 col-md-9 col-lg-9' }; }, diff --git a/js/components/edition_container.js b/js/components/edition_container.js index 8f8af927..eaf94864 100644 --- a/js/components/edition_container.js +++ b/js/components/edition_container.js @@ -2,12 +2,8 @@ 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'; -import UserStore from '../stores/user_store'; import Edition from './edition'; @@ -16,7 +12,7 @@ import Edition from './edition'; */ let EditionContainer = React.createClass({ getInitialState() { - return mergeOptions(UserStore.getState(), EditionStore.getState()); + return EditionStore.getState(); }, onChange(state) { @@ -25,20 +21,13 @@ let EditionContainer = React.createClass({ componentDidMount() { EditionStore.listen(this.onChange); - UserStore.listen(this.onChange); - - UserActions.fetchCurrentUser(); EditionActions.fetchOne(this.props.params.editionId); }, componentWillUnmount() { EditionStore.unlisten(this.onChange); - UserStore.unlisten(this.onChange); }, - deleteEdition() { - // Delete Edition from server - }, loadEdition() { EditionActions.fetchOne(this.props.params.editionId); @@ -49,8 +38,6 @@ let EditionContainer = React.createClass({ return ( ); } else { diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js index 39cf3af4..f8bffda4 100644 --- a/js/constants/api_urls.js +++ b/js/constants/api_urls.js @@ -3,8 +3,6 @@ import AppConstants from './application_constants'; let apiUrls = { - 'ownership_shares_mail': AppConstants.baseUrl + 'ownership/shares/mail/', - 'ownership_transfers': AppConstants.baseUrl + 'ownership/transfers/', 'user': AppConstants.baseUrl + 'users/', 'piece': AppConstants.baseUrl + 'pieces/${piece_id}', 'pieces_list': AppConstants.baseUrl + 'pieces/', @@ -12,10 +10,19 @@ let apiUrls = { 'edition': AppConstants.baseUrl + 'editions/${bitcoin_id}/', 'editions_list': AppConstants.baseUrl + 'pieces/${piece_id}/editions/', 'edition_delete': AppConstants.baseUrl + 'editions/${edition_id}/', - 'ownership_loans': AppConstants.baseUrl + 'ownership/loans/', + 'edition_remove_from_collection': AppConstants.baseUrl + 'ownership/shares/${edition_id}/', + 'ownership_shares_mail': AppConstants.baseUrl + 'ownership/shares/mail/', + 'ownership_transfers': AppConstants.baseUrl + 'ownership/transfers/', 'ownership_consigns': AppConstants.baseUrl + 'ownership/consigns/', + 'ownership_consigns_confirm': AppConstants.baseUrl + 'ownership/consigns/confirm/', + 'ownership_consigns_deny': AppConstants.baseUrl + 'ownership/consigns/deny/', 'ownership_unconsigns': AppConstants.baseUrl + 'ownership/unconsigns/', 'ownership_unconsigns_request': AppConstants.baseUrl + 'ownership/unconsigns/request/', + 'ownership_unconsigns_deny': AppConstants.baseUrl + 'ownership/unconsigns/deny/', + 'ownership_loans': AppConstants.baseUrl + 'ownership/loans/', + 'ownership_loans_confirm': AppConstants.baseUrl + 'ownership/loans/confirm/', + 'ownership_loans_deny': AppConstants.baseUrl + 'ownership/loans/deny/', + 'note_notes': AppConstants.baseUrl + 'note/notes/' }; diff --git a/js/constants/application_constants.js b/js/constants/application_constants.js index 778033b4..81eadc26 100644 --- a/js/constants/application_constants.js +++ b/js/constants/application_constants.js @@ -4,7 +4,8 @@ let constants = { 'baseUrl': 'http://localhost:8000/api/', //'baseUrl': 'http://staging.ascribe.io/api/', 'debugCredentialBase64': 'ZGltaUBtYWlsaW5hdG9yLmNvbTowMDAwMDAwMDAw', // dimi@mailinator:0000000000 - 'aclList': ['edit', 'consign', 'transfer', 'loan', 'share', 'download', 'view', 'delete', 'del_from_collection', 'add_to_collection'] + 'aclList': ['edit', 'consign', 'consign_request', 'unconsign', 'unconsign_request', 'transfer', + 'loan', 'loan_request', 'share', 'download', 'view', 'delete', 'del_from_collection', 'add_to_collection'] }; export default constants; diff --git a/js/mixins/form_mixin.js b/js/mixins/form_mixin.js index 8404b5b3..770083ec 100644 --- a/js/mixins/form_mixin.js +++ b/js/mixins/form_mixin.js @@ -25,19 +25,19 @@ export const FormMixin = { this.setState({submitted: true}); this.clearErrors(); let action = (this.httpVerb && this.httpVerb()) || 'post'; - this[action](); + this[action](e); }, - post(){ + post(e){ fetch - .post(this.url(), { body: this.getFormData() }) + .post(this.url(e), { body: this.getFormData() }) .then(this.handleSuccess) .catch(this.handleError); }, - delete(){ + delete(e){ fetch - .delete(this.url()) + .delete(this.url(e)) .then(this.handleSuccess) .catch(this.handleError); }, diff --git a/js/stores/edition_list_store.js b/js/stores/edition_list_store.js index 092e498e..8773b7dc 100644 --- a/js/stores/edition_list_store.js +++ b/js/stores/edition_list_store.js @@ -16,7 +16,9 @@ class EditionListStore { this.editionList[pieceId].forEach((edition, i) => { // 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]}); + if (editionListOfPiece[i]){ + editionListOfPiece[i] = React.addons.update(edition, {$merge: editionListOfPiece[i]}); + } }); } this.editionList[pieceId] = editionListOfPiece; diff --git a/js/utils/acl_utils.js b/js/utils/acl_utils.js new file mode 100644 index 00000000..a29aa7bf --- /dev/null +++ b/js/utils/acl_utils.js @@ -0,0 +1,23 @@ +'use strict'; + +export function getAvailableAcls(editions) { + let availableAcls = []; + + // If no edition has been selected, availableActions is empty + // If only one edition has been selected, their actions are available + // If more than one editions have been selected, their acl properties are intersected + if(editions.length >= 1) { + availableAcls = editions[0].acl; + } + if(editions.length >= 2) { + for(let i = 1; i < editions.length; i++) { + availableAcls = intersectAcls(availableAcls, editions[i].acl); + } + } + + return availableAcls; +} + +export function intersectAcls(a, b) { + return a.filter((val) => b.indexOf(val) > -1); +} \ No newline at end of file From dcd770ab5fa302323706ab082730481ab2ba9e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 12 Jun 2015 13:36:55 +0200 Subject: [PATCH 06/11] readd sourcemaps --- gulpfile.js | 2 +- index.html | 1 + js/components/ascribe_buttons/delete_button.js | 2 +- js/components/ascribe_table/table_item_checkbox.js | 4 +++- js/constants/application_constants.js | 4 ++-- sass/main.scss | 6 ++++++ 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 80b57550..3e7f9c1e 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -94,7 +94,7 @@ gulp.task('sass:build', function () { }); gulp.task('sass:watch', function () { - gulp.watch('./sass/**/*.scss', ['sass']); + gulp.watch('./sass/**/*.scss', ['sass:build']); }); gulp.task('copy', function () { diff --git a/index.html b/index.html index 852f9027..6c7681c4 100644 --- a/index.html +++ b/index.html @@ -7,6 +7,7 @@ +
diff --git a/js/components/ascribe_buttons/delete_button.js b/js/components/ascribe_buttons/delete_button.js index 0d37a236..e52ff119 100644 --- a/js/components/ascribe_buttons/delete_button.js +++ b/js/components/ascribe_buttons/delete_button.js @@ -45,7 +45,7 @@ let DeleteButton = React.createClass({ } else if (availableAcls.indexOf('del_from_collection') > -1){ content = ; - btnDelete = ; + btnDelete = ; } else{ return
; diff --git a/js/components/ascribe_table/table_item_checkbox.js b/js/components/ascribe_table/table_item_checkbox.js index 131f7427..cb368369 100644 --- a/js/components/ascribe_table/table_item_checkbox.js +++ b/js/components/ascribe_table/table_item_checkbox.js @@ -17,7 +17,9 @@ let TableItemCheckbox = React.createClass({ render() { return ( - + + + ); } }); diff --git a/js/constants/application_constants.js b/js/constants/application_constants.js index 81eadc26..7b23a41f 100644 --- a/js/constants/application_constants.js +++ b/js/constants/application_constants.js @@ -1,8 +1,8 @@ 'use strict'; let constants = { - 'baseUrl': 'http://localhost:8000/api/', - //'baseUrl': 'http://staging.ascribe.io/api/', + //'baseUrl': 'http://localhost:8000/api/', + 'baseUrl': 'http://staging.ascribe.io/api/', 'debugCredentialBase64': 'ZGltaUBtYWlsaW5hdG9yLmNvbTowMDAwMDAwMDAw', // dimi@mailinator:0000000000 'aclList': ['edit', 'consign', 'consign_request', 'unconsign', 'unconsign_request', 'transfer', 'loan', 'loan_request', 'share', 'download', 'view', 'delete', 'del_from_collection', 'add_to_collection'] diff --git a/sass/main.scss b/sass/main.scss index 877c594c..587884eb 100644 --- a/sass/main.scss +++ b/sass/main.scss @@ -46,6 +46,12 @@ margin-bottom:0; } +/*This is aligning the first checkbox in pieclist detail with all the other ones*/ +.table > thead:first-child > tr:first-child > th { + padding-left:0; +} + + .ascribe-table-header-column > span { display: table-cell; vertical-align: middle; From 87bc6b3559fa6ad4655356dd33207116efbd8d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 12 Jun 2015 13:41:15 +0200 Subject: [PATCH 07/11] fix checkbox in edition list --- sass/main.scss | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sass/main.scss b/sass/main.scss index 587884eb..8db3e7a0 100644 --- a/sass/main.scss +++ b/sass/main.scss @@ -60,10 +60,6 @@ color: #424242; } -.ascribe-table-header-column > span > .glyphicon { - font-size: .5em; -} - .ascribe-table-item-column { display: table; font-family: 'Source Sans Pro'; @@ -79,6 +75,10 @@ text-overflow: ellipsis; } +.ascribe-table-item-column > span > input { + margin-top:14px; +} + .ascribe-table-item-selected { background-color: rgba(2, 182, 163, 0.5); } From 2bb004d2fb1abcd880f2e8869ec9f75fa23f2830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 12 Jun 2015 15:00:26 +0200 Subject: [PATCH 08/11] remove edition list count in table --- gulpfile.js | 2 +- .../ascribe_accordion_list/accordion_list_item.js | 3 --- .../accordion_list_item_table_editions.js | 9 ++------- .../accordion_list_item_table_toggle.js | 5 ++--- js/components/ascribe_table/table.js | 1 - js/components/ascribe_table/table_item_wrapper.js | 5 +---- js/components/header.js | 4 ++-- js/components/piece_list.js | 3 +-- js/stores/edition_list_store.js | 9 ++++----- js/stores/piece_list_store.js | 11 +++++++++++ 10 files changed, 24 insertions(+), 28 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 3e7f9c1e..9efe54a3 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -53,7 +53,7 @@ gulp.task('js:build', function() { bundle(false); }); -gulp.task('serve', ['browser-sync', 'run-server', 'sass:build', 'sass:watch', 'copy'], function() { +gulp.task('serve', ['browser-sync', 'run-server', 'lint:watch', 'sass:build', 'sass:watch', 'copy'], function() { bundle(true); }); diff --git a/js/components/ascribe_accordion_list/accordion_list_item.js b/js/components/ascribe_accordion_list/accordion_list_item.js index e822b5c6..57c16435 100644 --- a/js/components/ascribe_accordion_list/accordion_list_item.js +++ b/js/components/ascribe_accordion_list/accordion_list_item.js @@ -1,12 +1,9 @@ 'use strict'; import React from 'react'; -import Router from 'react-router'; import { getLangText } from '../../utils/lang_utils'; -let Link = Router.Link; - let AccordionListItem = React.createClass({ propTypes: { className: React.PropTypes.string, 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 c98e632d..67bec486 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,7 +1,6 @@ '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'; @@ -19,14 +18,11 @@ import TableItemAclFiltered from '../ascribe_table/table_item_acl_filtered'; import { getLangText } from '../../utils/lang_utils'; -let Link = Router.Link; - let AccordionListItemTableEditions = React.createClass({ propTypes: { className: React.PropTypes.string, parentId: React.PropTypes.number, - numOfEditions: React.PropTypes.number, show: React.PropTypes.bool }, @@ -88,7 +84,7 @@ let AccordionListItemTableEditions = React.createClass({ orderAsc = this.state.editionList[this.props.parentId].orderAsc; } - let transition = new TransitionModel('edition', 'editionId', 'bitcoin_id', PieceListActions.closeAllEditionLists); + let transition = new TransitionModel('edition', 'editionId', 'bitcoin_id'); let columnList = [ new ColumnModel( @@ -161,8 +157,7 @@ let AccordionListItemTableEditions = React.createClass({ + show={this.props.show} />
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 1f05de4b..542027cd 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 @@ -6,8 +6,7 @@ let AccordionListItemTableToggle = React.createClass({ propTypes: { className: React.PropTypes.string, onClick: React.PropTypes.func, - show: React.PropTypes.bool, - numOfTableItems: React.PropTypes.number + show: React.PropTypes.bool }, render() { @@ -15,7 +14,7 @@ let AccordionListItemTableToggle = React.createClass({ - {this.props.show ? 'Hide all ' + this.props.numOfTableItems + ' Editions' : 'Show all ' + this.props.numOfTableItems + ' Editions'} + {this.props.show ? 'Hide all Editions' : 'Show all Editions'} ); } diff --git a/js/components/ascribe_table/table.js b/js/components/ascribe_table/table.js index 44ba5d61..fa040a0b 100644 --- a/js/components/ascribe_table/table.js +++ b/js/components/ascribe_table/table.js @@ -20,7 +20,6 @@ let Table = React.createClass({ }, renderChildren() { - var that = this; return ReactAddons.Children.map(this.props.children, (child, i) => { return ReactAddons.addons.cloneWithProps(child, { columnList: this.props.columnList, diff --git a/js/components/ascribe_table/table_item_wrapper.js b/js/components/ascribe_table/table_item_wrapper.js index 9e1696f4..32b8df8f 100644 --- a/js/components/ascribe_table/table_item_wrapper.js +++ b/js/components/ascribe_table/table_item_wrapper.js @@ -4,7 +4,6 @@ import React from 'react'; import Router from 'react-router'; import { ColumnModel } from './models/table_models'; -import TableColumnMixin from '../../mixins/table_column_mixin'; let Link = Router.Link; @@ -15,7 +14,7 @@ let TableItemWrapper = React.createClass({ columnWidth: React.PropTypes.number.isRequired }, - mixins: [TableColumnMixin, Router.Navigation], + mixins: [Router.Navigation], render() { return ( @@ -25,8 +24,6 @@ let TableItemWrapper = React.createClass({ let TypeElement = column.displayType; let typeElementProps = column.transformFn(this.props.columnContent); - let columnClass = this.calcColumnClasses(this.props.columnList, i, this.props.columnWidth); - if(!column.transition) { return (
diff --git a/js/components/piece_list.js b/js/components/piece_list.js index 642cff3f..fd9cd183 100644 --- a/js/components/piece_list.js +++ b/js/components/piece_list.js @@ -77,8 +77,7 @@ let PieceList = React.createClass({ key={i}> + parentId={item.id} /> ); })} diff --git a/js/stores/edition_list_store.js b/js/stores/edition_list_store.js index f3c30ee1..c5ee36fe 100644 --- a/js/stores/edition_list_store.js +++ b/js/stores/edition_list_store.js @@ -8,6 +8,7 @@ import EditionsListActions from '../actions/edition_list_actions'; class EditionListStore { constructor() { this.editionList = {}; + this.editionOpenList = {}; this.bindActions(EditionsListActions); } @@ -24,6 +25,11 @@ class EditionListStore { this.editionList[pieceId] = editionListOfPiece; + // ToDo: Do merging later + this.editionOpenList[pieceId] = { + show: this.editionOpenList[pieceId] ? !this.editionOpenList[pieceId].show : true + }; + /** * orderBy and orderAsc are specific to a single list of editons * therefore they need to be saved in relation to their parent-piece. diff --git a/js/stores/piece_list_store.js b/js/stores/piece_list_store.js index 754f2d4a..3789b313 100644 --- a/js/stores/piece_list_store.js +++ b/js/stores/piece_list_store.js @@ -28,7 +28,7 @@ class PieceListStore { this.bindActions(PieceListActions); } - onShowEditionList(pieceId) { + /*onShowEditionList(pieceId) { this.pieceList .forEach((piece) => { if(piece.id === pieceId) { @@ -39,14 +39,14 @@ class PieceListStore { } } }); - } + }*/ - onCloseAllEditionLists() { + /*onCloseAllEditionLists() { this.pieceList .forEach((piece) => { piece.show = false; }); - } + }*/ onUpdatePieceList({ page, pageSize, search, pieceList, orderBy, orderAsc, pieceListCount }) { this.page = page; From 6e7037e5f2ddfc25d8b6b7d2efcffb5b174db0f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 15 Jun 2015 09:29:34 +0200 Subject: [PATCH 11/11] Finish implementing refactor for open and close for edition lists --- js/actions/edition_list_actions.js | 1 + .../accordion_list_item_table_editions.js | 13 +++++++++---- .../ascribe_buttons/delete_button.js | 3 ++- js/components/ascribe_forms/form_loan.js | 11 ++++++----- .../piece_list_bulk_modal.js | 1 + js/components/header.js | 2 +- js/stores/edition_list_store.js | 19 ++++++++++++------- 7 files changed, 32 insertions(+), 18 deletions(-) diff --git a/js/actions/edition_list_actions.js b/js/actions/edition_list_actions.js index e36ae1b0..c54bc6fd 100644 --- a/js/actions/edition_list_actions.js +++ b/js/actions/edition_list_actions.js @@ -10,6 +10,7 @@ class EditionListActions { 'updateEditionList', 'selectEdition', 'clearAllEditionSelections', + 'closeAllEditionLists', 'toggleEditionList' ); } 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 ea5d9d94..ed717c57 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 @@ -59,8 +59,13 @@ let AccordionListItemTableEditions = React.createClass({ }, toggleTable() { - // This is triggered everytime show all editions is clicked, which is wrong - EditionListActions.fetchEditionList(this.props.parentId); + let isEditionListOpen = this.state.isEditionListOpenForPieceId[this.props.parentId] ? this.state.isEditionListOpenForPieceId[this.props.parentId].show : false; + if(isEditionListOpen) { + EditionListActions.toggleEditionList(this.props.parentId); + } else { + EditionListActions.toggleEditionList(this.props.parentId); + EditionListActions.fetchEditionList(this.props.parentId); + } }, changeEditionListOrder(orderBy, orderAsc) { @@ -84,8 +89,8 @@ let AccordionListItemTableEditions = React.createClass({ orderAsc = this.state.editionList[this.props.parentId].orderAsc; } - if(this.props.parentId in this.state.editionOpenList) { - show = this.state.editionOpenList[this.props.parentId].show; + if(this.props.parentId in this.state.isEditionListOpenForPieceId) { + show = this.state.isEditionListOpenForPieceId[this.props.parentId].show; } let transition = new TransitionModel('edition', 'editionId', 'bitcoin_id'); diff --git a/js/components/ascribe_buttons/delete_button.js b/js/components/ascribe_buttons/delete_button.js index e52ff119..1b2a7748 100644 --- a/js/components/ascribe_buttons/delete_button.js +++ b/js/components/ascribe_buttons/delete_button.js @@ -23,12 +23,13 @@ let DeleteButton = React.createClass({ mixins: [Router.Navigation], - showNotification(response){ + showNotification(response) { this.props.editions .forEach((edition) => { EditionListActions.fetchEditionList(edition.parent); }); EditionListActions.clearAllEditionSelections(); + EditionListActions.closeAllEditionLists(); this.transitionTo('pieces'); let notification = new GlobalNotificationModel(response.notification, 'success'); GlobalNotificationActions.appendGlobalNotification(notification); diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index 2623c8bb..ae4ca49e 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -52,7 +52,7 @@ let LoanForm = React.createClass({ loaneeHasContract: true }); } - else{ + else { this.resetLoanContract(); } }) @@ -63,10 +63,11 @@ let LoanForm = React.createClass({ }, resetLoanContract(){ - this.setState({contract_key: null, - contract_url: null, - loaneeHasContract: false - }); + this.setState({ + contract_key: null, + contract_url: null, + loaneeHasContract: false + }); }, renderForm() { 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 d3e7f127..c50c09fd 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 @@ -65,6 +65,7 @@ let PieceListBulkModal = React.createClass({ clearAllSelections() { EditionListActions.clearAllEditionSelections(); + EditionListActions.closeAllEditionLists(); }, handleSuccess() { diff --git a/js/components/header.js b/js/components/header.js index 140aeead..2ad26657 100644 --- a/js/components/header.js +++ b/js/components/header.js @@ -38,7 +38,7 @@ let Header = React.createClass({ return (