From d3cc6a500705784dce0e11ce3aea3c7c746f6b3f Mon Sep 17 00:00:00 2001 From: diminator Date: Fri, 28 Aug 2015 15:24:32 +0200 Subject: [PATCH 001/192] request actions first cut --- js/actions/piece_list_actions.js | 2 +- .../accordion_list_item_wallet.js | 5 +- js/components/piece_list.js | 26 +++++++ .../ascribe_detail/prize_piece_container.js | 1 - js/stores/piece_list_store.js | 21 +++++- sass/ascribe_accordion_list.scss | 2 +- sass/ascribe_global_action.scss | 73 +++++++++++++++++++ sass/main.scss | 1 + 8 files changed, 122 insertions(+), 9 deletions(-) create mode 100644 sass/ascribe_global_action.scss diff --git a/js/actions/piece_list_actions.js b/js/actions/piece_list_actions.js index 1ebe7f42..d1ff363c 100644 --- a/js/actions/piece_list_actions.js +++ b/js/actions/piece_list_actions.js @@ -55,7 +55,7 @@ class PieceListActions { PieceListFetcher .fetchRequestActions() .then((res) => { - this.actions.updatePieceListRequestActions(res.piece_ids); + this.actions.updatePieceListRequestActions(res); }) .catch((err) => console.logGlobal(err)); } diff --git a/js/components/ascribe_accordion_list/accordion_list_item_wallet.js b/js/components/ascribe_accordion_list/accordion_list_item_wallet.js index f7bca334..178a7db4 100644 --- a/js/components/ascribe_accordion_list/accordion_list_item_wallet.js +++ b/js/components/ascribe_accordion_list/accordion_list_item_wallet.js @@ -61,12 +61,13 @@ let AccordionListItemWallet = React.createClass({ }, getGlyphicon(){ - if (this.props.content.requestAction && this.props.content.requestAction.length > 0) { + if ((this.props.content.request_action && this.props.content.request_action.length > 0) || + (this.props.content.request_action_editions)){ return ( {getLangText('You have actions pending in one of your editions')}}> + overlay={{getLangText('You have actions pending')}}> ); } diff --git a/js/components/piece_list.js b/js/components/piece_list.js index 79f1471c..185b0f05 100644 --- a/js/components/piece_list.js +++ b/js/components/piece_list.js @@ -147,8 +147,34 @@ let PieceList = React.createClass({ render() { let loadingElement = (); let AccordionListItemType = this.props.accordionListItemType; + + let pieceActions = null; + if (this.state.requestActions && this.state.requestActions.pieces){ + pieceActions = this.state.requestActions.pieces.map((item) => { + return ( +
+ test +
); + }); + } + let editionActions = null; + if (this.state.requestActions && this.state.requestActions.editions){ + for (let pieceId in this.state.requestActions.editions) { + editionActions = this.state.requestActions.editions[pieceId].map((item) => { + return ( +
+ test +
); + }); + } + } + return (
+
+ {pieceActions} + {editionActions} +
{ - piece.requestAction = requestActions.indexOf(piece.id) > -1; - }); + onUpdatePieceListRequestActions(res) { + this.requestActions.pieces = res.piece_actions; + this.requestActions.editions = res.edition_actions; + for (let pieceId in res.edition_actions){ + try { + this.onUpdatePropertyForPiece({ + pieceId: parseInt(pieceId, 10), + key: 'request_action_editions', + value: res.edition_actions[pieceId] + }); + } + catch(err) { + console.warn('couldnt match request action with piecelist, maybe on other page'); + } + + } } onUpdatePropertyForPiece({pieceId, key, value}) { diff --git a/sass/ascribe_accordion_list.scss b/sass/ascribe_accordion_list.scss index 1ef4bef9..6f809b27 100644 --- a/sass/ascribe_accordion_list.scss +++ b/sass/ascribe_accordion_list.scss @@ -158,7 +158,7 @@ span.ascribe-accordion-list-table-toggle { right: 0px; color: $ascribe-color-green; font-size: 1.2em; - padding: 0.3em; + padding: 0.8em; } .ascribe-accordion-list-item-edition-widget { diff --git a/sass/ascribe_global_action.scss b/sass/ascribe_global_action.scss new file mode 100644 index 00000000..bcc3f50d --- /dev/null +++ b/sass/ascribe_global_action.scss @@ -0,0 +1,73 @@ +.ascribe-global-action-wrapper { + position: fixed; + width: 100%; + height:3.5em; + left:0; + top:0; + z-index: 2000; + display:table; +} + +.ascribe-global-action { + width: 40%; + margin: 1px auto; + text-align: center; + padding: 1em; + color: black; + border: 1px solid #cccccc; + background-color: white; +} + +.ascribe-global-notification-off { + bottom: -3.5em; +} + +.ascribe-global-notification-on { + bottom: 0; +} + +.ascribe-global-notification > div, .ascribe-global-notification-bubble > div { + display:table-cell; + vertical-align: middle; + font-size: 1.25em; + font-family: 'Source Sans Pro'; + text-align: right; + padding-right: 3em; +} + +.ascribe-global-notification-bubble > div { + padding: .75em 1.5em .75em 1.5em; +} + +.ascribe-global-notification-bubble { + position: fixed; + bottom: 3em; + right: -50em; + + display:table; + + height: 3.5em; + + background-color: #212121; + border-radius: 2px; + + color: white; + + transition: 1s right ease; +} + +.ascribe-global-notification-bubble-off { + right: -100em; +} + +.ascribe-global-notification-bubble-on { + right: 3.5em; +} + +.ascribe-global-notification-danger { + background-color: #d9534f; +} + +.ascribe-global-notification-success { + background-color: rgba(2, 182, 163, 1); +} \ No newline at end of file diff --git a/sass/main.scss b/sass/main.scss index a6ab05b3..34bf42b1 100644 --- a/sass/main.scss +++ b/sass/main.scss @@ -22,6 +22,7 @@ $BASE_URL: '<%= BASE_URL %>'; @import 'ascribe_media_player'; @import 'ascribe_uploader'; @import 'ascribe_footer'; +@import 'ascribe_global_action'; @import 'ascribe_global_notification'; @import 'ascribe_piece_register'; @import 'offset_right'; From 848321a3f3efbfafebd5e180a783064d1cb7c7c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 28 Aug 2015 15:29:30 +0200 Subject: [PATCH 002/192] fix nav links on logged out user --- js/components/header.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/js/components/header.js b/js/components/header.js index 4cd8e4b0..0863624f 100644 --- a/js/components/header.js +++ b/js/components/header.js @@ -91,8 +91,9 @@ let Header = React.createClass({ }, render() { - let account = null; - let signup = null; + let account; + let signup; + let navRoutesLinks; if (this.state.currentUser.username){ account = ( @@ -101,6 +102,7 @@ let Header = React.createClass({ {getLangText('Log out')} ); + navRoutesLinks = ; } else { account = {getLangText('LOGIN')}; @@ -124,7 +126,7 @@ let Header = React.createClass({ {account} {signup} - + {navRoutesLinks}
From d9f3f2a9d7871f6e04e977c28349ce1b1dbe3e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 28 Aug 2015 15:55:39 +0200 Subject: [PATCH 003/192] rename contract_form to form_contract --- .../ascribe_forms/{contract_form.js => form_contract.js} | 0 .../wallet/components/ikonotv/ikonotv_request_loan.js | 2 +- js/components/whitelabel/wallet/wallet_routes.js | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename js/components/ascribe_forms/{contract_form.js => form_contract.js} (100%) diff --git a/js/components/ascribe_forms/contract_form.js b/js/components/ascribe_forms/form_contract.js similarity index 100% rename from js/components/ascribe_forms/contract_form.js rename to js/components/ascribe_forms/form_contract.js diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_request_loan.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_request_loan.js index e9c61f51..db74db3b 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_request_loan.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_request_loan.js @@ -2,7 +2,7 @@ import React from 'react'; -import ContractForm from '../../../../../components/ascribe_forms/contract_form'; +import ContractForm from '../../../../../components/ascribe_forms/form_contract'; let IkonotvRequestLoan = React.createClass({ diff --git a/js/components/whitelabel/wallet/wallet_routes.js b/js/components/whitelabel/wallet/wallet_routes.js index 40f092d6..1a32f46f 100644 --- a/js/components/whitelabel/wallet/wallet_routes.js +++ b/js/components/whitelabel/wallet/wallet_routes.js @@ -71,7 +71,7 @@ let ROUTES = { - + From dd20afff9090de307aa8026336d1b0d639fd3b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 28 Aug 2015 16:18:10 +0200 Subject: [PATCH 004/192] rename LoanContract to Contract --- ...ontract_actions.js => contract_actions.js} | 16 +++++------ js/actions/contract_list_actions.js | 27 +++++++++++++++++++ js/actions/loan_contract_list_actions.js | 27 ------------------- js/components/ascribe_forms/form_contract.js | 14 +++++----- js/components/ascribe_forms/form_loan.js | 14 +++++----- js/constants/api_urls.js | 2 +- js/fetchers/ownership_fetcher.js | 10 +++---- js/stores/contract_list_store.js | 22 +++++++++++++++ ...an_contract_store.js => contract_store.js} | 12 ++++----- js/stores/loan_contract_list_store.js | 22 --------------- 10 files changed, 83 insertions(+), 83 deletions(-) rename js/actions/{loan_contract_actions.js => contract_actions.js} (75%) create mode 100644 js/actions/contract_list_actions.js delete mode 100644 js/actions/loan_contract_list_actions.js create mode 100644 js/stores/contract_list_store.js rename js/stores/{loan_contract_store.js => contract_store.js} (56%) delete mode 100644 js/stores/loan_contract_list_store.js diff --git a/js/actions/loan_contract_actions.js b/js/actions/contract_actions.js similarity index 75% rename from js/actions/loan_contract_actions.js rename to js/actions/contract_actions.js index cc7e5a5b..83a788b8 100644 --- a/js/actions/loan_contract_actions.js +++ b/js/actions/contract_actions.js @@ -4,27 +4,27 @@ import alt from '../alt'; import OwnershipFetcher from '../fetchers/ownership_fetcher'; -class LoanContractActions { +class ContractActions { constructor() { this.generateActions( - 'updateLoanContract', - 'flushLoanContract' + 'updateContract', + 'flushContract' ); } fetchLoanContract(email) { if(email.match(/.+\@.+\..+/)) { - OwnershipFetcher.fetchLoanContract(email) + OwnershipFetcher.fetchContract(email) .then((contracts) => { if (contracts && contracts.length > 0) { - this.actions.updateLoanContract({ + this.actions.updateContract({ contractKey: contracts[0].s3Key, contractUrl: contracts[0].s3Url, contractEmail: email }); } else { - this.actions.updateLoanContract({ + this.actions.updateContract({ contractKey: null, contractUrl: null, contractEmail: null @@ -33,7 +33,7 @@ class LoanContractActions { }) .catch((err) => { console.logGlobal(err); - this.actions.updateLoanContract({ + this.actions.updateContract({ contractKey: null, contractUrl: null, contractEmail: null @@ -45,4 +45,4 @@ class LoanContractActions { } } -export default alt.createActions(LoanContractActions); +export default alt.createActions(ContractActions); diff --git a/js/actions/contract_list_actions.js b/js/actions/contract_list_actions.js new file mode 100644 index 00000000..f4257d37 --- /dev/null +++ b/js/actions/contract_list_actions.js @@ -0,0 +1,27 @@ +'use strict'; + +import alt from '../alt'; +import OwnershipFetcher from '../fetchers/ownership_fetcher'; + + +class ContractListActions { + constructor() { + this.generateActions( + 'updateContractList', + 'flushContractList' + ); + } + + fetchContractList() { + OwnershipFetcher.fetchContractList() + .then((contracts) => { + this.actions.updateContractList(contracts); + }) + .catch((err) => { + console.logGlobal(err); + this.actions.updateContractList([]); + }); + } +} + +export default alt.createActions(ContractListActions); diff --git a/js/actions/loan_contract_list_actions.js b/js/actions/loan_contract_list_actions.js deleted file mode 100644 index bc5cef82..00000000 --- a/js/actions/loan_contract_list_actions.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; - -import alt from '../alt'; -import OwnershipFetcher from '../fetchers/ownership_fetcher'; - - -class LoanContractListActions { - constructor() { - this.generateActions( - 'updateLoanContractList', - 'flushLoanContractList' - ); - } - - fetchLoanContractList() { - OwnershipFetcher.fetchLoanContractList() - .then((contracts) => { - this.actions.updateLoanContractList(contracts); - }) - .catch((err) => { - console.logGlobal(err); - this.actions.updateLoanContractList([]); - }); - } -} - -export default alt.createActions(LoanContractListActions); diff --git a/js/components/ascribe_forms/form_contract.js b/js/components/ascribe_forms/form_contract.js index 5b811cf6..d4e58c79 100644 --- a/js/components/ascribe_forms/form_contract.js +++ b/js/components/ascribe_forms/form_contract.js @@ -2,8 +2,8 @@ import React from 'react'; -import LoanContractListActions from '../../actions/loan_contract_list_actions'; -import LoanContractListStore from '../../stores/loan_contract_list_store'; +import ContractListActions from '../../actions/contract_list_actions'; +import ContractListStore from '../../stores/contract_list_store'; import GlobalNotificationModel from '../../models/global_notification_model'; import GlobalNotificationActions from '../../actions/global_notification_actions'; @@ -26,7 +26,7 @@ let ContractForm = React.createClass({ getInitialState() { return mergeOptions( - LoanContractListStore.getState(), + ContractListStore.getState(), { selectedContract: 0 } @@ -34,12 +34,12 @@ let ContractForm = React.createClass({ }, componentDidMount() { - LoanContractListStore.listen(this.onChange); - LoanContractListActions.fetchLoanContractList(); + ContractListStore.listen(this.onChange); + ContractListActions.fetchContractList(); }, componentWillUnmount() { - LoanContractListStore.unlisten(this.onChange); + ContractListStore.unlisten(this.onChange); }, onChange(state) { @@ -92,7 +92,7 @@ let ContractForm = React.createClass({
Date: Fri, 28 Aug 2015 15:56:08 +0200 Subject: [PATCH 005/192] Get rid of ascribe-btn-gray --- .../prize/components/prize_settings_container.js | 6 +++--- sass/ascribe_button.scss | 9 --------- sass/ascribe_variables.scss | 1 - sass/main.scss | 1 - sass/variables.scss | 2 +- 5 files changed, 4 insertions(+), 15 deletions(-) delete mode 100644 sass/ascribe_button.scss diff --git a/js/components/whitelabel/prize/components/prize_settings_container.js b/js/components/whitelabel/prize/components/prize_settings_container.js index f81e7078..3c48f254 100644 --- a/js/components/whitelabel/prize/components/prize_settings_container.js +++ b/js/components/whitelabel/prize/components/prize_settings_container.js @@ -190,7 +190,7 @@ let PrizeJurySettings = React.createClass({ {getLangText('RESEND')}
+ + + }/> + ); + }, this); + } + return content; + }, + + render() { + return ( + +
+ + + +
+
+
+                    Usage: curl <url> -H 'Authorization: Bearer <token>'
+                
+ {this.getApplications()} +
+ ); + } +}); + +export default APISettings; \ No newline at end of file diff --git a/js/components/ascribe_settings/bitcoin_wallet_settings.js b/js/components/ascribe_settings/bitcoin_wallet_settings.js new file mode 100644 index 00000000..18646d75 --- /dev/null +++ b/js/components/ascribe_settings/bitcoin_wallet_settings.js @@ -0,0 +1,72 @@ +'use strict'; + +import React from 'react'; + +import WalletSettingsStore from '../../stores/wallet_settings_store'; +import WalletSettingsActions from '../../actions/wallet_settings_actions'; + +import Form from '../ascribe_forms/form'; +import Property from '../ascribe_forms/property'; + +import CollapsibleParagraph from '../ascribe_collapsible/collapsible_paragraph'; + +import AppConstants from '../../constants/application_constants'; + +import { getLangText } from '../../utils/lang_utils'; + + +let BitcoinWalletSettings = React.createClass({ + propTypes: { + defaultExpanded: React.PropTypes.bool + }, + + getInitialState() { + return WalletSettingsStore.getState(); + }, + + componentDidMount() { + WalletSettingsStore.listen(this.onChange); + WalletSettingsActions.fetchWalletSettings(); + }, + + componentWillUnmount() { + WalletSettingsStore.unlisten(this.onChange); + }, + + onChange(state) { + this.setState(state); + }, + + render() { + let content = ; + + if (this.state.walletSettings.btc_public_key) { + content = ( +
+ +
{this.state.walletSettings.btc_public_key}
+
+ +
{this.state.walletSettings.btc_root_address}
+
+
+
); + } + return ( + + {content} + + ); + } +}); + +export default BitcoinWalletSettings; \ No newline at end of file diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js new file mode 100644 index 00000000..1730fe08 --- /dev/null +++ b/js/components/ascribe_settings/contract_settings.js @@ -0,0 +1,79 @@ +'use strict'; + +import React from 'react'; + +import Form from '../ascribe_forms/form'; +import Property from '../ascribe_forms/property'; + +import CollapsibleParagraph from '../ascribe_collapsible/collapsible_paragraph'; + +import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader'; + +import AppConstants from '../../constants/application_constants'; +import ApiUrls from '../../constants/api_urls'; + +import { getCookie } from '../../utils/fetch_api_utils'; +import { getLangText } from '../../utils/lang_utils'; + + +let ContractSettings = React.createClass({ + propTypes: { + defaultExpanded: React.PropTypes.bool + }, + + render() { + return ( + +
+ + + +
+
+
+ ); + } +}); + +export default ContractSettings; \ No newline at end of file diff --git a/js/components/ascribe_settings/settings_container.js b/js/components/ascribe_settings/settings_container.js new file mode 100644 index 00000000..485b26d7 --- /dev/null +++ b/js/components/ascribe_settings/settings_container.js @@ -0,0 +1,36 @@ +'use strict'; + +import React from 'react'; +import Router from 'react-router'; + +import AccountSettings from './account_settings'; +import BitcoinWalletSettings from './bitcoin_wallet_settings'; +import ContractSettings from './contract_settings'; +import APISettings from './api_settings'; + + +let SettingsContainer = React.createClass({ + propTypes: { + children: React.PropTypes.oneOfType([ + React.PropTypes.arrayOf(React.PropTypes.element), + React.PropTypes.element]) + }, + + mixins: [Router.Navigation], + + render() { + return ( +
+ + {this.props.children} + + + +
+
+
+ ); + } +}); + +export default SettingsContainer; diff --git a/js/components/piece_list.js b/js/components/piece_list.js index 79f1471c..02286374 100644 --- a/js/components/piece_list.js +++ b/js/components/piece_list.js @@ -60,6 +60,7 @@ let PieceList = React.createClass({ PieceListStore.listen(this.onChange); EditionListStore.listen(this.onChange); + let orderBy = this.props.orderBy ? this.props.orderBy : this.state.orderBy; if (this.state.pieceList.length === 0 || this.state.page !== page){ PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search, diff --git a/js/components/settings_container.js b/js/components/settings_container.js deleted file mode 100644 index d5821b7a..00000000 --- a/js/components/settings_container.js +++ /dev/null @@ -1,408 +0,0 @@ -'use strict'; - -import React from 'react'; -import Router from 'react-router'; - -import UserActions from '../actions/user_actions'; -import UserStore from '../stores/user_store'; - -import WalletSettingsActions from '../actions/wallet_settings_actions'; -import WalletSettingsStore from '../stores/wallet_settings_store'; - -import ApplicationActions from '../actions/application_actions'; -import ApplicationStore from '../stores/application_store'; - -import GlobalNotificationModel from '../models/global_notification_model'; -import GlobalNotificationActions from '../actions/global_notification_actions'; - -import ReactS3FineUploader from './ascribe_uploader/react_s3_fine_uploader'; - -import CollapsibleParagraph from './ascribe_collapsible/collapsible_paragraph'; -import Form from './ascribe_forms/form'; -import Property from './ascribe_forms/property'; -import InputCheckbox from './ascribe_forms/input_checkbox'; - -import ActionPanel from './ascribe_panel/action_panel'; - -import ApiUrls from '../constants/api_urls'; -import AppConstants from '../constants/application_constants'; - -import { getLangText } from '../utils/lang_utils'; -import { getCookie } from '../utils/fetch_api_utils'; - -let SettingsContainer = React.createClass({ - propTypes: { - children: React.PropTypes.oneOfType([ - React.PropTypes.arrayOf(React.PropTypes.element), - React.PropTypes.element]) - }, - - mixins: [Router.Navigation], - - render() { - return ( -
- - {this.props.children} - - - -
-
-
- ); - } -}); - - -let AccountSettings = React.createClass({ - getInitialState() { - return UserStore.getState(); - }, - - componentDidMount() { - UserStore.listen(this.onChange); - UserActions.fetchCurrentUser(); - }, - - componentWillUnmount() { - UserStore.unlisten(this.onChange); - }, - - onChange(state) { - this.setState(state); - }, - - handleSuccess(){ - UserActions.fetchCurrentUser(); - let notification = new GlobalNotificationModel(getLangText('Settings succesfully updated'), 'success', 5000); - GlobalNotificationActions.appendGlobalNotification(notification); - }, - - getFormDataProfile(){ - return {'email': this.state.currentUser.email}; - }, - - render() { - let content = ; - let profile = null; - - if (this.state.currentUser.username) { - content = ( -
- - - - - - -
-
- ); - profile = ( -
- - - - {' ' + getLangText('Enable hash option, e.g. slow connections or to keep piece private')} - - - -
- {/* - - */} -
- ); - } - return ( - - {content} - {profile} - {/*
- - - -
-
*/} -
- ); - } -}); - - - -let BitcoinWalletSettings = React.createClass({ - - propTypes: { - defaultExpanded: React.PropTypes.bool - }, - - getInitialState() { - return WalletSettingsStore.getState(); - }, - - componentDidMount() { - WalletSettingsStore.listen(this.onChange); - WalletSettingsActions.fetchWalletSettings(); - }, - - componentWillUnmount() { - WalletSettingsStore.unlisten(this.onChange); - }, - - onChange(state) { - this.setState(state); - }, - - render() { - let content = ; - if (this.state.walletSettings.btc_public_key) { - content = ( -
- -
{this.state.walletSettings.btc_public_key}
-
- -
{this.state.walletSettings.btc_root_address}
-
-
-
); - } - return ( - - {content} - - ); - } -}); - -let ContractSettings = React.createClass({ - propTypes: { - defaultExpanded: React.PropTypes.bool - }, - - render() { - return ( - - - - ); - } -}); - -let FileUploader = React.createClass({ - propTypes: { - }, - - render() { - return ( -
- - - -
-
- ); - } -}); - -let APISettings = React.createClass({ - propTypes: { - defaultExpanded: React.PropTypes.bool - }, - - getInitialState() { - return ApplicationStore.getState(); - }, - - componentDidMount() { - ApplicationStore.listen(this.onChange); - ApplicationActions.fetchApplication(); - }, - - componentWillUnmount() { - ApplicationStore.unlisten(this.onChange); - }, - - onChange(state) { - this.setState(state); - }, - - handleCreateSuccess() { - ApplicationActions.fetchApplication(); - let notification = new GlobalNotificationModel(getLangText('Application successfully created'), 'success', 5000); - GlobalNotificationActions.appendGlobalNotification(notification); - }, - - handleTokenRefresh(event) { - let applicationName = event.target.getAttribute('data-id'); - ApplicationActions.refreshApplicationToken(applicationName); - - let notification = new GlobalNotificationModel(getLangText('Token refreshed'), 'success', 2000); - GlobalNotificationActions.appendGlobalNotification(notification); - }, - - getApplications(){ - let content = ; - if (this.state.applications.length > -1) { - content = this.state.applications.map(function(app, i) { - return ( - -
- {app.name} -
-
- {'Bearer ' + app.bearer_token.token} -
- - } - buttons={ -
-
- -
-
- }/> - ); - }, this); - } - return content; - }, - - render() { - return ( - -
- - - -
-
-
-                    Usage: curl <url> -H 'Authorization: Bearer <token>'
-                
- {this.getApplications()} -
- ); - } -}); - -export default SettingsContainer; diff --git a/js/components/whitelabel/prize/components/prize_settings_container.js b/js/components/whitelabel/prize/components/prize_settings_container.js index f81e7078..86d0f77d 100644 --- a/js/components/whitelabel/prize/components/prize_settings_container.js +++ b/js/components/whitelabel/prize/components/prize_settings_container.js @@ -9,7 +9,7 @@ import PrizeStore from '../stores/prize_store'; import PrizeJuryActions from '../actions/prize_jury_actions'; import PrizeJuryStore from '../stores/prize_jury_store'; -import SettingsContainer from '../../../settings_container'; +import SettingsContainer from '../../../ascribe_settings/settings_container'; import CollapsibleParagraph from '../../../ascribe_collapsible/collapsible_paragraph'; import Form from '../../../ascribe_forms/form'; diff --git a/js/components/whitelabel/wallet/wallet_routes.js b/js/components/whitelabel/wallet/wallet_routes.js index 1a32f46f..1c4ef4a7 100644 --- a/js/components/whitelabel/wallet/wallet_routes.js +++ b/js/components/whitelabel/wallet/wallet_routes.js @@ -11,7 +11,7 @@ import PasswordResetContainer from '../../../components/password_reset_container import PieceList from '../../../components/piece_list'; import PieceContainer from '../../../components/ascribe_detail/piece_container'; import EditionContainer from '../../../components/ascribe_detail/edition_container'; -import SettingsContainer from '../../../components/settings_container'; +import SettingsContainer from '../../../components/ascribe_settings/settings_container'; import RegisterPiece from '../../../components/register_piece'; import CylandLanding from './components/cyland/cyland_landing'; diff --git a/js/routes.js b/js/routes.js index f76e4b45..2762052b 100644 --- a/js/routes.js +++ b/js/routes.js @@ -17,7 +17,7 @@ import LogoutContainer from './components/logout_container'; import SignupContainer from './components/signup_container'; import PasswordResetContainer from './components/password_reset_container'; -import SettingsContainer from './components/settings_container'; +import SettingsContainer from './components/ascribe_settings/settings_container'; import CoaVerifyContainer from './components/coa_verify_container'; import RegisterPiece from './components/register_piece'; From 96fdb598f76f65229fa800cbab6cac2dbc6e5682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 31 Aug 2015 17:29:43 +0200 Subject: [PATCH 009/192] change api endpoints to contractblobs --- js/components/ascribe_forms/form_contract.js | 2 +- js/components/ascribe_settings/contract_settings.js | 4 ++-- js/components/ascribe_uploader/react_s3_fine_uploader.js | 3 +++ js/constants/api_urls.js | 3 ++- js/fetchers/ownership_fetcher.js | 2 +- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/js/components/ascribe_forms/form_contract.js b/js/components/ascribe_forms/form_contract.js index d4e58c79..4c51e7a3 100644 --- a/js/components/ascribe_forms/form_contract.js +++ b/js/components/ascribe_forms/form_contract.js @@ -92,7 +92,7 @@ let ContractForm = React.createClass({
a { text-decoration: none; @@ -85,46 +93,47 @@ $ascribe-accordion-list-font: 'Source Sans Pro'; } .ascribe-accordion-list-item-table { - font-size: .9em; - text-align: center; background-color: white; - - //border-bottom-left-radius: 1px; - //border-bottom-right-radius: 1px; - border-bottom: 0.1em solid rgba(0,0,0,.15); - border-left: 0.1em solid rgba(0,0,0,.2); - border-right: 0.1em solid rgba(0,0,0,.2); + border-bottom: .1em solid rgba(0, 0, 0, .15); + border-left: .1em solid rgba(0, 0, 0, .2); + border-right: .1em solid rgba(0, 0, 0, .2); + font-size: .9em; padding: 0; + text-align: center; + thead:first-child { + border-bottom: 1px solid rgba(0, 0, 0, .05); + border-left: 3px solid rgba(0, 0, 0, 0); + tr:first-child { - border: none! important; + border: none !important; th { + border: none !important; padding-left: 10px; - border: none! important; } } - border-left: 3px solid rgba(0,0,0,0); - //border-top: 1px solid rgba(0,0,0,.1); - border-bottom: 1px solid rgba(0,0,0,.05); } + tbody { tr { + border-bottom: 1px solid rgba(0, 0, 0, .03); + border-left: 3px solid rgba(0, 0, 0, 0); padding: 1em; - &:hover{ + + &:hover { background-color: rgba(2, 182, 163, 0.05); border-left: 3px solid rgba(2, 182, 163, 0.4); } - border-left: 3px solid rgba(0,0,0,0); - border-bottom: 1px solid rgba(0,0,0,.03); - td { - border: none! important; - a { - color: #444 - } + td { + border: none !important; + a { + color: #444; + } } } - tr{ + + tr { td:first-child { margin-left: 10px; } @@ -132,48 +141,51 @@ $ascribe-accordion-list-font: 'Source Sans Pro'; } } -span.ascribe-accordion-list-table-toggle { - -webkit-user-select: none; - -moz-user-select: none; +.ascribe-accordion-list-table-toggle { -khtml-user-select: none; + -moz-user-select: none; -ms-user-select: none; - + -webkit-user-select: none; + &:hover { color: $ascribe-color-green; - cursor:pointer; + cursor: pointer; } } .ascribe-accordion-list-table-list { margin-bottom: .5em; - th, td { - font-size:.85em; - text-align: center; + + th, + td { + font-size: .85em; + text-align: center; } } .request-action-badge { - position: absolute; - top: 0px; - right: 0px; color: $ascribe-color-green; font-size: 1.2em; - padding: 0.3em; + padding: .3em; + position: absolute; + right: 0; + top: 0; } .ascribe-accordion-list-item-edition-widget { cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; -khtml-user-select: none; + -moz-user-select: none; -ms-user-select: none; + -webkit-user-select: none; &:hover { color: $ascribe-color-green; } + .glyphicon { + font-size: .8em; top: 1px !important; - font-size: 0.8em; } -} \ No newline at end of file +} diff --git a/sass/ascribe_edition.scss b/sass/ascribe_edition.scss index fe647e2d..f86f74e2 100644 --- a/sass/ascribe_edition.scss +++ b/sass/ascribe_edition.scss @@ -5,46 +5,48 @@ .ascribe-edition-collapsible-wrapper { vertical-align: bottom; - width:100%; -} - -.ascribe-edition-collapsible-wrapper > div:first-child { width: 100%; - cursor: pointer; - background-color: rgba(0,0,0,0); - padding: 0 10px 10px 0; - margin-top: 20px; -} -.ascribe-edition-collapsible-wrapper > div > span { - font-size: 1.2em; - margin-right: .5em; -} -.ascribe-edition-collapsible-wrapper > div > span:nth-child(2) { - font-size: 0.9em; + + > div:first-child { + background-color: rgba(0, 0, 0, 0); + cursor: pointer; + margin-top: 20px; + padding: 0 10px 10px 0; + width: 100%; + } + + > div > span { + font-size: 1.2em; + margin-right: .5em; + } + + > div > span:nth-child(2) { + font-size: .9em; + } } .ascribe-edition-collapsible-content { - width:100%; background: none; - border: none; + border: 0; + width: 100%; } .coa-file-wrapper { display: table; height: 200px; - overflow: hidden; margin: 0 auto; - width: 100%; + overflow: hidden; padding: 1em; + width: 100%; } .coa-file { + background-color: #F8F8F8; + border: 1px solid #CCC; display: table-cell; vertical-align: middle; - border: 1px solid #CCC; - background-color: #F8F8F8; } .ascribe-button-list { margin-top: 1em; -} \ No newline at end of file +} diff --git a/sass/ascribe_footer.scss b/sass/ascribe_footer.scss index e51443be..fe52b798 100644 --- a/sass/ascribe_footer.scss +++ b/sass/ascribe_footer.scss @@ -1,17 +1,32 @@ .ascribe-footer { text-align: center; -} -.ascribe-footer hr { - border: 0; - border-top: 1px solid #eee; - background-color: rgba(0,0,0,0); - margin-bottom: 0 !important; -} + hr { + background-color: rgba(0, 0, 0, 0); + border-top: 1px solid #eee; + border: 0; + margin-bottom: 0 !important; + } + + .btn-ascribe-landing { + margin-top: 2em; + } + + .social-icons-wrapper { + margin-top: 1em; + + a { + color: #424242; + font-size: 1.3em; + margin-left: 1em; + } + + a:hover { + color: #48DACB; + } + } -.ascribe-footer .btn-ascribe-landing { - margin-top: 2em; } .ascribe-footer-statement { @@ -21,7 +36,8 @@ margin-top: 0; } -.ascribe-footer-statement a, .ascribe-footer-sub-statement a { +.ascribe-footer-statement a, +.ascribe-footer-sub-statement a { color: #424242; } @@ -30,23 +46,7 @@ margin-bottom: 2.5em; } -.ascribe-footer-statement a, .ascribe-footer-sub-statement a { - color: #424242; +.ascribe-footer-statement a:hover, +.ascribe-footer-sub-statement a:hover { + color: #48dacb; } -.ascribe-footer-statement a:hover, .ascribe-footer-sub-statement a:hover { - color: #48DACB; -} - -.ascribe-footer .social-icons-wrapper { - margin-top: 1em; -} - -.ascribe-footer .social-icons-wrapper a { - color: #424242; - margin-left: 1em; - font-size: 1.3em; -} - -.ascribe-footer .social-icons-wrapper a:hover { - color: #48DACB; -} \ No newline at end of file diff --git a/sass/ascribe_form.scss b/sass/ascribe_form.scss index d2802ee8..41e17de1 100644 --- a/sass/ascribe_form.scss +++ b/sass/ascribe_form.scss @@ -1,25 +1,26 @@ .ascribe-form-bordered { - border: 1px solid #F5F5F5; + border: 1px solid #f5f5f5; } .ascribe-form-header { - padding-bottom: 0; - margin-bottom: 0; background-color: white; -} - -.ascribe-form-header > h3 { - padding: .75em 0 .75em 1em; - margin-top: 0; margin-bottom: 0; - color: #616161; + padding-bottom: 0; + + > h3 { + color: #616161; + margin-bottom: 0; + margin-top: 0; + padding: .75em 0 .75em 1em; + } } .ascribe-form-wrapper { - width: 80%; margin: 0 auto; max-width: 600px; + width: 80%; + @media (max-width: 550px) { width: 100%; } -} \ No newline at end of file +} diff --git a/sass/ascribe_global_notification.scss b/sass/ascribe_global_notification.scss index 527b1f06..5286a32c 100644 --- a/sass/ascribe_global_notification.scss +++ b/sass/ascribe_global_notification.scss @@ -1,14 +1,12 @@ .ascribe-global-notification { - position: fixed; - background-color: #212121; color: white; + display: table; + height: 3.5em; + left: 0; + position: fixed; + transition: .2s bottom cubic-bezier(.77, 0, .175, 1); width: 100%; - height:3.5em; - left:0; - display:table; - - transition: .2s bottom cubic-bezier(0.77, 0, 0.175, 1); } .ascribe-global-notification-off { @@ -19,34 +17,29 @@ bottom: 0; } -.ascribe-global-notification > div, .ascribe-global-notification-bubble > div { - display:table-cell; - vertical-align: middle; - font-size: 1.25em; - font-family: 'Source Sans Pro'; - text-align: right; - padding-right: 3em; -} - +.ascribe-global-notification > div, .ascribe-global-notification-bubble > div { - padding: .75em 1.5em .75em 1.5em; + display: table-cell; + font-size: 1.25em; + padding-right: 3em; + text-align: right; + vertical-align: middle; } .ascribe-global-notification-bubble { - position: fixed; - bottom: 3em; - right: -50em; - - display:table; - - height: 3.5em; - background-color: #212121; border-radius: 2px; - + bottom: 3em; color: white; - + display: table; + height: 3.5em; + position: fixed; + right: -50em; transition: 1s right ease; + + > div { + padding: .75em 1.5em; + } } .ascribe-global-notification-bubble-off { @@ -63,4 +56,4 @@ .ascribe-global-notification-success { background-color: rgba(2, 182, 163, 1); -} \ No newline at end of file +} diff --git a/sass/ascribe_login.scss b/sass/ascribe_login.scss index 9ff2857f..9060fee5 100644 --- a/sass/ascribe_login.scss +++ b/sass/ascribe_login.scss @@ -2,84 +2,91 @@ $break-small: 764px; .ascribe-btn-login { - padding: 0.5em; - font-weight: 500; - text-align: center; - background-color: rgba(2, 182, 163, 1); - color: white; - font-size: 1.2em; - border-radius: 0; - width: 100%; - border:none; - //margin-left: 1.2em; - - &:hover { - color: white; - background-color: rgba(2, 182, 163, 0.8); + background-color: rgba(2, 182, 163, 1); border: none; - } - &:active, &:focus { + border-radius: 0; color: white; - background-color: rgba(2, 182, 163, 0.6); - border: none; - } + font-size: 1.2em; + font-weight: 500; + padding: .5em; + text-align: center; + width: 100%; + //margin-left: 1.2em; - &[disabled] { - opacity: .3; - } + &:hover { + background-color: rgba(2, 182, 163, .8); + border: 0; + color: white; + } + + &:active, + &:focus { + background-color: rgba(2, 182, 163, .6); + border: 0; + color: white; + } + + &[disabled] { + opacity: .3; + } } -.ascribe-btn-login-spinner{ - background-color: rgba(2, 182, 163, 0.4); - padding: 0.4em; - img { - height: 1.6em; - } - &:hover { - background-color: rgba(2, 182, 163, 0.4); - } - &:active, &:focus { - background-color: rgba(2, 182, 163, 0.4); - } +.ascribe-btn-login-spinner { + background-color: rgba(2, 182, 163, .4); + padding: .4em; + + img { + height: 1.6em; + } + + &:hover { + background-color: rgba(2, 182, 163, .4); + } + + &:active, + &:focus { + background-color: rgba(2, 182, 163, .4); + } } .ascribe-login-wrapper { - width: 80%; - margin: 0 auto; - max-width: 600px; - @media screen and (max-width: $break-small) { - width: 100%; - } + margin: 0 auto; + max-width: 600px; + width: 80%; + + @media screen and (max-width: $break-small) { + width: 100%; + } } .ascribe-login-text { - font-size: 0.8em; - padding: 0 0 1em 0; - margin-left: 0.4em; - margin-top: 1.5em; - color: rgba(0, 0, 0, 0.6); + color: rgba(0, 0, 0, .6); + font-size: .8em; + margin-left: .4em; + margin-top: 1.5em; + padding: 0 0 1em; } .ascribe-login-header { - font-size: 2em; - margin-left: 0.8em; + font-size: 2em; + margin-left: .8em; } .ascribe-form { - hr { - color: rgba(0, 0, 0, 0.05); - border: none; - height: 1px; - background-color: rgba(0, 0, 0, 0.05); - margin-top: 0; - } + hr { + background-color: rgba(0, 0, 0, .05); + border: 0; + color: rgba(0, 0, 0, .05); + height: 1px; + margin-top: 0; + } } %vertical-align { - position: relative; - top: 50%; - -webkit-transform: translateY(-50%); - -ms-transform: translateY(-50%); - transform: translateY(-50%); -} \ No newline at end of file + position: relative; + top: 50%; + -ms-transform: translateY(-50%); + -webkit-transform: translateY(-50%); + transform: translateY(-50%); +} diff --git a/sass/ascribe_media_player.scss b/sass/ascribe_media_player.scss index f3b87618..6a70ad4d 100644 --- a/sass/ascribe_media_player.scss +++ b/sass/ascribe_media_player.scss @@ -3,35 +3,35 @@ video, img { - max-width: 100%; - max-height: 640px; - width: auto; - height: auto; display: block; + height: auto; margin: 0 auto; + max-height: 640px; + max-width: 100%; + width: auto; } .media-other { - font-size: 500%; color: #cccccc; + font-size: 500%; } .audiojs { + background-image: none; margin: 50px auto; - background-image: none; - } + * { + box-sizing: content-box; + } - .audiojs * { - box-sizing: content-box; - } + .loaded { + background-color: $ascribe-color-green; + background-image: none; + } - .audiojs .loaded { - background-color: $ascribe-color-green; - background-image: none; - } - .audiojs .progress { - background-color: rgba(255,255,255,0.8); - background-image: none; + .progress { + background-color: rgba(255, 255, 255, .8); + background-image: none; + } } .video-js, @@ -44,12 +44,13 @@ } .vjs-fullscreen { - padding-top: 0px; + padding-top: 0; + + video { + max-height: 100%; + } } - .vjs-fullscreen video { - max-height: 100%; - } .vjs-default-skin .vjs-play-progress, .vjs-default-skin .vjs-volume-level { @@ -57,41 +58,35 @@ } .vjs-default-skin .vjs-big-play-button { - border-radius: 6px; - -o-border-radius: 6px; + background-color: rgba(0, 0, 0, .8); + border: 0; -moz-border-radius: 6px; + -o-border-radius: 6px; -webkit-border-radius: 6px; - - box-shadow: none; - -o-box-shadow: none; + border-radius: 6px; -moz-box-shadow: none; + -o-box-shadow: none; -webkit-box-shadow: none; - - width: 100px; + box-shadow: none; height: 60px; - top: 50%; left: 50%; margin: -30px -50px; - - border: none; - - background-color: rgba(0,0,0,.8); + top: 50%; + width: 100px; } .vjs-default-skin:hover .vjs-big-play-button, .vjs-default-skin .vjs-big-play-button:focus { + background-color: rgba(0, 0, 0, .9); border-color: #fff; - background-color: rgba(0,0,0,.9); - - box-shadow: none; - -o-box-shadow: none; -moz-box-shadow: none; + -o-box-shadow: none; -webkit-box-shadow: none; - - transition: all 0s; - -o-transition: all 0s; + box-shadow: none; -moz-transition: all 0s; + -o-transition: all 0s; -webkit-transition: all 0s; + transition: all 0s; } .vjs-default-skin .vjs-big-play-button:before { @@ -108,7 +103,7 @@ } .vjs-default-skin .vjs-control-bar { - background-color: rgba(0,0,0,.7); + background-color: rgba(0, 0, 0, .7); } } diff --git a/sass/ascribe_panel.scss b/sass/ascribe_panel.scss index 73fe572e..9d53b911 100644 --- a/sass/ascribe_panel.scss +++ b/sass/ascribe_panel.scss @@ -1,13 +1,12 @@ .ascribe-panel-wrapper { - border: 1px solid #DDD; - min-height: 5em; + border: 1px solid #ddd; height: 5em; - margin-top: 1em; + min-height: 5em; > div { - height: 100%; float: left; + height: 100%; &:first-child { width: 60%; @@ -20,7 +19,7 @@ } .ascribe-panel-table { - display:table; + display: table; > .ascribe-panel-content { display: table-cell; @@ -32,7 +31,6 @@ > div { padding-left: 1em; } - } &:nth-child(2) { @@ -40,7 +38,7 @@ padding-right: 1em; > button { - float:right; + float: right; } } } @@ -52,7 +50,6 @@ > div { padding-left: 2em; } - } &:nth-child(2) { @@ -60,7 +57,7 @@ padding-right: 2em; > button { - float:right; + float: right; } } } @@ -73,8 +70,8 @@ } .ascribe-panel-subtitle { + color: rgba(0, 0, 0, .5); font-size: .7em; - color: rgba(0,0,0,0.5); } } @@ -85,8 +82,8 @@ } .ascribe-panel-subtitle { + color: rgba(0, 0, 0, .5); font-size: .9em; - color: rgba(0,0,0,0.5); } } diff --git a/sass/ascribe_piece_list_bulk_modal.scss b/sass/ascribe_piece_list_bulk_modal.scss index 1811982b..4af61e1f 100644 --- a/sass/ascribe_piece_list_bulk_modal.scss +++ b/sass/ascribe_piece_list_bulk_modal.scss @@ -1,20 +1,17 @@ .ascribe-piece-list-bulk-modal { - position: fixed; - top:0; - left: 3%; - width:94%; - - background-color: #FAFAFA; - - border-left: 0.1em solid #E0E0E0; - border-right: 0.1em solid #E0E0E0; - border-top: 0.1em solid #E0E0E0; + background-color: #fafafa; + border-bottom: .2em solid #e0e0e0; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; - border-bottom: 0.2em solid #E0E0E0; - z-index:1000; - + border-left: .1em solid #e0e0e0; + border-right: .1em solid #e0e0e0; + border-top: .1em solid #e0e0e0; + left: 3%; padding-bottom: 1em; + position: fixed; + top: 0; + width: 94%; + z-index: 1000; } @media(min-width:1174px){ @@ -25,6 +22,6 @@ } .piece-list-bulk-modal-clear-all { + cursor: pointer; text-decoration: underline; - cursor:pointer; -} \ No newline at end of file +} diff --git a/sass/ascribe_piece_list_toolbar.scss b/sass/ascribe_piece_list_toolbar.scss index 8756adf4..aeec1bff 100644 --- a/sass/ascribe_piece_list_toolbar.scss +++ b/sass/ascribe_piece_list_toolbar.scss @@ -6,6 +6,7 @@ .search-bar { max-width: 200px; + input { height: 33px; } @@ -13,37 +14,45 @@ .ascribe-input-glyph > .form-group > .input-group { margin-left: 6px; + input { - box-shadow: none; background-color: transparent; border: 1px solid #02b6a3; border-right: 0; + box-shadow: none; } + > .input-group-addon { background-color: transparent; + > .filter-glyph { color: #02b6a3; } + border: 1px solid #02b6a3; border-left: 0; } } .ascribe-piece-list-toolbar-filter-widget { + button { - background-color: rgba(0,0,0,0); + background-color: rgba(0, 0, 0, 0); + border: 1px solid rgba(0, 0, 0, 0); color: #02b6a3; - border: 1px solid rgba(0,0,0,0); padding: 6px 4px 6px 8px; - &:hover, &:active { + + &:hover, + &:active { background-color: #02b6a3 !important; - color: white; border: 1px solid #02b6a3 !important; + color: white; } .caret { display: none; } } + .filter-widget-item { > a { @@ -53,23 +62,22 @@ } .checkbox-line { - position: relative; height: 25px; + position: relative; span { - position: absolute; - left: 9px; - top: 3px; cursor: pointer; - + left: 9px; margin-right: 10px; + position: absolute; + top: 3px; } input { - position: absolute; - top: 2px; - right: 9px; margin-left: 10px; + position: absolute; + right: 9px; + top: 2px; } } -} \ No newline at end of file +} diff --git a/sass/ascribe_piece_register.scss b/sass/ascribe_piece_register.scss index 1e4c0fa6..5bc6c3d7 100644 --- a/sass/ascribe_piece_register.scss +++ b/sass/ascribe_piece_register.scss @@ -2,15 +2,16 @@ $break-small: 764px; $break-medium: 991px; .ascribe-row { - @media screen and (max-width: $break-medium) { - max-width: 600px; - } - @media screen and (min-width: $break-medium) { - max-width: 1200px; - } - margin: 0 auto; + @media screen and (max-width: $break-medium) { + max-width: 600px; + } + @media screen and (min-width: $break-medium) { + max-width: 1200px; + } + margin: 0 auto; + + > div { + padding-left: 0; + } } -.ascribe-row > div { - padding-left: 0; -} \ No newline at end of file diff --git a/sass/ascribe_settings.scss b/sass/ascribe_settings.scss index 624b8a3b..c47ddb67 100644 --- a/sass/ascribe_settings.scss +++ b/sass/ascribe_settings.scss @@ -1,98 +1,108 @@ -.settings-container{ - max-width: 600px; +.settings-container { margin: auto; + max-width: 600px; } .ascribe-settings-wrapper { - width: 100%; - text-align: center; - padding-bottom: 1em; - background-color: white; - - border-left: 3px solid rgba(0,0,0,0); + border-left: 3px solid rgba(0, 0, 0, 0); + padding-bottom: 1em; + text-align: center; + width: 100%; &div:last-of-type { - border-bottom: 1px solid rgba(0,0,0,.05); + border-bottom: 1px solid rgba(0, 0, 0, .05); } - &:hover{ - border-left: 3px solid rgba(2, 182, 163, 0.4); + + &:hover { + border-left: 3px solid rgba(2, 182, 163, .4); } } -.is-hidden{ - display: none; +.is-hidden { + display: none; } .is-focused { - background-color: rgba(2, 182, 163, 0.05); + background-color: rgba(2, 182, 163, .05); border-left: 3px solid rgba(2, 182, 163, 1) !important; } .is-error { - background-color: rgba(169, 68, 66, 0.05); + background-color: rgba(169, 68, 66, .05); border-left: 3px solid rgba(169, 68, 66, 1); + > div { > span { color: rgba(169, 68, 66, 1); - font-size: 0.9em; + font-size: .9em; margin-right: 1em; } - > input, > textarea { + + > input, + > textarea { color: #666; } } - &:hover{ + &:hover { border-left: 3px solid rgba(169, 68, 66, 1); } } .is-fixed { cursor: default; + > div { cursor: default; + > span { cursor: default; } - > input, > div, > pre, > textarea { - cursor: default; + + > input, + > div, + > pre, + > textarea { color: #666; + cursor: default; } } } .ascribe-settings-property { + border-top: 1px solid rgba(0, 0, 0, .05); + cursor: pointer; display: inline-block; - width: 100%; - text-align: left; - border-top: 1px solid rgba(0,0,0,.05); - - padding-top: 1em; padding-left: 1.5em; padding-right: 1.5em; + padding-top: 1em; + text-align: left; + width: 100%; - cursor:pointer; - - > input, > div, > span:not(.glyphicon), > pre, > textarea, > select { + > div, + > input, + > pre, + > select, + > span:not(.glyphicon), + > textarea { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } - + > span { + color: rgba(0, 0, 0, .5); + font-size: .9em; font-weight: normal; - font-size: 0.9em; - color: rgba(0,0,0,.5); } > div { - /* margin-top: 10px; */ > div:not(.file-drag-and-drop div) { - padding-left: 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: normal; - font-size: 1.1em; - cursor: default; - color: rgba(0, 0, 0, .5); + color: rgba(0, 0, 0, .5); + cursor: default; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 1.1em; + font-weight: normal; + padding-left: 0; } } @@ -100,29 +110,34 @@ margin-top: 0 !important; } - > input, > pre, > textarea, > select, .datepicker__input { - font-weight: 400; - font-size: 1.1em; - width:100%; - margin-top: .5em; + > input, + > pre, + > textarea, + > select, + .datepicker__input { + background-color: rgba(0, 0, 0, 0); border: 0; - background-color: rgba(0,0,0,0); - color: rgba(0,0,0,.8); - padding-left: 0; box-shadow: none; + color: rgba(0, 0, 0, .8); + font-size: 1.1em; + font-weight: 400; + margin-top: .5em; + padding-left: 0; + width: 100%; &:focus { - border:0; - outline:0; + border: 0; box-shadow: none; + outline: 0; } &::selection { + background-color: rgba(0, 0, 0, 1); color: white; - background-color: rgba(0,0,0,1); } } + .datepicker__input { padding: 0; } @@ -135,78 +150,75 @@ } .ascribe-property-footer { - font-size: 0.8em; + font-size: .8em; margin-top: 10px; width: 100%; } .ascribe-settings-property-collapsible-toggle { - text-align: left; + border-top: 1px solid rgba(0, 0, 0, .05); display: inline-block; + padding: .5em 1.5em; + text-align: left; width: 100%; - border-top: 1px solid rgba(0,0,0,.05); - - padding: .5em 1.5em .5em 1.5em; } .ascribe-checkbox-wrapper{ - .checkbox > span {color: black;} + .checkbox > span { + color: black; + } } .ascribe-settings-property-collapsible-toggle, .ascribe-checkbox-wrapper { + cursor: pointer; - cursor:pointer; - - /* Taken from: http://www.htmllion.com/css3-checkbox.html */ + // Taken from: http://www.htmllion.com/css3-checkbox.html .checkbox { display: inline-block; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: normal; font-size: .9em; - vertical-align:middle; + font-weight: normal; + vertical-align: middle; > span { + left: 5px; position: relative; top: 1px; - left: 5px; - -webkit-user-select: none; - -moz-user-select: none; -khtml-user-select: none; + -moz-user-select: none; -ms-user-select: none; + -webkit-user-select: none; } } - input[type=checkbox] { - display:none; + [type=checkbox] { + display: none; } .checkbox:before { + background-color: white; + border: 1px solid rgba(0, 0, 0, .5); + border-radius: 1px; + color: #f3f3f3; content: ""; display: inline-block; - width: 17px; height: 17px; - vertical-align:middle; - background-color: white; - color: #f3f3f3; text-align: center; - - border-radius: 1px; - border: 1px solid rgba(0, 0, 0, .5); + vertical-align: middle; + width: 17px; } - input[type=checkbox]:checked + .checkbox:before { - line-height: .8; - + [type=checkbox]:checked + .checkbox:before { + color: rgba(2, 182, 163, 1); content: "\2713"; font-size: 20px; - color: rgba(2, 182, 163, 1); + line-height: .8; } } -.ascribe-checkbox-badge{ +.ascribe-checkbox-badge { > span > span { margin-top: 0; } -} \ No newline at end of file +} diff --git a/sass/ascribe_slides_container.scss b/sass/ascribe_slides_container.scss index 4b96017c..c213e15b 100644 --- a/sass/ascribe_slides_container.scss +++ b/sass/ascribe_slides_container.scss @@ -5,41 +5,42 @@ padding-right: 0; } -.ascribe-sliding-container { - transition: transform 1s cubic-bezier(0.23, 1, 0.32, 1); +.ascribe-sliding-container { padding-left: 0; padding-right: 0; + transition: transform 1s cubic-bezier(.23, 1, .32, 1); } .ascribe-slide { - position: relative; + float: left; min-height: 1px; - float:left; + position: relative; } -.ascribe-breadcrumb-container{ +.ascribe-breadcrumb-container { div:last-child { .ascribe-breadcrumb { - border-right: 1px solid #EEE; + border-right: 1px solid #eee; } } } .ascribe-breadcrumb { - padding: 1em; - border: 1px solid #EEE; - border-right: 1px solid rgba(0, 0, 0, 0); - margin-bottom: 0.6em; background-color: white; + border: 1px solid #eee; + border-right: 1px solid rgba(0, 0, 0, 0); + margin-bottom: .6em; + padding: 1em; .active { color: #666; } + a { - color: #DDD; - text-decoration: none; + color: #ddd; font-size: 1.1em; font-style: italic; + text-decoration: none; } } diff --git a/sass/ascribe_table.scss b/sass/ascribe_table.scss index 225c27ca..c4b82a29 100644 --- a/sass/ascribe_table.scss +++ b/sass/ascribe_table.scss @@ -1,11 +1,11 @@ .ascribe-table { - margin-bottom:0; + margin-bottom: 0; font-size: 1.1em; } -/*This is aligning the first checkbox in pieclist detail with all the other ones*/ +// 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; + padding-left: 0; } @@ -14,38 +14,36 @@ } .ascribe-table-header-column > span { - display: table-cell; - vertical-align: middle; - font-family: 'Source Sans Pro'; - font-weight: 600; color: #424242; + display: table-cell; + font-weight: 600; + vertical-align: middle; } .ascribe-table-item-column { - font-family: 'Source Sans Pro'; + display: table-cell; font-size: .8em; - height:3em; + height: 3em; vertical-align: middle; - display: table-cell; -} -.ascribe-table-item-column > * { - display: table-cell; - vertical-align: middle; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} + > * { + display: table-cell; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: middle; + white-space: nowrap; + } -.ascribe-table-item-column > span > input { - margin-top:10px; - margin-left:2px; + > span > input { + margin-left: 2px; + margin-top: 10px; + } } .ascribe-table-item-selected { - background-color: rgba(2, 182, 163, 0.5); + background-color: rgba(2, 182, 163, .5); } .ascribe-table-item-selectable { cursor: default; -} \ No newline at end of file +} diff --git a/sass/ascribe_textarea.scss b/sass/ascribe_textarea.scss index 2d368dbf..bcd0502a 100644 --- a/sass/ascribe_textarea.scss +++ b/sass/ascribe_textarea.scss @@ -1,24 +1,23 @@ .ascribe-textarea { - border: none; + border: 0; box-shadow: none; margin-bottom: 1em; } .ascribe-textarea-editable:hover { - //border: 1px solid #AAA;; - border: none; + border: 0; } -.ascribe-pre{ - word-break: break-word; - white-space: pre-wrap; - white-space: -moz-pre-wrap; - white-space: -pre-wrap; - white-space: -o-pre-wrap; - font-family: inherit; - text-align: justify; +.ascribe-pre { background-color: white; - border: none; + border: 0; + font-family: inherit; + margin: 0; padding: 0; - margin:0; + text-align: justify; + white-space: -moz-pre-wrap; + white-space: -o-pre-wrap; + white-space: -pre-wrap; + white-space: pre-wrap; + word-break: break-word; } diff --git a/sass/ascribe_theme.scss b/sass/ascribe_theme.scss index e02b97c6..5f1dd563 100644 --- a/sass/ascribe_theme.scss +++ b/sass/ascribe_theme.scss @@ -1,15 +1,15 @@ -/* All bootstrap overwrites should take place in this file */ +// All bootstrap overwrites should take place in this file .pager li a { color: white; } .panel-default { - border: none; + border: 0; box-shadow: none; margin-bottom: 0; } .panel-body { - padding:0; -} \ No newline at end of file + padding: 0; +} diff --git a/sass/ascribe_uploader.scss b/sass/ascribe_uploader.scss index 2aab021a..f7120fe7 100644 --- a/sass/ascribe_uploader.scss +++ b/sass/ascribe_uploader.scss @@ -1,21 +1,26 @@ .file-drag-and-drop { - display: block; - outline: 1px dashed #9E9E9E; - vertical-align: middle; - text-align: center; - height: auto; - background-color: #FEFEFE; - overflow: auto; - margin-top: 1em; - + background-color: #fefefe; cursor: default !important; + display: block; + height: auto; + margin-top: 1em; + outline: 1px dashed #9e9e9e; + overflow: auto; + padding: 1.5em 0; + text-align: center; + vertical-align: middle; - padding: 1.5em 0 1.5em 0; + .file-drag-and-drop-dialog > p:first-child { + font-size: 1.5em !important; + margin-bottom: 0; + margin-top: 0; + padding-bottom: 0; + } } .inactive-dropzone { + background-color: rgba(0, 0, 0, 0) !important; cursor: default !important; - background-color: rgba(0,0,0,0) !important; outline: 0; } @@ -25,44 +30,34 @@ } .btn { - margin: 0 1em 0 1em; + margin: 0 1em; } } -.file-drag-and-drop .file-drag-and-drop-dialog > p:first-child { - font-size: 1.5em !important; - - margin-top: 0; - margin-bottom: 0; - padding-bottom: 0; -} .file-drag-and-drop-position { - position: relative; display: inline-block; - margin-left: .7em; margin-right: .7em; + position: relative; .delete-file { - display: block; background-color: black; - - width: 20px; + border-radius: 1em; + cursor: pointer; + display: block; height: 20px; position: absolute; right: -7px; - top: -7px; - border-radius: 1em; text-align: center; - - cursor: pointer; + top: -7px; + width: 20px; span { color: white; - top: 1; - left: 0; font-size: .8em; + left: 0; + top: 1px; &:hover { color: $brand-danger; @@ -73,68 +68,74 @@ .file-drag-and-drop-preview-table-wrapper { display: table; - height:94px; - width:104px; + height: 94px; + width: 104px; } .file-drag-and-drop-preview { - overflow:hidden; - cursor: default; - background-color: #EEEEEE; + background-color: #eeeeee; border: 1px solid #616161; + cursor: default; + overflow: hidden; } .file-drag-and-drop-preview-image { - display: table; - height:104px; - width:104px; - overflow:hidden; border: 1px solid #616161; + display: table; + height: 104px; + overflow: hidden; text-align: center; -} + width: 104px; -.file-drag-and-drop-preview-image .action-file { - font-size: 2.5em; - margin-top: .6em; - color: white; - text-shadow: -2px 0 black, 0 2px black, 2px 0 black, 0 -2px black; - cursor: pointer; + .action-file { + color: white; + cursor: pointer; + font-size: 2.5em; + margin-top: .6em; + text-shadow: -2px 0 black, 0 2px black, 2px 0 black, 0 -2px black; - &:link, &:visited, &:hover, &:active { - text-decoration: none; - } + &:link, + &:visited, + &:hover, + &:active { + text-decoration: none; + } - &:hover { - color: #d9534f; + &:hover { + color: #d9534f; + } } } -.file-drag-and-drop-preview-other .action-file { - position: relative; - top: .3em; - margin-top: 0; - font-size: 2.5em; - color: white; - text-shadow: -2px 0 black, 0 2px black, 2px 0 black, 0 -2px black; - cursor: pointer; - - &:link, &:visited, &:hover, &:active { - text-decoration: none; - } - - &:hover { - color: #d9534f; - } -} .file-drag-and-drop-preview-other { display: table-cell; text-align: center; vertical-align: middle; -} + .action-file { + color: white; + cursor: pointer; + font-size: 2.5em; + margin-top: 0; + position: relative; + text-shadow: -2px 0 black, 0 2px black, 2px 0 black, 0 -2px black; + top: .3em; -.file-drag-and-drop-preview-other span:not(:first-child) { - display: block; - margin-top: .5em; + &:link, + &:visited, + &:hover, + &:active { + text-decoration: none; + } + + &:hover { + color: #d9534f; + } + + span:not(:first-child) { + display: block; + margin-top: .5em; + } + } } diff --git a/sass/ascribe_variables.scss b/sass/ascribe_variables.scss index 761cbfc3..2af5c6d3 100644 --- a/sass/ascribe_variables.scss +++ b/sass/ascribe_variables.scss @@ -1,3 +1,3 @@ $ascribe-color-green: rgba(2, 182, 163, 1); -$ascribe-brand-danger: #FC535F; +$ascribe-brand-danger: #fc535f; diff --git a/sass/main.scss b/sass/main.scss index 8a4f1306..b8587635 100644 --- a/sass/main.scss +++ b/sass/main.scss @@ -33,9 +33,11 @@ $BASE_URL: '<%= BASE_URL %>'; @import 'whitelabel/index'; -html, body { +html, +body { + background-color: #fdfdfd; + font-family: 'Source Sans Pro'; height: 100%; - background-color: #FDFDFD; } html { @@ -43,8 +45,8 @@ html { } .ascribe-default-app { - padding-top: 70px; overflow-x: hidden; + padding-top: 70px; } hr { @@ -59,154 +61,182 @@ hr { display: none; } -.no-margin{ +.no-margin { margin: 0; + margin-left: 0; + margin-right: 0; } -.no-padding{ + +.no-padding { padding: 0; } -.inline{ + +.inline { display: inline; } .navbar-default { - border: none; - border-left:0; - border-right:0; + border: 0; + border-color: #ccc; + border-left: 0; + border-right: 0; + border-top: 0; + font-size: .8em; margin-bottom: 1.5em; - border-top:0; - border-color: #CCC; - font-size: 0.8em; -} -.navbar-default .navbar-nav > .active { - a { - background-color: transparent!important; - > span {color: #02b6a3;} - color: #02b6a3; - border-bottom: 1px solid #02b6a3; + .navbar-nav > li > a { + border: 1px solid rgba(0, 0, 0, 0); + } - &:hover, &:focus{ - > span {color: #02b6a3;} - color: #02b6a3; - background-color: transparent; + .navbar-nav > .active { + a { + background-color: transparent !important; border-bottom: 1px solid #02b6a3; + color: #02b6a3; + + > span { + color: #02b6a3; + } + + &:hover, + &:focus { + background-color: transparent; + border-bottom: 1px solid #02b6a3; + color: #02b6a3; + + > span { + color: #02b6a3; + } + } } } } -.navbar-default .navbar-nav > li > a { - border: 1px solid rgba(0,0,0,0); -} + + .img-brand { - padding: 0; height: 45px; - margin: 5px 0 5px 0; + margin: 5px 0; + padding: 0; } + .truncate { - white-space: nowrap; - width: 4em; overflow: hidden; text-overflow: ellipsis; + white-space: nowrap; + width: 4em; + @media only screen and (min-width: 400px) { width: 8em; } + @media only screen and (min-width: 600px) { width: 12em; } + @media only screen and (min-width: 1000px) { width: 14em; } + @media only screen and (min-width: 1200px) { width: 16em; } + @media only screen and (min-width: 1400px) { width: 18em; } } + .navbar-right { margin-right: 0; } .clear-paddings { - padding-left:0; - padding-right:0; + padding-left: 0; + padding-right: 0; } .clear-margins { - margin-top:0; - margin-bottom:0; + margin-bottom: 0; + margin-top: 0; } .ascribe-color { color: $ascribe-color-green; } -.ascribe-subheader{ +.ascribe-subheader { padding-bottom: 10px; margin-top: -10px; + a { - cursor: pointer; - font-size: 0.8em; color: #222; + cursor: pointer; + font-size: .8em; } } -.tooltip-inner{ +.tooltip-inner { + background-color: #fcfafa; + border: 1px solid; + border-radius: 0; + color: #000; max-width: 300px; padding: 3px 8px; - color: #000; text-align: center; text-decoration: none; - background-color: #FCFAFA; - border-radius: 0; - border: 1px solid; } -/* Taken from http://stackoverflow.com/a/20548578 */ +// Taken from http://stackoverflow.com/a/20548578 .vcenter { display: inline-block; - vertical-align: middle; float: none; + vertical-align: middle; } -.filter-glyph{ + +.filter-glyph { color: white; } -.no-margin { - margin-right: 0; - margin-left: 0; -} -.btn-delete{ - background-color: rgba(0,0,0,0); + +.btn-delete { + background-color: rgba(0, 0, 0, 0); + border: 1px solid rgba(0, 0, 0, 0); color: #888; - border: 1px solid rgba(0,0,0,0); - &:hover{ + + &:hover { border: 1px solid $ascribe-brand-danger; } } -.btn-ascribe, .btn-ascribe-inv { + +.btn-ascribe, +.btn-ascribe-inv { border: 1px solid #444; - line-height: 2em; - margin-right: 1px; - margin-left: 0 !important; - font-family: sans-serif !important; border-radius: 0 !important; + font-family: sans-serif !important; + line-height: 2em; + margin-left: 0 !important; + margin-right: 1px; } -.btn-ascribe, .btn-ascribe-inv:active, .btn-ascribe-inv:hover { +.btn-ascribe, +.btn-ascribe-inv:active, +.btn-ascribe-inv:hover { + background-color: #fff; color: #222 !important; - background-color: #FFF; } -.btn-ascribe:active, .btn-ascribe:hover, .btn-ascribe-inv { - color: #FFF !important; +.btn-ascribe:active, +.btn-ascribe:hover, +.btn-ascribe-inv { background-color: #444; + color: #fff !important; } -.btn-ascribe-inv:disabled, .btn-ascribe-inv:focus { - color: #444 !important; +.btn-ascribe-inv:disabled, +.btn-ascribe-inv:focus { background-color: #BBB !important; border: 1px solid #444 !important; + color: #444 !important; } .btn-ascribe-sm { @@ -214,24 +244,29 @@ hr { line-height: 1.3em; } -.btn-ascribe-green, .btn-ascribe-green-inv { - border: 1px solid #48DACB; +.btn-ascribe-green, +.btn-ascribe-green-inv { + border: 1px solid #48dacb; + border-radius: 0 !important; + font-family: sans-serif !important; line-height: 2em; margin-left: 0 !important; - font-family: sans-serif !important; - border-radius: 0 !important; } -.btn-ascribe-green, .btn-ascribe-green-inv:active, .btn-ascribe-green-inv:hover { - background-color: #FFF; - border: 1px solid rgba(2, 182, 163, 0.5); +.btn-ascribe-green, +.btn-ascribe-green-inv:active, +.btn-ascribe-green-inv:hover { + background-color: #fff; + border: 1px solid rgba(2, 182, 163, .5); color: rgba(2, 182, 163, 0.5); } -.btn-ascribe-green:active, .btn-ascribe-green:hover, .btn-ascribe-green-inv { - border: 1px solid rgba(2, 182, 163, 0.5); +.btn-ascribe-green:active, +.btn-ascribe-green:hover, +.btn-ascribe-green-inv { + background-color: rgba(2, 182, 163, .5); + border: 1px solid rgba(2, 182, 163, .5); color: white; - background-color: rgba(2, 182, 163, 0.5); } .ascribe-detail-title { @@ -240,33 +275,34 @@ hr { } .ascribe-detail-property { - padding-bottom: 0.4em; + padding-bottom: .4em; } .ascribe-detail-property-label { - font-size: 0.8em; + font-size: .8em; } .ascribe-detail-property-value { - /* white-space: nowrap; - overflow: hidden; */ text-overflow: ellipsis; } -::-webkit-input-placeholder { /* WebKit browsers */ - font-size: 0.9em; +::-webkit-input-placeholder { // WebKit browsers + font-size: .9em; font-style: italic; } -:-moz-placeholder { /* Mozilla Firefox 4 to 18 */ - font-size: 0.9em; + +:-moz-placeholder { // Mozilla Firefox 4 to 18 + font-size: .9em; font-style: italic; } -::-moz-placeholder { /* Mozilla Firefox 19+ */ - font-size: 0.9em; + +::-moz-placeholder { // Mozilla Firefox 19+ + font-size: .9em; font-style: italic; } -:-ms-input-placeholder { /* Internet Explorer 10+ */ - font-size: 0.9em; + +:-ms-input-placeholder { // Internet Explorer 10+ + font-size: .9em; font-style: italic; } @@ -275,15 +311,15 @@ hr { } .input-checkbox-ascribe { - text-align: left; line-height: 1.6; - width: 90%; margin-left: 1.6em; margin-right: auto; + text-align: left; + width: 90%; } -/* columns of same height styles */ -/* http://www.minimit.com/articles/solutions-tutorials/bootstrap-3-responsive-columns-of-same-height */ +// columns of same height styles +// http://www.minimit.com/articles/solutions-tutorials/bootstrap-3-responsive-columns-of-same-height .row-full-height { height: 100%; } @@ -295,9 +331,9 @@ hr { .row-same-height { display: table; - width: 100%; - /* fix overflow */ + // fix overflow table-layout: fixed; + width: 100%; } .col-xs-height { @@ -326,7 +362,7 @@ hr { } } -/* vertical alignment styles */ +// vertical alignment styles .col-top { vertical-align: top; @@ -350,40 +386,44 @@ hr { } .spin { - display:inline-block; - -webkit-animation: spin 1s infinite linear; -moz-animation: spin 1s infinite linear; - -o-animation: spin 1s infinite linear; -ms-animation: spin 1s infinite linear; + -o-animation: spin 1s infinite linear; + -webkit-animation: spin 1s infinite linear; animation: spin 1s infinite linear; - -webkit-transform-origin: 55% 70%; -moz-transform-origin: 55% 70%; -o-transform-origin: 55% 70%; + -webkit-transform-origin: 55% 70%; + display: inline-block; transform-origin: 55% 70%; width: 10px; height: 10px; } @-webkit-keyframes spin { -0% { -webkit-transform: rotate(0deg);} -100% { -webkit-transform: rotate(360deg);} + 0% { -webkit-transform: rotate(0deg);} + 100% { -webkit-transform: rotate(360deg);} } + @-moz-keyframes spin { -0% { -moz-transform: rotate(0deg); } -100% { -moz-transform: rotate(360deg);} + 0% { -moz-transform: rotate(0deg); } + 100% { -moz-transform: rotate(360deg);} } + @-o-keyframes spin { -0% { -o-transform: rotate(0deg);} -100% { -o-transform: rotate(360deg);} + 0% { -o-transform: rotate(0deg);} + 100% { -o-transform: rotate(360deg);} } + @-ms-keyframes spin { -0% { -ms-transform: rotate(0deg);} -100% { -ms-transform: rotate(360deg);} + 0% { -ms-transform: rotate(0deg);} + 100% { -ms-transform: rotate(360deg);} } + @-keyframes spin { -0% { transform: rotate(0deg); } -100% { transform: rotate(360deg);} -} + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg);} +} .btn-default { .glyph-ascribe-spool { @@ -392,9 +432,8 @@ hr { } .fullpage-spinner { - padding-top: 30%; padding-bottom: 30%; - + padding-top: 30%; text-align: center; > span { @@ -404,21 +443,22 @@ hr { .disable-select { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -webkit-user-select: none; user-select: none; } .link-ascribe { color: #666; + &:hover { color: #000; } } .ascribe-loading-position { - padding-top: 30%; padding-bottom: 30%; + padding-top: 30%; text-align: center; } diff --git a/sass/offset_right.scss b/sass/offset_right.scss index f844ce20..a90e2078 100644 --- a/sass/offset_right.scss +++ b/sass/offset_right.scss @@ -1,164 +1,214 @@ -/* Taken from: http://stackoverflow.com/a/27501063/1263876 */ +// Taken from: http://stackoverflow.com/a/27501063/1263876 .col-xs-offset-right-12 { - margin-right: 100%; -} -.col-xs-offset-right-11 { - margin-right: 91.66666667%; -} -.col-xs-offset-right-10 { - margin-right: 83.33333333%; -} -.col-xs-offset-right-9 { - margin-right: 75%; -} -.col-xs-offset-right-8 { - margin-right: 66.66666667%; -} -.col-xs-offset-right-7 { - margin-right: 58.33333333%; -} -.col-xs-offset-right-6 { - margin-right: 50%; -} -.col-xs-offset-right-5 { - margin-right: 41.66666667%; -} -.col-xs-offset-right-4 { - margin-right: 33.33333333%; -} -.col-xs-offset-right-3 { - margin-right: 25%; -} -.col-xs-offset-right-2 { - margin-right: 16.66666667%; -} -.col-xs-offset-right-1 { - margin-right: 8.33333333%; -} -.col-xs-offset-right-0 { - margin-right: 0; -} -@media (min-width: 768px) { - .col-sm-offset-right-12 { margin-right: 100%; - } - .col-sm-offset-right-11 { +} + +.col-xs-offset-right-11 { margin-right: 91.66666667%; - } - .col-sm-offset-right-10 { +} + +.col-xs-offset-right-10 { margin-right: 83.33333333%; - } - .col-sm-offset-right-9 { +} + +.col-xs-offset-right-9 { margin-right: 75%; - } - .col-sm-offset-right-8 { +} + +.col-xs-offset-right-8 { margin-right: 66.66666667%; - } - .col-sm-offset-right-7 { +} + +.col-xs-offset-right-7 { margin-right: 58.33333333%; - } - .col-sm-offset-right-6 { +} + +.col-xs-offset-right-6 { margin-right: 50%; - } - .col-sm-offset-right-5 { +} + +.col-xs-offset-right-5 { margin-right: 41.66666667%; - } - .col-sm-offset-right-4 { +} + +.col-xs-offset-right-4 { margin-right: 33.33333333%; - } - .col-sm-offset-right-3 { +} + +.col-xs-offset-right-3 { margin-right: 25%; - } - .col-sm-offset-right-2 { +} + +.col-xs-offset-right-2 { margin-right: 16.66666667%; - } - .col-sm-offset-right-1 { +} + +.col-xs-offset-right-1 { margin-right: 8.33333333%; - } - .col-sm-offset-right-0 { +} + +.col-xs-offset-right-0 { margin-right: 0; - } +} + +@media (min-width: 768px) { + .col-sm-offset-right-12 { + margin-right: 100%; + } + + .col-sm-offset-right-11 { + margin-right: 91.66666667%; + } + + .col-sm-offset-right-10 { + margin-right: 83.33333333%; + } + + .col-sm-offset-right-9 { + margin-right: 75%; + } + + .col-sm-offset-right-8 { + margin-right: 66.66666667%; + } + + .col-sm-offset-right-7 { + margin-right: 58.33333333%; + } + + .col-sm-offset-right-6 { + margin-right: 50%; + } + + .col-sm-offset-right-5 { + margin-right: 41.66666667%; + } + + .col-sm-offset-right-4 { + margin-right: 33.33333333%; + } + + .col-sm-offset-right-3 { + margin-right: 25%; + } + + .col-sm-offset-right-2 { + margin-right: 16.66666667%; + } + + .col-sm-offset-right-1 { + margin-right: 8.33333333%; + } + + .col-sm-offset-right-0 { + margin-right: 0; + } } @media (min-width: 992px) { - .col-md-offset-right-12 { - margin-right: 100%; - } - .col-md-offset-right-11 { - margin-right: 91.66666667%; - } - .col-md-offset-right-10 { - margin-right: 83.33333333%; - } - .col-md-offset-right-9 { - margin-right: 75%; - } - .col-md-offset-right-8 { - margin-right: 66.66666667%; - } - .col-md-offset-right-7 { - margin-right: 58.33333333%; - } - .col-md-offset-right-6 { - margin-right: 50%; - } - .col-md-offset-right-5 { - margin-right: 41.66666667%; - } - .col-md-offset-right-4 { - margin-right: 33.33333333%; - } - .col-md-offset-right-3 { - margin-right: 25%; - } - .col-md-offset-right-2 { - margin-right: 16.66666667%; - } - .col-md-offset-right-1 { - margin-right: 8.33333333%; - } - .col-md-offset-right-0 { - margin-right: 0; - } + .col-md-offset-right-12 { + margin-right: 100%; + } + + .col-md-offset-right-11 { + margin-right: 91.66666667%; + } + + .col-md-offset-right-10 { + margin-right: 83.33333333%; + } + + .col-md-offset-right-9 { + margin-right: 75%; + } + + .col-md-offset-right-8 { + margin-right: 66.66666667%; + } + + .col-md-offset-right-7 { + margin-right: 58.33333333%; + } + + .col-md-offset-right-6 { + margin-right: 50%; + } + + .col-md-offset-right-5 { + margin-right: 41.66666667%; + } + + .col-md-offset-right-4 { + margin-right: 33.33333333%; + } + + .col-md-offset-right-3 { + margin-right: 25%; + } + + .col-md-offset-right-2 { + margin-right: 16.66666667%; + } + + .col-md-offset-right-1 { + margin-right: 8.33333333%; + } + + .col-md-offset-right-0 { + margin-right: 0; + } } + @media (min-width: 1200px) { - .col-lg-offset-right-12 { - margin-right: 100%; - } - .col-lg-offset-right-11 { - margin-right: 91.66666667%; - } - .col-lg-offset-right-10 { - margin-right: 83.33333333%; - } - .col-lg-offset-right-9 { - margin-right: 75%; - } - .col-lg-offset-right-8 { - margin-right: 66.66666667%; - } - .col-lg-offset-right-7 { - margin-right: 58.33333333%; - } - .col-lg-offset-right-6 { - margin-right: 50%; - } - .col-lg-offset-right-5 { - margin-right: 41.66666667%; - } - .col-lg-offset-right-4 { - margin-right: 33.33333333%; - } - .col-lg-offset-right-3 { - margin-right: 25%; - } - .col-lg-offset-right-2 { - margin-right: 16.66666667%; - } - .col-lg-offset-right-1 { - margin-right: 8.33333333%; - } - .col-lg-offset-right-0 { - margin-right: 0; - } -} \ No newline at end of file + .col-lg-offset-right-12 { + margin-right: 100%; + } + + .col-lg-offset-right-11 { + margin-right: 91.66666667%; + } + + .col-lg-offset-right-10 { + margin-right: 83.33333333%; + } + + .col-lg-offset-right-9 { + margin-right: 75%; + } + + .col-lg-offset-right-8 { + margin-right: 66.66666667%; + } + + .col-lg-offset-right-7 { + margin-right: 58.33333333%; + } + + .col-lg-offset-right-6 { + margin-right: 50%; + } + + .col-lg-offset-right-5 { + margin-right: 41.66666667%; + } + + .col-lg-offset-right-4 { + margin-right: 33.33333333%; + } + + .col-lg-offset-right-3 { + margin-right: 25%; + } + + .col-lg-offset-right-2 { + margin-right: 16.66666667%; + } + + .col-lg-offset-right-1 { + margin-right: 8.33333333%; + } + + .col-lg-offset-right-0 { + margin-right: 0; + } +} diff --git a/sass/variables.scss b/sass/variables.scss index 6a3571e2..909440c9 100644 --- a/sass/variables.scss +++ b/sass/variables.scss @@ -51,14 +51,14 @@ $font-family-base: $font-family-sans-serif !default; $font-size-base: 14px !default; $font-size-large: ceil(($font-size-base * 1.25)) !default; // ~18px -$font-size-small: ceil(($font-size-base * 0.85)) !default; // ~12px +$font-size-small: ceil(($font-size-base * .85)) !default; // ~12px $font-size-h1: floor(($font-size-base * 2.6)) !default; // ~36px $font-size-h2: floor(($font-size-base * 2.15)) !default; // ~30px $font-size-h3: ceil(($font-size-base * 1.7)) !default; // ~24px $font-size-h4: ceil(($font-size-base * 1.25)) !default; // ~18px $font-size-h5: $font-size-base !default; -$font-size-h6: ceil(($font-size-base * 0.85)) !default; // ~12px +$font-size-h6: ceil(($font-size-base * .85)) !default; // ~12px //** Unit-less `line-height` for use in components like buttons. $line-height-base: 1.428571429 !default; // 20/14 @@ -234,7 +234,7 @@ $cursor-disabled: not-allowed !default; //** Background for the dropdown menu. $dropdown-bg: #fff !default; //** Dropdown menu `border-color`. -$dropdown-border: rgba(0,0,0,.15) !default; +$dropdown-border: rgba(0, 0, 0, .15) !default; //** Dropdown menu `border-color` **for IE8**. $dropdown-fallback-border: #ccc !default; //** Divider color for between dropdown items. @@ -541,7 +541,7 @@ $popover-bg: #fff !default; //** Popover maximum width $popover-max-width: 276px !default; //** Popover border color -$popover-border-color: rgba(0,0,0,.2) !default; +$popover-border-color: rgba(0, 0, 0, .2) !default; //** Popover fallback border color $popover-fallback-border-color: #ccc !default; @@ -556,7 +556,7 @@ $popover-arrow-color: $popover-bg !default; //** Popover outer arrow width $popover-arrow-outer-width: ($popover-arrow-width + 1) !default; //** Popover outer arrow color -$popover-arrow-outer-color: fade_in($popover-border-color, 0.05) !default; +$popover-arrow-outer-color: fade_in($popover-border-color, .05) !default; //** Popover outer arrow fallback color $popover-arrow-outer-fallback-color: darken($popover-fallback-border-color, 20%) !default; @@ -804,7 +804,7 @@ $breadcrumb-separator: "/" !default; // //## -$carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6) !default; +$carousel-text-shadow: 0 1px 2px rgba(0, 0, 0, .6) !default; $carousel-control-color: #fff !default; $carousel-control-width: 15% !default; From b6fc0e931de3d6328d6fd222b51c63d907c8c963 Mon Sep 17 00:00:00 2001 From: vrde Date: Mon, 31 Aug 2015 19:13:09 +0200 Subject: [PATCH 011/192] Update readme with doc on how to install the linter --- README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 270c4a5f..a3258576 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,8 @@ Additionally, to work on the white labeling functionality, you need to edit your ``` -Code Conventions -================ +JavaScript Code Conventions +=========================== For this project, we're using: * 4 Spaces @@ -42,6 +42,15 @@ For this project, we're using: * We don't use camel case for file naming but in everything Javascript related * We use `let` instead of `var`: [SA Post](http://stackoverflow.com/questions/762011/javascript-let-keyword-vs-var-keyword) + +SCSS Code Conventions +===================== +Install [lint-scss](https://github.com/brigade/scss-lint), check the [editor integration docs](https://github.com/brigade/scss-lint#editor-integration) to integrate the lint in your editor. + +Some interesting links: +* [Improving Sass code quality on theguardian.com](https://www.theguardian.com/info/developer-blog/2014/may/13/improving-sass-code-quality-on-theguardiancom) + + Testing =============== We're using Facebook's jest to do testing as it integrates nicely with react.js as well. @@ -127,4 +136,4 @@ Moar stuff - [24ways.org: JavaScript Modules the ES6 Way](http://24ways.org/2014/javascript-modules-the-es6-way/) - [Babel: Learn ES6](https://babeljs.io/docs/learn-es6/) - [egghead's awesome reactjs and flux tutorials](https://egghead.io/) -- [Crockford's genious Javascript: The Good Parts (Tim has a copy)](http://www.amazon.de/JavaScript-Parts-Working-Shallow-Grain/dp/0596517742) \ No newline at end of file +- [Crockford's genious Javascript: The Good Parts (Tim has a copy)](http://www.amazon.de/JavaScript-Parts-Working-Shallow-Grain/dp/0596517742) From b5b1e3610992110a5abf75a6f61f332657279d16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 1 Sep 2015 14:00:06 +0200 Subject: [PATCH 012/192] nested collapsible paragraphs --- .scss-lint.yml | 4 +- .../collapsible_paragraph.js | 4 +- .../ascribe_settings/contract_settings.js | 93 ++++++++++--------- .../components/prize_settings_container.js | 2 +- sass/ascribe_collapsible.scss | 33 +++++++ sass/ascribe_edition.scss | 28 ------ sass/main.scss | 1 + 7 files changed, 88 insertions(+), 77 deletions(-) create mode 100644 sass/ascribe_collapsible.scss diff --git a/.scss-lint.yml b/.scss-lint.yml index 6d4fd6ba..61b1c624 100644 --- a/.scss-lint.yml +++ b/.scss-lint.yml @@ -48,7 +48,7 @@ linters: enabled: false FinalNewline: - enabled: true + enabled: false present: true HexLength: @@ -106,7 +106,7 @@ linters: max_properties: 10 PropertySortOrder: - enabled: true + enabled: false ignore_unspecified: false min_properties: 2 separate_groups: false diff --git a/js/components/ascribe_collapsible/collapsible_paragraph.js b/js/components/ascribe_collapsible/collapsible_paragraph.js index 8b3b3cf4..a5c884e5 100644 --- a/js/components/ascribe_collapsible/collapsible_paragraph.js +++ b/js/components/ascribe_collapsible/collapsible_paragraph.js @@ -38,14 +38,14 @@ const CollapsibleParagraph = React.createClass({ if(this.props.show) { return (
-
+
{text} {this.props.title}
+ className="ascribe-collapsible-content"> {this.props.children}
diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index d2928457..bba04754 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -27,50 +27,55 @@ let ContractSettings = React.createClass({ title={getLangText('Contract Settings')} show={true} defaultExpanded={this.props.defaultExpanded}> - - - - -
- + +
+ + + +
+
+
); } diff --git a/js/components/whitelabel/prize/components/prize_settings_container.js b/js/components/whitelabel/prize/components/prize_settings_container.js index e0c30d46..e6a53bbb 100644 --- a/js/components/whitelabel/prize/components/prize_settings_container.js +++ b/js/components/whitelabel/prize/components/prize_settings_container.js @@ -265,7 +265,7 @@ let PrizeJurySettings = React.createClass({ if (this.state.members.length > -1) { content = ( -
+
div:first-child { + background-color: rgba(0, 0, 0, 0); + cursor: pointer; + margin-top: 20px; + padding: 0 10px 10px 0; + width: 100%; + } + + > div > span { + font-size: 1.2em; + margin-right: .5em; + } + + > div > span:nth-child(2) { + font-size: .9em; + } +} + +.ascribe-collapsible-content { + background: none; + border: 0; + width: 100%; + + /* Shrink the size of the headline for a nested element */ + .ascribe-collapsible-wrapper > div:first-child { + padding-left: 1em; + font-size: 90%; + } +} \ No newline at end of file diff --git a/sass/ascribe_edition.scss b/sass/ascribe_edition.scss index f86f74e2..9fa30387 100644 --- a/sass/ascribe_edition.scss +++ b/sass/ascribe_edition.scss @@ -3,34 +3,6 @@ margin-bottom: 1em; } -.ascribe-edition-collapsible-wrapper { - vertical-align: bottom; - width: 100%; - - > div:first-child { - background-color: rgba(0, 0, 0, 0); - cursor: pointer; - margin-top: 20px; - padding: 0 10px 10px 0; - width: 100%; - } - - > div > span { - font-size: 1.2em; - margin-right: .5em; - } - - > div > span:nth-child(2) { - font-size: .9em; - } -} - -.ascribe-edition-collapsible-content { - background: none; - border: 0; - width: 100%; -} - .coa-file-wrapper { display: table; height: 200px; diff --git a/sass/main.scss b/sass/main.scss index 510599bd..6ec1d37d 100644 --- a/sass/main.scss +++ b/sass/main.scss @@ -29,6 +29,7 @@ $BASE_URL: '<%= BASE_URL %>'; @import 'ascribe_slides_container'; @import 'ascribe_form'; @import 'ascribe_panel'; +@import 'ascribe_collapsible'; @import 'whitelabel/index'; From b4abe7a24569f1a30f16d99f5d64fe31c31d23a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 1 Sep 2015 14:42:09 +0200 Subject: [PATCH 013/192] generic form submission determination for fineuploader --- .../ascribe_detail/further_details.js | 4 +- .../ascribe_forms/form_create_contract.js | 102 ++++++++++++++++++ .../ascribe_forms/form_register_piece.js | 6 +- .../ascribe_settings/contract_settings.js | 63 +---------- .../react_s3_fine_uploader_utils.js | 44 +++++--- .../cyland_additional_data_form.js | 14 +-- 6 files changed, 145 insertions(+), 88 deletions(-) create mode 100644 js/components/ascribe_forms/form_create_contract.js diff --git a/js/components/ascribe_detail/further_details.js b/js/components/ascribe_detail/further_details.js index 9fc5bf15..863ed491 100644 --- a/js/components/ascribe_detail/further_details.js +++ b/js/components/ascribe_detail/further_details.js @@ -15,7 +15,7 @@ import GlobalNotificationActions from '../../actions/global_notification_actions import FurtherDetailsFileuploader from './further_details_fileuploader'; -import { isReadyForFormSubmission } from '../ascribe_uploader/react_s3_fine_uploader_utils'; +import { formSubmissionValidation } from '../ascribe_uploader/react_s3_fine_uploader_utils'; let FurtherDetails = React.createClass({ propTypes: { @@ -80,7 +80,7 @@ let FurtherDetails = React.createClass({ + {getLangText('Create new contract')} + + } + spinner={ + + + + }> + + + + + + + + ); + } +}); + +export default CreateContractForm; \ No newline at end of file diff --git a/js/components/ascribe_forms/form_register_piece.js b/js/components/ascribe_forms/form_register_piece.js index 3519c976..c6a28626 100644 --- a/js/components/ascribe_forms/form_register_piece.js +++ b/js/components/ascribe_forms/form_register_piece.js @@ -16,7 +16,7 @@ import ApiUrls from '../../constants/api_urls'; import { getCookie } from '../../utils/fetch_api_utils'; import { getLangText } from '../../utils/lang_utils'; import { mergeOptions } from '../../utils/general_utils'; -import { isReadyForFormSubmission } from '../ascribe_uploader/react_s3_fine_uploader_utils'; +import { formSubmissionValidation } from '../ascribe_uploader/react_s3_fine_uploader_utils'; let RegisterPieceForm = React.createClass({ @@ -115,7 +115,7 @@ let RegisterPieceForm = React.createClass({ - -
- - - -
-
-
+ defaultExpanded={true}> + {/* this should be this.props.defaultExpanded */} +
); } diff --git a/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js b/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js index dbf62619..dbbfd63f 100644 --- a/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js +++ b/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js @@ -1,16 +1,34 @@ 'use strict'; -/** - * Returns a boolean if there has been at least one file uploaded - * successfully without it being deleted or canceled. - * @param {array of files} files provided by react fine uploader - * @return {Boolean} - */ -export function isReadyForFormSubmission(files) { - files = files.filter((file) => file.status !== 'deleted' && file.status !== 'canceled'); - if (files.length > 0 && files[0].status === 'upload successful') { - return true; - } else { - return false; +export const formSubmissionValidation = { + /** + * Returns a boolean if there has been at least one file uploaded + * successfully without it being deleted or canceled. + * @param {array of files} files provided by react fine uploader + * @return {boolean} + */ + atLeastOneUploadedFile(files) { + files = files.filter((file) => file.status !== 'deleted' && file.status !== 'canceled'); + if (files.length > 0 && files[0].status === 'upload successful') { + return true; + } else { + return false; + } + }, + + /** + * File submission for the form is optional, but if the user decides to submit a file + * the form is not ready until there are no more files currently uploading. + * @param {array of files} files files provided by react fine uploader + * @return {boolean} [description] + */ + fileOptional(files) { + let uploadingFiles = files.filter((file) => file.status === 'submitting'); + + if (uploadingFiles.length === 0) { + return true; + } else { + return false; + } } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js b/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js index f7946be5..13e731ef 100644 --- a/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js +++ b/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js @@ -15,6 +15,8 @@ import AppConstants from '../../../../../../constants/application_constants'; import requests from '../../../../../../utils/requests'; import { getLangText } from '../../../../../../utils/lang_utils'; +import { formSubmissionValidation } from '../../../../../ascribe_uploader/react_s3_fine_uploader_utils'; + let CylandAdditionalDataForm = React.createClass({ propTypes: { @@ -60,16 +62,6 @@ let CylandAdditionalDataForm = React.createClass({ }); }, - isReadyForFormSubmission(files) { - let uploadingFiles = files.filter((file) => file.status === 'submitting'); - - if (uploadingFiles.length === 0) { - return true; - } else { - return false; - } - }, - render() { if(this.props.piece && this.props.piece.id) { return ( @@ -122,7 +114,7 @@ let CylandAdditionalDataForm = React.createClass({ uploadStarted={this.uploadStarted} submitKey={this.submitKey} setIsUploadReady={this.setIsUploadReady} - isReadyForFormSubmission={this.isReadyForFormSubmission} + isReadyForFormSubmission={formSubmissionValidation.fileOptional} editable={!this.props.disabled} pieceId={this.props.piece.id} otherData={this.props.piece.other_data} From bfaf4886a49d13e803eaf7ac7da85541f58da9eb Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 1 Sep 2015 14:45:14 +0200 Subject: [PATCH 014/192] notifications unoptimized --- .../ascribe_detail/edition_container.js | 9 ++ js/components/global_action.js | 43 ++++++++ js/components/header.js | 98 ++++++++++++++++++- js/components/piece_list.js | 27 +---- js/stores/piece_list_store.js | 16 +-- sass/ascribe_global_action.scss | 64 ++---------- sass/ascribe_notification_list.scss | 65 ++++++++++++ sass/main.scss | 1 + 8 files changed, 226 insertions(+), 97 deletions(-) create mode 100644 js/components/global_action.js create mode 100644 sass/ascribe_notification_list.scss diff --git a/js/components/ascribe_detail/edition_container.js b/js/components/ascribe_detail/edition_container.js index 15086434..62efa709 100644 --- a/js/components/ascribe_detail/edition_container.js +++ b/js/components/ascribe_detail/edition_container.js @@ -34,6 +34,15 @@ let EditionContainer = React.createClass({ EditionActions.fetchOne(this.props.params.editionId); }, + // This is done to update the container when the user clicks on the prev or next + // button to update the URL parameter (and therefore to switch pieces) + componentWillReceiveProps(nextProps) { + if(this.props.params.editionId !== nextProps.params.editionId) { + EditionActions.updateEdition({}); + EditionActions.fetchOne(nextProps.params.editionId); + } + }, + componentWillUnmount() { // Every time we're leaving the edition detail page, // just reset the edition that is saved in the edition store diff --git a/js/components/global_action.js b/js/components/global_action.js new file mode 100644 index 00000000..80df0c75 --- /dev/null +++ b/js/components/global_action.js @@ -0,0 +1,43 @@ +'use strict'; + +import React from 'react'; + +let GlobalAction = React.createClass({ + propTypes: { + requestActions: React.PropTypes.object + }, + + render() { + let pieceActions = null; + if (this.props.requestActions && this.props.requestActions.pieces){ + pieceActions = this.props.requestActions.pieces.map((item) => { + return ( +
+ {item} +
); + }); + } + let editionActions = null; + if (this.props.requestActions && this.props.requestActions.editions){ + editionActions = Object.keys(this.props.requestActions.editions).map((pieceId) => { + return this.props.requestActions.editions[pieceId].map((item) => { + return ( +
+ {item} +
); + }); + }); + } + + if (pieceActions || editionActions) { + return ( +
+ {pieceActions} + {editionActions} +
); + } + return null; + } +}); + +export default GlobalAction; \ No newline at end of file diff --git a/js/components/header.js b/js/components/header.js index 0863624f..7cd0e455 100644 --- a/js/components/header.js +++ b/js/components/header.js @@ -3,6 +3,8 @@ import React from 'react'; import Router from 'react-router'; +import Glyphicon from 'react-bootstrap/lib/Glyphicon'; + import UserActions from '../actions/user_actions'; import UserStore from '../stores/user_store'; @@ -10,6 +12,8 @@ import WhitelabelActions from '../actions/whitelabel_actions'; import WhitelabelStore from '../stores/whitelabel_store'; import EventActions from '../actions/event_actions'; +import PieceListStore from '../stores/piece_list_store'; + import Nav from 'react-bootstrap/lib/Nav'; import Navbar from 'react-bootstrap/lib/Navbar'; import CollapsibleNav from 'react-bootstrap/lib/CollapsibleNav'; @@ -25,6 +29,8 @@ import NavRoutesLinks from './nav_routes_links'; import { mergeOptions } from '../utils/general_utils'; import { getLangText } from '../utils/lang_utils'; +let Link = Router.Link; + let Header = React.createClass({ propTypes: { @@ -41,7 +47,11 @@ let Header = React.createClass({ }, getInitialState() { - return mergeOptions(WhitelabelStore.getState(), UserStore.getState()); + return mergeOptions( + WhitelabelStore.getState(), + UserStore.getState(), + PieceListStore.getState() + ); }, componentDidMount() { @@ -49,11 +59,13 @@ let Header = React.createClass({ UserStore.listen(this.onChange); WhitelabelActions.fetchWhitelabel(); WhitelabelStore.listen(this.onChange); + PieceListStore.listen(this.onChange); }, componentWillUnmount() { UserStore.unlisten(this.onChange); WhitelabelStore.unlisten(this.onChange); + PieceListStore.unlisten(this.onChange); }, getLogo(){ @@ -90,6 +102,34 @@ let Header = React.createClass({ } }, + getNotifications() { + if (this.state.requestActions && this.state.requestActions.length > 0) { + return ( + + + + ({this.state.requestActions.length}) + + } + className="notification-menu"> + {this.state.requestActions.map((pieceOrEdition, i) => { + return ( + + + ); + }) + } + + ); + } + return null; + }, + render() { let account; let signup; @@ -100,7 +140,7 @@ let Header = React.createClass({ {getLangText('Account Settings')} {getLangText('Log out')} - + ); navRoutesLinks = ; } @@ -122,6 +162,7 @@ let Header = React.createClass({ {this.getPoweredBy()} + {navRoutesLinks} @@ -175,57 +141,4 @@ let Header = React.createClass({ } }); -let NotificationListItem = React.createClass({ - propTypes: { - pieceOrEdition: React.PropTypes.object - }, - - getLinkData() { - - if(this.props.pieceOrEdition && this.props.pieceOrEdition.bitcoin_id) { - return { - to: 'edition', - params: { - editionId: this.props.pieceOrEdition.bitcoin_id - } - }; - } else { - return { - to: 'piece', - params: { - pieceId: this.props.pieceOrEdition.id - } - }; - } - - }, - - render() { - if (this.props.pieceOrEdition) { - return ( - -
-
-
- -
-
-
-

{this.props.pieceOrEdition.title}

-
by {this.props.pieceOrEdition.artist_name}
-
- { - this.props.pieceOrEdition.request_action.map((requestAction) => { - return 'Pending ' + requestAction.action + ' request'; - }) - } -
-
-
- ); - } - return null; - } -}); - export default Header; diff --git a/js/components/header_notification.js b/js/components/header_notification.js new file mode 100644 index 00000000..c838e346 --- /dev/null +++ b/js/components/header_notification.js @@ -0,0 +1,122 @@ +'use strict'; + +import React from 'react'; +import Router from 'react-router'; +import DropdownButton from 'react-bootstrap/lib/DropdownButton'; +import Glyphicon from 'react-bootstrap/lib/Glyphicon'; +import MenuItem from 'react-bootstrap/lib/MenuItem'; + +import Nav from 'react-bootstrap/lib/Nav'; + +import PieceListStore from '../stores/piece_list_store'; + +import { mergeOptions } from '../utils/general_utils'; +import { getLangText } from '../utils/lang_utils'; + +let Link = Router.Link; + + +let HeaderNotifications = React.createClass({ + + getInitialState() { + return mergeOptions( + PieceListStore.getState() + ); + }, + + componentDidMount() { + PieceListStore.listen(this.onChange); + }, + + componentWillUnmount() { + PieceListStore.unlisten(this.onChange); + }, + + onChange(state) { + this.setState(state); + }, + + render() { + if (this.state.requestActions && this.state.requestActions.length > 0) { + return ( + + ); + } + return null; + } +}); + +let NotificationListItem = React.createClass({ + propTypes: { + pieceOrEdition: React.PropTypes.object + }, + + getLinkData() { + + if(this.props.pieceOrEdition && this.props.pieceOrEdition.parent) { + return { + to: 'edition', + params: { + editionId: this.props.pieceOrEdition.bitcoin_id + } + }; + } else { + return { + to: 'piece', + params: { + pieceId: this.props.pieceOrEdition.id + } + }; + } + + }, + + render() { + if (this.props.pieceOrEdition) { + return ( + +
+
+
+ +
+
+
+

{this.props.pieceOrEdition.title}

+
by {this.props.pieceOrEdition.artist_name}
+
+ { + this.props.pieceOrEdition.request_action.map((requestAction) => { + return 'Pending ' + requestAction.action + ' request'; + }) + } +
+
+
+ ); + } + return null; + } +}); + +export default HeaderNotifications; From 71c438ee599fa96b1c74542ab432b753c3d3dd98 Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 1 Sep 2015 18:38:24 +0200 Subject: [PATCH 017/192] close notifications dropdown after click --- js/components/header.js | 4 +++- js/components/header_notification.js | 24 +++++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/js/components/header.js b/js/components/header.js index 6876885c..dcf3c475 100644 --- a/js/components/header.js +++ b/js/components/header.js @@ -102,7 +102,9 @@ let Header = React.createClass({ let navRoutesLinks; if (this.state.currentUser.username){ account = ( - + {getLangText('Account Settings')} {getLangText('Log out')} diff --git a/js/components/header_notification.js b/js/components/header_notification.js index c838e346..9222c0c4 100644 --- a/js/components/header_notification.js +++ b/js/components/header_notification.js @@ -36,6 +36,27 @@ let HeaderNotifications = React.createClass({ this.setState(state); }, + onSelected(event) { + /* + This is a hack to make the dropdown close after clicking on an item + The function just need to be defined + + from https://github.com/react-bootstrap/react-bootstrap/issues/368: + + @jvillasante - Have you tried to use onSelect with the DropdownButton? + I don't have a working example that is exactly like yours, + but I just noticed that the Dropdown closes when I've attached an event handler to OnSelect: + + + + onSelected: function(e) { + // doesn't need to have functionality (necessarily) ... just wired up + } + Internally, a call to DropdownButton.setDropDownState(false) is made which will hide the dropdown menu. + So, you should be able to call that directly on the DropdownButton instance as well if needed. + */ + }, + render() { if (this.state.requestActions && this.state.requestActions.length > 0) { return ( @@ -48,7 +69,8 @@ let HeaderNotifications = React.createClass({ ({this.state.requestActions.length}) } - className="notification-menu"> + className="notification-menu" + onSelect={this.onSelected}> {this.state.requestActions.map((pieceOrEdition, i) => { return ( From bf5d1de635fea9d55ee6cc5ec49a17374dec9dfc Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 1 Sep 2015 19:14:48 +0200 Subject: [PATCH 018/192] update notification on request action --- .../ascribe_forms/form_request_action.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/js/components/ascribe_forms/form_request_action.js b/js/components/ascribe_forms/form_request_action.js index 5ca7db6c..2448720a 100644 --- a/js/components/ascribe_forms/form_request_action.js +++ b/js/components/ascribe_forms/form_request_action.js @@ -6,6 +6,8 @@ import AclButton from './../ascribe_buttons/acl_button'; import ActionPanel from '../ascribe_panel/action_panel'; import Form from './form'; +import PieceListActions from '../../actions/piece_list_actions'; + import GlobalNotificationModel from '../../models/global_notification_model'; import GlobalNotificationActions from '../../actions/global_notification_actions'; @@ -71,12 +73,18 @@ let RequestActionForm = React.createClass({ let notification = new GlobalNotificationModel(message, 'success'); GlobalNotificationActions.appendGlobalNotification(notification); - if(this.props.handleSuccess) { - this.props.handleSuccess(); - } + this.handleSuccess(); + }; }, + handleSuccess() { + PieceListActions.fetchPieceRequestActions(); + if(this.props.handleSuccess) { + this.props.handleSuccess(); + } + }, + getContent() { let pieceOrEditionStr = this.isPiece() ? getLangText('this work%s', '.') : getLangText('this edition%s', '.'); let message = this.props.requestUser + ' ' + getLangText('requests you') + ' ' + this.props.requestAction + ' ' + pieceOrEditionStr; @@ -99,7 +107,7 @@ let RequestActionForm = React.createClass({ buttonAcceptClassName='inline pull-right btn-sm ascribe-margin-1px' pieceOrEditions={this.props.pieceOrEditions} currentUser={this.props.currentUser} - handleSuccess={this.props.handleSuccess} /> + handleSuccess={this.handleSuccess} /> ); } else if(this.props.requestAction === 'loan_request') { return ( @@ -110,7 +118,7 @@ let RequestActionForm = React.createClass({ buttonAcceptClassName='inline pull-right btn-sm ascribe-margin-1px' pieceOrEditions={this.props.pieceOrEditions} currentUser={this.props.currentUser} - handleSuccess={this.props.handleSuccess} /> + handleSuccess={this.handleSuccess} /> ); } else { return ( From 07ce180ff7a69a4d826e6326336ee897bc56ab5a Mon Sep 17 00:00:00 2001 From: diminator Date: Wed, 2 Sep 2015 13:57:41 +0200 Subject: [PATCH 019/192] contract form POST --- js/components/ascribe_forms/form_create_contract.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js index 1b3fcfd6..416ae0e5 100644 --- a/js/components/ascribe_forms/form_create_contract.js +++ b/js/components/ascribe_forms/form_create_contract.js @@ -18,14 +18,20 @@ let CreateContractForm = React.createClass({ getInitialState() { return { - digitalWorkKey: null, + contractKey: null, isUploadReady: false }; }, + getFormData(){ + return { + blob: this.state.contractKey + }; + }, + submitKey(key) { this.setState({ - digitalWorkKey: key + contractKey: key }); }, @@ -39,6 +45,7 @@ let CreateContractForm = React.createClass({ return (
Date: Wed, 2 Sep 2015 14:02:23 +0200 Subject: [PATCH 020/192] contract list add --- js/components/ascribe_detail/edition.js | 1 - .../ascribe_detail/edition_container.js | 3 ++ .../ascribe_settings/contract_settings.js | 31 +++++++++++++++++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/js/components/ascribe_detail/edition.js b/js/components/ascribe_detail/edition.js index 696e5057..49175851 100644 --- a/js/components/ascribe_detail/edition.js +++ b/js/components/ascribe_detail/edition.js @@ -305,7 +305,6 @@ let EditionSummary = React.createClass({
); - } }); diff --git a/js/components/ascribe_detail/edition_container.js b/js/components/ascribe_detail/edition_container.js index 15086434..3be63974 100644 --- a/js/components/ascribe_detail/edition_container.js +++ b/js/components/ascribe_detail/edition_container.js @@ -9,6 +9,8 @@ import Edition from './edition'; import AppConstants from '../../constants/application_constants'; + + /** * This is the component that implements resource/data specific functionality */ @@ -50,6 +52,7 @@ let EditionContainer = React.createClass({ }, render() { + console.log(this.state); if('title' in this.state.edition) { return ( {/* this should be this.props.defaultExpanded */} - + + {this.state.contractList} + + + + ); } From 19726560ba707a7fdbebe6db95b96c93380348c6 Mon Sep 17 00:00:00 2001 From: diminator Date: Wed, 2 Sep 2015 14:39:32 +0200 Subject: [PATCH 021/192] bitbucket test --- ...contract.js => form_contract_agreement.js} | 28 +++++++++---------- .../ikonotv/ikonotv_request_loan.js | 4 +-- js/constants/api_urls.js | 1 + 3 files changed, 16 insertions(+), 17 deletions(-) rename js/components/ascribe_forms/{form_contract.js => form_contract_agreement.js} (85%) diff --git a/js/components/ascribe_forms/form_contract.js b/js/components/ascribe_forms/form_contract_agreement.js similarity index 85% rename from js/components/ascribe_forms/form_contract.js rename to js/components/ascribe_forms/form_contract_agreement.js index 4c51e7a3..747bdfa4 100644 --- a/js/components/ascribe_forms/form_contract.js +++ b/js/components/ascribe_forms/form_contract_agreement.js @@ -19,7 +19,7 @@ import { getLangText } from '../../utils/lang_utils'; import { mergeOptions } from '../../utils/general_utils'; -let ContractForm = React.createClass({ +let ContractAgreementForm = React.createClass({ propTypes: { handleSuccess: React.PropTypes.func }, @@ -55,8 +55,13 @@ let ContractForm = React.createClass({ GlobalNotificationActions.appendGlobalNotification(notification); }, + getFormData(){ + return {'appendix': {'default': this.refs.form.refs.appendix.value}} + }, + getContracts() { - if (this.state.contractList && this.state.contractList.length > 0) { + if (this.state.contractList && this.state.contractList.count > 0) { + let contractList = this.state.contractList.results; return ( {getLangText('Learn more')} }> - - + ); } }); diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js index b056ee03..6e43b8ef 100644 --- a/js/constants/api_urls.js +++ b/js/constants/api_urls.js @@ -27,6 +27,7 @@ let ApiUrls = { 'note_private_piece': AppConstants.apiEndpoint + 'note/private/pieces/', 'note_public_edition': AppConstants.apiEndpoint + 'note/public/editions/', 'note_public_piece': AppConstants.apiEndpoint + 'note/public/pieces/', + 'ownership_contract_agreements': AppConstants.apiEndpoint + 'ownership/contract_agreements/', 'ownership_consigns': AppConstants.apiEndpoint + 'ownership/consigns/', 'ownership_consigns_confirm': AppConstants.apiEndpoint + 'ownership/consigns/confirm/', 'ownership_consigns_deny': AppConstants.apiEndpoint + 'ownership/consigns/deny/', From 7f39c62130d3633422f59d40be6ff2f44ce6ad77 Mon Sep 17 00:00:00 2001 From: diminator Date: Wed, 2 Sep 2015 16:34:43 +0200 Subject: [PATCH 022/192] create contract and agreement --- .../ascribe_forms/form_contract_agreement.js | 2 +- js/components/ascribe_forms/form_create_contract.js | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/js/components/ascribe_forms/form_contract_agreement.js b/js/components/ascribe_forms/form_contract_agreement.js index 747bdfa4..1d9f7c72 100644 --- a/js/components/ascribe_forms/form_contract_agreement.js +++ b/js/components/ascribe_forms/form_contract_agreement.js @@ -56,7 +56,7 @@ let ContractAgreementForm = React.createClass({ }, getFormData(){ - return {'appendix': {'default': this.refs.form.refs.appendix.value}} + return {'appendix': {'default': this.refs.form.refs.appendix.state.value}}; }, getContracts() { diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js index 416ae0e5..a5f719e2 100644 --- a/js/components/ascribe_forms/form_create_contract.js +++ b/js/components/ascribe_forms/form_create_contract.js @@ -5,6 +5,9 @@ import React from 'react'; import Form from '../ascribe_forms/form'; import Property from '../ascribe_forms/property'; +import GlobalNotificationModel from '../../models/global_notification_model'; +import GlobalNotificationActions from '../../actions/global_notification_actions'; + import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader'; import AppConstants from '../../constants/application_constants'; @@ -41,11 +44,18 @@ let CreateContractForm = React.createClass({ }); }, + handleCreateSuccess(response) { + let notification = new GlobalNotificationModel(getLangText('Contract %s successfully created', response.name), 'success', 5000); + GlobalNotificationActions.appendGlobalNotification(notification); + }, + + render() { return ( Date: Thu, 3 Sep 2015 14:15:00 +0200 Subject: [PATCH 023/192] notification app notification refactor in onion - split by piece/edition --- js/actions/notification_actions.js | 34 +++++ .../ascribe_detail/edition_container.js | 1 - js/components/header.js | 33 ++++- js/components/header_notification.js | 129 +++++++++++++----- js/components/piece_list.js | 3 +- js/constants/api_urls.js | 3 +- js/fetchers/notification_fetcher.js | 17 +++ js/stores/notification_store.js | 26 ++++ sass/ascribe_notification_list.scss | 28 +++- 9 files changed, 231 insertions(+), 43 deletions(-) create mode 100644 js/actions/notification_actions.js create mode 100644 js/fetchers/notification_fetcher.js create mode 100644 js/stores/notification_store.js diff --git a/js/actions/notification_actions.js b/js/actions/notification_actions.js new file mode 100644 index 00000000..06fce61f --- /dev/null +++ b/js/actions/notification_actions.js @@ -0,0 +1,34 @@ +'use strict'; + +import alt from '../alt'; + +import NotificationFetcher from '../fetchers/notification_fetcher'; + +class NotificationActions { + constructor() { + this.generateActions( + 'updatePieceListNotifications', + 'updateEditionListNotifications' + ); + } + + fetchPieceListNotifications() { + NotificationFetcher + .fetchPieceListNotifications() + .then((res) => { + this.actions.updatePieceListNotifications(res); + }) + .catch((err) => console.logGlobal(err)); + } + + fetchEditionListNotifications() { + NotificationFetcher + .fetchEditionListNotifications() + .then((res) => { + this.actions.updateEditionListNotifications(res); + }) + .catch((err) => console.logGlobal(err)); + } +} + +export default alt.createActions(NotificationActions); diff --git a/js/components/ascribe_detail/edition_container.js b/js/components/ascribe_detail/edition_container.js index 78b1e477..a19f67b9 100644 --- a/js/components/ascribe_detail/edition_container.js +++ b/js/components/ascribe_detail/edition_container.js @@ -61,7 +61,6 @@ let EditionContainer = React.createClass({ }, render() { - console.log(this.state); if('title' in this.state.edition) { return ( + + onSelected: function(e) { + // doesn't need to have functionality (necessarily) ... just wired up + } + Internally, a call to DropdownButton.setDropDownState(false) is made which will hide the dropdown menu. + So, you should be able to call that directly on the DropdownButton instance as well if needed. + + NOW, THAT DIDN'T WORK - the onSelect routine isnt triggered in all cases + Hence, we do this manually + */ + this.refs.dropdownbutton.setDropdownState(false); + }, + render() { let account; let signup; @@ -103,9 +128,15 @@ let Header = React.createClass({ if (this.state.currentUser.username){ account = ( - {getLangText('Account Settings')} + + {getLangText('Account Settings')} + {getLangText('Log out')} diff --git a/js/components/header_notification.js b/js/components/header_notification.js index 9222c0c4..73d68a5d 100644 --- a/js/components/header_notification.js +++ b/js/components/header_notification.js @@ -8,7 +8,8 @@ import MenuItem from 'react-bootstrap/lib/MenuItem'; import Nav from 'react-bootstrap/lib/Nav'; -import PieceListStore from '../stores/piece_list_store'; +import NotificationActions from '../actions/notification_actions'; +import NotificationStore from '../stores/notification_store'; import { mergeOptions } from '../utils/general_utils'; import { getLangText } from '../utils/lang_utils'; @@ -20,23 +21,25 @@ let HeaderNotifications = React.createClass({ getInitialState() { return mergeOptions( - PieceListStore.getState() + NotificationStore.getState() ); }, componentDidMount() { - PieceListStore.listen(this.onChange); + NotificationStore.listen(this.onChange); + NotificationActions.fetchPieceListNotifications(); + NotificationActions.fetchEditionListNotifications(); }, componentWillUnmount() { - PieceListStore.unlisten(this.onChange); + NotificationStore.unlisten(this.onChange); }, onChange(state) { this.setState(state); }, - onSelected(event) { + onMenuItemClick(event) { /* This is a hack to make the dropdown close after clicking on an item The function just need to be defined @@ -54,32 +57,87 @@ let HeaderNotifications = React.createClass({ } Internally, a call to DropdownButton.setDropDownState(false) is made which will hide the dropdown menu. So, you should be able to call that directly on the DropdownButton instance as well if needed. + + NOW, THAT DIDN'T WORK - the onSelect routine isnt triggered in all cases + Hence, we do this manually */ + this.refs.dropdownbutton.setDropdownState(false); + }, + + getPieceNotifications(){ + if (this.state.pieceListNotifications && this.state.pieceListNotifications.length > 0) { + return ( +
+
+ Artworks ({this.state.pieceListNotifications.length}) +
+ {this.state.pieceListNotifications.map((pieceNotification, i) => { + return ( + + + + ); + } + )} +
+ ); + } + return null; + }, + + getEditionNotifications(){ + if (this.state.editionListNotifications && this.state.editionListNotifications.length > 0) { + return ( +
+
+ Editions ({this.state.editionListNotifications.length}) +
+ {this.state.editionListNotifications.map((editionNotification, i) => { + return ( + + + + ); + } + )} +
+ ); + } + return null; }, render() { - if (this.state.requestActions && this.state.requestActions.length > 0) { + if ((this.state.pieceListNotifications && this.state.pieceListNotifications.length > 0) || + (this.state.editionListNotifications && this.state.editionListNotifications.length > 0)){ + let numNotifications = 0; + if (this.state.pieceListNotifications && this.state.pieceListNotifications.length > 0) { + numNotifications += this.state.pieceListNotifications.length; + } + if (this.state.editionListNotifications && this.state.editionListNotifications.length > 0) { + numNotifications += this.state.editionListNotifications.length; + } return ( ); @@ -90,33 +148,42 @@ let HeaderNotifications = React.createClass({ let NotificationListItem = React.createClass({ propTypes: { - pieceOrEdition: React.PropTypes.object + notification: React.PropTypes.array, + pieceOrEdition: React.PropTypes.object, + onClick: React.PropTypes.func + }, + + isPiece() { + return !(this.props.pieceOrEdition && this.props.pieceOrEdition.parent); }, getLinkData() { - if(this.props.pieceOrEdition && this.props.pieceOrEdition.parent) { - return { - to: 'edition', - params: { - editionId: this.props.pieceOrEdition.bitcoin_id - } - }; - } else { + if (this.isPiece()) { return { to: 'piece', params: { pieceId: this.props.pieceOrEdition.id } }; + } else { + return { + to: 'edition', + params: { + editionId: this.props.pieceOrEdition.bitcoin_id + } + }; } }, + onClick(event){ + this.props.onClick(event); + }, render() { if (this.props.pieceOrEdition) { return ( - +
@@ -127,11 +194,7 @@ let NotificationListItem = React.createClass({

{this.props.pieceOrEdition.title}

by {this.props.pieceOrEdition.artist_name}
- { - this.props.pieceOrEdition.request_action.map((requestAction) => { - return 'Pending ' + requestAction.action + ' request'; - }) - } + {'Pending ' + this.props.notification[0].action + ' request'}
diff --git a/js/components/piece_list.js b/js/components/piece_list.js index d841f7af..71304a63 100644 --- a/js/components/piece_list.js +++ b/js/components/piece_list.js @@ -65,8 +65,7 @@ let PieceList = React.createClass({ let orderBy = this.props.orderBy ? this.props.orderBy : this.state.orderBy; if (this.state.pieceList.length === 0 || this.state.page !== page){ PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search, - orderBy, this.state.orderAsc, this.state.filterBy) - .then(() => PieceListActions.fetchPieceRequestActions()); + orderBy, this.state.orderAsc, this.state.filterBy); } }, diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js index 6e43b8ef..f72eabdd 100644 --- a/js/constants/api_urls.js +++ b/js/constants/api_urls.js @@ -27,6 +27,8 @@ let ApiUrls = { 'note_private_piece': AppConstants.apiEndpoint + 'note/private/pieces/', 'note_public_edition': AppConstants.apiEndpoint + 'note/public/editions/', 'note_public_piece': AppConstants.apiEndpoint + 'note/public/pieces/', + 'notification_piecelist': AppConstants.apiEndpoint + 'notifications/pieces/', + 'notification_editionlist': AppConstants.apiEndpoint + 'notifications/editions/', 'ownership_contract_agreements': AppConstants.apiEndpoint + 'ownership/contract_agreements/', 'ownership_consigns': AppConstants.apiEndpoint + 'ownership/consigns/', 'ownership_consigns_confirm': AppConstants.apiEndpoint + 'ownership/consigns/confirm/', @@ -52,7 +54,6 @@ let ApiUrls = { 'piece_extradata': AppConstants.apiEndpoint + 'pieces/${piece_id}/extradata/', 'piece_first_edition_id': AppConstants.apiEndpoint + 'pieces/${piece_id}/edition_index/', 'pieces_list': AppConstants.apiEndpoint + 'pieces/', - 'pieces_list_request_actions': AppConstants.apiEndpoint + 'pieces/request_actions/', 'piece_remove_from_collection': AppConstants.apiEndpoint + 'ownership/shares/pieces/${piece_id}/', 'user': AppConstants.apiEndpoint + 'users/', 'users_login': AppConstants.apiEndpoint + 'users/login/', diff --git a/js/fetchers/notification_fetcher.js b/js/fetchers/notification_fetcher.js new file mode 100644 index 00000000..c6f9be54 --- /dev/null +++ b/js/fetchers/notification_fetcher.js @@ -0,0 +1,17 @@ +'use strict'; + +import requests from '../utils/requests'; + + +let NotificationFetcher = { + + fetchPieceListNotifications() { + return requests.get('notification_piecelist'); + }, + + fetchEditionListNotifications() { + return requests.get('notification_editionlist'); + } +}; + +export default NotificationFetcher; diff --git a/js/stores/notification_store.js b/js/stores/notification_store.js new file mode 100644 index 00000000..c5401190 --- /dev/null +++ b/js/stores/notification_store.js @@ -0,0 +1,26 @@ +'use strict'; + +import React from 'react'; +import alt from '../alt'; + +import NotificationActions from '../actions/notification_actions'; + + +class NotificationStore { + constructor() { + this.pieceListNotifications = {}; + this.editionListNotifications = {}; + this.bindActions(NotificationActions); + } + + onUpdatePieceListNotifications(res) { + this.pieceListNotifications = res.notifications; + } + + onUpdateEditionListNotifications(res) { + this.editionListNotifications = res.notifications; + } + +} + +export default alt.createStore(NotificationStore, 'NotificationStore'); diff --git a/sass/ascribe_notification_list.scss b/sass/ascribe_notification_list.scss index bd3c0b20..c1d2ef65 100644 --- a/sass/ascribe_notification_list.scss +++ b/sass/ascribe_notification_list.scss @@ -2,13 +2,27 @@ $break-small: 764px; $break-medium: 991px; $break-medium: 1200px; -.notification-wrapper { +.notification-header,.notification-wrapper { width: 350px; - height:8em; - padding: 0.3em; - border-bottom: 1px solid #cccccc; - margin: -3px -20px; +} +.notification-header { + border-bottom: 1px solid #cccccc; + border-top: 1px solid #cccccc; + padding: 0.3em 1em; + background-color: #eeeeee; +} + +.notification-wrapper { + height:8.4em; + border-bottom: 1px solid #eeeeee; + margin: -3px 0; + padding: 0.5em; + color: black; + + &:hover{ + background-color: rgba(2, 182, 163, .05); + } // ToDo: Include media queries for thumbnail .thumbnail-wrapper { width: 7.4em; @@ -46,6 +60,10 @@ $break-medium: 1200px; li a { padding-top: 0; } + border-top: 0; + overflow-y:auto; + overflow-x:hidden; + max-height: 70vh; } } From 9334251fd388ca17c30ffde05d6e26388e764fc3 Mon Sep 17 00:00:00 2001 From: diminator Date: Thu, 3 Sep 2015 15:17:12 +0200 Subject: [PATCH 024/192] notifications on piece details (www, ikono, cyland) and edition details --- js/actions/notification_actions.js | 22 ++++++++++++++- js/components/ascribe_detail/edition.js | 26 +++++++++++++++-- .../ascribe_detail/piece_container.js | 15 ++++++---- .../ascribe_forms/form_request_action.js | 11 ++++++-- .../ascribe_detail/prize_piece_container.js | 28 +++++++++++++++---- .../ascribe_detail/ikonotv_piece_container.js | 16 +++++++---- js/constants/api_urls.js | 2 ++ js/fetchers/notification_fetcher.js | 8 ++++++ js/stores/notification_store.js | 10 +++++++ sass/ascribe_notification_list.scss | 4 +-- 10 files changed, 119 insertions(+), 23 deletions(-) diff --git a/js/actions/notification_actions.js b/js/actions/notification_actions.js index 06fce61f..429ae666 100644 --- a/js/actions/notification_actions.js +++ b/js/actions/notification_actions.js @@ -8,7 +8,9 @@ class NotificationActions { constructor() { this.generateActions( 'updatePieceListNotifications', - 'updateEditionListNotifications' + 'updateEditionListNotifications', + 'updateEditionNotifications', + 'updatePieceNotifications' ); } @@ -21,6 +23,15 @@ class NotificationActions { .catch((err) => console.logGlobal(err)); } + fetchPieceNotifications(pieceId) { + NotificationFetcher + .fetchPieceNotifications(pieceId) + .then((res) => { + this.actions.updatePieceNotifications(res); + }) + .catch((err) => console.logGlobal(err)); + } + fetchEditionListNotifications() { NotificationFetcher .fetchEditionListNotifications() @@ -29,6 +40,15 @@ class NotificationActions { }) .catch((err) => console.logGlobal(err)); } + + fetchEditionNotifications(editionId) { + NotificationFetcher + .fetchEditionNotifications(editionId) + .then((res) => { + this.actions.updateEditionNotifications(res); + }) + .catch((err) => console.logGlobal(err)); + } } export default alt.createActions(NotificationActions); diff --git a/js/components/ascribe_detail/edition.js b/js/components/ascribe_detail/edition.js index 49175851..db8f0b7e 100644 --- a/js/components/ascribe_detail/edition.js +++ b/js/components/ascribe_detail/edition.js @@ -16,6 +16,9 @@ import PieceListActions from '../../actions/piece_list_actions'; import PieceListStore from '../../stores/piece_list_store'; import EditionListActions from '../../actions/edition_list_actions'; +import NotificationActions from '../../actions/notification_actions'; +import NotificationStore from '../../stores/notification_store'; + import HistoryIterator from './history_iterator'; import MediaContainer from './media_container'; @@ -208,6 +211,25 @@ let EditionSummary = React.createClass({ handleDeleteSuccess: React.PropTypes.func }, + getInitialState() { + return mergeOptions( + NotificationStore.getState() + ); + }, + + componentDidMount() { + NotificationStore.listen(this.onChange); + NotificationActions.fetchEditionNotifications(this.props.edition.bitcoin_id); + }, + + componentWillUnmount() { + NotificationStore.unlisten(this.onChange); + }, + + onChange(state) { + this.setState(state); + }, + getTransferWithdrawData(){ return {'bitcoin_id': this.props.edition.bitcoin_id}; }, @@ -234,13 +256,13 @@ let EditionSummary = React.createClass({ getActions(){ let actions = null; - if (this.props.edition.request_action && this.props.edition.request_action.length > 0){ + if (this.state.editionNotifications && this.state.editionNotifications.notification){ actions = ( ); + requestActions={this.state.editionNotifications.notification}/>); } else { diff --git a/js/components/ascribe_detail/piece_container.js b/js/components/ascribe_detail/piece_container.js index 7297825d..0de25beb 100644 --- a/js/components/ascribe_detail/piece_container.js +++ b/js/components/ascribe_detail/piece_container.js @@ -9,6 +9,9 @@ import PieceStore from '../../stores/piece_store'; import PieceListActions from '../../actions/piece_list_actions'; import PieceListStore from '../../stores/piece_list_store'; +import NotificationActions from '../../actions/notification_actions'; +import NotificationStore from '../../stores/notification_store'; + import UserActions from '../../actions/user_actions'; import UserStore from '../../stores/user_store'; @@ -62,6 +65,8 @@ let PieceContainer = React.createClass({ UserActions.fetchCurrentUser(); PieceStore.listen(this.onChange); PieceActions.fetchOne(this.props.params.pieceId); + NotificationStore.listen(this.onChange); + NotificationActions.fetchPieceNotifications(this.props.params.pieceId); }, componentWillUnmount() { @@ -73,6 +78,7 @@ let PieceContainer = React.createClass({ PieceStore.unlisten(this.onChange); UserStore.unlisten(this.onChange); PieceListStore.unlisten(this.onChange); + NotificationStore.unlisten(this.onChange); }, onChange(state) { @@ -172,17 +178,16 @@ let PieceContainer = React.createClass({ return {'id': this.state.piece.id}; }, - getActions(){ + getActions() { if (this.state.piece && - this.state.piece.request_action && - this.state.piece.request_action.length > 0) { + this.state.pieceNotifications && + this.state.pieceNotifications.notification) { return ( - ); + requestActions={this.state.pieceNotifications.notification}/>); } else { return ( diff --git a/js/components/ascribe_forms/form_request_action.js b/js/components/ascribe_forms/form_request_action.js index 2448720a..c65a7394 100644 --- a/js/components/ascribe_forms/form_request_action.js +++ b/js/components/ascribe_forms/form_request_action.js @@ -6,7 +6,7 @@ import AclButton from './../ascribe_buttons/acl_button'; import ActionPanel from '../ascribe_panel/action_panel'; import Form from './form'; -import PieceListActions from '../../actions/piece_list_actions'; +import NotificationActions from '../../actions/notification_actions'; import GlobalNotificationModel from '../../models/global_notification_model'; import GlobalNotificationActions from '../../actions/global_notification_actions'; @@ -79,7 +79,14 @@ let RequestActionForm = React.createClass({ }, handleSuccess() { - PieceListActions.fetchPieceRequestActions(); + if (this.isPiece()){ + NotificationActions.fetchPieceListNotifications(); + //NotificationActions.fetchPieceNotifications(this.props.pieceOrEditions.id); + } + else { + NotificationActions.fetchEditionListNotifications(); + NotificationActions.fetchEditionNotifications(this.props.pieceOrEditions[0].bitcoin_id); + } if(this.props.handleSuccess) { this.props.handleSuccess(); } diff --git a/js/components/whitelabel/prize/components/ascribe_detail/prize_piece_container.js b/js/components/whitelabel/prize/components/ascribe_detail/prize_piece_container.js index 9e927ac4..cb9e1593 100644 --- a/js/components/whitelabel/prize/components/ascribe_detail/prize_piece_container.js +++ b/js/components/whitelabel/prize/components/ascribe_detail/prize_piece_container.js @@ -15,6 +15,9 @@ import PieceListActions from '../../../../../actions/piece_list_actions'; import PrizeRatingActions from '../../actions/prize_rating_actions'; import PrizeRatingStore from '../../stores/prize_rating_store'; +import NotificationStore from '../../../../../stores/notification_store'; +import NotificationActions from '../../../../../actions/notification_actions.js'; + import UserStore from '../../../../../stores/user_store'; import Piece from '../../../../../components/ascribe_detail/piece'; @@ -50,7 +53,8 @@ let PieceContainer = React.createClass({ getInitialState() { return mergeOptions( PieceStore.getState(), - UserStore.getState() + UserStore.getState(), + NotificationStore.getState() ); }, @@ -58,6 +62,8 @@ let PieceContainer = React.createClass({ PieceStore.listen(this.onChange); PieceActions.fetchOne(this.props.params.pieceId); UserStore.listen(this.onChange); + NotificationStore.listen(this.onChange); + NotificationActions.fetchPieceNotifications(this.props.params.pieceId); }, // This is done to update the container when the user clicks on the prev or next @@ -77,6 +83,7 @@ let PieceContainer = React.createClass({ PieceActions.updatePiece({}); PieceStore.unlisten(this.onChange); UserStore.unlisten(this.onChange); + NotificationStore.unlisten(this.onChange); }, @@ -88,6 +95,19 @@ let PieceContainer = React.createClass({ PieceActions.fetchOne(this.props.params.pieceId); }, + getActions() { + if (this.state.piece && + this.state.pieceNotifications && + this.state.pieceNotifications.notification) { + return ( + ); + } + }, + render() { if('title' in this.state.piece) { // Only show the artist name if you are the participant or if you are a judge and the piece is shortlisted @@ -111,11 +131,7 @@ let PieceContainer = React.createClass({ {artistEmail} - + {this.getActions()}
} diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js index 7f094a26..781b148b 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js @@ -10,6 +10,9 @@ import PieceListStore from '../../../../../../stores/piece_list_store'; import UserStore from '../../../../../../stores/user_store'; +import NotificationStore from '../../../../../../stores/notification_store'; +import NotificationActions from '../../../../../../actions/notification_actions.js'; + import Piece from '../../../../../../components/ascribe_detail/piece'; import ListRequestActions from '../../../../../ascribe_forms/list_form_request_actions'; @@ -41,7 +44,8 @@ let IkonotvPieceContainer = React.createClass({ return mergeOptions( PieceStore.getState(), UserStore.getState(), - PieceListStore.getState() + PieceListStore.getState(), + NotificationStore.getState() ); }, @@ -50,6 +54,8 @@ let IkonotvPieceContainer = React.createClass({ PieceActions.fetchOne(this.props.params.pieceId); UserStore.listen(this.onChange); PieceListStore.listen(this.onChange); + NotificationStore.listen(this.onChange); + NotificationActions.fetchPieceNotifications(this.props.params.pieceId); }, componentWillReceiveProps(nextProps) { @@ -68,6 +74,7 @@ let IkonotvPieceContainer = React.createClass({ PieceStore.unlisten(this.onChange); UserStore.unlisten(this.onChange); PieceListStore.unlisten(this.onChange); + NotificationStore.unlisten(this.onChange); }, onChange(state) { @@ -89,15 +96,14 @@ let IkonotvPieceContainer = React.createClass({ getActions(){ if (this.state.piece && - this.state.piece.request_action && - this.state.piece.request_action.length > 0) { + this.state.pieceNotifications && + this.state.pieceNotifications.notification) { return ( - ); + requestActions={this.state.pieceNotifications.notification}/>); } else { diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js index f72eabdd..6b1d7dee 100644 --- a/js/constants/api_urls.js +++ b/js/constants/api_urls.js @@ -28,7 +28,9 @@ let ApiUrls = { 'note_public_edition': AppConstants.apiEndpoint + 'note/public/editions/', 'note_public_piece': AppConstants.apiEndpoint + 'note/public/pieces/', 'notification_piecelist': AppConstants.apiEndpoint + 'notifications/pieces/', + 'notification_piece': AppConstants.apiEndpoint + 'notifications/pieces/${piece_id}/', 'notification_editionlist': AppConstants.apiEndpoint + 'notifications/editions/', + 'notification_edition': AppConstants.apiEndpoint + 'notifications/editions/${edition_id}/', 'ownership_contract_agreements': AppConstants.apiEndpoint + 'ownership/contract_agreements/', 'ownership_consigns': AppConstants.apiEndpoint + 'ownership/consigns/', 'ownership_consigns_confirm': AppConstants.apiEndpoint + 'ownership/consigns/confirm/', diff --git a/js/fetchers/notification_fetcher.js b/js/fetchers/notification_fetcher.js index c6f9be54..6d2f7424 100644 --- a/js/fetchers/notification_fetcher.js +++ b/js/fetchers/notification_fetcher.js @@ -9,8 +9,16 @@ let NotificationFetcher = { return requests.get('notification_piecelist'); }, + fetchPieceNotifications(pieceId) { + return requests.get('notification_piece', {'piece_id': pieceId}); + }, + fetchEditionListNotifications() { return requests.get('notification_editionlist'); + }, + + fetchEditionNotifications(editionId) { + return requests.get('notification_edition', {'edition_id': editionId}); } }; diff --git a/js/stores/notification_store.js b/js/stores/notification_store.js index c5401190..6e706699 100644 --- a/js/stores/notification_store.js +++ b/js/stores/notification_store.js @@ -10,6 +10,8 @@ class NotificationStore { constructor() { this.pieceListNotifications = {}; this.editionListNotifications = {}; + this.editionNotifications = null; + this.pieceNotifications = null; this.bindActions(NotificationActions); } @@ -17,10 +19,18 @@ class NotificationStore { this.pieceListNotifications = res.notifications; } + onUpdatePieceNotifications(res) { + this.pieceNotifications = res.notification; + } + onUpdateEditionListNotifications(res) { this.editionListNotifications = res.notifications; } + onUpdateEditionNotifications(res) { + this.editionNotifications = res.notification; + } + } export default alt.createStore(NotificationStore, 'NotificationStore'); diff --git a/sass/ascribe_notification_list.scss b/sass/ascribe_notification_list.scss index c1d2ef65..696d9169 100644 --- a/sass/ascribe_notification_list.scss +++ b/sass/ascribe_notification_list.scss @@ -61,8 +61,8 @@ $break-medium: 1200px; padding-top: 0; } border-top: 0; - overflow-y:auto; - overflow-x:hidden; + overflow-y: auto; + overflow-x: hidden; max-height: 70vh; } } From d2f8b658afc14c9366a634bc8947e045cba9dbf0 Mon Sep 17 00:00:00 2001 From: Cevo Date: Thu, 3 Sep 2015 15:53:02 +0200 Subject: [PATCH 025/192] contract listing being done --- .gitignore~ | 24 ++++++++ js/actions/contract_actions.js | 1 + js/actions/contract_list_actions.js | 13 +++- .../ascribe_forms/form_create_contract.js | 2 +- js/components/ascribe_panel/action_panel.js | 1 - .../ascribe_settings/contract_settings.js | 60 +++++++++++++++++-- js/constants/api_urls.js | 3 +- js/fetchers/ownership_fetcher.js | 7 ++- js/utils/general_utils.js | 13 ++++ js/utils/requests.js | 21 +++++-- 10 files changed, 130 insertions(+), 15 deletions(-) create mode 100644 .gitignore~ diff --git a/.gitignore~ b/.gitignore~ new file mode 100644 index 00000000..41b217c2 --- /dev/null +++ b/.gitignore~ @@ -0,0 +1,24 @@ +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz +*.sublime-project +.idea +spool-project.sublime-project +*.sublime-workspace +*.sublime-workspace +webapp-dependencies.txt + +pids +logs +results +README.md~ +node_modules/* + +build + +.DS_Store diff --git a/js/actions/contract_actions.js b/js/actions/contract_actions.js index e14dbf83..c6055ffc 100644 --- a/js/actions/contract_actions.js +++ b/js/actions/contract_actions.js @@ -43,6 +43,7 @@ class ContractActions { /* No email was entered - Ignore and keep going*/ } } + } export default alt.createActions(ContractActions); diff --git a/js/actions/contract_list_actions.js b/js/actions/contract_list_actions.js index f4257d37..b019ecc0 100644 --- a/js/actions/contract_list_actions.js +++ b/js/actions/contract_list_actions.js @@ -3,7 +3,6 @@ import alt from '../alt'; import OwnershipFetcher from '../fetchers/ownership_fetcher'; - class ContractListActions { constructor() { this.generateActions( @@ -15,13 +14,23 @@ class ContractListActions { fetchContractList() { OwnershipFetcher.fetchContractList() .then((contracts) => { - this.actions.updateContractList(contracts); + this.actions.updateContractList(contracts.results); }) .catch((err) => { console.logGlobal(err); this.actions.updateContractList([]); }); } + + makeContractPublic(contract){ + OwnershipFetcher.makeContractPublic(contract) + .then((res) =>{ + return res; + }) + .catch((err)=>{ + console.logGlobal(err); + }); + } } export default alt.createActions(ContractListActions); diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js index 416ae0e5..e3b4321a 100644 --- a/js/components/ascribe_forms/form_create_contract.js +++ b/js/components/ascribe_forms/form_create_contract.js @@ -44,7 +44,7 @@ let CreateContractForm = React.createClass({ render() { return ( ContractListActions.fetchContractList()) + .catch((error)=>{console.log("Error ", error)}) + }, + getPublicContracts(){ + return this.state.contractList.filter((contract) => contract.public); + }, + getPrivateContracts(){ + return this.state.contractList.filter((contract) => !contract.public); + }, + getblobEndName(contract){ + return contract.blob.match(/.*\/(.*)/)[1]; + }, render() { + let publicContracts = this.getPublicContracts(); + let privateContracts = this.getPrivateContracts(); + console.log(this.state.contractList); return ( + defaultExpanded={false}> {/* this should be this.props.defaultExpanded */} - {this.state.contractList} + defaultExpanded={false}> + {
+

Public Contracts

+ {(publicContracts.length > 0) ? + publicContracts.map( + (contract) => { + return( + + + + } + />) + } + ) : null } +
} + + {
+

Private Contracts

+ {(privateContracts.length>0) ? + privateContracts.map( + (contract) => { + return( + + + } + />) + } + ) : null} +
}
+ defaultExpanded={false}>
diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js index b056ee03..1e159ed7 100644 --- a/js/constants/api_urls.js +++ b/js/constants/api_urls.js @@ -46,7 +46,8 @@ let ApiUrls = { 'ownership_unconsigns': AppConstants.apiEndpoint + 'ownership/unconsigns/', 'ownership_unconsigns_deny': AppConstants.apiEndpoint + 'ownership/unconsigns/deny/', 'ownership_unconsigns_request': AppConstants.apiEndpoint + 'ownership/unconsigns/request/', - 'ownership_contract': AppConstants.apiEndpoint + 'ownership/contracts/', + 'ownership_contract':AppConstants.apiEndpoint + 'ownership/contracts/${contract_id}', + "ownership_contract_list": AppConstants.apiEndpoint + 'ownership/contracts/', 'piece': AppConstants.apiEndpoint + 'pieces/${piece_id}/', 'piece_extradata': AppConstants.apiEndpoint + 'pieces/${piece_id}/extradata/', 'piece_first_edition_id': AppConstants.apiEndpoint + 'pieces/${piece_id}/edition_index/', diff --git a/js/fetchers/ownership_fetcher.js b/js/fetchers/ownership_fetcher.js index 051f2d08..8f97add5 100644 --- a/js/fetchers/ownership_fetcher.js +++ b/js/fetchers/ownership_fetcher.js @@ -16,11 +16,16 @@ let OwnershipFetcher = { * Fetch the contracts of the logged-in user from the API. */ fetchContractList(){ - return requests.get(ApiUrls.ownership_contract); + return requests.get(ApiUrls.ownership_contract_list); }, fetchLoanPieceRequestList(){ return requests.get(ApiUrls.ownership_loans_pieces_request); + }, + + makeContractPublic(contractObj){ + console.log(contractObj); + return requests.put('ownership_contract_list',{ body: contractObj, contract_id:contractObj.id }); } }; diff --git a/js/utils/general_utils.js b/js/utils/general_utils.js index 15b0e85f..673a5509 100644 --- a/js/utils/general_utils.js +++ b/js/utils/general_utils.js @@ -52,6 +52,19 @@ export function sumNumList(l) { return sum; } +export function excludePropFromObject(obj, propList){ + let clonedObj = mergeOptions({},obj); + for (let item in propList){ + console.log(item); + if (clonedObj[propList[item]]){ + console.log('deleting... '); + delete clonedObj[propList[item]]; + } + } + console.log(clonedObj); + return clonedObj; +} + /* Taken from http://stackoverflow.com/a/4795914/1263876 Behaves like C's format string function diff --git a/js/utils/requests.js b/js/utils/requests.js index 793e1f21..3cf84690 100644 --- a/js/utils/requests.js +++ b/js/utils/requests.js @@ -6,6 +6,7 @@ import { argsToQueryParams, getCookie } from '../utils/fetch_api_utils'; import AppConstants from '../constants/application_constants'; +import {excludePropFromObject} from '../utils/general_utils'; class Requests { _merge(defaults, options) { @@ -137,15 +138,25 @@ class Requests { return this.request('delete', newUrl); } - post(url, params) { - let paramsCopy = this._merge(params); - let newUrl = this.prepareUrl(url, paramsCopy); + _putOrPost(url,paramsAndBody,method){ + let paramsCopy = this._merge(paramsAndBody); + let params = excludePropFromObject(paramsAndBody,['body']); + let newUrl = this.prepareUrl(url, params); let body = null; - if (paramsCopy && paramsCopy.body) { + console.log(paramsCopy.body); body = JSON.stringify(paramsCopy.body); } - return this.request('post', newUrl, { body }); + return this.request(method, newUrl, { body }); + } + + post(url, params) { + return this._putOrPost(url,params,'post') + } + + put(url, params){ + console.log(params); + return this._putOrPost(url,params,'put') } defaults(options) { From 8a75e944133f2ad181f7a033485db240cfa8fb47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 4 Sep 2015 16:24:29 +0200 Subject: [PATCH 026/192] fix bug --- js/fetchers/ownership_fetcher.js | 3 +-- js/utils/requests.js | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/js/fetchers/ownership_fetcher.js b/js/fetchers/ownership_fetcher.js index 8f97add5..9b5e81f7 100644 --- a/js/fetchers/ownership_fetcher.js +++ b/js/fetchers/ownership_fetcher.js @@ -24,8 +24,7 @@ let OwnershipFetcher = { }, makeContractPublic(contractObj){ - console.log(contractObj); - return requests.put('ownership_contract_list',{ body: contractObj, contract_id:contractObj.id }); + return requests.put('ownership_contract', { body: contractObj, contract_id: contractObj.id }); } }; diff --git a/js/utils/requests.js b/js/utils/requests.js index 3cf84690..f9e1af04 100644 --- a/js/utils/requests.js +++ b/js/utils/requests.js @@ -78,7 +78,6 @@ class Requests { throw new Error(`Cannot find a mapping for "${name}"`); } } - return url; } @@ -138,9 +137,10 @@ class Requests { return this.request('delete', newUrl); } - _putOrPost(url,paramsAndBody,method){ + _putOrPost(url, paramsAndBody, method){ let paramsCopy = this._merge(paramsAndBody); let params = excludePropFromObject(paramsAndBody,['body']); + let newUrl = this.prepareUrl(url, params); let body = null; if (paramsCopy && paramsCopy.body) { @@ -155,7 +155,6 @@ class Requests { } put(url, params){ - console.log(params); return this._putOrPost(url,params,'put') } From 57c4076c1ef8349cae21fe17afdebfaf140d238d Mon Sep 17 00:00:00 2001 From: Cevo Date: Thu, 3 Sep 2015 17:19:29 +0200 Subject: [PATCH 027/192] pushing the contract u[pdate on client side --- js/actions/contract_list_actions.js | 19 ++++++++++++------- .../ascribe_settings/contract_settings.js | 7 ++++++- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/js/actions/contract_list_actions.js b/js/actions/contract_list_actions.js index b019ecc0..c57bceb9 100644 --- a/js/actions/contract_list_actions.js +++ b/js/actions/contract_list_actions.js @@ -2,6 +2,7 @@ import alt from '../alt'; import OwnershipFetcher from '../fetchers/ownership_fetcher'; +import Q from 'q'; class ContractListActions { constructor() { @@ -23,13 +24,17 @@ class ContractListActions { } makeContractPublic(contract){ - OwnershipFetcher.makeContractPublic(contract) - .then((res) =>{ - return res; - }) - .catch((err)=>{ - console.logGlobal(err); - }); + contract.public=true; + return Q.Promise((resolve, reject) => { + OwnershipFetcher.makeContractPublic(contract) + .then((res) => { + resolve(res); + }) + .catch((err)=> { + console.logGlobal(err); + reject(err); + }); + }); } } diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 6b4c624e..222bd42e 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -11,6 +11,8 @@ import ContractListActions from '../../actions/contract_list_actions'; import ActionPanel from '../ascribe_panel/action_panel'; import { getLangText } from '../../utils/lang_utils'; +import GlobalNotificationModel from '../../models/global_notification_model'; +import GlobalNotificationActions from '../../actions/global_notification_actions'; let ContractSettings = React.createClass({ propTypes: { @@ -33,7 +35,10 @@ let ContractSettings = React.createClass({ console.log(contract); ContractListActions.makeContractPublic(contract) .then(( ) => ContractListActions.fetchContractList()) - .catch((error)=>{console.log("Error ", error)}) + .catch((error)=>{console.log("Error ", error); + let notification = new GlobalNotificationModel("Service is unavailable", 'danger', 10000); + GlobalNotificationActions.appendGlobalNotification(notification); +}) }, getPublicContracts(){ return this.state.contractList.filter((contract) => contract.public); From 73ee0753c1431c4b9cb92155528e69253c8dcd59 Mon Sep 17 00:00:00 2001 From: diminator Date: Thu, 3 Sep 2015 17:25:22 +0200 Subject: [PATCH 028/192] refactored notifications per detail --- .../accordion_list_item_table_editions.js | 2 +- .../accordion_list_item_wallet.js | 3 +- js/components/ascribe_detail/edition.js | 30 ++----- .../ascribe_detail/piece_container.js | 12 +-- .../ascribe_forms/form_request_action.js | 34 +++----- .../list_form_request_actions.js | 11 ++- .../prizes_dashboard.js | 82 ------------------- .../ascribe_table/table_item_acl_filtered.js | 6 +- js/components/header_notification.js | 17 +++- .../ascribe_detail/prize_piece_container.js | 15 +--- .../ascribe_detail/ikonotv_piece_container.js | 15 +--- js/routes.js | 2 - sass/ascribe_notification_list.scss | 8 +- 13 files changed, 60 insertions(+), 177 deletions(-) delete mode 100644 js/components/ascribe_prizes_dashboard/prizes_dashboard.js 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 d1ab2112..350d61a8 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 @@ -160,7 +160,7 @@ let AccordionListItemTableEditions = React.createClass({ let content = item.acl; return { 'content': content, - 'requestAction': item.request_action + 'notifications': item.notifications }; }, 'acl', getLangText('Actions'), diff --git a/js/components/ascribe_accordion_list/accordion_list_item_wallet.js b/js/components/ascribe_accordion_list/accordion_list_item_wallet.js index 178a7db4..dde5c43d 100644 --- a/js/components/ascribe_accordion_list/accordion_list_item_wallet.js +++ b/js/components/ascribe_accordion_list/accordion_list_item_wallet.js @@ -61,8 +61,7 @@ let AccordionListItemWallet = React.createClass({ }, getGlyphicon(){ - if ((this.props.content.request_action && this.props.content.request_action.length > 0) || - (this.props.content.request_action_editions)){ + if ((this.props.content.notifications && this.props.content.notifications.length > 0)){ return ( 0){ actions = ( ); + notifications={this.props.edition.notifications}/>); } else { diff --git a/js/components/ascribe_detail/piece_container.js b/js/components/ascribe_detail/piece_container.js index 0de25beb..a4460073 100644 --- a/js/components/ascribe_detail/piece_container.js +++ b/js/components/ascribe_detail/piece_container.js @@ -9,9 +9,6 @@ import PieceStore from '../../stores/piece_store'; import PieceListActions from '../../actions/piece_list_actions'; import PieceListStore from '../../stores/piece_list_store'; -import NotificationActions from '../../actions/notification_actions'; -import NotificationStore from '../../stores/notification_store'; - import UserActions from '../../actions/user_actions'; import UserStore from '../../stores/user_store'; @@ -65,8 +62,6 @@ let PieceContainer = React.createClass({ UserActions.fetchCurrentUser(); PieceStore.listen(this.onChange); PieceActions.fetchOne(this.props.params.pieceId); - NotificationStore.listen(this.onChange); - NotificationActions.fetchPieceNotifications(this.props.params.pieceId); }, componentWillUnmount() { @@ -78,7 +73,6 @@ let PieceContainer = React.createClass({ PieceStore.unlisten(this.onChange); UserStore.unlisten(this.onChange); PieceListStore.unlisten(this.onChange); - NotificationStore.unlisten(this.onChange); }, onChange(state) { @@ -180,14 +174,14 @@ let PieceContainer = React.createClass({ getActions() { if (this.state.piece && - this.state.pieceNotifications && - this.state.pieceNotifications.notification) { + this.state.piece.notifications && + this.state.piece.notifications.length > 0) { return ( ); + notifications={this.state.piece.notifications}/>); } else { return ( diff --git a/js/components/ascribe_forms/form_request_action.js b/js/components/ascribe_forms/form_request_action.js index c65a7394..b0f3b6c6 100644 --- a/js/components/ascribe_forms/form_request_action.js +++ b/js/components/ascribe_forms/form_request_action.js @@ -22,8 +22,7 @@ let RequestActionForm = React.createClass({ React.PropTypes.object, React.PropTypes.array ]).isRequired, - requestAction: React.PropTypes.string, - requestUser: React.PropTypes.string, + notifications: React.PropTypes.object, currentUser: React.PropTypes.object, handleSuccess: React.PropTypes.func }, @@ -35,19 +34,19 @@ let RequestActionForm = React.createClass({ getUrls() { let urls = {}; - if (this.props.requestAction === 'consign'){ + if (this.props.notifications.action === 'consign'){ urls.accept = ApiUrls.ownership_consigns_confirm; urls.deny = ApiUrls.ownership_consigns_deny; - } else if (this.props.requestAction === 'unconsign'){ + } else if (this.props.notifications.action === 'unconsign'){ urls.accept = ApiUrls.ownership_unconsigns; urls.deny = ApiUrls.ownership_unconsigns_deny; - } else if (this.props.requestAction === '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.requestAction === '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.requestAction === '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; } @@ -70,8 +69,8 @@ let RequestActionForm = React.createClass({ return () => { let message = getLangText('You have successfully') + ' ' + option + ' the ' + action + ' request ' + getLangText('from') + ' ' + owner; - let notification = new GlobalNotificationModel(message, 'success'); - GlobalNotificationActions.appendGlobalNotification(notification); + let notifications = new GlobalNotificationModel(message, 'success'); + GlobalNotificationActions.appendGlobalNotification(notifications); this.handleSuccess(); @@ -81,11 +80,9 @@ let RequestActionForm = React.createClass({ handleSuccess() { if (this.isPiece()){ NotificationActions.fetchPieceListNotifications(); - //NotificationActions.fetchPieceNotifications(this.props.pieceOrEditions.id); } else { NotificationActions.fetchEditionListNotifications(); - NotificationActions.fetchEditionNotifications(this.props.pieceOrEditions[0].bitcoin_id); } if(this.props.handleSuccess) { this.props.handleSuccess(); @@ -93,20 +90,15 @@ let RequestActionForm = React.createClass({ }, getContent() { - let pieceOrEditionStr = this.isPiece() ? getLangText('this work%s', '.') : getLangText('this edition%s', '.'); - let message = this.props.requestUser + ' ' + getLangText('requests you') + ' ' + this.props.requestAction + ' ' + pieceOrEditionStr; - if (this.props.requestAction === 'loan_request'){ - message = this.props.requestUser + ' ' + getLangText('requests you to loan') + ' ' + pieceOrEditionStr; - } return ( - {message} + {this.props.notifications.action_str + ' by ' + this.props.notifications.by} ); }, getAcceptButtonForm(urls) { - if(this.props.requestAction === 'unconsign') { + if(this.props.notifications.action === 'unconsign') { return ( ); - } else if(this.props.requestAction === 'loan_request') { + } else if(this.props.notifications.action === 'loan_request') { return ( @@ -158,7 +150,7 @@ let RequestActionForm = React.createClass({ isInline={true} getFormData={this.getFormData} handleSuccess={ - this.showNotification(getLangText('denied'), this.props.requestAction, this.props.requestUser) + this.showNotification(getLangText('denied'), this.props.notifications.action, this.props.notifications.by) } className='inline pull-right'>
); diff --git a/js/components/whitelabel/prize/components/ascribe_detail/prize_piece_container.js b/js/components/whitelabel/prize/components/ascribe_detail/prize_piece_container.js index cb9e1593..2dd56dca 100644 --- a/js/components/whitelabel/prize/components/ascribe_detail/prize_piece_container.js +++ b/js/components/whitelabel/prize/components/ascribe_detail/prize_piece_container.js @@ -15,9 +15,6 @@ import PieceListActions from '../../../../../actions/piece_list_actions'; import PrizeRatingActions from '../../actions/prize_rating_actions'; import PrizeRatingStore from '../../stores/prize_rating_store'; -import NotificationStore from '../../../../../stores/notification_store'; -import NotificationActions from '../../../../../actions/notification_actions.js'; - import UserStore from '../../../../../stores/user_store'; import Piece from '../../../../../components/ascribe_detail/piece'; @@ -53,8 +50,7 @@ let PieceContainer = React.createClass({ getInitialState() { return mergeOptions( PieceStore.getState(), - UserStore.getState(), - NotificationStore.getState() + UserStore.getState() ); }, @@ -62,8 +58,6 @@ let PieceContainer = React.createClass({ PieceStore.listen(this.onChange); PieceActions.fetchOne(this.props.params.pieceId); UserStore.listen(this.onChange); - NotificationStore.listen(this.onChange); - NotificationActions.fetchPieceNotifications(this.props.params.pieceId); }, // This is done to update the container when the user clicks on the prev or next @@ -83,7 +77,6 @@ let PieceContainer = React.createClass({ PieceActions.updatePiece({}); PieceStore.unlisten(this.onChange); UserStore.unlisten(this.onChange); - NotificationStore.unlisten(this.onChange); }, @@ -97,14 +90,14 @@ let PieceContainer = React.createClass({ getActions() { if (this.state.piece && - this.state.pieceNotifications && - this.state.pieceNotifications.notification) { + this.state.piece.notifications && + this.state.piece.notifications.length > 0) { return ( ); + notifications={this.state.piece.notifications}/>); } }, diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js index 781b148b..fac26f7d 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js @@ -10,9 +10,6 @@ import PieceListStore from '../../../../../../stores/piece_list_store'; import UserStore from '../../../../../../stores/user_store'; -import NotificationStore from '../../../../../../stores/notification_store'; -import NotificationActions from '../../../../../../actions/notification_actions.js'; - import Piece from '../../../../../../components/ascribe_detail/piece'; import ListRequestActions from '../../../../../ascribe_forms/list_form_request_actions'; @@ -44,8 +41,7 @@ let IkonotvPieceContainer = React.createClass({ return mergeOptions( PieceStore.getState(), UserStore.getState(), - PieceListStore.getState(), - NotificationStore.getState() + PieceListStore.getState() ); }, @@ -54,8 +50,6 @@ let IkonotvPieceContainer = React.createClass({ PieceActions.fetchOne(this.props.params.pieceId); UserStore.listen(this.onChange); PieceListStore.listen(this.onChange); - NotificationStore.listen(this.onChange); - NotificationActions.fetchPieceNotifications(this.props.params.pieceId); }, componentWillReceiveProps(nextProps) { @@ -74,7 +68,6 @@ let IkonotvPieceContainer = React.createClass({ PieceStore.unlisten(this.onChange); UserStore.unlisten(this.onChange); PieceListStore.unlisten(this.onChange); - NotificationStore.unlisten(this.onChange); }, onChange(state) { @@ -96,14 +89,14 @@ let IkonotvPieceContainer = React.createClass({ getActions(){ if (this.state.piece && - this.state.pieceNotifications && - this.state.pieceNotifications.notification) { + this.state.piece.notifications && + this.state.piece.notifications.length > 0) { return ( ); + notifications={this.state.piece.notifications}/>); } else { diff --git a/js/routes.js b/js/routes.js index 2762052b..314dc89a 100644 --- a/js/routes.js +++ b/js/routes.js @@ -22,7 +22,6 @@ import CoaVerifyContainer from './components/coa_verify_container'; import RegisterPiece from './components/register_piece'; -import PrizesDashboard from './components/ascribe_prizes_dashboard/prizes_dashboard'; import AppConstants from './constants/application_constants'; @@ -45,7 +44,6 @@ const COMMON_ROUTES = ( - ); diff --git a/sass/ascribe_notification_list.scss b/sass/ascribe_notification_list.scss index 696d9169..1b4b6a0c 100644 --- a/sass/ascribe_notification_list.scss +++ b/sass/ascribe_notification_list.scss @@ -45,9 +45,15 @@ $break-medium: 1200px; margin-top: 0.3em; margin-bottom: 0.15em; font-size: 1.8em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .sub-header{ - margin-bottom: 1em; + margin-bottom: 0.6em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .notification-action{ color: $ascribe-color-green; From eb4994b05eb94ef4687e2f8d895135ddd6a38dc4 Mon Sep 17 00:00:00 2001 From: Cevo Date: Thu, 3 Sep 2015 18:25:12 +0200 Subject: [PATCH 029/192] add more --- js/actions/contract_actions.js | 2 -- .../ascribe_settings/contract_settings.js | 16 ++++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/js/actions/contract_actions.js b/js/actions/contract_actions.js index c6055ffc..d1bf1432 100644 --- a/js/actions/contract_actions.js +++ b/js/actions/contract_actions.js @@ -39,8 +39,6 @@ class ContractActions { contractEmail: null }); }); - } else { - /* No email was entered - Ignore and keep going*/ } } diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 222bd42e..f38464f3 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -35,10 +35,10 @@ let ContractSettings = React.createClass({ console.log(contract); ContractListActions.makeContractPublic(contract) .then(( ) => ContractListActions.fetchContractList()) - .catch((error)=>{console.log("Error ", error); - let notification = new GlobalNotificationModel("Service is unavailable", 'danger', 10000); + .catch((error)=>{console.log('Error ', error); + let notification = new GlobalNotificationModel('Service is unavailable', 'danger', 10000); GlobalNotificationActions.appendGlobalNotification(notification); -}) +}); }, getPublicContracts(){ return this.state.contractList.filter((contract) => contract.public); @@ -68,31 +68,31 @@ let ContractSettings = React.createClass({ {(publicContracts.length > 0) ? publicContracts.map( (contract) => { - return( + return ( } - />) + />); } ) : null }
} {

Private Contracts

- {(privateContracts.length>0) ? + {(privateContracts.length > 0) ? privateContracts.map( (contract) => { - return( + return ( } - />) + />); } ) : null}
} From f312c94eeb9ce57371d866486bcf5d33325135e2 Mon Sep 17 00:00:00 2001 From: Cevo Date: Fri, 4 Sep 2015 11:31:53 +0200 Subject: [PATCH 030/192] if there is anything else --- js/actions/contract_list_actions.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/actions/contract_list_actions.js b/js/actions/contract_list_actions.js index c57bceb9..608b5df1 100644 --- a/js/actions/contract_list_actions.js +++ b/js/actions/contract_list_actions.js @@ -24,13 +24,15 @@ class ContractListActions { } makeContractPublic(contract){ - contract.public=true; + contract.public = true; return Q.Promise((resolve, reject) => { OwnershipFetcher.makeContractPublic(contract) .then((res) => { + console.log('Here is the result... '); resolve(res); }) .catch((err)=> { + console.log('Here we have an error'); console.logGlobal(err); reject(err); }); From 9b7a69bc20deb3b0a37c29395006710b3e886f26 Mon Sep 17 00:00:00 2001 From: diminator Date: Fri, 4 Sep 2015 11:49:55 +0200 Subject: [PATCH 031/192] contract agreement notifications --- js/actions/notification_actions.js | 16 ++++++- js/app.js | 3 +- .../ascribe_forms/form_contract_agreement.js | 6 +-- js/components/contract_notification.js | 36 +++++++++++++++ .../ikonotv/ikonotv_contract_notifications.js | 45 +++++++++++++++++++ .../whitelabel/wallet/wallet_routes.js | 2 + js/constants/api_urls.js | 5 ++- js/fetchers/notification_fetcher.js | 4 ++ js/routes.js | 3 +- js/stores/notification_store.js | 5 +++ js/third_party/notifications.js | 36 +++++++++++++++ 11 files changed, 153 insertions(+), 8 deletions(-) create mode 100644 js/components/contract_notification.js create mode 100644 js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js create mode 100644 js/third_party/notifications.js diff --git a/js/actions/notification_actions.js b/js/actions/notification_actions.js index 429ae666..9318c922 100644 --- a/js/actions/notification_actions.js +++ b/js/actions/notification_actions.js @@ -1,6 +1,7 @@ 'use strict'; import alt from '../alt'; +import Q from 'q'; import NotificationFetcher from '../fetchers/notification_fetcher'; @@ -10,7 +11,8 @@ class NotificationActions { 'updatePieceListNotifications', 'updateEditionListNotifications', 'updateEditionNotifications', - 'updatePieceNotifications' + 'updatePieceNotifications', + 'updateContractAgreementListNotifications' ); } @@ -49,6 +51,18 @@ class NotificationActions { }) .catch((err) => console.logGlobal(err)); } + + fetchContractAgreementListNotifications() { + return Q.Promise((resolve, reject) => { + NotificationFetcher + .fetchContractAgreementListNotifications() + .then((res) => { + this.actions.updateContractAgreementListNotifications(res); + resolve(res); + }) + .catch((err) => console.logGlobal(err)); + }); + } } export default alt.createActions(NotificationActions); diff --git a/js/app.js b/js/app.js index 6dcf58bf..785068a4 100644 --- a/js/app.js +++ b/js/app.js @@ -26,6 +26,7 @@ import EventActions from './actions/event_actions'; import GoogleAnalyticsHandler from './third_party/ga'; import RavenHandler from './third_party/raven'; import IntercomHandler from './third_party/intercom'; +import NotificationsHandler from './third_party/notifications'; /* eslint-enable */ initLogging(); @@ -73,7 +74,7 @@ class AppGateway { } EventActions.applicationWillBoot(settings); - Router.run(getRoutes(type, subdomain), Router.HistoryLocation, (App) => { + window.appRouter = Router.run(getRoutes(type, subdomain), Router.HistoryLocation, (App) => { React.render( , document.getElementById('main') diff --git a/js/components/ascribe_forms/form_contract_agreement.js b/js/components/ascribe_forms/form_contract_agreement.js index 1d9f7c72..d3b352c4 100644 --- a/js/components/ascribe_forms/form_contract_agreement.js +++ b/js/components/ascribe_forms/form_contract_agreement.js @@ -60,8 +60,8 @@ let ContractAgreementForm = React.createClass({ }, getContracts() { - if (this.state.contractList && this.state.contractList.count > 0) { - let contractList = this.state.contractList.results; + if (this.state.contractList && this.state.contractList.length > 0) { + let contractList = this.state.contractList; return ( + value={ contract.id }> { contract.name } ); diff --git a/js/components/contract_notification.js b/js/components/contract_notification.js new file mode 100644 index 00000000..cd6ceb53 --- /dev/null +++ b/js/components/contract_notification.js @@ -0,0 +1,36 @@ +'use strict'; + +import React from 'react'; + +import NotificationStore from '../stores/notification_store'; + +import { mergeOptions } from '../utils/general_utils'; + +let ContractNotification = React.createClass({ + getInitialState() { + return mergeOptions( + NotificationStore.getState() + ); + }, + + componentDidMount() { + NotificationStore.listen(this.onChange); + }, + + componentWillUnmount() { + NotificationStore.unlisten(this.onChange); + }, + + onChange(state) { + this.setState(state); + }, + + render() { + + return ( + null + ); + } +}); + +export default ContractNotification; \ No newline at end of file diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js new file mode 100644 index 00000000..80b39bee --- /dev/null +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js @@ -0,0 +1,45 @@ +'use strict'; + +import React from 'react'; + +import NotificationStore from '../../../../../stores/notification_store'; +import WhitelabelStore from '../../../../../stores/whitelabel_store'; + +import { mergeOptions } from '../../../../../utils/general_utils'; + +let IkonotvContractNotifications = React.createClass({ + + getInitialState() { + return mergeOptions( + NotificationStore.getState(), + WhitelabelStore.getState() + ); + }, + + componentDidMount() { + NotificationStore.listen(this.onChange); + WhitelabelStore.listen(this.onChange); + }, + + componentWillUnmount() { + NotificationStore.unlisten(this.onChange); + WhitelabelStore.unlisten(this.onChange); + }, + + onChange(state) { + this.setState(state); + }, + + render() { + console.log(this.state) + return ( +
+
+ +
+
+ ); + } +}); + +export default IkonotvContractNotifications; \ No newline at end of file diff --git a/js/components/whitelabel/wallet/wallet_routes.js b/js/components/whitelabel/wallet/wallet_routes.js index 1c4ef4a7..4a0f022c 100644 --- a/js/components/whitelabel/wallet/wallet_routes.js +++ b/js/components/whitelabel/wallet/wallet_routes.js @@ -22,6 +22,7 @@ import CylandPieceList from './components/cyland/cyland_piece_list'; import IkonotvPieceList from './components/ikonotv/ikonotv_piece_list'; import IkonotvRequestLoan from './components/ikonotv/ikonotv_request_loan'; import IkonotvPieceContainer from './components/ikonotv/ascribe_detail/ikonotv_piece_container'; +import IkonotvContractNotifications from './components/ikonotv/ikonotv_contract_notifications'; import CCRegisterPiece from './components/cc/cc_register_piece'; @@ -77,6 +78,7 @@ let ROUTES = { + ) }; diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js index aa484142..54a398d2 100644 --- a/js/constants/api_urls.js +++ b/js/constants/api_urls.js @@ -31,6 +31,7 @@ let ApiUrls = { 'notification_piece': AppConstants.apiEndpoint + 'notifications/pieces/${piece_id}/', 'notification_editionlist': AppConstants.apiEndpoint + 'notifications/editions/', 'notification_edition': AppConstants.apiEndpoint + 'notifications/editions/${edition_id}/', + 'notification_contractagreementlist': AppConstants.apiEndpoint + 'notifications/contract_agreements/', 'ownership_contract_agreements': AppConstants.apiEndpoint + 'ownership/contract_agreements/', 'ownership_consigns': AppConstants.apiEndpoint + 'ownership/consigns/', 'ownership_consigns_confirm': AppConstants.apiEndpoint + 'ownership/consigns/confirm/', @@ -51,8 +52,8 @@ let ApiUrls = { 'ownership_unconsigns': AppConstants.apiEndpoint + 'ownership/unconsigns/', 'ownership_unconsigns_deny': AppConstants.apiEndpoint + 'ownership/unconsigns/deny/', 'ownership_unconsigns_request': AppConstants.apiEndpoint + 'ownership/unconsigns/request/', - 'ownership_contract':AppConstants.apiEndpoint + 'ownership/contracts/${contract_id}', - "ownership_contract_list": AppConstants.apiEndpoint + 'ownership/contracts/', + 'ownership_contract': AppConstants.apiEndpoint + 'ownership/contracts/${contract_id}', + 'ownership_contract_list': AppConstants.apiEndpoint + 'ownership/contracts/', 'piece': AppConstants.apiEndpoint + 'pieces/${piece_id}/', 'piece_extradata': AppConstants.apiEndpoint + 'pieces/${piece_id}/extradata/', 'piece_first_edition_id': AppConstants.apiEndpoint + 'pieces/${piece_id}/edition_index/', diff --git a/js/fetchers/notification_fetcher.js b/js/fetchers/notification_fetcher.js index 6d2f7424..48606b70 100644 --- a/js/fetchers/notification_fetcher.js +++ b/js/fetchers/notification_fetcher.js @@ -19,6 +19,10 @@ let NotificationFetcher = { fetchEditionNotifications(editionId) { return requests.get('notification_edition', {'edition_id': editionId}); + }, + + fetchContractAgreementListNotifications() { + return requests.get('notification_contractagreementlist'); } }; diff --git a/js/routes.js b/js/routes.js index 314dc89a..1d521cab 100644 --- a/js/routes.js +++ b/js/routes.js @@ -21,7 +21,7 @@ import SettingsContainer from './components/ascribe_settings/settings_container' import CoaVerifyContainer from './components/coa_verify_container'; import RegisterPiece from './components/register_piece'; - +import ContractNotification from './components/contract_notification'; import AppConstants from './constants/application_constants'; @@ -44,6 +44,7 @@ const COMMON_ROUTES = ( + ); diff --git a/js/stores/notification_store.js b/js/stores/notification_store.js index 6e706699..84c5f5d7 100644 --- a/js/stores/notification_store.js +++ b/js/stores/notification_store.js @@ -10,6 +10,7 @@ class NotificationStore { constructor() { this.pieceListNotifications = {}; this.editionListNotifications = {}; + this.contractAgreementListNotifications = {}; this.editionNotifications = null; this.pieceNotifications = null; this.bindActions(NotificationActions); @@ -31,6 +32,10 @@ class NotificationStore { this.editionNotifications = res.notification; } + onUpdateContractAgreementListNotifications(res) { + this.contractAgreementListNotifications = res.notifications; + } + } export default alt.createStore(NotificationStore, 'NotificationStore'); diff --git a/js/third_party/notifications.js b/js/third_party/notifications.js new file mode 100644 index 00000000..8887bbe2 --- /dev/null +++ b/js/third_party/notifications.js @@ -0,0 +1,36 @@ +'use strict'; + +import alt from '../alt'; +import EventActions from '../actions/event_actions'; + +import NotificationActions from '../actions/notification_actions'; + + +class NotificationsHandler { + + constructor() { + this.bindActions(EventActions); + this.loaded = false; + } + + onProfileDidLoad(profile) { + if (this.loaded) { + return; + } + let subdomain = window.location.host.split('.')[0]; + if (subdomain === 'ikonotv') { + NotificationActions.fetchContractAgreementListNotifications().then( + (res) => { + if (res.notifications && res.notifications.length > 0) { + this.loaded = true; + console.log('Contractagreement notifications loaded'); + setTimeout(() => window.appRouter.transitionTo('contract_notifications'), 0); + } + } + ); + } + this.loaded = true; + } +} + +export default alt.createStore(NotificationsHandler, 'NotificationsHandler'); From 4bdab3410e46c1951e1a13ffb3f40006aba1b87e Mon Sep 17 00:00:00 2001 From: diminator Date: Fri, 4 Sep 2015 14:48:10 +0200 Subject: [PATCH 032/192] contractagreementserializer with contract fully expanded --- js/app.js | 1 - .../components/ikonotv/ikonotv_contract_notifications.js | 9 ++++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/js/app.js b/js/app.js index 785068a4..5ad36d28 100644 --- a/js/app.js +++ b/js/app.js @@ -72,7 +72,6 @@ class AppGateway { type = settings.type; subdomain = settings.subdomain; } - EventActions.applicationWillBoot(settings); window.appRouter = Router.run(getRoutes(type, subdomain), Router.HistoryLocation, (App) => { React.render( diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js index 80b39bee..636948d6 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js @@ -35,7 +35,14 @@ let IkonotvContractNotifications = React.createClass({ return (
- +
+ +
+
+ +
); From 1611a750365d4654d09ccb86eca6a5f95a1865e5 Mon Sep 17 00:00:00 2001 From: diminator Date: Fri, 4 Sep 2015 16:48:00 +0200 Subject: [PATCH 033/192] Merge remote-tracking branch 'remotes/origin/AD-858-contract-history' into AD-883-show-notificationsrequests-on-col Conflicts: ownership/serializers.py --- .../wallet/components/ikonotv/ikonotv_contract_notifications.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js index 636948d6..5e30d370 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js @@ -39,7 +39,7 @@ let IkonotvContractNotifications = React.createClass({
-
From ae21686f263bf648829d1d9d3df8543cb9d64e3a Mon Sep 17 00:00:00 2001 From: Cevo Date: Mon, 7 Sep 2015 10:23:39 +0200 Subject: [PATCH 034/192] slash added to route --- js/constants/api_urls.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js index bad04be5..1af9c609 100644 --- a/js/constants/api_urls.js +++ b/js/constants/api_urls.js @@ -47,7 +47,7 @@ let ApiUrls = { 'ownership_unconsigns': AppConstants.apiEndpoint + 'ownership/unconsigns/', 'ownership_unconsigns_deny': AppConstants.apiEndpoint + 'ownership/unconsigns/deny/', 'ownership_unconsigns_request': AppConstants.apiEndpoint + 'ownership/unconsigns/request/', - 'ownership_contract':AppConstants.apiEndpoint + 'ownership/contracts/${contract_id}', + 'ownership_contract': AppConstants.apiEndpoint + 'ownership/contracts/${contract_id}/', "ownership_contract_list": AppConstants.apiEndpoint + 'ownership/contracts/', 'piece': AppConstants.apiEndpoint + 'pieces/${piece_id}/', 'piece_extradata': AppConstants.apiEndpoint + 'pieces/${piece_id}/extradata/', From 501d7ac7c03d3f125a3e0474dd33ba70290f8a68 Mon Sep 17 00:00:00 2001 From: Cevo Date: Mon, 7 Sep 2015 11:38:23 +0200 Subject: [PATCH 035/192] now committing the remove contract --- js/actions/contract_list_actions.js | 15 +++++++++++ .../ascribe_settings/contract_settings.js | 25 +++++++++++++------ js/constants/api_urls.js | 2 +- js/fetchers/ownership_fetcher.js | 4 +++ 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/js/actions/contract_list_actions.js b/js/actions/contract_list_actions.js index 608b5df1..b9dad5db 100644 --- a/js/actions/contract_list_actions.js +++ b/js/actions/contract_list_actions.js @@ -38,6 +38,21 @@ class ContractListActions { }); }); } + + removeContract(contract){ + return Q.Promise((resolve, reject) => { + OwnershipFetcher.deleteContract(contract) + .then((res) => { + console.log('Contract deleted'); + resolve(res); + }) + .catch( (err) => { + console.log('Error while deleting'); + console.logGlobal(err); + reject(err); + }); + }); + } } export default alt.createActions(ContractListActions); diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index f38464f3..95130f28 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -36,9 +36,18 @@ let ContractSettings = React.createClass({ ContractListActions.makeContractPublic(contract) .then(( ) => ContractListActions.fetchContractList()) .catch((error)=>{console.log('Error ', error); - let notification = new GlobalNotificationModel('Service is unavailable', 'danger', 10000); - GlobalNotificationActions.appendGlobalNotification(notification); -}); + let notification = new GlobalNotificationModel('Service is unavailable', 'danger', 10000); + GlobalNotificationActions.appendGlobalNotification(notification); + }); + }, + removeContract(contract){ + console.log(contract); + ContractListActions.removeContract(contract) + .then(( ) => ContractListActions.fetchContractList()) + .catch((error) => {console.log('Error', error); + let notification = new GlobalNotificationModel('Service is unavailable', 'danger', 10000); + GlobalNotificationActions.appendGlobalNotification(notification); + }); }, getPublicContracts(){ return this.state.contractList.filter((contract) => contract.public); @@ -70,10 +79,11 @@ let ContractSettings = React.createClass({ (contract) => { return ( - + } />); } @@ -87,9 +97,10 @@ let ContractSettings = React.createClass({ (contract) => { return ( - + } />); diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js index 1af9c609..5af07ba6 100644 --- a/js/constants/api_urls.js +++ b/js/constants/api_urls.js @@ -48,7 +48,7 @@ let ApiUrls = { 'ownership_unconsigns_deny': AppConstants.apiEndpoint + 'ownership/unconsigns/deny/', 'ownership_unconsigns_request': AppConstants.apiEndpoint + 'ownership/unconsigns/request/', 'ownership_contract': AppConstants.apiEndpoint + 'ownership/contracts/${contract_id}/', - "ownership_contract_list": AppConstants.apiEndpoint + 'ownership/contracts/', + 'ownership_contract_list': AppConstants.apiEndpoint + 'ownership/contracts/', 'piece': AppConstants.apiEndpoint + 'pieces/${piece_id}/', 'piece_extradata': AppConstants.apiEndpoint + 'pieces/${piece_id}/extradata/', 'piece_first_edition_id': AppConstants.apiEndpoint + 'pieces/${piece_id}/edition_index/', diff --git a/js/fetchers/ownership_fetcher.js b/js/fetchers/ownership_fetcher.js index 9b5e81f7..751790ba 100644 --- a/js/fetchers/ownership_fetcher.js +++ b/js/fetchers/ownership_fetcher.js @@ -25,6 +25,10 @@ let OwnershipFetcher = { makeContractPublic(contractObj){ return requests.put('ownership_contract', { body: contractObj, contract_id: contractObj.id }); + }, + + deleteContract(contractObj){ + return requests.delete('ownership_contract', {body: contractObj, contract_id: contractObj.id}); } }; From 22aa0139aee197cdf718275e360478a9ca2d17b2 Mon Sep 17 00:00:00 2001 From: diminator Date: Mon, 7 Sep 2015 12:03:59 +0200 Subject: [PATCH 036/192] terms and conditions page with accept/deny Needed: copyright societies in backend --- .../ikonotv/ikonotv_contract_notifications.js | 132 ++++++++++++++++-- .../whitelabel/wallet/wallet_routes.js | 2 +- js/constants/api_urls.js | 2 + js/stores/notification_store.js | 2 +- sass/ascribe_notification_page.scss | 51 +++++++ sass/main.scss | 1 + 6 files changed, 176 insertions(+), 14 deletions(-) create mode 100644 sass/ascribe_notification_page.scss diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js index 5e30d370..db369564 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js @@ -1,14 +1,34 @@ 'use strict'; import React from 'react'; +import Router from 'react-router'; +import Glyphicon from 'react-bootstrap/lib/Glyphicon'; +import Button from 'react-bootstrap/lib/Button'; + +import Form from '../../../../ascribe_forms/form'; +import Property from '../../../../ascribe_forms/property'; +import InputCheckbox from '../../../../ascribe_forms/input_checkbox'; + +import NotificationActions from '../../../../../actions/notification_actions'; import NotificationStore from '../../../../../stores/notification_store'; import WhitelabelStore from '../../../../../stores/whitelabel_store'; +import GlobalNotificationModel from '../../../../../models/global_notification_model'; +import GlobalNotificationActions from '../../../../../actions/global_notification_actions'; + +import apiUrls from '../../../../../constants/api_urls'; + +import requests from '../../../../../utils/requests'; +import { getLangText } from '../../../../../utils/lang_utils'; import { mergeOptions } from '../../../../../utils/general_utils'; +let Navigation = Router.Navigation; + let IkonotvContractNotifications = React.createClass({ + mixins: [Navigation], + getInitialState() { return mergeOptions( NotificationStore.getState(), @@ -19,6 +39,9 @@ let IkonotvContractNotifications = React.createClass({ componentDidMount() { NotificationStore.listen(this.onChange); WhitelabelStore.listen(this.onChange); + if (this.state.contractAgreementListNotifications === null){ + NotificationActions.fetchContractAgreementListNotifications(); + } }, componentWillUnmount() { @@ -30,22 +53,107 @@ let IkonotvContractNotifications = React.createClass({ this.setState(state); }, - render() { - console.log(this.state) - return ( -
-
-
- -
-
- + displayContract(){ + let notifications = this.state.contractAgreementListNotifications[0]; + let blob = notifications.contract_agreement.contract.blob; + if (blob.mime === 'pdf') { + return ( + + ); + } + return ( + ); + }, + + handleConfirmSuccess() { + let notification = new GlobalNotificationModel(getLangText('You have accepted the conditions'), 'success', 10000); + GlobalNotificationActions.appendGlobalNotification(notification); + this.transitionTo('pieces'); + }, + + handleDeny() { + let contractAgreement = this.state.contractAgreementListNotifications[0].contract_agreement; + requests.post(apiUrls.ownership_contract_agreements_deny, {contract_agreement_id: contractAgreement.id}).then( + () => this.handleDenySuccess() + ); + }, + + handleDenySuccess() { + let notification = new GlobalNotificationModel(getLangText('You have denied the conditions'), 'success', 10000); + GlobalNotificationActions.appendGlobalNotification(notification); + this.transitionTo('pieces'); + }, + + render() { + + if (this.state.contractAgreementListNotifications && + this.state.contractAgreementListNotifications.length > 0) { + let contractAgreement = this.state.contractAgreementListNotifications[0].contract_agreement; + return ( +
+
+
+ +
+ {getLangText('Production Contract')} +
+
+ {this.displayContract()} +
+

{getLangText('Are you a member of any copyright societies?')}

+

+ ARS, DACS, Bildkunst, Pictoright, SODRAC, Copyright Agency/Viscopy, SAVA, Bildrecht GmbH, + SABAM, AUTVIS, CREAIMAGEN, SONECA, Copydan, EAU, Kuvasto, GCA, HUNGART, IVARO, SIAE, JASPAR-SPDA, + AKKA/LAA, LATGA-A, SOMAAP, ARTEGESTION, CARIER, BONO, APSAV, SPA, GESTOR, VISaRTA, RAO, LITA, + DALRO, VeGaP, BUS, ProLitteris, AGADU, AUTORARTE, BUBEDRA, BBDA, BCDA, BURIDA, ADAVIS, BSDA +

+ + + +

+ }> + + + + {' ' + getLangText('Yes') } + + + + + +
+
+
+ ); + } + return null; } }); diff --git a/js/components/whitelabel/wallet/wallet_routes.js b/js/components/whitelabel/wallet/wallet_routes.js index 4a0f022c..bc9e0e19 100644 --- a/js/components/whitelabel/wallet/wallet_routes.js +++ b/js/components/whitelabel/wallet/wallet_routes.js @@ -78,7 +78,7 @@ let ROUTES = { - + ) }; diff --git a/js/constants/api_urls.js b/js/constants/api_urls.js index 54a398d2..fcf9be6f 100644 --- a/js/constants/api_urls.js +++ b/js/constants/api_urls.js @@ -33,6 +33,8 @@ let ApiUrls = { 'notification_edition': AppConstants.apiEndpoint + 'notifications/editions/${edition_id}/', 'notification_contractagreementlist': AppConstants.apiEndpoint + 'notifications/contract_agreements/', 'ownership_contract_agreements': AppConstants.apiEndpoint + 'ownership/contract_agreements/', + 'ownership_contract_agreements_confirm': AppConstants.apiEndpoint + 'ownership/contract_agreements/${contract_agreement_id}/accept/', + 'ownership_contract_agreements_deny': AppConstants.apiEndpoint + 'ownership/contract_agreements/${contract_agreement_id}/reject/', 'ownership_consigns': AppConstants.apiEndpoint + 'ownership/consigns/', 'ownership_consigns_confirm': AppConstants.apiEndpoint + 'ownership/consigns/confirm/', 'ownership_consigns_deny': AppConstants.apiEndpoint + 'ownership/consigns/deny/', diff --git a/js/stores/notification_store.js b/js/stores/notification_store.js index 84c5f5d7..9f6bdecf 100644 --- a/js/stores/notification_store.js +++ b/js/stores/notification_store.js @@ -10,7 +10,7 @@ class NotificationStore { constructor() { this.pieceListNotifications = {}; this.editionListNotifications = {}; - this.contractAgreementListNotifications = {}; + this.contractAgreementListNotifications = null; this.editionNotifications = null; this.pieceNotifications = null; this.bindActions(NotificationActions); diff --git a/sass/ascribe_notification_page.scss b/sass/ascribe_notification_page.scss new file mode 100644 index 00000000..f7cccbde --- /dev/null +++ b/sass/ascribe_notification_page.scss @@ -0,0 +1,51 @@ + +.notification-contract-download { + +} + +.notification-contract-wrapper{ + text-align: center; +} + +.notification-contract-logo { + + img { + margin-bottom: 1em; + } + .notification-contract-header { + font-size: 2em; + text-transform: uppercase; + margin-bottom: 0.8em; + } +} + +.notification-contract-pdf, .notification-contract-footer { + width: 100%; + max-width: 750px; + margin: 0 auto; +} +.notification-contract-pdf { + embed { + border: 1px solid #cccccc; + width: 100%; + height: 60vh; + margin-bottom: 0.4em; + } + .notification-contract-pdf-download { + text-align: left; + margin-left: 1em; + } +} + +.notification-contract-footer { + text-align: left; + padding: 1em; + h1 { + margin-top: 0.4em; + font-size: 1.4em; + } + p { + font-size: 0.9em; + color: #444444; + } +} \ No newline at end of file diff --git a/sass/main.scss b/sass/main.scss index fb71ff2a..c325fdf7 100644 --- a/sass/main.scss +++ b/sass/main.scss @@ -25,6 +25,7 @@ $BASE_URL: '<%= BASE_URL %>'; @import 'ascribe_global_action'; @import 'ascribe_global_notification'; @import 'ascribe_notification_list'; +@import 'ascribe_notification_page'; @import 'ascribe_piece_register'; @import 'offset_right'; @import 'ascribe_settings'; From 1dba9196e70f9f233f4b7c7599035e9f487ea37d Mon Sep 17 00:00:00 2001 From: Cevo Date: Mon, 7 Sep 2015 14:30:45 +0200 Subject: [PATCH 037/192] tabs inserted in jsx --- js/components/ascribe_settings/contract_settings.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 95130f28..9a345605 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -81,8 +81,8 @@ let ContractSettings = React.createClass({ - - + } />); @@ -99,9 +99,9 @@ let ContractSettings = React.createClass({ - - + } />); } From 6b9bf039414be7f9c5b90d0bf53cd2dcdba33ae6 Mon Sep 17 00:00:00 2001 From: Cevo Date: Mon, 7 Sep 2015 15:08:01 +0200 Subject: [PATCH 038/192] tabs inserted in jsx --- js/actions/contract_list_actions.js | 2 -- js/components/ascribe_settings/contract_settings.js | 6 +++--- js/fetchers/ownership_fetcher.js | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/js/actions/contract_list_actions.js b/js/actions/contract_list_actions.js index b9dad5db..7df5d549 100644 --- a/js/actions/contract_list_actions.js +++ b/js/actions/contract_list_actions.js @@ -28,11 +28,9 @@ class ContractListActions { return Q.Promise((resolve, reject) => { OwnershipFetcher.makeContractPublic(contract) .then((res) => { - console.log('Here is the result... '); resolve(res); }) .catch((err)=> { - console.log('Here we have an error'); console.logGlobal(err); reject(err); }); diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 9a345605..919c1960 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -35,8 +35,8 @@ let ContractSettings = React.createClass({ console.log(contract); ContractListActions.makeContractPublic(contract) .then(( ) => ContractListActions.fetchContractList()) - .catch((error)=>{console.log('Error ', error); - let notification = new GlobalNotificationModel('Service is unavailable', 'danger', 10000); + .catch((error)=>{ + let notification = new GlobalNotificationModel(error, 'danger', 10000); GlobalNotificationActions.appendGlobalNotification(notification); }); }, @@ -45,7 +45,7 @@ let ContractSettings = React.createClass({ ContractListActions.removeContract(contract) .then(( ) => ContractListActions.fetchContractList()) .catch((error) => {console.log('Error', error); - let notification = new GlobalNotificationModel('Service is unavailable', 'danger', 10000); + let notification = new GlobalNotificationModel(error, 'danger', 10000); GlobalNotificationActions.appendGlobalNotification(notification); }); }, diff --git a/js/fetchers/ownership_fetcher.js b/js/fetchers/ownership_fetcher.js index 751790ba..e698e199 100644 --- a/js/fetchers/ownership_fetcher.js +++ b/js/fetchers/ownership_fetcher.js @@ -24,7 +24,7 @@ let OwnershipFetcher = { }, makeContractPublic(contractObj){ - return requests.put('ownership_contract', { body: contractObj, contract_id: contractObj.id }); + return requests.put('ownership_csontract', { body: contractObj, contract_id: contractObj.id }); }, deleteContract(contractObj){ From 632c04149dde6b38c9c07f9fef803c90f86f707c Mon Sep 17 00:00:00 2001 From: Cevo Date: Mon, 7 Sep 2015 15:43:44 +0200 Subject: [PATCH 039/192] tabs inserted in jsx --- js/actions/contract_list_actions.js | 4 +- .../ascribe_settings/contract_settings.js | 42 ++++++++++++------- js/fetchers/ownership_fetcher.js | 4 +- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/js/actions/contract_list_actions.js b/js/actions/contract_list_actions.js index 7df5d549..307706ef 100644 --- a/js/actions/contract_list_actions.js +++ b/js/actions/contract_list_actions.js @@ -37,9 +37,9 @@ class ContractListActions { }); } - removeContract(contract){ + removeContract(contractId){ return Q.Promise((resolve, reject) => { - OwnershipFetcher.deleteContract(contract) + OwnershipFetcher.deleteContract(contractId) .then((res) => { console.log('Contract deleted'); resolve(res); diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 919c1960..880cd744 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -32,21 +32,21 @@ let ContractSettings = React.createClass({ this.setState(state); }, makeContractPublic(contract){ - console.log(contract); ContractListActions.makeContractPublic(contract) .then(( ) => ContractListActions.fetchContractList()) .catch((error)=>{ - let notification = new GlobalNotificationModel(error, 'danger', 10000); - GlobalNotificationActions.appendGlobalNotification(notification); + let notification = new GlobalNotificationModel(error, 'danger', 10000); + GlobalNotificationActions.appendGlobalNotification(notification); }); }, removeContract(contract){ console.log(contract); - ContractListActions.removeContract(contract) + ContractListActions.removeContract(contract.id) .then(( ) => ContractListActions.fetchContractList()) - .catch((error) => {console.log('Error', error); - let notification = new GlobalNotificationModel(error, 'danger', 10000); - GlobalNotificationActions.appendGlobalNotification(notification); + .catch((error) => { + console.log('Error', error); + let notification = new GlobalNotificationModel(error, 'danger', 10000); + GlobalNotificationActions.appendGlobalNotification(notification); }); }, getPublicContracts(){ @@ -81,9 +81,13 @@ let ContractSettings = React.createClass({ - - + + } />); } @@ -98,11 +102,19 @@ let ContractSettings = React.createClass({ return ( - - } + buttons = { + + + + } />); } ) : null} diff --git a/js/fetchers/ownership_fetcher.js b/js/fetchers/ownership_fetcher.js index e698e199..07b37bf5 100644 --- a/js/fetchers/ownership_fetcher.js +++ b/js/fetchers/ownership_fetcher.js @@ -27,8 +27,8 @@ let OwnershipFetcher = { return requests.put('ownership_csontract', { body: contractObj, contract_id: contractObj.id }); }, - deleteContract(contractObj){ - return requests.delete('ownership_contract', {body: contractObj, contract_id: contractObj.id}); + deleteContract(contractObjId){ + return requests.delete('ownership_contract', {contract_id: contractObjId}); } }; From 66cd4a1d7bfbb798bf669c54ac5f4d967a47bc38 Mon Sep 17 00:00:00 2001 From: Cevo Date: Mon, 7 Sep 2015 16:33:21 +0200 Subject: [PATCH 040/192] git ignore removed --- js/components/ascribe_buttons/button_submit_close.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/components/ascribe_buttons/button_submit_close.js b/js/components/ascribe_buttons/button_submit_close.js index 11d3c0a4..cdf0ebae 100644 --- a/js/components/ascribe_buttons/button_submit_close.js +++ b/js/components/ascribe_buttons/button_submit_close.js @@ -3,7 +3,7 @@ import React from 'react'; import AppConstants from '../../constants/application_constants'; -import { getLangText } from '../../utils/lang_utils.js' +import { getLangText } from '../../utils/lang_utils.js'; let ButtonSubmitOrClose = React.createClass({ propTypes: { From 86306fc089b106132909306dedd9529a29c29de6 Mon Sep 17 00:00:00 2001 From: Cevo Date: Mon, 7 Sep 2015 16:36:31 +0200 Subject: [PATCH 041/192] console.log remove from requests.js --- js/utils/requests.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/js/utils/requests.js b/js/utils/requests.js index f9e1af04..8e846d7c 100644 --- a/js/utils/requests.js +++ b/js/utils/requests.js @@ -144,18 +144,17 @@ class Requests { let newUrl = this.prepareUrl(url, params); let body = null; if (paramsCopy && paramsCopy.body) { - console.log(paramsCopy.body); body = JSON.stringify(paramsCopy.body); } return this.request(method, newUrl, { body }); } post(url, params) { - return this._putOrPost(url,params,'post') + return this._putOrPost(url, params, 'post'); } put(url, params){ - return this._putOrPost(url,params,'put') + return this._putOrPost(url, params, 'put'); } defaults(options) { From 2c9370e555723f90811bf187d9f5d0d30ddda5b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 8 Sep 2015 10:03:20 +0200 Subject: [PATCH 042/192] restyle contract settings list --- .../ascribe_settings/contract_settings.js | 82 ++++++++++--------- sass/ascribe_collapsible.scss | 2 +- 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 880cd744..16225dc9 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -61,49 +61,51 @@ let ContractSettings = React.createClass({ render() { let publicContracts = this.getPublicContracts(); let privateContracts = this.getPrivateContracts(); - console.log(this.state.contractList); + return ( - {/* this should be this.props.defaultExpanded */} + defaultExpanded={true}> - {
-

Public Contracts

- {(publicContracts.length > 0) ? - publicContracts.map( - (contract) => { + defaultExpanded={true}> + + {publicContracts.map((contract) => { return ( - - - - } - />); - } - ) : null } -
} - - {
-

Private Contracts

- {(privateContracts.length > 0) ? - privateContracts.map( - (contract) => { + + + + + }/> + ); + })} + + + {privateContracts.map((contract) => { return ( - - - } - />); - } - ) : null} -
} + + }/> + ); + })} +
+ defaultExpanded={true}> diff --git a/sass/ascribe_collapsible.scss b/sass/ascribe_collapsible.scss index f6c9a623..85fd4270 100644 --- a/sass/ascribe_collapsible.scss +++ b/sass/ascribe_collapsible.scss @@ -26,7 +26,7 @@ width: 100%; /* Shrink the size of the headline for a nested element */ - .ascribe-collapsible-wrapper > div:first-child { + .ascribe-collapsible-wrapper > .ascribe-collapsible-content { padding-left: 1em; font-size: 90%; } From 38b7dcd79fa5aa675a8a053e394767cc1a056361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 8 Sep 2015 10:15:26 +0200 Subject: [PATCH 043/192] finalize contract styles --- js/components/ascribe_panel/action_panel.js | 17 +++++++-- .../ascribe_settings/contract_settings.js | 37 +++++++++++-------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/js/components/ascribe_panel/action_panel.js b/js/components/ascribe_panel/action_panel.js index 3146f1ba..f6fe9a70 100644 --- a/js/components/ascribe_panel/action_panel.js +++ b/js/components/ascribe_panel/action_panel.js @@ -12,8 +12,12 @@ let ActionPanel = React.createClass({ ]), buttons: React.PropTypes.element, onClick: React.PropTypes.func, - ignoreFocus: React.PropTypes.bool + ignoreFocus: React.PropTypes.bool, + + leftColumnWidth: React.PropTypes.string, + rightColumnWidth: React.PropTypes.string }, + getInitialState() { return { isFocused: false @@ -40,14 +44,21 @@ let ActionPanel = React.createClass({ }, render() { + + let { leftColumnWidth, rightColumnWidth } = this.props; + return (
-
+
{this.props.content}
-
+
{this.props.buttons}
diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 16225dc9..72d2b233 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -81,7 +81,7 @@ let ContractSettings = React.createClass({ title={contract.name} content={contract.name} buttons={ - +
@@ -89,8 +89,11 @@ let ContractSettings = React.createClass({ onClick={this.removeContract.bind(this, contract)}> REMOVE - - }/> +
+ } + leftColumnWidth="40%" + rightColumnWidth="60%" + /> ); })} @@ -104,20 +107,22 @@ let ContractSettings = React.createClass({ title={contract.name} content={contract.name} buttons={ - +
- - - - }/> + UPDATE + + + +
+ } + leftColumnWidth="40%" + rightColumnWidth="60%"/> ); })} From 06ce603c44e92b6b9420dde7ed62519def59ce00 Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 8 Sep 2015 11:01:43 +0200 Subject: [PATCH 044/192] list only is_active --- js/actions/contract_list_actions.js | 4 ++-- js/components/ascribe_forms/form_contract_agreement.js | 2 +- js/fetchers/ownership_fetcher.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/actions/contract_list_actions.js b/js/actions/contract_list_actions.js index 608b5df1..f48eb58f 100644 --- a/js/actions/contract_list_actions.js +++ b/js/actions/contract_list_actions.js @@ -12,8 +12,8 @@ class ContractListActions { ); } - fetchContractList() { - OwnershipFetcher.fetchContractList() + fetchContractList(isActive) { + OwnershipFetcher.fetchContractList(isActive) .then((contracts) => { this.actions.updateContractList(contracts.results); }) diff --git a/js/components/ascribe_forms/form_contract_agreement.js b/js/components/ascribe_forms/form_contract_agreement.js index d3b352c4..4079b741 100644 --- a/js/components/ascribe_forms/form_contract_agreement.js +++ b/js/components/ascribe_forms/form_contract_agreement.js @@ -35,7 +35,7 @@ let ContractAgreementForm = React.createClass({ componentDidMount() { ContractListStore.listen(this.onChange); - ContractListActions.fetchContractList(); + ContractListActions.fetchContractList({is_active: 'True'}); }, componentWillUnmount() { diff --git a/js/fetchers/ownership_fetcher.js b/js/fetchers/ownership_fetcher.js index 9b5e81f7..ee71d1f0 100644 --- a/js/fetchers/ownership_fetcher.js +++ b/js/fetchers/ownership_fetcher.js @@ -15,8 +15,8 @@ let OwnershipFetcher = { /** * Fetch the contracts of the logged-in user from the API. */ - fetchContractList(){ - return requests.get(ApiUrls.ownership_contract_list); + fetchContractList(isActive){ + return requests.get(ApiUrls.ownership_contract_list, isActive); }, fetchLoanPieceRequestList(){ From 2c1ad6dc464fdc34d5496fe9f8ac33c5119b2289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 8 Sep 2015 11:19:11 +0200 Subject: [PATCH 045/192] fix bug in contract settings and expand actionpanel functionality --- .../ascribe_forms/form_create_contract.js | 12 ++-- .../ascribe_settings/contract_settings.js | 64 +++++++++++-------- sass/ascribe_collapsible.scss | 2 +- 3 files changed, 45 insertions(+), 33 deletions(-) diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js index 55a94511..488a2153 100644 --- a/js/components/ascribe_forms/form_create_contract.js +++ b/js/components/ascribe_forms/form_create_contract.js @@ -9,6 +9,8 @@ import InputCheckbox from '../ascribe_forms/input_checkbox'; import GlobalNotificationModel from '../../models/global_notification_model'; import GlobalNotificationActions from '../../actions/global_notification_actions'; +import ContractListActions from '../../actions/contract_list_actions'; + import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader'; import AppConstants from '../../constants/application_constants'; @@ -48,6 +50,9 @@ let CreateContractForm = React.createClass({ handleCreateSuccess(response) { let notification = new GlobalNotificationModel(getLangText('Contract %s successfully created', response.name), 'success', 5000); GlobalNotificationActions.appendGlobalNotification(notification); + + // also refresh contract lists for the rest of the contract settings page + ContractListActions.fetchContractList(); }, @@ -109,7 +114,7 @@ let CreateContractForm = React.createClass({ label={getLangText('Contract name')}> - {' ' + getLangText('I agree to the Terms of Service') + ' '} - ( - {getLangText('read')} - ) + Make contract public (this will replace the current public contract) diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 72d2b233..e34772f2 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -10,54 +10,63 @@ import ContractListActions from '../../actions/contract_list_actions'; import ActionPanel from '../ascribe_panel/action_panel'; -import { getLangText } from '../../utils/lang_utils'; import GlobalNotificationModel from '../../models/global_notification_model'; import GlobalNotificationActions from '../../actions/global_notification_actions'; +import { getLangText } from '../../utils/lang_utils'; + let ContractSettings = React.createClass({ propTypes: { defaultExpanded: React.PropTypes.bool }, + getInitialState(){ return ContractListStore.getState(); }, + componentDidMount() { ContractListStore.listen(this.onChange); ContractListActions.fetchContractList(); }, + componentWillUnmount() { ContractListStore.unlisten(this.onChange); }, + onChange(state) { this.setState(state); }, - makeContractPublic(contract){ - ContractListActions.makeContractPublic(contract) - .then(( ) => ContractListActions.fetchContractList()) - .catch((error)=>{ - let notification = new GlobalNotificationModel(error, 'danger', 10000); - GlobalNotificationActions.appendGlobalNotification(notification); - }); + + makeContractPublic(contract) { + return () => { + ContractListActions.makeContractPublic(contract) + .then(() => ContractListActions.fetchContractList()) + .catch((error) => { + let notification = new GlobalNotificationModel(error, 'success', 10000); + GlobalNotificationActions.appendGlobalNotification(notification); + }); + }; }, - removeContract(contract){ - console.log(contract); - ContractListActions.removeContract(contract.id) - .then(( ) => ContractListActions.fetchContractList()) - .catch((error) => { - console.log('Error', error); - let notification = new GlobalNotificationModel(error, 'danger', 10000); - GlobalNotificationActions.appendGlobalNotification(notification); - }); + + removeContract(contract) { + return () => { + ContractListActions.removeContract(contract.id) + .then(( ) => ContractListActions.fetchContractList()) + .catch((error) => { + let notification = new GlobalNotificationModel(error, 'danger', 10000); + GlobalNotificationActions.appendGlobalNotification(notification); + }); + }; }, + getPublicContracts(){ return this.state.contractList.filter((contract) => contract.public); }, + getPrivateContracts(){ return this.state.contractList.filter((contract) => !contract.public); }, - getblobEndName(contract){ - return contract.blob.match(/.*\/(.*)/)[1]; - }, + render() { let publicContracts = this.getPublicContracts(); let privateContracts = this.getPrivateContracts(); @@ -75,9 +84,10 @@ let ContractSettings = React.createClass({ title={getLangText('Public Contracts')} show={true} defaultExpanded={true}> - {publicContracts.map((contract) => { + {publicContracts.map((contract, i) => { return (
} leftColumnWidth="40%" - rightColumnWidth="60%" - /> + rightColumnWidth="60%"/> ); })} @@ -101,9 +110,10 @@ let ContractSettings = React.createClass({ title={getLangText('Private Contracts')} show={true} defaultExpanded={true}> - {privateContracts.map((contract) => { + {privateContracts.map((contract, i) => { return (
diff --git a/sass/ascribe_collapsible.scss b/sass/ascribe_collapsible.scss index 85fd4270..2b65567c 100644 --- a/sass/ascribe_collapsible.scss +++ b/sass/ascribe_collapsible.scss @@ -28,6 +28,6 @@ /* Shrink the size of the headline for a nested element */ .ascribe-collapsible-wrapper > .ascribe-collapsible-content { padding-left: 1em; - font-size: 90%; + font-size: 95%; } } \ No newline at end of file From 9409af4e1eb3002237816e45fe68c8c202746731 Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 8 Sep 2015 11:35:34 +0200 Subject: [PATCH 046/192] acls on user level for ikonotv --- js/components/whitelabel/wallet/constants/wallet_api_urls.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/components/whitelabel/wallet/constants/wallet_api_urls.js b/js/components/whitelabel/wallet/constants/wallet_api_urls.js index c1b101a1..e0d8a862 100644 --- a/js/components/whitelabel/wallet/constants/wallet_api_urls.js +++ b/js/components/whitelabel/wallet/constants/wallet_api_urls.js @@ -14,7 +14,8 @@ function getWalletApiUrls(subdomain) { else if (subdomain === 'ikonotv'){ return { 'pieces_list': walletConstants.walletApiEndpoint + subdomain + '/pieces/', - 'piece': walletConstants.walletApiEndpoint + subdomain + '/pieces/${piece_id}/' + 'piece': walletConstants.walletApiEndpoint + subdomain + '/pieces/${piece_id}/', + 'user': walletConstants.walletApiEndpoint + subdomain + '/users/' }; } return {}; From ba2ebe81fd341c6493298975680ff6ed26df7da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 8 Sep 2015 11:44:05 +0200 Subject: [PATCH 047/192] code restructuring --- js/actions/contract_list_actions.js | 5 +--- .../ascribe_settings/contract_settings.js | 26 +++++++++++-------- js/utils/general_utils.js | 23 +++++++--------- js/utils/requests.js | 5 ++-- 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/js/actions/contract_list_actions.js b/js/actions/contract_list_actions.js index 307706ef..60144ef6 100644 --- a/js/actions/contract_list_actions.js +++ b/js/actions/contract_list_actions.js @@ -23,8 +23,7 @@ class ContractListActions { }); } - makeContractPublic(contract){ - contract.public = true; + changeContract(contract){ return Q.Promise((resolve, reject) => { OwnershipFetcher.makeContractPublic(contract) .then((res) => { @@ -41,11 +40,9 @@ class ContractListActions { return Q.Promise((resolve, reject) => { OwnershipFetcher.deleteContract(contractId) .then((res) => { - console.log('Contract deleted'); resolve(res); }) .catch( (err) => { - console.log('Error while deleting'); console.logGlobal(err); reject(err); }); diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index e34772f2..c48ca0d7 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -39,10 +39,11 @@ let ContractSettings = React.createClass({ makeContractPublic(contract) { return () => { - ContractListActions.makeContractPublic(contract) + contract.public = true; + ContractListActions.changeContract(contract) .then(() => ContractListActions.fetchContractList()) - .catch((error) => { - let notification = new GlobalNotificationModel(error, 'success', 10000); + .catch((err) => { + let notification = new GlobalNotificationModel(err, 'danger', 10000); GlobalNotificationActions.appendGlobalNotification(notification); }); }; @@ -52,8 +53,8 @@ let ContractSettings = React.createClass({ return () => { ContractListActions.removeContract(contract.id) .then(( ) => ContractListActions.fetchContractList()) - .catch((error) => { - let notification = new GlobalNotificationModel(error, 'danger', 10000); + .catch((err) => { + let notification = new GlobalNotificationModel(err, 'danger', 10000); GlobalNotificationActions.appendGlobalNotification(notification); }); }; @@ -95,8 +96,9 @@ let ContractSettings = React.createClass({ -
@@ -121,12 +123,14 @@ let ContractSettings = React.createClass({ - -
diff --git a/js/utils/general_utils.js b/js/utils/general_utils.js index 673a5509..7717a96a 100644 --- a/js/utils/general_utils.js +++ b/js/utils/general_utils.js @@ -52,19 +52,6 @@ export function sumNumList(l) { return sum; } -export function excludePropFromObject(obj, propList){ - let clonedObj = mergeOptions({},obj); - for (let item in propList){ - console.log(item); - if (clonedObj[propList[item]]){ - console.log('deleting... '); - delete clonedObj[propList[item]]; - } - } - console.log(clonedObj); - return clonedObj; -} - /* Taken from http://stackoverflow.com/a/4795914/1263876 Behaves like C's format string function @@ -207,4 +194,14 @@ function _mergeOptions(obj1, obj2) { */ export function escapeHTML(s) { return document.createElement('div').appendChild(document.createTextNode(s)).parentNode.innerHTML; +} + +export function excludePropFromObject(obj, propList){ + let clonedObj = mergeOptions({}, obj); + for (let item in propList){ + if (clonedObj[propList[item]]){ + delete clonedObj[propList[item]]; + } + } + return clonedObj; } \ No newline at end of file diff --git a/js/utils/requests.js b/js/utils/requests.js index 8e846d7c..c785abf6 100644 --- a/js/utils/requests.js +++ b/js/utils/requests.js @@ -33,7 +33,7 @@ class Requests { // If this is the case, we can not try to parse it as JSON. if(responseText !== 'None') { let body = JSON.parse(responseText); - + if(body && body.errors) { let error = new Error('Form Error'); error.json = body; @@ -134,12 +134,13 @@ class Requests { delete(url, params) { let paramsCopy = this._merge(params); let newUrl = this.prepareUrl(url, paramsCopy, true); + return this.request('delete', newUrl); } _putOrPost(url, paramsAndBody, method){ let paramsCopy = this._merge(paramsAndBody); - let params = excludePropFromObject(paramsAndBody,['body']); + let params = excludePropFromObject(paramsAndBody, ['body']); let newUrl = this.prepareUrl(url, params); let body = null; From a8fce698a63e542a4219da6fc69f1514c8ed89d5 Mon Sep 17 00:00:00 2001 From: Cevo Date: Tue, 8 Sep 2015 11:53:09 +0200 Subject: [PATCH 048/192] createcontract refresh added --- js/actions/contract_list_actions.js | 7 +++---- js/components/ascribe_forms/form_create_contract.js | 5 ++++- js/components/ascribe_settings/contract_settings.js | 8 +++++--- js/fetchers/ownership_fetcher.js | 4 ++-- js/utils/requests.js | 6 ++++-- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/js/actions/contract_list_actions.js b/js/actions/contract_list_actions.js index 307706ef..fd7b01c0 100644 --- a/js/actions/contract_list_actions.js +++ b/js/actions/contract_list_actions.js @@ -24,7 +24,6 @@ class ContractListActions { } makeContractPublic(contract){ - contract.public = true; return Q.Promise((resolve, reject) => { OwnershipFetcher.makeContractPublic(contract) .then((res) => { @@ -38,14 +37,14 @@ class ContractListActions { } removeContract(contractId){ - return Q.Promise((resolve, reject) => { + return Q.Promise( (resolve, reject) => { OwnershipFetcher.deleteContract(contractId) .then((res) => { - console.log('Contract deleted'); + console.log('Success...'); resolve(res); }) .catch( (err) => { - console.log('Error while deleting'); + console.log('Bad news...'); console.logGlobal(err); reject(err); }); diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js index 55a94511..82c80485 100644 --- a/js/components/ascribe_forms/form_create_contract.js +++ b/js/components/ascribe_forms/form_create_contract.js @@ -8,12 +8,14 @@ import InputCheckbox from '../ascribe_forms/input_checkbox'; import GlobalNotificationModel from '../../models/global_notification_model'; import GlobalNotificationActions from '../../actions/global_notification_actions'; - +import ContractListActions from '../../actions/contract_list_actions'; import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader'; import AppConstants from '../../constants/application_constants'; import ApiUrls from '../../constants/api_urls'; + + import { getLangText } from '../../utils/lang_utils'; import { getCookie } from '../../utils/fetch_api_utils'; import { formSubmissionValidation } from '../ascribe_uploader/react_s3_fine_uploader_utils'; @@ -46,6 +48,7 @@ let CreateContractForm = React.createClass({ }, handleCreateSuccess(response) { + ContractListActions.fetchContractList(); let notification = new GlobalNotificationModel(getLangText('Contract %s successfully created', response.name), 'success', 5000); GlobalNotificationActions.appendGlobalNotification(notification); }, diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 880cd744..7b981250 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -33,7 +33,7 @@ let ContractSettings = React.createClass({ }, makeContractPublic(contract){ ContractListActions.makeContractPublic(contract) - .then(( ) => ContractListActions.fetchContractList()) + .then( ( ) => ContractListActions.fetchContractList()) .catch((error)=>{ let notification = new GlobalNotificationModel(error, 'danger', 10000); GlobalNotificationActions.appendGlobalNotification(notification); @@ -42,9 +42,11 @@ let ContractSettings = React.createClass({ removeContract(contract){ console.log(contract); ContractListActions.removeContract(contract.id) - .then(( ) => ContractListActions.fetchContractList()) + .then( + () => { + ContractListActions.fetchContractList(); + }) .catch((error) => { - console.log('Error', error); let notification = new GlobalNotificationModel(error, 'danger', 10000); GlobalNotificationActions.appendGlobalNotification(notification); }); diff --git a/js/fetchers/ownership_fetcher.js b/js/fetchers/ownership_fetcher.js index 07b37bf5..46588c5d 100644 --- a/js/fetchers/ownership_fetcher.js +++ b/js/fetchers/ownership_fetcher.js @@ -24,11 +24,11 @@ let OwnershipFetcher = { }, makeContractPublic(contractObj){ - return requests.put('ownership_csontract', { body: contractObj, contract_id: contractObj.id }); + return requests.put('ownership_contract', { body: contractObj, contract_id: contractObj.id }); }, deleteContract(contractObjId){ - return requests.delete('ownership_contract', {contract_id: contractObjId}); + return requests.delete(ApiUrls.ownership_contract, {contract_id: contractObjId}); } }; diff --git a/js/utils/requests.js b/js/utils/requests.js index 8e846d7c..c66dfd27 100644 --- a/js/utils/requests.js +++ b/js/utils/requests.js @@ -119,7 +119,9 @@ class Requests { return fetch(url, merged) .then(this.unpackResponse) - .catch(this.handleError); + .catch( () => { + this.handleError(); + }); } get(url, params) { @@ -139,7 +141,7 @@ class Requests { _putOrPost(url, paramsAndBody, method){ let paramsCopy = this._merge(paramsAndBody); - let params = excludePropFromObject(paramsAndBody,['body']); + let params = excludePropFromObject(paramsAndBody, ['body']); let newUrl = this.prepareUrl(url, params); let body = null; From 3e1b362cc0a14ef46d9b8cf424049e601552db96 Mon Sep 17 00:00:00 2001 From: Cevo Date: Tue, 8 Sep 2015 13:08:49 +0200 Subject: [PATCH 049/192] remove debugged 204 no response comes as error, handled gracefully --- js/actions/contract_list_actions.js | 8 ++++++-- js/fetchers/ownership_fetcher.js | 3 ++- js/utils/requests.js | 3 --- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/js/actions/contract_list_actions.js b/js/actions/contract_list_actions.js index b6d20b05..4ad25381 100644 --- a/js/actions/contract_list_actions.js +++ b/js/actions/contract_list_actions.js @@ -44,8 +44,12 @@ class ContractListActions { resolve(res); }) .catch( (err) => { - console.logGlobal(err); - reject(err); + if(typeof err === 'undefined') { + resolve(err); + } + else{ + reject(err); + } }); }); } diff --git a/js/fetchers/ownership_fetcher.js b/js/fetchers/ownership_fetcher.js index 46588c5d..baccd45e 100644 --- a/js/fetchers/ownership_fetcher.js +++ b/js/fetchers/ownership_fetcher.js @@ -24,7 +24,8 @@ let OwnershipFetcher = { }, makeContractPublic(contractObj){ - return requests.put('ownership_contract', { body: contractObj, contract_id: contractObj.id }); + console.log(ApiUrls.ownership_contract); + return requests.put(ApiUrls.ownership_contract, { body: contractObj, contract_id: contractObj.id }); }, deleteContract(contractObjId){ diff --git a/js/utils/requests.js b/js/utils/requests.js index 720f184f..459cd480 100644 --- a/js/utils/requests.js +++ b/js/utils/requests.js @@ -116,7 +116,6 @@ class Requests { merged.headers['X-CSRFToken'] = csrftoken; } merged.method = verb; - return fetch(url, merged) .then(this.unpackResponse) .catch( () => { @@ -136,14 +135,12 @@ class Requests { delete(url, params) { let paramsCopy = this._merge(params); let newUrl = this.prepareUrl(url, paramsCopy, true); - return this.request('delete', newUrl); } _putOrPost(url, paramsAndBody, method){ let paramsCopy = this._merge(paramsAndBody); let params = excludePropFromObject(paramsAndBody, ['body']); - let newUrl = this.prepareUrl(url, params); let body = null; if (paramsCopy && paramsCopy.body) { From cb6c4aaf0e4c668242393982c29868b0a461bc89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 8 Sep 2015 14:20:06 +0200 Subject: [PATCH 050/192] integrate acl into navrouteslist + little refactor on those components --- js/components/header.js | 2 +- js/components/nav_routes_links.js | 64 +++++++++++-------- js/components/nav_routes_links_link.js | 49 ++++++++++++++ .../whitelabel/wallet/wallet_routes.js | 2 +- 4 files changed, 89 insertions(+), 28 deletions(-) create mode 100644 js/components/nav_routes_links_link.js diff --git a/js/components/header.js b/js/components/header.js index dcf3c475..0ae18751 100644 --- a/js/components/header.js +++ b/js/components/header.js @@ -110,7 +110,7 @@ let Header = React.createClass({ {getLangText('Log out')} ); - navRoutesLinks = ; + navRoutesLinks = ; } else { account = {getLangText('LOGIN')}; diff --git a/js/components/nav_routes_links.js b/js/components/nav_routes_links.js index 9a266ba8..cb950a95 100644 --- a/js/components/nav_routes_links.js +++ b/js/components/nav_routes_links.js @@ -3,53 +3,63 @@ import React from 'react'; import Nav from 'react-bootstrap/lib/Nav'; -import DropdownButton from 'react-bootstrap/lib/DropdownButton'; -import MenuItemLink from 'react-router-bootstrap/lib/MenuItemLink'; -import NavItemLink from 'react-router-bootstrap/lib/NavItemLink'; + +import NavRoutesLinksLink from './nav_routes_links_link'; + +import AclProxy from './acl_proxy'; import { sanitizeList } from '../utils/general_utils'; let NavRoutesLinks = React.createClass({ propTypes: { - routes: React.PropTypes.element + routes: React.PropTypes.element, + userAcl: React.PropTypes.object }, - extractLinksFromRoutes(node, i) { + extractLinksFromRoutes(node, userAcl, i) { if(!node) { return; } - node = node.props; + let links = node.props.children.map((child, j) => { - let links = node.children.map((child, j) => { + let childrenFn = null; - // check if this a candidate for a link generation - if(child.props.headerTitle && typeof child.props.headerTitle === 'string') { + if(child.props.children && child.props.children.length > 0) { + childrenFn = this.extractLinksFromRoutes(child, userAcl, i++); + } - // also check if it is a candidate for generating a dropdown menu - if(child.props.children && child.props.children.length > 0) { + let { aclName, headerTitle, name, children } = child.props; + if(headerTitle && typeof headerTitle === 'string') { + + if(aclName && typeof aclName !== 'undefined') { return ( - - {this.extractLinksFromRoutes(child, i++)} - - ); - } else if(i === 1) { - // if the node's child is actually a node of level one (a child of a node), we're - // returning a DropdownButton matching MenuItemLink - return ( - {child.props.headerTitle} - ); - } else if(i === 0) { - return ( - {child.props.headerTitle} + + + ); } else { - return null; + return ( + + ); } } else { return null; } + }); // remove all nulls from the list of generated links @@ -57,9 +67,11 @@ let NavRoutesLinks = React.createClass({ }, render() { + let {routes, userAcl} = this.props; + return ( ); } diff --git a/js/components/nav_routes_links_link.js b/js/components/nav_routes_links_link.js new file mode 100644 index 00000000..0e9fa912 --- /dev/null +++ b/js/components/nav_routes_links_link.js @@ -0,0 +1,49 @@ +'use strict'; + +import React from 'react'; + +import DropdownButton from 'react-bootstrap/lib/DropdownButton'; +import MenuItemLink from 'react-router-bootstrap/lib/MenuItemLink'; +import NavItemLink from 'react-router-bootstrap/lib/NavItemLink'; + +let NavRoutesLinksLink = React.createClass({ + propTypes: { + headerTitle: React.PropTypes.string, + routeName: React.PropTypes.string, + + children: React.PropTypes.oneOfType([ + React.PropTypes.arrayOf(React.PropTypes.element), + React.PropTypes.element + ]), + + depth: React.PropTypes.number + }, + + render() { + let { children, headerTitle, depth, routeName } = this.props; + + if(children) { + return ( + + {children} + + ); + } else { + if(depth === 1) { + // if the node's child is actually a node of level one (a child of a node), we're + // returning a DropdownButton matching MenuItemLink + return ( + {headerTitle} + ); + } else if(depth === 0) { + return ( + {headerTitle} + ); + } else { + return null; + } + } + } +}); + +export default NavRoutesLinksLink; \ No newline at end of file diff --git a/js/components/whitelabel/wallet/wallet_routes.js b/js/components/whitelabel/wallet/wallet_routes.js index 1c4ef4a7..f6723a55 100644 --- a/js/components/whitelabel/wallet/wallet_routes.js +++ b/js/components/whitelabel/wallet/wallet_routes.js @@ -71,7 +71,7 @@ let ROUTES = { - + From f850176b7c00587f4348e33d46f1bc150cf54a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 8 Sep 2015 14:26:56 +0200 Subject: [PATCH 051/192] add documentation for nav routes links --- js/components/nav_routes_links.js | 24 +++++++++++++++++++++--- js/components/nav_routes_links_link.js | 2 ++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/js/components/nav_routes_links.js b/js/components/nav_routes_links.js index cb950a95..68fddc55 100644 --- a/js/components/nav_routes_links.js +++ b/js/components/nav_routes_links.js @@ -17,29 +17,47 @@ let NavRoutesLinks = React.createClass({ userAcl: React.PropTypes.object }, + /** + * This method generales a bunch of react-bootstrap specific links + * from the routes we defined in one of the specific routes.js file + * + * We can define a headerTitle as well as a aclName and according to that the + * link will be created for a specific user + * @param {ReactElement} node Starts at the very top of a routes files root + * @param {object} userAcl ACL object we use throughout the whole app + * @param {number} i Depth of the route in comparison to the root + * @return {Array} Array of ReactElements that can be displayed to the user + */ extractLinksFromRoutes(node, userAcl, i) { if(!node) { return; } let links = node.props.children.map((child, j) => { - let childrenFn = null; + let { aclName, headerTitle, name, children } = child.props; + // If the node has children that could be rendered, then we want + // to execute this function again with the child as the root + // + // Otherwise we'll just pass childrenFn as false if(child.props.children && child.props.children.length > 0) { childrenFn = this.extractLinksFromRoutes(child, userAcl, i++); } - let { aclName, headerTitle, name, children } = child.props; + // We validate if the user has set the title correctly, + // otherwise we're not going to render his route if(headerTitle && typeof headerTitle === 'string') { + // if there is an aclName present on the route definition, + // we evaluate it against the user's acl if(aclName && typeof aclName !== 'undefined') { return ( From e892becc5006222e6d88202adcdbe33992debbec Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 8 Sep 2015 14:43:06 +0200 Subject: [PATCH 052/192] contract settings update --- js/components/ascribe_forms/form_contract_agreement.js | 4 +++- js/components/ascribe_settings/contract_settings.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/js/components/ascribe_forms/form_contract_agreement.js b/js/components/ascribe_forms/form_contract_agreement.js index 4079b741..783f6696 100644 --- a/js/components/ascribe_forms/form_contract_agreement.js +++ b/js/components/ascribe_forms/form_contract_agreement.js @@ -56,12 +56,14 @@ let ContractAgreementForm = React.createClass({ }, getFormData(){ - return {'appendix': {'default': this.refs.form.refs.appendix.state.value}}; + return {'appendix': {'default': this.refs.form.refs.appendix.state.value}, + 'contract': this.state.contractList[this.state.selectedContract].id}; }, getContracts() { if (this.state.contractList && this.state.contractList.length > 0) { let contractList = this.state.contractList; + console.log(contractList) return ( { - contract.public = true; + contract.is_public = true; ContractListActions.changeContract(contract) .then(() => ContractListActions.fetchContractList()) .catch((err) => { From a87879dd3d13c4a236a7f72a9dc53ae8bd2e9247 Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 8 Sep 2015 15:06:19 +0200 Subject: [PATCH 053/192] contractSerializer with readonly for update --- js/components/ascribe_settings/contract_settings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index b39d20d1..87c64bf4 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -61,11 +61,11 @@ let ContractSettings = React.createClass({ }, getPublicContracts(){ - return this.state.contractList.filter((contract) => contract.public); + return this.state.contractList.filter((contract) => contract.is_public); }, getPrivateContracts(){ - return this.state.contractList.filter((contract) => !contract.public); + return this.state.contractList.filter((contract) => !contract.is_public); }, render() { From 17f7be925710483a9bdd45b70978aab305ecf4d1 Mon Sep 17 00:00:00 2001 From: diminator Date: Wed, 9 Sep 2015 11:11:16 +0200 Subject: [PATCH 054/192] contract list make public --- js/actions/contract_list_actions.js | 8 ++------ .../ascribe_forms/form_contract_agreement.js | 3 +-- .../ascribe_forms/form_create_contract.js | 8 ++++---- .../ascribe_settings/contract_settings.js | 19 ++++++++++++++----- js/fetchers/ownership_fetcher.js | 1 - 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/js/actions/contract_list_actions.js b/js/actions/contract_list_actions.js index 5248203f..aaee33c6 100644 --- a/js/actions/contract_list_actions.js +++ b/js/actions/contract_list_actions.js @@ -44,12 +44,8 @@ class ContractListActions { resolve(res); }) .catch( (err) => { - if(typeof err === 'undefined') { - resolve(err); - } - else{ - reject(err); - } + console.logGlobal(err); + reject(err); }); }); } diff --git a/js/components/ascribe_forms/form_contract_agreement.js b/js/components/ascribe_forms/form_contract_agreement.js index 783f6696..c2f2b810 100644 --- a/js/components/ascribe_forms/form_contract_agreement.js +++ b/js/components/ascribe_forms/form_contract_agreement.js @@ -56,8 +56,7 @@ let ContractAgreementForm = React.createClass({ }, getFormData(){ - return {'appendix': {'default': this.refs.form.refs.appendix.state.value}, - 'contract': this.state.contractList[this.state.selectedContract].id}; + return {'appendix': {'default': this.refs.form.refs.appendix.state.value}}; }, getContracts() { diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js index 69404055..ee26adfc 100644 --- a/js/components/ascribe_forms/form_create_contract.js +++ b/js/components/ascribe_forms/form_create_contract.js @@ -50,12 +50,12 @@ let CreateContractForm = React.createClass({ }, handleCreateSuccess(response) { - ContractListActions.fetchContractList(); + ContractListActions.fetchContractList({is_active: 'True'}); let notification = new GlobalNotificationModel(getLangText('Contract %s successfully created', response.name), 'success', 5000); GlobalNotificationActions.appendGlobalNotification(notification); - - // also refresh contract lists for the rest of the contract settings page - ContractListActions.fetchContractList(); + // + //// also refresh contract lists for the rest of the contract settings page + //ContractListActions.fetchContractList(); }, diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 87c64bf4..278c4c1b 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -26,7 +26,7 @@ let ContractSettings = React.createClass({ componentDidMount() { ContractListStore.listen(this.onChange); - ContractListActions.fetchContractList(); + ContractListActions.fetchContractList({is_active: 'True'}); }, componentWillUnmount() { @@ -41,22 +41,31 @@ let ContractSettings = React.createClass({ return () => { contract.is_public = true; ContractListActions.changeContract(contract) - .then(() => ContractListActions.fetchContractList()) + .then(() => { + ContractListActions.fetchContractList({is_active: 'True'}); + let notification = getLangText('Contract %s is now public', contract.name); + notification = new GlobalNotificationModel(notification, 'success', 4000); + GlobalNotificationActions.appendGlobalNotification(notification); + }) .catch((err) => { let notification = new GlobalNotificationModel(err, 'danger', 10000); GlobalNotificationActions.appendGlobalNotification(notification); - }); + }); }; }, removeContract(contract) { return () => { ContractListActions.removeContract(contract.id) - .then(( ) => ContractListActions.fetchContractList()) + .then((response) => { + ContractListActions.fetchContractList({is_active: 'True'}); + let notification = new GlobalNotificationModel(response.notification, 'success', 4000); + GlobalNotificationActions.appendGlobalNotification(notification); + }) .catch((err) => { let notification = new GlobalNotificationModel(err, 'danger', 10000); GlobalNotificationActions.appendGlobalNotification(notification); - }); + }); }; }, diff --git a/js/fetchers/ownership_fetcher.js b/js/fetchers/ownership_fetcher.js index 02990f3a..c0d32d71 100644 --- a/js/fetchers/ownership_fetcher.js +++ b/js/fetchers/ownership_fetcher.js @@ -24,7 +24,6 @@ let OwnershipFetcher = { }, makeContractPublic(contractObj){ - console.log(ApiUrls.ownership_contract); return requests.put(ApiUrls.ownership_contract, { body: contractObj, contract_id: contractObj.id }); }, From ec2ae39e15565bbfe1ed52fad2759e89b55cbae0 Mon Sep 17 00:00:00 2001 From: diminator Date: Wed, 9 Sep 2015 13:53:03 +0200 Subject: [PATCH 055/192] contractagreement with PUT instead of PATCH --- js/components/ascribe_forms/form.js | 14 ++++++++++++++ .../ascribe_forms/form_contract_agreement.js | 8 ++++---- .../ikonotv/ikonotv_contract_notifications.js | 1 + js/utils/requests.js | 4 ++++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/js/components/ascribe_forms/form.js b/js/components/ascribe_forms/form.js index d0117251..16ad4020 100644 --- a/js/components/ascribe_forms/form.js +++ b/js/components/ascribe_forms/form.js @@ -93,6 +93,20 @@ let Form = React.createClass({ .catch(this.handleError); }, + put() { + requests + .put(this.props.url, { body: this.getFormData() }) + .then(this.handleSuccess) + .catch(this.handleError); + }, + + patch() { + requests + .patch(this.props.url, { body: this.getFormData() }) + .then(this.handleSuccess) + .catch(this.handleError); + }, + delete() { requests .delete(this.props.url, this.getFormData()) diff --git a/js/components/ascribe_forms/form_contract_agreement.js b/js/components/ascribe_forms/form_contract_agreement.js index c2f2b810..9aad8827 100644 --- a/js/components/ascribe_forms/form_contract_agreement.js +++ b/js/components/ascribe_forms/form_contract_agreement.js @@ -50,8 +50,9 @@ let ContractAgreementForm = React.createClass({ this.setState({selectedContract: event.target.selectedIndex}); }, - handleSubmitSuccess(response) { - let notification = new GlobalNotificationModel(response.notification, 'success', 10000); + handleSubmitSuccess() { + let notification = 'Contract agreement send'; + notification = new GlobalNotificationModel(notification, 'success', 10000); GlobalNotificationActions.appendGlobalNotification(notification); }, @@ -62,7 +63,6 @@ let ContractAgreementForm = React.createClass({ getContracts() { if (this.state.contractList && this.state.contractList.length > 0) { let contractList = this.state.contractList; - console.log(contractList) return ( diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js index db369564..274eea5c 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js @@ -128,6 +128,7 @@ let IkonotvContractNotifications = React.createClass({ ref='form' url={requests.prepareUrl(apiUrls.ownership_contract_agreements_confirm, {contract_agreement_id: contractAgreement.id})} handleSuccess={this.handleConfirmSuccess} + method='put' buttons={

diff --git a/js/utils/requests.js b/js/utils/requests.js index 459cd480..b36351a2 100644 --- a/js/utils/requests.js +++ b/js/utils/requests.js @@ -157,6 +157,10 @@ class Requests { return this._putOrPost(url, params, 'put'); } + patch(url, params){ + return this._putOrPost(url, params, 'patch'); + } + defaults(options) { this.httpOptions = options.http || {}; this.urlMap = options.urlMap || {}; From ecb51ca5e74bb6bd00155f4209c47bc8f70fa5ac Mon Sep 17 00:00:00 2001 From: diminator Date: Wed, 9 Sep 2015 14:15:00 +0200 Subject: [PATCH 056/192] added appendix --- .../ikonotv/ikonotv_contract_notifications.js | 11 +++++++++-- sass/ascribe_notification_page.scss | 15 +++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js index 274eea5c..e7e2d851 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js @@ -76,7 +76,9 @@ let IkonotvContractNotifications = React.createClass({

); @@ -90,7 +92,7 @@ let IkonotvContractNotifications = React.createClass({ handleDeny() { let contractAgreement = this.state.contractAgreementListNotifications[0].contract_agreement; - requests.post(apiUrls.ownership_contract_agreements_deny, {contract_agreement_id: contractAgreement.id}).then( + requests.put(apiUrls.ownership_contract_agreements_deny, {contract_agreement_id: contractAgreement.id}).then( () => this.handleDenySuccess() ); }, @@ -116,7 +118,12 @@ let IkonotvContractNotifications = React.createClass({
{this.displayContract()} +
+

{getLangText('Appendix')}

+
+                                {contractAgreement.appendix.default}
+                            

{getLangText('Are you a member of any copyright societies?')}

ARS, DACS, Bildkunst, Pictoright, SODRAC, Copyright Agency/Viscopy, SAVA, Bildrecht GmbH, diff --git a/sass/ascribe_notification_page.scss b/sass/ascribe_notification_page.scss index f7cccbde..ad277aed 100644 --- a/sass/ascribe_notification_page.scss +++ b/sass/ascribe_notification_page.scss @@ -40,12 +40,23 @@ .notification-contract-footer { text-align: left; padding: 1em; - h1 { + > h1 { margin-top: 0.4em; font-size: 1.4em; } - p { + > p { font-size: 0.9em; color: #444444; } + > pre { + color: #444; + cursor: default; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + background-color: rgba(0, 0, 0, 0); + border: 0; + box-shadow: none; + margin-bottom: 1em; + padding-left: 0; + width: 100%; + } } \ No newline at end of file From 1c5b0c7172e5674ed773ffd06c5c619c332ac5b5 Mon Sep 17 00:00:00 2001 From: diminator Date: Wed, 9 Sep 2015 19:29:58 +0200 Subject: [PATCH 057/192] only one agreement pending agreement notifications per subdomain (only by whitelabel owner) --- .../ascribe_forms/form_contract_agreement.js | 1 + .../ascribe_forms/form_create_contract.js | 8 +++--- js/components/ascribe_forms/property.js | 6 ++-- .../ikonotv/ikonotv_contract_notifications.js | 28 +++++++++++++------ js/utils/requests.js | 4 +-- 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/js/components/ascribe_forms/form_contract_agreement.js b/js/components/ascribe_forms/form_contract_agreement.js index 9aad8827..0c20383c 100644 --- a/js/components/ascribe_forms/form_contract_agreement.js +++ b/js/components/ascribe_forms/form_contract_agreement.js @@ -54,6 +54,7 @@ let ContractAgreementForm = React.createClass({ let notification = 'Contract agreement send'; notification = new GlobalNotificationModel(notification, 'success', 10000); GlobalNotificationActions.appendGlobalNotification(notification); + this.refs.form.reset(); }, getFormData(){ diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js index ee26adfc..9cf97db7 100644 --- a/js/components/ascribe_forms/form_create_contract.js +++ b/js/components/ascribe_forms/form_create_contract.js @@ -53,15 +53,14 @@ let CreateContractForm = React.createClass({ ContractListActions.fetchContractList({is_active: 'True'}); let notification = new GlobalNotificationModel(getLangText('Contract %s successfully created', response.name), 'success', 5000); GlobalNotificationActions.appendGlobalNotification(notification); - // - //// also refresh contract lists for the rest of the contract settings page - //ContractListActions.fetchContractList(); + this.refs.form.reset(); }, render() { return (

diff --git a/js/components/ascribe_forms/property.js b/js/components/ascribe_forms/property.js index cfc4c4d9..90aa0490 100644 --- a/js/components/ascribe_forms/property.js +++ b/js/components/ascribe_forms/property.js @@ -90,8 +90,10 @@ let Property = React.createClass({ // maybe do reset by reload instead of front end state? this.setState({value: this.state.initialValue}); - // resets the value of a custom react component input - this.refs.input.state.value = this.state.initialValue; + if (this.refs.input.state && this.refs.input.state.value) { + // resets the value of a custom react component input + this.refs.input.state.value = this.state.initialValue; + } // resets the value of a plain HTML5 input this.refs.input.getDOMNode().value = this.state.initialValue; diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js index e7e2d851..6a63657c 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js @@ -53,7 +53,7 @@ let IkonotvContractNotifications = React.createClass({ this.setState(state); }, - displayContract(){ + getContract(){ let notifications = this.state.contractAgreementListNotifications[0]; let blob = notifications.contract_agreement.contract.blob; if (blob.mime === 'pdf') { @@ -62,7 +62,7 @@ let IkonotvContractNotifications = React.createClass({ - {this.displayContract()} + {this.getContract()}
-

{getLangText('Appendix')}

-
-                                {contractAgreement.appendix.default}
-                            
+ {this.getAppendix}

{getLangText('Are you a member of any copyright societies?')}

ARS, DACS, Bildkunst, Pictoright, SODRAC, Copyright Agency/Viscopy, SAVA, Bildrecht GmbH, diff --git a/js/utils/requests.js b/js/utils/requests.js index b36351a2..fd676896 100644 --- a/js/utils/requests.js +++ b/js/utils/requests.js @@ -118,9 +118,7 @@ class Requests { merged.method = verb; return fetch(url, merged) .then(this.unpackResponse) - .catch( () => { - this.handleError(); - }); + .catch(this.handleError); } get(url, params) { From 12e7c2c89809c2882f3cbe3cbfba561bf88367bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Thu, 10 Sep 2015 15:47:27 +0200 Subject: [PATCH 058/192] add download button to contract list --- .../ascribe_settings/contract_settings.js | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 278c4c1b..06584a8d 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -105,6 +105,12 @@ let ContractSettings = React.createClass({ + + DOWNLOAD + - + + + DOWNLOAD + +

} leftColumnWidth="40%" From 01ebee87ec4c5a0b6c14fe4d16c76f5b27245a54 Mon Sep 17 00:00:00 2001 From: diminator Date: Thu, 10 Sep 2015 17:46:50 +0200 Subject: [PATCH 059/192] form loan edit --- js/components/ascribe_forms/form_loan.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index 34a4cfae..44a24ad2 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -71,9 +71,9 @@ let LoanForm = React.createClass({ handleOnChange(event) { // event.target.value is the submitted email of the loanee if(event && event.target && event.target.value && event.target.value.match(/.*@.*/)) { - LoanContractActions.fetchLoanContract(event.target.value); + ContractActions.fetchContract(event.target.value); } else { - LoanContractActions.flushLoanContract(); + ContractActions.flushContract(); } }, From b45c68b2dc43871aa62eeb210127f5b907e85b89 Mon Sep 17 00:00:00 2001 From: diminator Date: Thu, 10 Sep 2015 18:54:25 +0200 Subject: [PATCH 060/192] Merge remote-tracking branch 'remotes/origin/AD-885-convert-roles-to-acls' into AD-924-apply-contractagreements-to-loan- Conflicts: ownership/serializers.py --- js/components/acl_proxy.js | 21 ++++++++++++------- js/components/nav_routes_links.js | 1 - .../whitelabel/wallet/wallet_routes.js | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/js/components/acl_proxy.js b/js/components/acl_proxy.js index be0d8466..10a7516e 100644 --- a/js/components/acl_proxy.js +++ b/js/components/acl_proxy.js @@ -20,21 +20,28 @@ let AclProxy = React.createClass({ show: React.PropTypes.bool }, - render() { - if(this.props.show) { + getChildren() { + if (this.props.children.length && this.props.children.length > 1){ + /* + This might ruin styles for header items in the navbar etc + */ return ( {this.props.children} ); + } + /* can only do this when there is only 1 child, but will preserve styles */ + return this.props.children; + }, + + render() { + if(this.props.show) { + return this.getChildren(); } else { if(this.props.aclObject) { if(this.props.aclObject[this.props.aclName]) { - return ( - - {this.props.children} - - ); + return this.getChildren(); } else { /* if(typeof this.props.aclObject[this.props.aclName] === 'undefined') { console.warn('The aclName you\'re filtering for was not present (or undefined) in the aclObject.'); diff --git a/js/components/nav_routes_links.js b/js/components/nav_routes_links.js index 68fddc55..d3342cb8 100644 --- a/js/components/nav_routes_links.js +++ b/js/components/nav_routes_links.js @@ -48,7 +48,6 @@ let NavRoutesLinks = React.createClass({ // We validate if the user has set the title correctly, // otherwise we're not going to render his route if(headerTitle && typeof headerTitle === 'string') { - // if there is an aclName present on the route definition, // we evaluate it against the user's acl if(aclName && typeof aclName !== 'undefined') { diff --git a/js/components/whitelabel/wallet/wallet_routes.js b/js/components/whitelabel/wallet/wallet_routes.js index f333e6bb..25fc1d80 100644 --- a/js/components/whitelabel/wallet/wallet_routes.js +++ b/js/components/whitelabel/wallet/wallet_routes.js @@ -72,7 +72,7 @@ let ROUTES = { - + From 23eb3a7fd9cc5f0322b19e091f3913f3ef7caf0f Mon Sep 17 00:00:00 2001 From: diminator Date: Thu, 10 Sep 2015 20:20:42 +0200 Subject: [PATCH 061/192] Fetch contractagreements, order them and filter by accepted or pending Merge remote-tracking branch 'remotes/origin/AD-885-convert-roles-to-acls' into AD-924-apply-contractagreements-to-loan- Conflicts: ownership/serializers.py --- js/actions/contract_agreement_list_actions.js | 40 +++++++++++++++++++ js/components/ascribe_forms/form_loan.js | 32 ++++++++++----- js/fetchers/ownership_fetcher.js | 12 ++++++ js/stores/contract_agreement_list_store.js | 22 ++++++++++ 4 files changed, 95 insertions(+), 11 deletions(-) create mode 100644 js/actions/contract_agreement_list_actions.js create mode 100644 js/stores/contract_agreement_list_store.js diff --git a/js/actions/contract_agreement_list_actions.js b/js/actions/contract_agreement_list_actions.js new file mode 100644 index 00000000..2c34be65 --- /dev/null +++ b/js/actions/contract_agreement_list_actions.js @@ -0,0 +1,40 @@ +'use strict'; + +import alt from '../alt'; +import Q from 'q'; + +import OwnershipFetcher from '../fetchers/ownership_fetcher'; + + +class ContractAgreementListActions { + constructor() { + this.generateActions( + 'updateContractAgreementList', + 'flushContractAgreementList' + ); + } + + fetchContractAgreementList(issuer, accepted, pending) { + return Q.Promise((resolve, reject) => { + OwnershipFetcher.fetchContractAgreementList(issuer, accepted, pending) + .then((contractAgreementList) => { + if (contractAgreementList.count > 0) { + this.actions.updateContractAgreementList(contractAgreementList.results); + } + else { + this.actions.updateContractAgreementList(null); + } + resolve(); + }) + .catch((err) => { + console.logGlobal(err); + this.actions.updateContractAgreementList(null); + reject(err); + }); + } + ); + } + +} + +export default alt.createActions(ContractAgreementListActions); diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index 44a24ad2..a307acae 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -12,8 +12,8 @@ import InputTextAreaToggable from './input_textarea_toggable'; import InputDate from './input_date'; import InputCheckbox from './input_checkbox'; -import ContractStore from '../../stores/contract_store'; -import ContractActions from '../../actions/contract_actions'; +import ContractAgreementListStore from '../../stores/contract_agreement_list_store'; +import ContractAgreementListActions from '../../actions/contract_agreement_list_actions'; import AppConstants from '../../constants/application_constants'; @@ -48,16 +48,24 @@ let LoanForm = React.createClass({ }, getInitialState() { - return ContractStore.getState(); + return ContractAgreementListStore.getState(); }, componentDidMount() { - ContractStore.listen(this.onChange); - ContractActions.flushContract.defer(); + ContractAgreementListStore.listen(this.onChange); + if (this.props.email){ + ContractAgreementListActions.fetchContractAgreementList( + this.props.email, 'True', null); + } + + /* @Tim: + throws Uncaught TypeError: Cannot read property 'defer' of undefined + We might not need this + ContractAgreementListActions.flushContractAgreementList().defer();*/ }, componentWillUnmount() { - ContractStore.unlisten(this.onChange); + ContractAgreementListStore.unlisten(this.onChange); }, onChange(state) { @@ -71,17 +79,19 @@ let LoanForm = React.createClass({ handleOnChange(event) { // event.target.value is the submitted email of the loanee if(event && event.target && event.target.value && event.target.value.match(/.*@.*/)) { - ContractActions.fetchContract(event.target.value); + ContractAgreementListActions.fetchContractAgreementList(event.target.value, 'True', null); } else { - ContractActions.flushContract(); + ContractAgreementListActions.flushContractAgreementList(); } }, getContractCheckbox() { - if(this.state.contractKey && this.state.contractUrl) { + if(this.state.contractAgreementList && this.state.contractAgreementList.length > 0) { // we need to define a key on the InputCheckboxes as otherwise // react is not rerendering them on a store switch and is keeping // the default value of the component (which is in that case true) + let contract = this.state.contractAgreementList[0].contract; + return ( {getLangText('I agree to the')}  - - {getLangText('terms of')} {this.state.contractEmail} + + {getLangText('terms of')} {contract.issuer}
diff --git a/js/fetchers/ownership_fetcher.js b/js/fetchers/ownership_fetcher.js index c0d32d71..6738a59f 100644 --- a/js/fetchers/ownership_fetcher.js +++ b/js/fetchers/ownership_fetcher.js @@ -19,6 +19,18 @@ let OwnershipFetcher = { return requests.get(ApiUrls.ownership_contract_list, isActive); }, + /** + * Fetch the contractagreement between the logged-in user and the email from the API. + */ + fetchContractAgreementList(issuer, accepted, pending) { + let queryParams = { + issuer, + accepted, + pending + }; + return requests.get(ApiUrls.ownership_contract_agreements, queryParams); + }, + fetchLoanPieceRequestList(){ return requests.get(ApiUrls.ownership_loans_pieces_request); }, diff --git a/js/stores/contract_agreement_list_store.js b/js/stores/contract_agreement_list_store.js new file mode 100644 index 00000000..ca1d8e6b --- /dev/null +++ b/js/stores/contract_agreement_list_store.js @@ -0,0 +1,22 @@ +'use strict'; + +import alt from '../alt'; +import ContractAgreementListActions from '../actions/contract_agreement_list_actions'; + + +class ContractAgreementListStore { + constructor() { + this.contractAgreementList = null; + this.bindActions(ContractAgreementListActions); + } + + onUpdateContractAgreementList(contractAgreementList) { + this.contractAgreementList = contractAgreementList; + } + + onFlushContractAgreementList() { + this.contractAgreementList = null; + } +} + +export default alt.createStore(ContractAgreementListStore, 'ContractAgreementListStore'); From c8ece4c532fe18be6d126f1fca23f9da02368ee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 11 Sep 2015 10:11:07 +0200 Subject: [PATCH 062/192] refactor contract creation form --- .../ascribe_forms/form_create_contract.js | 44 +++---------------- .../ascribe_forms/form_register_piece.js | 16 ++++++- .../ascribe_forms/input_fineuploader.js | 26 ++++++----- 3 files changed, 35 insertions(+), 51 deletions(-) diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js index 9cf97db7..d0e160a3 100644 --- a/js/components/ascribe_forms/form_create_contract.js +++ b/js/components/ascribe_forms/form_create_contract.js @@ -11,38 +11,23 @@ import GlobalNotificationActions from '../../actions/global_notification_actions import ContractListActions from '../../actions/contract_list_actions'; -import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader'; - import AppConstants from '../../constants/application_constants'; import ApiUrls from '../../constants/api_urls'; - +import InputFineUploader from './input_fineuploader'; import { getLangText } from '../../utils/lang_utils'; -import { getCookie } from '../../utils/fetch_api_utils'; import { formSubmissionValidation } from '../ascribe_uploader/react_s3_fine_uploader_utils'; + let CreateContractForm = React.createClass({ getInitialState() { return { - contractKey: null, isUploadReady: false }; }, - getFormData(){ - return { - blob: this.state.contractKey - }; - }, - - submitKey(key) { - this.setState({ - contractKey: key - }); - }, - setIsUploadReady(isReady) { this.setState({ isUploadReady: isReady @@ -62,7 +47,6 @@ let CreateContractForm = React.createClass({ }> - + isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile} /> - Make contract public (this will replace the current public contract) + {getLangText('Make contract public (this will replace the current public contract')} diff --git a/js/components/ascribe_forms/form_register_piece.js b/js/components/ascribe_forms/form_register_piece.js index 8f2666c0..dab0b251 100644 --- a/js/components/ascribe_forms/form_register_piece.js +++ b/js/components/ascribe_forms/form_register_piece.js @@ -10,10 +10,11 @@ import Property from './property'; import InputFineUploader from './input_fineuploader'; import ApiUrls from '../../constants/api_urls'; +import AppConstants from '../../constants/application_constants'; import { getLangText } from '../../utils/lang_utils'; import { mergeOptions } from '../../utils/general_utils'; -import { isReadyForFormSubmission } from '../ascribe_uploader/react_s3_fine_uploader_utils'; +import { formSubmissionValidation } from '../ascribe_uploader/react_s3_fine_uploader_utils'; let RegisterPieceForm = React.createClass({ @@ -99,8 +100,19 @@ let RegisterPieceForm = React.createClass({ name="digital_work_key" ignoreFocus={true}> Date: Fri, 11 Sep 2015 18:23:31 +0200 Subject: [PATCH 063/192] create public agreement --- js/actions/contract_actions.js | 47 ---------------- js/actions/contract_agreement_list_actions.js | 54 +++++++++++++++++-- js/actions/contract_list_actions.js | 22 ++++---- js/components/ascribe_forms/form_loan.js | 8 +-- js/fetchers/ownership_fetcher.js | 17 +++++- js/stores/contract_store.js | 28 ---------- 6 files changed, 78 insertions(+), 98 deletions(-) delete mode 100644 js/actions/contract_actions.js delete mode 100644 js/stores/contract_store.js diff --git a/js/actions/contract_actions.js b/js/actions/contract_actions.js deleted file mode 100644 index d1bf1432..00000000 --- a/js/actions/contract_actions.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -import alt from '../alt'; -import OwnershipFetcher from '../fetchers/ownership_fetcher'; - - -class ContractActions { - constructor() { - this.generateActions( - 'updateContract', - 'flushContract' - ); - } - - fetchContract(email) { - if(email.match(/.+\@.+\..+/)) { - OwnershipFetcher.fetchContract(email) - .then((contracts) => { - if (contracts && contracts.length > 0) { - this.actions.updateContract({ - contractKey: contracts[0].s3Key, - contractUrl: contracts[0].s3Url, - contractEmail: email - }); - } - else { - this.actions.updateContract({ - contractKey: null, - contractUrl: null, - contractEmail: null - }); - } - }) - .catch((err) => { - console.logGlobal(err); - this.actions.updateContract({ - contractKey: null, - contractUrl: null, - contractEmail: null - }); - }); - } - } - -} - -export default alt.createActions(ContractActions); diff --git a/js/actions/contract_agreement_list_actions.js b/js/actions/contract_agreement_list_actions.js index 2c34be65..4f5ff7d6 100644 --- a/js/actions/contract_agreement_list_actions.js +++ b/js/actions/contract_agreement_list_actions.js @@ -4,7 +4,7 @@ import alt from '../alt'; import Q from 'q'; import OwnershipFetcher from '../fetchers/ownership_fetcher'; - +import ContractListActions from './contract_list_actions'; class ContractAgreementListActions { constructor() { @@ -16,25 +16,69 @@ class ContractAgreementListActions { fetchContractAgreementList(issuer, accepted, pending) { return Q.Promise((resolve, reject) => { + this.actions.updateContractAgreementList(null); OwnershipFetcher.fetchContractAgreementList(issuer, accepted, pending) .then((contractAgreementList) => { if (contractAgreementList.count > 0) { this.actions.updateContractAgreementList(contractAgreementList.results); + resolve(contractAgreementList.results); } - else { - this.actions.updateContractAgreementList(null); + else{ + resolve(null); } - resolve(); }) .catch((err) => { console.logGlobal(err); - this.actions.updateContractAgreementList(null); reject(err); }); } ); } + fetchAvailableContractAgreementList(issuer){ + this.actions.fetchContractAgreementList(issuer, 'True', null) + .then((contractAgreementListAccepted) => { + if (!contractAgreementListAccepted) { + // fetch pending agreements if no accepted ones + return this.actions.fetchContractAgreementList(issuer, null, 'True'); + } + }).then((contractAgreementListPending) => { + // fetch public contract if no accepted nor pending agreements + if (!contractAgreementListPending) { + return ContractListActions.fetchContractList(null, null, issuer); + } + }).then((publicContract) => { + // create an agreement with the public contract if there is one + if (publicContract && publicContract.length > 0) { + return this.actions.createContractAgreement(null, publicContract[0]); + } + else { + /* + contractAgreementList in the store is already set to null; + */ + } + }).then((publicContracAgreement) => { + if (publicContracAgreement) { + this.actions.updateContractAgreementList([publicContracAgreement]); + } + }).catch((err) => { + console.logGlobal(err); + }); + } + + createContractAgreement(issuer, contract){ + return Q.Promise((resolve, reject) => { + OwnershipFetcher.createContractAgreement(issuer, contract).then( + (contractAgreement) => { + resolve(contractAgreement); + } + ).catch((err) => { + console.logGlobal(err); + reject(err); + }); + }); + } + } export default alt.createActions(ContractAgreementListActions); diff --git a/js/actions/contract_list_actions.js b/js/actions/contract_list_actions.js index aaee33c6..a856fb2b 100644 --- a/js/actions/contract_list_actions.js +++ b/js/actions/contract_list_actions.js @@ -12,15 +12,19 @@ class ContractListActions { ); } - fetchContractList(isActive) { - OwnershipFetcher.fetchContractList(isActive) - .then((contracts) => { - this.actions.updateContractList(contracts.results); - }) - .catch((err) => { - console.logGlobal(err); - this.actions.updateContractList([]); - }); + fetchContractList(isActive, isPublic, issuer) { + return Q.Promise((resolve, reject) => { + OwnershipFetcher.fetchContractList(isActive, isPublic, issuer) + .then((contracts) => { + this.actions.updateContractList(contracts.results); + resolve(contracts.results); + }) + .catch((err) => { + console.logGlobal(err); + this.actions.updateContractList([]); + reject(err); + }); + }); } diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index a307acae..29d0ecd4 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -54,14 +54,8 @@ let LoanForm = React.createClass({ componentDidMount() { ContractAgreementListStore.listen(this.onChange); if (this.props.email){ - ContractAgreementListActions.fetchContractAgreementList( - this.props.email, 'True', null); + ContractAgreementListActions.fetchAvailableContractAgreementList.defer(this.props.email); } - - /* @Tim: - throws Uncaught TypeError: Cannot read property 'defer' of undefined - We might not need this - ContractAgreementListActions.flushContractAgreementList().defer();*/ }, componentWillUnmount() { diff --git a/js/fetchers/ownership_fetcher.js b/js/fetchers/ownership_fetcher.js index 6738a59f..fde66c7d 100644 --- a/js/fetchers/ownership_fetcher.js +++ b/js/fetchers/ownership_fetcher.js @@ -15,8 +15,21 @@ let OwnershipFetcher = { /** * Fetch the contracts of the logged-in user from the API. */ - fetchContractList(isActive){ - return requests.get(ApiUrls.ownership_contract_list, isActive); + fetchContractList(isActive, isPublic, issuer){ + let queryParams = { + isActive, + isPublic, + issuer + }; + return requests.get(ApiUrls.ownership_contract_list, queryParams); + }, + + + /** + * Create a contractagreement between the logged-in user and the email from the API with contract. + */ + createContractAgreement(signee, contractObj){ + return requests.post(ApiUrls.ownership_contract_agreements, { body: {signee: signee, contract: contractObj.id }}); }, /** diff --git a/js/stores/contract_store.js b/js/stores/contract_store.js deleted file mode 100644 index 623bec6a..00000000 --- a/js/stores/contract_store.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict'; - -import alt from '../alt'; -import ContractActions from '../actions/contract_actions'; - - -class ContractStore { - constructor() { - this.contractKey = null; - this.contractUrl = null; - this.contractEmail = null; - this.bindActions(ContractActions); - } - - onUpdateContract({contractKey, contractUrl, contractEmail}) { - this.contractKey = contractKey; - this.contractUrl = contractUrl; - this.contractEmail = contractEmail; - } - - onFlushContract() { - this.contractKey = null; - this.contractUrl = null; - this.contractEmail = null; - } -} - -export default alt.createStore(ContractStore, 'ContractStore'); From 7fd5516b797e51cd1ef73c16f7568d950d9e3147 Mon Sep 17 00:00:00 2001 From: diminator Date: Mon, 14 Sep 2015 14:16:53 +0200 Subject: [PATCH 064/192] contract, contractagreement migration contractagreement added to loanpiece --- .../ascribe_forms/form_contract_agreement.js | 2 +- .../ascribe_forms/form_create_contract.js | 2 +- js/components/ascribe_forms/form_loan.js | 15 +++++++++++++-- .../ascribe_settings/contract_settings.js | 6 +++--- .../ascribe_buttons/ikonotv_submit_button.js | 16 +--------------- 5 files changed, 19 insertions(+), 22 deletions(-) diff --git a/js/components/ascribe_forms/form_contract_agreement.js b/js/components/ascribe_forms/form_contract_agreement.js index 0c20383c..887b99db 100644 --- a/js/components/ascribe_forms/form_contract_agreement.js +++ b/js/components/ascribe_forms/form_contract_agreement.js @@ -35,7 +35,7 @@ let ContractAgreementForm = React.createClass({ componentDidMount() { ContractListStore.listen(this.onChange); - ContractListActions.fetchContractList({is_active: 'True'}); + ContractListActions.fetchContractList({is_active: true}); }, componentWillUnmount() { diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js index 9cf97db7..b275df03 100644 --- a/js/components/ascribe_forms/form_create_contract.js +++ b/js/components/ascribe_forms/form_create_contract.js @@ -50,7 +50,7 @@ let CreateContractForm = React.createClass({ }, handleCreateSuccess(response) { - ContractListActions.fetchContractList({is_active: 'True'}); + ContractListActions.fetchContractList({is_active: true}); let notification = new GlobalNotificationModel(getLangText('Contract %s successfully created', response.name), 'success', 5000); GlobalNotificationActions.appendGlobalNotification(notification); this.refs.form.reset(); diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index 29d0ecd4..6de68142 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -17,6 +17,7 @@ import ContractAgreementListActions from '../../actions/contract_agreement_list_ import AppConstants from '../../constants/application_constants'; +import { mergeOptions } from '../../utils/general_utils'; import { getLangText } from '../../utils/lang_utils'; @@ -67,7 +68,10 @@ let LoanForm = React.createClass({ }, getFormData(){ - return this.props.id; + return mergeOptions( + this.props.id, + this.getContractAgreementId() + ); }, handleOnChange(event) { @@ -79,6 +83,13 @@ let LoanForm = React.createClass({ } }, + getContractAgreementId() { + if (this.state.contractAgreementList && this.state.contractAgreementList.length > 0) { + return {'contract_agreement_id': this.state.contractAgreementList[0].id}; + } + return null; + }, + getContractCheckbox() { if(this.state.contractAgreementList && this.state.contractAgreementList.length > 0) { // we need to define a key on the InputCheckboxes as otherwise @@ -97,7 +108,7 @@ let LoanForm = React.createClass({ {getLangText('I agree to the')}  - {getLangText('terms of')} {contract.issuer} + {getLangText('terms of ')} {contract.issuer} diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 278c4c1b..b79f77f1 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -26,7 +26,7 @@ let ContractSettings = React.createClass({ componentDidMount() { ContractListStore.listen(this.onChange); - ContractListActions.fetchContractList({is_active: 'True'}); + ContractListActions.fetchContractList({is_active: true}); }, componentWillUnmount() { @@ -42,7 +42,7 @@ let ContractSettings = React.createClass({ contract.is_public = true; ContractListActions.changeContract(contract) .then(() => { - ContractListActions.fetchContractList({is_active: 'True'}); + ContractListActions.fetchContractList({is_active: true}); let notification = getLangText('Contract %s is now public', contract.name); notification = new GlobalNotificationModel(notification, 'success', 4000); GlobalNotificationActions.appendGlobalNotification(notification); @@ -58,7 +58,7 @@ let ContractSettings = React.createClass({ return () => { ContractListActions.removeContract(contract.id) .then((response) => { - ContractListActions.fetchContractList({is_active: 'True'}); + ContractListActions.fetchContractList({is_active: true}); let notification = new GlobalNotificationModel(response.notification, 'success', 4000); GlobalNotificationActions.appendGlobalNotification(notification); }) diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js index 41b47a82..4b7f3dbc 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js @@ -50,21 +50,7 @@ let IkonotvSubmitButton = React.createClass({ enddate={enddate} gallery="IkonoTV archive" showPersonalMessage={false} - handleSuccess={this.props.handleSuccess}> - - - - {' ' + getLangText('I agree to the Terms of Service of IkonoTV Archive') + ' '} - ( - {getLangText('read')} - ) - - - - + handleSuccess={this.props.handleSuccess} /> ); From 73c2a7c544fadcfc30040b9c4c5df649fb16208f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 14 Sep 2015 14:46:03 +0200 Subject: [PATCH 065/192] rename fineuploader's submitKey method to submitFile --- js/components/ascribe_detail/further_details.js | 6 +++--- .../ascribe_detail/further_details_fileuploader.js | 4 ++-- .../ascribe_forms/form_create_contract.js | 2 +- js/components/ascribe_forms/input_fineuploader.js | 6 +++--- .../ascribe_uploader/react_s3_fine_uploader.js | 14 +++++++------- .../ascribe_forms/cyland_additional_data_form.js | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/js/components/ascribe_detail/further_details.js b/js/components/ascribe_detail/further_details.js index 863ed491..db241f3d 100644 --- a/js/components/ascribe_detail/further_details.js +++ b/js/components/ascribe_detail/further_details.js @@ -38,9 +38,9 @@ let FurtherDetails = React.createClass({ GlobalNotificationActions.appendGlobalNotification(notification); }, - submitKey(key){ + submitFile(file){ this.setState({ - otherDataKey: key + otherDataKey: file.key }); }, @@ -78,7 +78,7 @@ let FurtherDetails = React.createClass({ extraData={this.props.extraData} />
diff --git a/js/components/ascribe_forms/input_fineuploader.js b/js/components/ascribe_forms/input_fineuploader.js index ebbaccfc..3bef7ccd 100644 --- a/js/components/ascribe_forms/input_fineuploader.js +++ b/js/components/ascribe_forms/input_fineuploader.js @@ -43,9 +43,9 @@ let InputFileUploader = React.createClass({ }; }, - submitKey(key){ + submitFile(file){ this.setState({ - value: key + value: file.key }); }, @@ -69,7 +69,7 @@ let InputFileUploader = React.createClass({ keyRoutine={this.props.keyRoutine} createBlobRoutine={this.props.createBlobRoutine} validation={this.props.validation} - submitKey={this.submitKey} + submitFile={this.submitFile} setIsUploadReady={this.props.setIsUploadReady} isReadyForFormSubmission={this.props.isReadyForFormSubmission} areAssetsDownloadable={false} diff --git a/js/components/ascribe_uploader/react_s3_fine_uploader.js b/js/components/ascribe_uploader/react_s3_fine_uploader.js index fe6f2611..5b27cb90 100644 --- a/js/components/ascribe_uploader/react_s3_fine_uploader.js +++ b/js/components/ascribe_uploader/react_s3_fine_uploader.js @@ -36,7 +36,7 @@ var ReactS3FineUploader = React.createClass({ React.PropTypes.number ]) }), - submitKey: React.PropTypes.func, + submitFile: React.PropTypes.func, autoUpload: React.PropTypes.bool, debug: React.PropTypes.bool, objectProperties: React.PropTypes.shape({ @@ -393,12 +393,12 @@ var ReactS3FineUploader = React.createClass({ // Only after the blob has been created server-side, we can make the form submittable. this.createBlob(files[id]) .then(() => { - // since the form validation props isReadyForFormSubmission, setIsUploadReady and submitKey + // since the form validation props isReadyForFormSubmission, setIsUploadReady and submitFile // are optional, we'll only trigger them when they're actually defined - if(this.props.submitKey) { - this.props.submitKey(files[id].key); + if(this.props.submitFile) { + this.props.submitFile(files[id]); } else { - console.warn('You didn\'t define submitKey in as a prop in react-s3-fine-uploader'); + console.warn('You didn\'t define submitFile in as a prop in react-s3-fine-uploader'); } // for explanation, check comment of if statement above @@ -458,7 +458,7 @@ var ReactS3FineUploader = React.createClass({ let notification = new GlobalNotificationModel(getLangText('File upload canceled'), 'success', 5000); GlobalNotificationActions.appendGlobalNotification(notification); - // since the form validation props isReadyForFormSubmission, setIsUploadReady and submitKey + // since the form validation props isReadyForFormSubmission, setIsUploadReady and submitFile // are optional, we'll only trigger them when they're actually defined if(this.props.isReadyForFormSubmission && this.props.setIsUploadReady) { if(this.props.isReadyForFormSubmission(this.state.filesToUpload)) { @@ -524,7 +524,7 @@ var ReactS3FineUploader = React.createClass({ GlobalNotificationActions.appendGlobalNotification(notification); } - // since the form validation props isReadyForFormSubmission, setIsUploadReady and submitKey + // since the form validation props isReadyForFormSubmission, setIsUploadReady and submitFile // are optional, we'll only trigger them when they're actually defined if(this.props.isReadyForFormSubmission && this.props.setIsUploadReady) { // also, lets check if after the completion of this upload, diff --git a/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js b/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js index 13e731ef..123ad2b7 100644 --- a/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js +++ b/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js @@ -112,7 +112,7 @@ let CylandAdditionalDataForm = React.createClass({ Date: Mon, 14 Sep 2015 16:15:01 +0200 Subject: [PATCH 066/192] make contract creation implicit --- .../ascribe_forms/form_create_contract.js | 47 +++++++------------ .../ascribe_forms/input_fineuploader.js | 9 +++- .../react_s3_fine_uploader.js | 5 +- 3 files changed, 28 insertions(+), 33 deletions(-) diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js index 7b71d293..614480a7 100644 --- a/js/components/ascribe_forms/form_create_contract.js +++ b/js/components/ascribe_forms/form_create_contract.js @@ -24,7 +24,8 @@ let CreateContractForm = React.createClass({ getInitialState() { return { - isUploadReady: false + isUploadReady: false, + contractName: '' }; }, @@ -41,30 +42,25 @@ let CreateContractForm = React.createClass({ this.refs.form.reset(); }, + submitFileName(fileName) { + this.setState({ + contractName: fileName + }); + + this.refs.form.submit(); + }, render() { return ( - {getLangText('Create new contract')} - - } - spinner={ - - - - }> + handleSuccess={this.handleCreateSuccess}> + label="Contract file (*.pdf)"> + label={getLangText('Contract name')} + hidden={true}> - - - - - {getLangText('Make contract public (this will replace the current public contract')} - - + value={this.state.contractName}/> ); diff --git a/js/components/ascribe_forms/input_fineuploader.js b/js/components/ascribe_forms/input_fineuploader.js index 3bef7ccd..d0c3410b 100644 --- a/js/components/ascribe_forms/input_fineuploader.js +++ b/js/components/ascribe_forms/input_fineuploader.js @@ -12,6 +12,8 @@ let InputFileUploader = React.createClass({ propTypes: { setIsUploadReady: React.PropTypes.func, isReadyForFormSubmission: React.PropTypes.func, + submitFileName: React.PropTypes.func, + onClick: React.PropTypes.func, keyRoutine: React.PropTypes.shape({ url: React.PropTypes.string, @@ -22,7 +24,8 @@ let InputFileUploader = React.createClass({ }), validation: React.PropTypes.shape({ itemLimit: React.PropTypes.number, - sizeLimit: React.PropTypes.string + sizeLimit: React.PropTypes.string, + allowedExtensions: React.PropTypes.arrayOf(React.PropTypes.string) }), // isFineUploaderActive is used to lock react fine uploader in case @@ -47,6 +50,10 @@ let InputFileUploader = React.createClass({ this.setState({ value: file.key }); + + if(typeof this.props.submitFileName === 'function') { + this.props.submitFileName(file.originalName); + } }, reset() { diff --git a/js/components/ascribe_uploader/react_s3_fine_uploader.js b/js/components/ascribe_uploader/react_s3_fine_uploader.js index 5b27cb90..e5609c60 100644 --- a/js/components/ascribe_uploader/react_s3_fine_uploader.js +++ b/js/components/ascribe_uploader/react_s3_fine_uploader.js @@ -83,7 +83,8 @@ var ReactS3FineUploader = React.createClass({ }), validation: React.PropTypes.shape({ itemLimit: React.PropTypes.number, - sizeLimit: React.PropTypes.string + sizeLimit: React.PropTypes.string, + allowedExtensions: React.PropTypes.arrayOf(React.PropTypes.string) }), messages: React.PropTypes.shape({ unsupportedBrowser: React.PropTypes.string @@ -433,7 +434,7 @@ var ReactS3FineUploader = React.createClass({ }); this.state.uploader.cancelAll(); - let notification = new GlobalNotificationModel(this.props.defaultErrorMessage, 'danger', 5000); + let notification = new GlobalNotificationModel(errorReason || this.props.defaultErrorMessage, 'danger', 5000); GlobalNotificationActions.appendGlobalNotification(notification); }, From d47ead1bff917aebd87075f405757af23b200334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 14 Sep 2015 16:33:32 +0200 Subject: [PATCH 067/192] add fileclassToUpload to react fineuploader --- .../ascribe_forms/form_create_contract.js | 6 +++++- .../ascribe_forms/input_fineuploader.js | 12 ++++++++++-- .../ascribe_uploader/file_drag_and_drop.js | 12 ++++++++++-- .../file_drag_and_drop_dialog.js | 17 ++++++++++++----- .../ascribe_uploader/react_s3_fine_uploader.js | 18 +++++++++++++++--- 5 files changed, 52 insertions(+), 13 deletions(-) diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js index 614480a7..23916c67 100644 --- a/js/components/ascribe_forms/form_create_contract.js +++ b/js/components/ascribe_forms/form_create_contract.js @@ -77,7 +77,11 @@ let CreateContractForm = React.createClass({ areAssetsEditable={true} submitFile={this.submitFile} setIsUploadReady={this.setIsUploadReady} - isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile} /> + isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile} + fileClassToUpload={{ + singular: 'contract', + plural: 'contracts' + }}/> + enableLocalHashing={this.props.enableLocalHashing} + fileClassToUpload={this.props.fileClassToUpload}/> ); } }); diff --git a/js/components/ascribe_uploader/file_drag_and_drop.js b/js/components/ascribe_uploader/file_drag_and_drop.js index 7d6c8a66..9de22d3d 100644 --- a/js/components/ascribe_uploader/file_drag_and_drop.js +++ b/js/components/ascribe_uploader/file_drag_and_drop.js @@ -37,7 +37,14 @@ let FileDragAndDrop = React.createClass({ hashingProgress: React.PropTypes.number, // sets the value of this.state.hashingProgress in reactfineuploader // to -1 which is code for: aborted - handleCancelHashing: React.PropTypes.func + handleCancelHashing: React.PropTypes.func, + + // A class of a file the user has to upload + // Needs to be defined both in singular as well as in plural + fileClassToUpload: React.PropTypes.shape({ + singular: React.PropTypes.string, + plural: React.PropTypes.string + }) }, handleDragStart(event) { @@ -192,7 +199,8 @@ let FileDragAndDrop = React.createClass({ multipleFiles={this.props.multiple} hasFiles={hasFiles} onClick={this.handleOnClick} - enableLocalHashing={this.props.enableLocalHashing}/> + enableLocalHashing={this.props.enableLocalHashing} + fileClassToUpload={this.props.fileClassToUpload}/> -

{getLangText('Drag files here')}

+

{getLangText('Drag %s here', this.props.fileClassToUpload.plural)}

{getLangText('or')}

- {getLangText('choose files to upload')} + {getLangText('choose %s to upload', this.props.fileClassToUpload.plural)} ); } else { - let dialog = queryParams.method === 'hash' ? getLangText('choose a file to hash') : getLangText('choose a file to upload'); + let dialog = queryParams.method === 'hash' ? getLangText('choose a %s to hash', this.props.fileClassToUpload.singular) : getLangText('choose a file to upload'); return ( -

{getLangText('Drag a file here')}

+

{getLangText('Drag a %s here', this.props.fileClassToUpload.singular)}

{getLangText('or')}

+ enableLocalHashing={this.props.enableLocalHashing} + fileClassToUpload={this.props.fileClassToUpload}/>
); } From 209d141939e323312806fe0f381c03cf11998fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 14 Sep 2015 17:02:47 +0200 Subject: [PATCH 068/192] extend fileClassToUpload functionality and implement it in contract settings --- .../ascribe_forms/form_create_contract.js | 25 ++++++++++++---- .../ascribe_forms/input_fineuploader.js | 2 +- .../ascribe_settings/contract_settings.js | 29 ++++++++++++++----- .../file_drag_and_drop_dialog.js | 2 +- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js index 23916c67..c91e97f0 100644 --- a/js/components/ascribe_forms/form_create_contract.js +++ b/js/components/ascribe_forms/form_create_contract.js @@ -4,7 +4,6 @@ import React from 'react'; import Form from '../ascribe_forms/form'; import Property from '../ascribe_forms/property'; -import InputCheckbox from '../ascribe_forms/input_checkbox'; import GlobalNotificationModel from '../../models/global_notification_model'; import GlobalNotificationActions from '../../actions/global_notification_actions'; @@ -21,6 +20,16 @@ import { formSubmissionValidation } from '../ascribe_uploader/react_s3_fine_uplo let CreateContractForm = React.createClass({ + propTypes: { + isPublic: React.PropTypes.bool, + + // A class of a file the user has to upload + // Needs to be defined both in singular as well as in plural + fileClassToUpload: React.PropTypes.shape({ + singular: React.PropTypes.string, + plural: React.PropTypes.string + }) + }, getInitialState() { return { @@ -58,7 +67,7 @@ let CreateContractForm = React.createClass({ handleSuccess={this.handleCreateSuccess}> + label="Contract file (*.pdf only)"> + fileClassToUpload={this.props.fileClassToUpload}/> + ); } diff --git a/js/components/ascribe_forms/input_fineuploader.js b/js/components/ascribe_forms/input_fineuploader.js index 4fa89ef8..82d6bf92 100644 --- a/js/components/ascribe_forms/input_fineuploader.js +++ b/js/components/ascribe_forms/input_fineuploader.js @@ -103,7 +103,7 @@ let InputFileUploader = React.createClass({ } }} onInactive={this.props.onLoggedOut} - enableLocalHashing={this.props.enableLocalHashing} + enableLocalHashing={this.props.enableLocalHashing} fileClassToUpload={this.props.fileClassToUpload}/> ); } diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 06584a8d..ed07e33f 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -80,6 +80,18 @@ let ContractSettings = React.createClass({ render() { let publicContracts = this.getPublicContracts(); let privateContracts = this.getPrivateContracts(); + let createPublicContractForm = null; + + if(publicContracts.length === 0) { + createPublicContractForm = ( + + ); + } return ( + {createPublicContractForm} {publicContracts.map((contract, i) => { return ( - DOWNLOAD + PREVIEW - - PREVIEW - - -
- } - leftColumnWidth="40%" - rightColumnWidth="60%"/> - ); - })} - - - - {privateContracts.map((contract, i) => { - return ( - - - - - PREVIEW - - - - } - leftColumnWidth="40%" - rightColumnWidth="60%"/> - ); - })} - + {createPublicContractForm} + {publicContracts.map((contract, i) => { + return ( + + + + PREVIEW + + + + } + leftColumnWidth="40%" + rightColumnWidth="60%"/> + ); + })} + + + + {privateContracts.map((contract, i) => { + return ( + + + + + PREVIEW + + + + } + leftColumnWidth="40%" + rightColumnWidth="60%"/> + ); + })} ); diff --git a/js/components/ascribe_settings/settings_container.js b/js/components/ascribe_settings/settings_container.js index 485b26d7..2d2440bf 100644 --- a/js/components/ascribe_settings/settings_container.js +++ b/js/components/ascribe_settings/settings_container.js @@ -26,8 +26,6 @@ let SettingsContainer = React.createClass({ -
-
); } diff --git a/js/components/ascribe_uploader/file_drag_and_drop_preview_other.js b/js/components/ascribe_uploader/file_drag_and_drop_preview_other.js index 1d948572..205eb177 100644 --- a/js/components/ascribe_uploader/file_drag_and_drop_preview_other.js +++ b/js/components/ascribe_uploader/file_drag_and_drop_preview_other.js @@ -59,7 +59,7 @@ let FileDragAndDropPreviewOther = React.createClass({
{actionSymbol} - {'.' + this.props.type} +

{'.' + this.props.type}

diff --git a/sass/ascribe_collapsible.scss b/sass/ascribe_collapsible.scss index 2b65567c..99b03f60 100644 --- a/sass/ascribe_collapsible.scss +++ b/sass/ascribe_collapsible.scss @@ -24,9 +24,8 @@ background: none; border: 0; width: 100%; - - /* Shrink the size of the headline for a nested element */ - .ascribe-collapsible-wrapper > .ascribe-collapsible-content { + + .ascribe-collapsible-wrapper { padding-left: 1em; font-size: 95%; } From 0ce298879ba98aeae9c74201e9c33ec9d395b1c2 Mon Sep 17 00:00:00 2001 From: diminator Date: Mon, 14 Sep 2015 17:53:50 +0200 Subject: [PATCH 070/192] fixed tests refactored contractagreement actions --- js/actions/contract_agreement_list_actions.js | 34 ++++++++++++------- js/components/ascribe_forms/form_loan.js | 22 ++++++++---- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/js/actions/contract_agreement_list_actions.js b/js/actions/contract_agreement_list_actions.js index 4f5ff7d6..94f292c5 100644 --- a/js/actions/contract_agreement_list_actions.js +++ b/js/actions/contract_agreement_list_actions.js @@ -36,18 +36,28 @@ class ContractAgreementListActions { } fetchAvailableContractAgreementList(issuer){ - this.actions.fetchContractAgreementList(issuer, 'True', null) - .then((contractAgreementListAccepted) => { - if (!contractAgreementListAccepted) { - // fetch pending agreements if no accepted ones - return this.actions.fetchContractAgreementList(issuer, null, 'True'); - } - }).then((contractAgreementListPending) => { - // fetch public contract if no accepted nor pending agreements - if (!contractAgreementListPending) { - return ContractListActions.fetchContractList(null, null, issuer); - } - }).then((publicContract) => { + return Q.Promise((resolve, reject) => { + this.actions.fetchContractAgreementList(issuer, 'True', null) + .then((contractAgreementListAccepted) => { + if (!contractAgreementListAccepted) { + // fetch pending agreements if no accepted ones + return this.actions.fetchContractAgreementList(issuer, null, 'True'); + } + else { + resolve(contractAgreementListAccepted); + } + }).then((contractAgreementListPending) => { + resolve(contractAgreementListPending); + }).catch((err) => { + console.logGlobal(err); + reject(err); + }); + }); + } + + createContractAgreementFromPublicContract(issuer){ + ContractListActions.fetchContractList(null, null, issuer) + .then((publicContract) => { // create an agreement with the public contract if there is one if (publicContract && publicContract.length > 0) { return this.actions.createContractAgreement(null, publicContract[0]); diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index 6de68142..8e83ca34 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -54,9 +54,7 @@ let LoanForm = React.createClass({ componentDidMount() { ContractAgreementListStore.listen(this.onChange); - if (this.props.email){ - ContractAgreementListActions.fetchAvailableContractAgreementList.defer(this.props.email); - } + this.getContractAgreementsOrCreatePublic(this.props.email); }, componentWillUnmount() { @@ -67,6 +65,18 @@ let LoanForm = React.createClass({ this.setState(state); }, + getContractAgreementsOrCreatePublic(email){ + if (email) { + ContractAgreementListActions.fetchAvailableContractAgreementList(email).then( + (contractAgreementList) => { + if (!contractAgreementList) { + ContractAgreementListActions.createContractAgreementFromPublicContract.defer(email); + } + } + ); + } + }, + getFormData(){ return mergeOptions( this.props.id, @@ -76,8 +86,8 @@ let LoanForm = React.createClass({ handleOnChange(event) { // event.target.value is the submitted email of the loanee - if(event && event.target && event.target.value && event.target.value.match(/.*@.*/)) { - ContractAgreementListActions.fetchContractAgreementList(event.target.value, 'True', null); + if(event && event.target && event.target.value && event.target.value.match(/.*@.*\..*/)) { + this.getContractAgreementsOrCreatePublic(event.target.value); } else { ContractAgreementListActions.flushContractAgreementList(); } @@ -172,8 +182,8 @@ let LoanForm = React.createClass({ Date: Tue, 15 Sep 2015 09:12:30 +0200 Subject: [PATCH 071/192] cyland loanform --- .../components/cyland/cyland_register_piece.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js b/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js index 3768adab..6e8a77c3 100644 --- a/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js +++ b/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js @@ -222,21 +222,7 @@ let CylandRegisterPiece = React.createClass({ showStartDate={false} showEndDate={false} showPersonalMessage={false} - handleSuccess={this.handleLoanSuccess}> - - - - {' ' + getLangText('I agree to the Terms of Service of Cyland Archive') + ' '} - ( - {getLangText('read')} - ) - - - - + handleSuccess={this.handleLoanSuccess} /> From 280f3bc73ac7b9a549ac349f006ccbb8ca14c196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 15 Sep 2015 10:15:56 +0200 Subject: [PATCH 072/192] Add input filter for specific file extensions to react fineuploader --- .../ascribe_forms/form_create_contract.js | 2 +- .../ascribe_uploader/file_drag_and_drop.js | 70 ++++++++++++++----- .../react_s3_fine_uploader.js | 3 +- 3 files changed, 56 insertions(+), 19 deletions(-) diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js index c91e97f0..f7f81e74 100644 --- a/js/components/ascribe_forms/form_create_contract.js +++ b/js/components/ascribe_forms/form_create_contract.js @@ -67,7 +67,7 @@ let CreateContractForm = React.createClass({ handleSuccess={this.handleCreateSuccess}> + label={getLangText('Contract file (*.pdf only, max. 50MB per contract)')}> file.status !== 'deleted' && file.status !== 'canceled' && file.size !== -1).length > 0; - let className = hasFiles ? 'has-files ' : ''; - className += this.props.dropzoneInactive ? 'inactive-dropzone' : 'active-dropzone'; - className += this.props.className ? ' ' + this.props.className : ''; + let hasFiles = filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled' && file.size !== -1).length > 0; + let updatedClassName = hasFiles ? 'has-files ' : ''; + updatedClassName += dropzoneInactive ? 'inactive-dropzone' : 'active-dropzone'; + updatedClassName += className ? ' ' + className : ''; // if !== -2: triggers a FileDragAndDrop-global spinner - if(this.props.hashingProgress !== -2) { + if(hashingProgress !== -2) { return (

{getLangText('Computing hash(es)... This may take a few minutes.')}

- {Math.ceil(this.props.hashingProgress)}% - {getLangText('Cancel hashing')} + {Math.ceil(hashingProgress)}% + {getLangText('Cancel hashing')}

- +
); } else { + let accept = ''; + + /** + * Fineuploader allows to specify the file extensions that are allowed to upload. + * For our self defined input, we can reuse those declarations to restrict which files + * the user can pick from his hard drive. + */ + if(validation && validation.allowedExtensions.length > 0) { + // add a dot in front of the extension + let prefixedAllowedExtensions = validation.allowedExtensions.map((ext) => '.' + ext); + + // generate a comma separated list to add them to the DOM element + // See: http://stackoverflow.com/questions/4328947/limit-file-format-when-using-input-type-file + accept = prefixedAllowedExtensions.join(', '); + } + return (
+ enableLocalHashing={enableLocalHashing} + fileClassToUpload={fileClassToUpload}/> + areAssetsDownloadable={areAssetsDownloadable} + areAssetsEditable={areAssetsEditable}/> + onChange={this.handleDrop} + accept={accept}/>
); } diff --git a/js/components/ascribe_uploader/react_s3_fine_uploader.js b/js/components/ascribe_uploader/react_s3_fine_uploader.js index f422b509..8429499f 100644 --- a/js/components/ascribe_uploader/react_s3_fine_uploader.js +++ b/js/components/ascribe_uploader/react_s3_fine_uploader.js @@ -840,7 +840,8 @@ var ReactS3FineUploader = React.createClass({ dropzoneInactive={this.isDropzoneInactive()} hashingProgress={this.state.hashingProgress} enableLocalHashing={this.props.enableLocalHashing} - fileClassToUpload={this.props.fileClassToUpload}/> + fileClassToUpload={this.props.fileClassToUpload} + validation={this.props.validation}/> ); } From 8b1193f05b9c39425db6068e241993792a6b75b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 15 Sep 2015 10:43:45 +0200 Subject: [PATCH 073/192] implement template functionality for react fineuploader --- .../react_s3_fine_uploader.js | 64 ++++++++++++------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/js/components/ascribe_uploader/react_s3_fine_uploader.js b/js/components/ascribe_uploader/react_s3_fine_uploader.js index 8429499f..2bc28c09 100644 --- a/js/components/ascribe_uploader/react_s3_fine_uploader.js +++ b/js/components/ascribe_uploader/react_s3_fine_uploader.js @@ -118,7 +118,12 @@ var ReactS3FineUploader = React.createClass({ fileClassToUpload: React.PropTypes.shape({ singular: React.PropTypes.string, plural: React.PropTypes.string - }) + }), + + // Uploading functionality of react fineuploader is disconnected from its UI + // layer, which means that literally every (properly adjusted) react element + // can handle the UI handling. + fileInputElement: React.PropTypes.func }, mixins: [Router.State], @@ -174,7 +179,8 @@ var ReactS3FineUploader = React.createClass({ fileClassToUpload: { singular: getLangText('file'), plural: getLangText('files') - } + }, + fileInputElement: FileDragAndDrop }; }, @@ -822,28 +828,38 @@ var ReactS3FineUploader = React.createClass({ }, render() { - return ( -
- -
- ); + let { + multiple, + areAssetsDownloadable, + areAssetsEditable, + onInactive, + enableLocalHashing, + fileClassToUpload, + validation, + fileInputElement + } = this.props; + + // Here we initialize the template that has been either provided from the outside + // or the default input that is FileDragAndDrop. + return React.createElement(fileInputElement, { + className: 'file-drag-and-drop', + onDrop: this.handleUploadFile, + filesToUpload: this.state.filesToUpload, + handleDeleteFile: this.handleDeleteFile, + handleCancelFile: this.handleCancelFile, + handlePauseFile: this.handlePauseFile, + handleResumeFile: this.handleResumeFile, + handleCancelHashing: this.handleCancelHashing, + multiple: multiple, + areAssetsDownloadable: areAssetsDownloadable, + areAssetsEditable: areAssetsEditable, + onInactive: onInactive, + dropzoneInactive: this.isDropzoneInactive(), + hashingProgress: this.state.hashingProgress, + enableLocalHashing: enableLocalHashing, + fileClassToUpload: fileClassToUpload, + validation: validation + }); } }); From c08f46bd69ada48d24f8961447014a1723e10a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 15 Sep 2015 11:13:17 +0200 Subject: [PATCH 074/192] separate FileDragAndDrop component --- .../{ => ascribe_file_drag_and_drop}/file_drag_and_drop.js | 4 ++-- .../file_drag_and_drop_dialog.js | 2 +- .../file_drag_and_drop_preview.js | 2 +- .../file_drag_and_drop_preview_image.js | 4 ++-- .../file_drag_and_drop_preview_iterator.js | 0 .../file_drag_and_drop_preview_other.js | 4 ++-- js/components/ascribe_uploader/react_s3_fine_uploader.js | 3 +-- 7 files changed, 9 insertions(+), 10 deletions(-) rename js/components/ascribe_uploader/{ => ascribe_file_drag_and_drop}/file_drag_and_drop.js (98%) rename js/components/ascribe_uploader/{ => ascribe_file_drag_and_drop}/file_drag_and_drop_dialog.js (98%) rename js/components/ascribe_uploader/{ => ascribe_file_drag_and_drop}/file_drag_and_drop_preview.js (98%) rename js/components/ascribe_uploader/{ => ascribe_file_drag_and_drop}/file_drag_and_drop_preview_image.js (95%) rename js/components/ascribe_uploader/{ => ascribe_file_drag_and_drop}/file_drag_and_drop_preview_iterator.js (100%) rename js/components/ascribe_uploader/{ => ascribe_file_drag_and_drop}/file_drag_and_drop_preview_other.js (95%) diff --git a/js/components/ascribe_uploader/file_drag_and_drop.js b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js similarity index 98% rename from js/components/ascribe_uploader/file_drag_and_drop.js rename to js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js index 478522a4..b6b5b218 100644 --- a/js/components/ascribe_uploader/file_drag_and_drop.js +++ b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js @@ -6,7 +6,7 @@ import ProgressBar from 'react-progressbar'; import FileDragAndDropDialog from './file_drag_and_drop_dialog'; import FileDragAndDropPreviewIterator from './file_drag_and_drop_preview_iterator'; -import { getLangText } from '../../utils/lang_utils'; +import { getLangText } from '../../../utils/lang_utils'; // Taken from: https://github.com/fedosejev/react-file-drag-and-drop let FileDragAndDrop = React.createClass({ @@ -189,7 +189,7 @@ let FileDragAndDrop = React.createClass({ let hasFiles = filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled' && file.size !== -1).length > 0; let updatedClassName = hasFiles ? 'has-files ' : ''; updatedClassName += dropzoneInactive ? 'inactive-dropzone' : 'active-dropzone'; - updatedClassName += className ? ' ' + className : ''; + updatedClassName += ' file-drag-and-drop'; // if !== -2: triggers a FileDragAndDrop-global spinner if(hashingProgress !== -2) { diff --git a/js/components/ascribe_uploader/file_drag_and_drop_dialog.js b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_dialog.js similarity index 98% rename from js/components/ascribe_uploader/file_drag_and_drop_dialog.js rename to js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_dialog.js index c34e6bdc..769a0f0d 100644 --- a/js/components/ascribe_uploader/file_drag_and_drop_dialog.js +++ b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_dialog.js @@ -3,7 +3,7 @@ import React from 'react'; import Router from 'react-router'; -import { getLangText } from '../../utils/lang_utils'; +import { getLangText } from '../../../utils/lang_utils'; let Link = Router.Link; diff --git a/js/components/ascribe_uploader/file_drag_and_drop_preview.js b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview.js similarity index 98% rename from js/components/ascribe_uploader/file_drag_and_drop_preview.js rename to js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview.js index 9c6cdbdd..e08f02b0 100644 --- a/js/components/ascribe_uploader/file_drag_and_drop_preview.js +++ b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview.js @@ -4,7 +4,7 @@ import React from 'react'; import FileDragAndDropPreviewImage from './file_drag_and_drop_preview_image'; import FileDragAndDropPreviewOther from './file_drag_and_drop_preview_other'; -import { getLangText } from '../../utils/lang_utils.js'; +import { getLangText } from '../../../utils/lang_utils'; let FileDragAndDropPreview = React.createClass({ diff --git a/js/components/ascribe_uploader/file_drag_and_drop_preview_image.js b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview_image.js similarity index 95% rename from js/components/ascribe_uploader/file_drag_and_drop_preview_image.js rename to js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview_image.js index f4b61760..8268f9ac 100644 --- a/js/components/ascribe_uploader/file_drag_and_drop_preview_image.js +++ b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview_image.js @@ -3,8 +3,8 @@ import React from 'react'; import ProgressBar from 'react-progressbar'; -import AppConstants from '../../constants/application_constants'; -import { getLangText } from '../../utils/lang_utils.js'; +import AppConstants from '../../../constants/application_constants'; +import { getLangText } from '../../../utils/lang_utils'; let FileDragAndDropPreviewImage = React.createClass({ propTypes: { diff --git a/js/components/ascribe_uploader/file_drag_and_drop_preview_iterator.js b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview_iterator.js similarity index 100% rename from js/components/ascribe_uploader/file_drag_and_drop_preview_iterator.js rename to js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview_iterator.js diff --git a/js/components/ascribe_uploader/file_drag_and_drop_preview_other.js b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview_other.js similarity index 95% rename from js/components/ascribe_uploader/file_drag_and_drop_preview_other.js rename to js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview_other.js index 205eb177..24b33da7 100644 --- a/js/components/ascribe_uploader/file_drag_and_drop_preview_other.js +++ b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview_other.js @@ -3,8 +3,8 @@ import React from 'react'; import ProgressBar from 'react-progressbar'; -import AppConstants from '../../constants/application_constants'; -import { getLangText } from '../../utils/lang_utils.js'; +import AppConstants from '../../../constants/application_constants'; +import { getLangText } from '../../../utils/lang_utils'; let FileDragAndDropPreviewOther = React.createClass({ propTypes: { diff --git a/js/components/ascribe_uploader/react_s3_fine_uploader.js b/js/components/ascribe_uploader/react_s3_fine_uploader.js index 2bc28c09..5d7b69ff 100644 --- a/js/components/ascribe_uploader/react_s3_fine_uploader.js +++ b/js/components/ascribe_uploader/react_s3_fine_uploader.js @@ -10,7 +10,7 @@ import { getLangText } from '../../utils/lang_utils'; import S3Fetcher from '../../fetchers/s3_fetcher'; import fineUploader from 'fineUploader'; -import FileDragAndDrop from './file_drag_and_drop'; +import FileDragAndDrop from './ascribe_file_drag_and_drop/file_drag_and_drop'; import GlobalNotificationModel from '../../models/global_notification_model'; import GlobalNotificationActions from '../../actions/global_notification_actions'; @@ -842,7 +842,6 @@ var ReactS3FineUploader = React.createClass({ // Here we initialize the template that has been either provided from the outside // or the default input that is FileDragAndDrop. return React.createElement(fileInputElement, { - className: 'file-drag-and-drop', onDrop: this.handleUploadFile, filesToUpload: this.state.filesToUpload, handleDeleteFile: this.handleDeleteFile, From c5ef3cacd51984450ef62e21d2504175ba45b1d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 15 Sep 2015 11:50:23 +0200 Subject: [PATCH 075/192] add ContractSettingsUpdateButton boilerplate code --- js/components/ascribe_forms/property.js | 2 +- .../ascribe_settings/contract_settings.js | 8 ++++---- .../contract_settings_update_button.js | 16 ++++++++++++++++ .../ascribe_uploader/react_s3_fine_uploader.js | 8 ++++---- 4 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 js/components/ascribe_settings/contract_settings_update_button.js diff --git a/js/components/ascribe_forms/property.js b/js/components/ascribe_forms/property.js index f446b64f..f3c26935 100644 --- a/js/components/ascribe_forms/property.js +++ b/js/components/ascribe_forms/property.js @@ -70,7 +70,7 @@ let Property = React.createClass({ // In order to set this.state.value from another component // the state of value should only be set if its not undefined and // actually references something - if(typeof childInput.getDOMNode().value !== 'undefined') { + if(childInput && typeof childInput.getDOMNode().value !== 'undefined') { this.setState({ value: childInput.getDOMNode().value }); diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 0e53c13b..0df6526e 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -9,12 +9,14 @@ import ContractListStore from '../../stores/contract_list_store'; import ContractListActions from '../../actions/contract_list_actions'; import ActionPanel from '../ascribe_panel/action_panel'; +import ContractSettingsUpdateButton from './contract_settings_update_button'; import GlobalNotificationModel from '../../models/global_notification_model'; import GlobalNotificationActions from '../../actions/global_notification_actions'; import { getLangText } from '../../utils/lang_utils'; + let ContractSettings = React.createClass({ propTypes: { defaultExpanded: React.PropTypes.bool @@ -97,7 +99,7 @@ let ContractSettings = React.createClass({ + defaultExpanded={true}> MAKE PUBLIC - + + UPDATE + + ); + } +}); + +export default ContractSettingsUpdateButton; \ No newline at end of file diff --git a/js/components/ascribe_uploader/react_s3_fine_uploader.js b/js/components/ascribe_uploader/react_s3_fine_uploader.js index 5d7b69ff..e4361ea7 100644 --- a/js/components/ascribe_uploader/react_s3_fine_uploader.js +++ b/js/components/ascribe_uploader/react_s3_fine_uploader.js @@ -2,14 +2,11 @@ import React from 'react/addons'; import Router from 'react-router'; +import fineUploader from 'fineUploader'; import Q from 'q'; -import { getCookie } from '../../utils/fetch_api_utils'; -import { getLangText } from '../../utils/lang_utils'; - import S3Fetcher from '../../fetchers/s3_fetcher'; -import fineUploader from 'fineUploader'; import FileDragAndDrop from './ascribe_file_drag_and_drop/file_drag_and_drop'; import GlobalNotificationModel from '../../models/global_notification_model'; @@ -17,8 +14,11 @@ import GlobalNotificationActions from '../../actions/global_notification_actions import AppConstants from '../../constants/application_constants'; +import { getCookie } from '../../utils/fetch_api_utils'; +import { getLangText } from '../../utils/lang_utils'; import { computeHashOfFile } from '../../utils/file_utils'; + var ReactS3FineUploader = React.createClass({ propTypes: { keyRoutine: React.PropTypes.shape({ From 6c8135d6aceb5783745bd73591ea5a62fb104427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 15 Sep 2015 13:13:58 +0200 Subject: [PATCH 076/192] fix length of undefined bug in fineuploadeer --- .../ascribe_file_drag_and_drop/file_drag_and_drop.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js index b6b5b218..aedfe1a3 100644 --- a/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js +++ b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js @@ -211,7 +211,7 @@ let FileDragAndDrop = React.createClass({ * For our self defined input, we can reuse those declarations to restrict which files * the user can pick from his hard drive. */ - if(validation && validation.allowedExtensions.length > 0) { + if(validation && validation.allowedExtensions && validation.allowedExtensions.length > 0) { // add a dot in front of the extension let prefixedAllowedExtensions = validation.allowedExtensions.map((ext) => '.' + ext); From b29bf38f1344ede45c9371400dc585dc10c90b77 Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 15 Sep 2015 13:15:29 +0200 Subject: [PATCH 077/192] ikono slides --- .../cyland/cyland_register_piece.js | 5 +- .../ascribe_buttons/ikonotv_submit_button.js | 58 ++--- .../ikonotv_additional_data_form.js | 134 +++++++++++ .../ikonotv/ikonotv_register_piece.js | 220 ++++++++++++++++++ .../whitelabel/wallet/wallet_routes.js | 3 +- 5 files changed, 378 insertions(+), 42 deletions(-) create mode 100644 js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_additional_data_form.js create mode 100644 js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js diff --git a/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js b/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js index 6e8a77c3..84713bd9 100644 --- a/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js +++ b/js/components/whitelabel/wallet/components/cyland/cyland_register_piece.js @@ -10,9 +10,6 @@ import Row from 'react-bootstrap/lib/Row'; import RegisterPieceForm from '../../../../ascribe_forms/form_register_piece'; -import Property from '../../../../ascribe_forms/property'; -import InputCheckbox from '../../../../ascribe_forms/input_checkbox'; - import WhitelabelActions from '../../../../../actions/whitelabel_actions'; import WhitelabelStore from '../../../../../stores/whitelabel_store'; @@ -136,7 +133,7 @@ let CylandRegisterPiece = React.createClass({ this.transitionTo('piece', {pieceId: this.state.piece.id}); }, - // We need to increase the step to lock the forms that are already filed out + // We need to increase the step to lock the forms that are already filled out incrementStep() { // also increase step let newStep = this.state.step + 1; diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js index 4b7f3dbc..be3bda77 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js @@ -1,17 +1,8 @@ 'use strict'; import React from 'react'; -import Moment from 'moment'; import classNames from 'classnames'; - -import ModalWrapper from '../../../../../ascribe_modal/modal_wrapper'; - -import LoanForm from '../../../../../ascribe_forms/form_loan'; - -import Property from '../../../../../ascribe_forms/property'; -import InputCheckbox from '../../../../../ascribe_forms/input_checkbox'; - -import ApiUrls from '../../../../../../constants/api_urls'; +import ButtonLink from 'react-router-bootstrap/lib/ButtonLink'; import { getLangText } from '../../../../../../utils/lang_utils'; @@ -22,37 +13,30 @@ let IkonotvSubmitButton = React.createClass({ piece: React.PropTypes.object.isRequired }, - getSubmitButton() { - return ( - - ); - }, - render() { + let piece = this.props.piece; + let startFrom = 1; - let today = new Moment(); - let enddate = new Moment(); - enddate.add(1, 'years'); + // In the Ikonotv loan page a user has to complete two steps. + // Since every one of those steps is atomic a user should always be able to continue + // where he left of. + // This is why we start the process form slide 1/2 if the user has already finished + // it in another session. + if(piece && piece.extra_data && Object.keys(piece.extra_data).length > 0) { + startFrom = 1; + } return ( - - - - + + {getLangText('Loan to IkonoTV')} + ); } }); diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_additional_data_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_additional_data_form.js new file mode 100644 index 00000000..6a2f8cc5 --- /dev/null +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_additional_data_form.js @@ -0,0 +1,134 @@ +'use strict'; + +import React from 'react'; + +import Form from '../../../../../ascribe_forms/form'; +import Property from '../../../../../ascribe_forms/property'; + +import InputTextAreaToggable from '../../../../../ascribe_forms/input_textarea_toggable'; + +import FurtherDetailsFileuploader from '../../../../../ascribe_detail/further_details_fileuploader'; + +import ApiUrls from '../../../../../../constants/api_urls'; +import AppConstants from '../../../../../../constants/application_constants'; + +import requests from '../../../../../../utils/requests'; + +import { getLangText } from '../../../../../../utils/lang_utils'; +import { formSubmissionValidation } from '../../../../../ascribe_uploader/react_s3_fine_uploader_utils'; + + +let IkonotvAdditionalDataForm = React.createClass({ + propTypes: { + handleSuccess: React.PropTypes.func.isRequired, + piece: React.PropTypes.object.isRequired, + + disabled: React.PropTypes.bool + }, + + getInitialState() { + return { + isUploadReady: true + }; + }, + + getFormData() { + let extradata = {}; + let formRefs = this.refs.form.refs; + + // Put additional fields in extra data object + Object + .keys(formRefs) + .forEach((fieldName) => { + extradata[fieldName] = formRefs[fieldName].state.value; + }); + + return { + extradata: extradata, + piece_id: this.props.piece.id + }; + + }, + + uploadStarted() { + this.setState({ + isUploadReady: false + }); + }, + + setIsUploadReady(isReady) { + this.setState({ + isUploadReady: isReady + }); + }, + + render() { + if(this.props.piece && this.props.piece.id) { + return ( +
+ {getLangText('Proceed to loan')} + + } + spinner={ +
+ +
+ }> +
+

+ {getLangText('Provide supporting materials')} +

+
+ + + + + + + + + ); + } else { + return ( +
+ +
+ ); + } + } +}); + +export default IkonotvAdditionalDataForm; \ No newline at end of file diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js new file mode 100644 index 00000000..6a2acbb8 --- /dev/null +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js @@ -0,0 +1,220 @@ +'use strict'; + +import React from 'react'; +import Moment from 'moment'; +import Router from 'react-router'; + +import Col from 'react-bootstrap/lib/Col'; +import Row from 'react-bootstrap/lib/Row'; + +import PieceListStore from '../../../../../stores/piece_list_store'; +import PieceListActions from '../../../../../actions/piece_list_actions'; + +import UserStore from '../../../../../stores/user_store'; +import UserActions from '../../../../../actions/user_actions'; + +import PieceStore from '../../../../../stores/piece_store'; +import PieceActions from '../../../../../actions/piece_actions'; + +import GlobalNotificationModel from '../../../../../models/global_notification_model'; +import GlobalNotificationActions from '../../../../../actions/global_notification_actions'; + +import RegisterPieceForm from '../../../../ascribe_forms/form_register_piece'; +import LoanForm from '../../../../ascribe_forms/form_loan'; +import IkonotvAdditionalDataForm from './ascribe_forms/ikonotv_additional_data_form'; + +import SlidesContainer from '../../../../ascribe_slides_container/slides_container'; + +import ApiUrls from '../../../../../constants/api_urls'; + +import { mergeOptions } from '../../../../../utils/general_utils'; +import { getLangText } from '../../../../../utils/lang_utils'; + +let IkonotvRegisterPiece = React.createClass({ + + propTypes: { + handleSuccess: React.PropTypes.func, + piece: React.PropTypes.object.isRequired + }, + + mixins: [Router.Navigation, Router.State], + + getInitialState(){ + return mergeOptions( + UserStore.getState(), + PieceListStore.getState(), + PieceStore.getState(), + { + step: 0 + }); + }, + + componentDidMount() { + PieceListStore.listen(this.onChange); + UserStore.listen(this.onChange); + PieceStore.listen(this.onChange); + UserActions.fetchCurrentUser(); + + let queryParams = this.getQuery(); + + // Since every step of this register process is atomic, + // we may need to enter the process at step 1 or 2. + // If this is the case, we'll need the piece number to complete submission. + // It is encoded in the URL as a queryParam and we're checking for it here. + // + // We're using 'in' here as we want to know if 'piece_id' is present in the url, + // we don't care about the value. + if (queryParams && 'piece_id' in queryParams) { + PieceActions.fetchOne(queryParams.piece_id); + } + }, + + componentWillUnmount() { + PieceListStore.unlisten(this.onChange); + UserStore.unlisten(this.onChange); + PieceStore.unlisten(this.onChange); + }, + + onChange(state) { + this.setState(state); + + if(this.state.currentUser && this.state.currentUser.email) { + // we should also make the fineuploader component editable again + this.setState({ + isFineUploaderActive: true + }); + } + }, + + + handleRegisterSuccess(response){ + + this.refreshPieceList(); + + // also start loading the piece for the next step + if(response && response.piece) { + PieceActions.updatePiece(response.piece); + } + + this.incrementStep(); + + this.refs.slidesContainer.nextSlide(); + }, + + handleAdditionalDataSuccess() { + + // We need to refetch the piece again after submitting the additional data + // since we want it's otherData to be displayed when the user choses to click + // on the browsers back button. + PieceActions.fetchOne(this.state.piece.id); + + this.refreshPieceList(); + + this.incrementStep(); + + this.refs.slidesContainer.nextSlide(); + }, + + handleLoanSuccess(response) { + let notification = new GlobalNotificationModel(response.notification, 'success', 10000); + GlobalNotificationActions.appendGlobalNotification(notification); + + this.refreshPieceList(); + + PieceActions.fetchOne(this.state.piece.id); + this.transitionTo('piece', {pieceId: this.state.piece.id}); + }, + + // We need to increase the step to lock the forms that are already filled out + incrementStep() { + // also increase step + let newStep = this.state.step + 1; + this.setState({ + step: newStep + }); + }, + + refreshPieceList() { + PieceListActions.fetchPieceList( + this.state.page, + this.state.pageSize, + this.state.searchTerm, + this.state.orderBy, + this.state.orderAsc, + this.state.filterBy + ); + }, + + changeSlide() { + // only transition to the login store, if user is not logged in + // ergo the currentUser object is not properly defined + if(this.state.currentUser && !this.state.currentUser.email) { + this.onLoggedOut(); + } + }, + + // basically redirects to the second slide (index: 1), when the user is not logged in + onLoggedOut() { + this.transitionTo('login'); + }, + + render() { + + let today = new Moment(); + let enddate = new Moment(); + enddate.add(1, 'years'); + + return ( + +
+ + + 0} + enableLocalHashing={false} + headerMessage={getLangText('Submit to Cyland Archive')} + submitMessage={getLangText('Submit')} + isFineUploaderActive={this.state.isFineUploaderActive} + handleSuccess={this.handleRegisterSuccess} + onLoggedOut={this.onLoggedOut} /> + + +
+
+ + + 1} + handleSuccess={this.handleAdditionalDataSuccess} + piece={this.state.piece}/> + + +
+
+ + + + + +
+
+ ); + } +}); + +export default IkonotvRegisterPiece; diff --git a/js/components/whitelabel/wallet/wallet_routes.js b/js/components/whitelabel/wallet/wallet_routes.js index 25fc1d80..6dd1ed24 100644 --- a/js/components/whitelabel/wallet/wallet_routes.js +++ b/js/components/whitelabel/wallet/wallet_routes.js @@ -21,6 +21,7 @@ import CylandPieceList from './components/cyland/cyland_piece_list'; import IkonotvPieceList from './components/ikonotv/ikonotv_piece_list'; import IkonotvRequestLoan from './components/ikonotv/ikonotv_request_loan'; +import IkonotvRegisterPiece from './components/ikonotv/ikonotv_register_piece'; import IkonotvPieceContainer from './components/ikonotv/ascribe_detail/ikonotv_piece_container'; import IkonotvContractNotifications from './components/ikonotv/ikonotv_contract_notifications'; @@ -73,7 +74,7 @@ let ROUTES = { - + From 71f94768d911860cf668077daa26e9f8637554f0 Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 15 Sep 2015 13:22:52 +0200 Subject: [PATCH 078/192] fix PR comments --- js/actions/contract_agreement_list_actions.js | 4 ++-- js/components/acl_proxy.js | 2 +- js/components/ascribe_forms/form_loan.js | 11 ++++++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/js/actions/contract_agreement_list_actions.js b/js/actions/contract_agreement_list_actions.js index 94f292c5..86988f47 100644 --- a/js/actions/contract_agreement_list_actions.js +++ b/js/actions/contract_agreement_list_actions.js @@ -37,11 +37,11 @@ class ContractAgreementListActions { fetchAvailableContractAgreementList(issuer){ return Q.Promise((resolve, reject) => { - this.actions.fetchContractAgreementList(issuer, 'True', null) + this.actions.fetchContractAgreementList(issuer, true, null) .then((contractAgreementListAccepted) => { if (!contractAgreementListAccepted) { // fetch pending agreements if no accepted ones - return this.actions.fetchContractAgreementList(issuer, null, 'True'); + return this.actions.fetchContractAgreementList(issuer, null, true); } else { resolve(contractAgreementListAccepted); diff --git a/js/components/acl_proxy.js b/js/components/acl_proxy.js index 10a7516e..4fc90a9b 100644 --- a/js/components/acl_proxy.js +++ b/js/components/acl_proxy.js @@ -21,7 +21,7 @@ let AclProxy = React.createClass({ }, getChildren() { - if (this.props.children.length && this.props.children.length > 1){ + if (React.Children.count(this.props.children) > 1){ /* This might ruin styles for header items in the navbar etc */ diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index 8e83ca34..180ee9ea 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -57,6 +57,15 @@ let LoanForm = React.createClass({ this.getContractAgreementsOrCreatePublic(this.props.email); }, + componentWillReceiveProps(nextProps) { + // however, it can also be that at the time the component is mounting, + // the email is not defined (because it's asynchronously fetched from the server). + // Then we need to update it as soon as it is included into LoanForm's props. + if(nextProps && nextProps.email) { + this.getContractAgreementsOrCreatePublic(nextProps.email); + } + }, + componentWillUnmount() { ContractAgreementListStore.unlisten(this.onChange); }, @@ -70,7 +79,7 @@ let LoanForm = React.createClass({ ContractAgreementListActions.fetchAvailableContractAgreementList(email).then( (contractAgreementList) => { if (!contractAgreementList) { - ContractAgreementListActions.createContractAgreementFromPublicContract.defer(email); + ContractAgreementListActions.createContractAgreementFromPublicContract(email); } } ); From 06f5b61cadaab760a2b2f67292eb8c2e0500cb55 Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 15 Sep 2015 13:37:18 +0200 Subject: [PATCH 079/192] reset agreements on mount of loan_form --- js/components/ascribe_forms/form_loan.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index 180ee9ea..dacbae77 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -75,6 +75,7 @@ let LoanForm = React.createClass({ }, getContractAgreementsOrCreatePublic(email){ + ContractAgreementListActions.flushContractAgreementList(); if (email) { ContractAgreementListActions.fetchAvailableContractAgreementList(email).then( (contractAgreementList) => { From 6a57a69e2944248bfb9e40abed1380f068a7af2c Mon Sep 17 00:00:00 2001 From: Cevo Date: Fri, 4 Sep 2015 16:18:29 +0200 Subject: [PATCH 080/192] main.scss edited --- js/components/ascribe_detail/edition.js | 2 +- .../components/ikonotv/ikonotv_piece_list.js | 1 - sass/main.scss | 28 +++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/js/components/ascribe_detail/edition.js b/js/components/ascribe_detail/edition.js index 47761e39..aa3d81ba 100644 --- a/js/components/ascribe_detail/edition.js +++ b/js/components/ascribe_detail/edition.js @@ -14,7 +14,7 @@ import CoaActions from '../../actions/coa_actions'; import CoaStore from '../../stores/coa_store'; import PieceListActions from '../../actions/piece_list_actions'; import PieceListStore from '../../stores/piece_list_store'; -import EditionListActions from '../../actions/edition_list_actions';; +import EditionListActions from '../../actions/edition_list_actions'; import HistoryIterator from './history_iterator'; diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_piece_list.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_piece_list.js index e4c83d97..4c8766e4 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_piece_list.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_piece_list.js @@ -8,7 +8,6 @@ import UserStore from '../../../../../stores/user_store'; import IkonotvAccordionListItem from './ascribe_accordion_list/ikonotv_accordion_list_item'; - let IkonotvPieceList = React.createClass({ getInitialState() { return UserStore.getState(); diff --git a/sass/main.scss b/sass/main.scss index 14526942..ae06eadb 100644 --- a/sass/main.scss +++ b/sass/main.scss @@ -122,6 +122,34 @@ hr { height: 60px; } +//http://stackoverflow.com/questions/22228239/bootstrap-navbar-static-top-menu-breaks-on-two-lines +@media (max-width: 990px) { + .navbar-header { + float: none; + } + .navbar-toggle { + display: block; + } + .navbar-collapse { + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.1); + } + .navbar-collapse.collapse { + display: none!important; + } + .navbar-nav { + float: none!important; + margin: 7.5px -15px; + } + .navbar-nav>li { + float: none; + } + .navbar-nav>li>a { + padding-top: 10px; + padding-bottom: 10px; + } +} + .truncate { overflow: hidden; text-overflow: ellipsis; From 83b20e64722a908fce81739066d5712f6a84ce29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 15 Sep 2015 16:35:45 +0200 Subject: [PATCH 081/192] First cut: Upload button for contract settings --- .../ascribe_settings/contract_settings.js | 4 +- .../contract_settings_update_button.js | 58 ++++++++- .../file_drag_and_drop.js | 27 +---- .../ascribe_upload_button/upload_button.js | 114 ++++++++++++++++++ .../react_s3_fine_uploader.js | 19 ++- .../react_s3_fine_uploader_utils.js | 19 +++ sass/ascribe_uploader.scss | 1 + 7 files changed, 209 insertions(+), 33 deletions(-) create mode 100644 js/components/ascribe_uploader/ascribe_upload_button/upload_button.js diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index a3c40380..8a6700f1 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -113,9 +113,7 @@ let ContractSettings = React.createClass({ content={contract.name} buttons={
- + - UPDATE - + ); } }); diff --git a/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js index 71f3a321..1e21aeb8 100644 --- a/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js +++ b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js @@ -12,7 +12,6 @@ import { getLangText } from '../../../utils/lang_utils'; // Taken from: https://github.com/fedosejev/react-file-drag-and-drop let FileDragAndDrop = React.createClass({ propTypes: { - className: React.PropTypes.string, onDragStart: React.PropTypes.func, onDrop: React.PropTypes.func.isRequired, onDrag: React.PropTypes.func, @@ -47,11 +46,7 @@ let FileDragAndDrop = React.createClass({ plural: React.PropTypes.string }), - validation: React.PropTypes.shape({ - itemLimit: React.PropTypes.number, - sizeLimit: React.PropTypes.string, - allowedExtensions: React.PropTypes.arrayOf(React.PropTypes.string) - }) + allowedExtensions: React.PropTypes.string }, handleDragStart(event) { @@ -183,7 +178,7 @@ let FileDragAndDrop = React.createClass({ fileClassToUpload, areAssetsDownloadable, areAssetsEditable, - validation + allowedExtensions } = this.props; // has files only is true if there are files that do not have the status deleted or canceled @@ -209,22 +204,6 @@ let FileDragAndDrop = React.createClass({
); } else { - let accept = ''; - - /** - * Fineuploader allows to specify the file extensions that are allowed to upload. - * For our self defined input, we can reuse those declarations to restrict which files - * the user can pick from his hard drive. - */ - if(validation && validation.allowedExtensions && validation.allowedExtensions.length > 0) { - // add a dot in front of the extension - let prefixedAllowedExtensions = validation.allowedExtensions.map((ext) => '.' + ext); - - // generate a comma separated list to add them to the DOM element - // See: http://stackoverflow.com/questions/4328947/limit-file-format-when-using-input-type-file - accept = prefixedAllowedExtensions.join(', '); - } - return (
+ accept={allowedExtensions}/>
); } diff --git a/js/components/ascribe_uploader/ascribe_upload_button/upload_button.js b/js/components/ascribe_uploader/ascribe_upload_button/upload_button.js new file mode 100644 index 00000000..a3fa985c --- /dev/null +++ b/js/components/ascribe_uploader/ascribe_upload_button/upload_button.js @@ -0,0 +1,114 @@ +'use strict'; + +import React from 'react'; + +import { displayValidProgressFilesFilter } from '../react_s3_fine_uploader_utils'; + +let UploadButton = React.createClass({ + propTypes: { + onDragStart: React.PropTypes.func, + onDrop: React.PropTypes.func.isRequired, + onDrag: React.PropTypes.func, + onDragEnter: React.PropTypes.func, + onLeave: React.PropTypes.func, + onDragLeave: React.PropTypes.func, + onDragOver: React.PropTypes.func, + onDragEnd: React.PropTypes.func, + onInactive: React.PropTypes.func, + filesToUpload: React.PropTypes.array, + handleDeleteFile: React.PropTypes.func, + handleCancelFile: React.PropTypes.func, + handlePauseFile: React.PropTypes.func, + handleResumeFile: React.PropTypes.func, + multiple: React.PropTypes.bool, + + + // For simplification purposes we're just going to use this prop as a + // label for the upload button + fileClassToUpload: React.PropTypes.shape({ + singular: React.PropTypes.string, + plural: React.PropTypes.string + }), + + allowedExtensions: React.PropTypes.string + }, + + handleDrop(event) { + event.preventDefault(); + event.stopPropagation(); + let files = event.target.files; + + if(typeof this.props.onDrop === 'function' && files) { + this.props.onDrop(files); + } + + }, + + getUploadingFiles() { + return this.props.filesToUpload.filter((file) => file.status === 'uploading'); + }, + + handleOnClick() { + let uploadingFiles = this.getUploadingFiles(); + + // We only want the button to be clickable if there are no files currently uploading + if(uploadingFiles.length === 0) { + // Firefox only recognizes the simulated mouse click if bubbles is set to true, + // but since Google Chrome propagates the event much further than needed, we + // need to stop propagation as soon as the event is created + var evt = new MouseEvent('click', { + view: window, + bubbles: true, + cancelable: true + }); + + evt.stopPropagation(); + this.refs.fileinput.getDOMNode().dispatchEvent(evt); + } + }, + + getButtonLabel() { + let { filesToUpload, fileClassToUpload } = this.props; + + // filter invalid files that might have been deleted or canceled... + filesToUpload = filesToUpload.filter(displayValidProgressFilesFilter); + + // Depending on wether there is an upload going on or not we + // display the progress + if(filesToUpload.length > 0) { + return 'Upload progress: ' + Math.ceil(filesToUpload[0].progress) + '%'; + } else { + return fileClassToUpload.singular; + } + }, + + render() { + let { + multiple, + fileClassToUpload, + allowedExtensions + } = this.props; + + return ( + + ); + } +}); + +export default UploadButton; \ No newline at end of file diff --git a/js/components/ascribe_uploader/react_s3_fine_uploader.js b/js/components/ascribe_uploader/react_s3_fine_uploader.js index 8ba53444..05709ad2 100644 --- a/js/components/ascribe_uploader/react_s3_fine_uploader.js +++ b/js/components/ascribe_uploader/react_s3_fine_uploader.js @@ -16,7 +16,7 @@ import AppConstants from '../../constants/application_constants'; import { computeHashOfFile } from '../../utils/file_utils'; -import { displayValidFilesFilter } from './react_s3_fine_uploader_utils'; +import { displayValidFilesFilter, transformAllowedExtensionsToInputAcceptProp } from './react_s3_fine_uploader_utils'; import { getCookie } from '../../utils/fetch_api_utils'; import { getLangText } from '../../utils/lang_utils'; @@ -125,7 +125,10 @@ let ReactS3FineUploader = React.createClass({ // Uploading functionality of react fineuploader is disconnected from its UI // layer, which means that literally every (properly adjusted) react element // can handle the UI handling. - fileInputElement: React.PropTypes.func + fileInputElement: React.PropTypes.oneOfType([ + React.PropTypes.func, + React.PropTypes.element + ]) }, mixins: [Router.State], @@ -838,6 +841,16 @@ let ReactS3FineUploader = React.createClass({ }, + getAllowedExtensions() { + let { validation } = this.props; + + if(validation && validation.allowedExtensions && validation.allowedExtensions.length > 0) { + return transformAllowedExtensionsToInputAcceptProp(validation.allowedExtensions); + } else { + return null; + } + }, + render() { let { multiple, @@ -868,7 +881,7 @@ let ReactS3FineUploader = React.createClass({ hashingProgress: this.state.hashingProgress, enableLocalHashing: enableLocalHashing, fileClassToUpload: fileClassToUpload, - validation: validation + allowedExtensions: this.getAllowedExtensions() }); } diff --git a/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js b/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js index 92d5c2ba..cd1dbce2 100644 --- a/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js +++ b/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js @@ -52,3 +52,22 @@ export function displayValidProgressFilesFilter(file) { return file.status !== 'deleted' && file.status !== 'canceled' && file.status !== 'online'; } + +/** + * Fineuploader allows to specify the file extensions that are allowed to upload. + * For our self defined input, we can reuse those declarations to restrict which files + * the user can pick from his hard drive. + * + * Takes an array of file extensions (['pdf', 'png', ...]) and transforms them into a string + * that can be passed into an html5 input via its 'accept' prop. + * @param {array} allowedExtensions Array of strings without a dot prefixed + * @return {string} Joined string (comma-separated) of the passed-in array + */ +export function transformAllowedExtensionsToInputAcceptProp(allowedExtensions) { + // add a dot in front of the extension + let prefixedAllowedExtensions = allowedExtensions.map((ext) => '.' + ext); + + // generate a comma separated list to add them to the DOM element + // See: http://stackoverflow.com/questions/4328947/limit-file-format-when-using-input-type-file + return prefixedAllowedExtensions.join(', '); +} diff --git a/sass/ascribe_uploader.scss b/sass/ascribe_uploader.scss index 6e9eebd9..331b6b00 100644 --- a/sass/ascribe_uploader.scss +++ b/sass/ascribe_uploader.scss @@ -9,6 +9,7 @@ text-align: center; vertical-align: middle; cursor: default !important; + padding: 1.5em 0 1.5em 0; .file-drag-and-drop-dialog > p:first-child { font-size: 1.5em !important; From 2656bdac14703fed6b151d09bc84436de0641c7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 15 Sep 2015 17:18:38 +0200 Subject: [PATCH 082/192] correct query parameters for contract list request --- js/components/ascribe_forms/form_contract_agreement.js | 2 +- js/components/ascribe_forms/form_create_contract.js | 2 +- js/components/ascribe_settings/contract_settings.js | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/components/ascribe_forms/form_contract_agreement.js b/js/components/ascribe_forms/form_contract_agreement.js index 887b99db..fb6793e6 100644 --- a/js/components/ascribe_forms/form_contract_agreement.js +++ b/js/components/ascribe_forms/form_contract_agreement.js @@ -35,7 +35,7 @@ let ContractAgreementForm = React.createClass({ componentDidMount() { ContractListStore.listen(this.onChange); - ContractListActions.fetchContractList({is_active: true}); + ContractListActions.fetchContractList(true); }, componentWillUnmount() { diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js index b275df03..d3d14966 100644 --- a/js/components/ascribe_forms/form_create_contract.js +++ b/js/components/ascribe_forms/form_create_contract.js @@ -50,7 +50,7 @@ let CreateContractForm = React.createClass({ }, handleCreateSuccess(response) { - ContractListActions.fetchContractList({is_active: true}); + ContractListActions.fetchContractList(true); let notification = new GlobalNotificationModel(getLangText('Contract %s successfully created', response.name), 'success', 5000); GlobalNotificationActions.appendGlobalNotification(notification); this.refs.form.reset(); diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index b79f77f1..0db6133e 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -26,7 +26,7 @@ let ContractSettings = React.createClass({ componentDidMount() { ContractListStore.listen(this.onChange); - ContractListActions.fetchContractList({is_active: true}); + ContractListActions.fetchContractList(true); }, componentWillUnmount() { @@ -42,7 +42,7 @@ let ContractSettings = React.createClass({ contract.is_public = true; ContractListActions.changeContract(contract) .then(() => { - ContractListActions.fetchContractList({is_active: true}); + ContractListActions.fetchContractList(true); let notification = getLangText('Contract %s is now public', contract.name); notification = new GlobalNotificationModel(notification, 'success', 4000); GlobalNotificationActions.appendGlobalNotification(notification); @@ -58,7 +58,7 @@ let ContractSettings = React.createClass({ return () => { ContractListActions.removeContract(contract.id) .then((response) => { - ContractListActions.fetchContractList({is_active: true}); + ContractListActions.fetchContractList(true); let notification = new GlobalNotificationModel(response.notification, 'success', 4000); GlobalNotificationActions.appendGlobalNotification(notification); }) From 17cb2223c2358a28782d8277e57117748eea514d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Wed, 16 Sep 2015 09:47:22 +0200 Subject: [PATCH 083/192] finalize contract update button --- js/actions/contract_list_actions.js | 2 +- .../ascribe_settings/contract_settings.js | 26 ++------------ .../contract_settings_update_button.js | 36 ++++++++++++++++--- .../ascribe_upload_button/upload_button.js | 5 +-- js/fetchers/ownership_fetcher.js | 2 +- 5 files changed, 38 insertions(+), 33 deletions(-) diff --git a/js/actions/contract_list_actions.js b/js/actions/contract_list_actions.js index a856fb2b..5b874caf 100644 --- a/js/actions/contract_list_actions.js +++ b/js/actions/contract_list_actions.js @@ -30,7 +30,7 @@ class ContractListActions { changeContract(contract){ return Q.Promise((resolve, reject) => { - OwnershipFetcher.makeContractPublic(contract) + OwnershipFetcher.changeContract(contract) .then((res) => { resolve(res); }) diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 00b37b78..278c0f52 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -39,23 +39,6 @@ let ContractSettings = React.createClass({ this.setState(state); }, - makeContractPublic(contract) { - return () => { - contract.is_public = true; - ContractListActions.changeContract(contract) - .then(() => { - ContractListActions.fetchContractList(true); - let notification = getLangText('Contract %s is now public', contract.name); - notification = new GlobalNotificationModel(notification, 'success', 4000); - GlobalNotificationActions.appendGlobalNotification(notification); - }) - .catch((err) => { - let notification = new GlobalNotificationModel(err, 'danger', 10000); - GlobalNotificationActions.appendGlobalNotification(notification); - }); - }; - }, - removeContract(contract) { return () => { ContractListActions.removeContract(contract.id) @@ -113,7 +96,7 @@ let ContractSettings = React.createClass({ content={contract.name} buttons={
- + - - + { + let notification = new GlobalNotificationModel(getLangText('Contract %s successfully updated', res.name), 'success', 5000); + GlobalNotificationActions.appendGlobalNotification(notification); + + return ContractListActions.fetchContractList(true); + }) + .then(() => { + this.refs.fineuploader.reset(); + }) + .catch((err) => { + console.logGlobal(err); + let notification = new GlobalNotificationModel(getLangText('Contract could not be updated'), 'success', 5000); + GlobalNotificationActions.appendGlobalNotification(notification); + }); }, render() { return ( {/* So that ReactS3FineUploader is not complaining */}} signature={{ endpoint: AppConstants.serverUrl + 's3/signature/', customHeaders: { diff --git a/js/components/ascribe_uploader/ascribe_upload_button/upload_button.js b/js/components/ascribe_uploader/ascribe_upload_button/upload_button.js index a3fa985c..47347d46 100644 --- a/js/components/ascribe_uploader/ascribe_upload_button/upload_button.js +++ b/js/components/ascribe_uploader/ascribe_upload_button/upload_button.js @@ -3,6 +3,8 @@ import React from 'react'; import { displayValidProgressFilesFilter } from '../react_s3_fine_uploader_utils'; +import { getLangText } from '../../../utils/lang_utils'; + let UploadButton = React.createClass({ propTypes: { @@ -22,7 +24,6 @@ let UploadButton = React.createClass({ handleResumeFile: React.PropTypes.func, multiple: React.PropTypes.bool, - // For simplification purposes we're just going to use this prop as a // label for the upload button fileClassToUpload: React.PropTypes.shape({ @@ -76,7 +77,7 @@ let UploadButton = React.createClass({ // Depending on wether there is an upload going on or not we // display the progress if(filesToUpload.length > 0) { - return 'Upload progress: ' + Math.ceil(filesToUpload[0].progress) + '%'; + return getLangText('Upload progress') + ': ' + Math.ceil(filesToUpload[0].progress) + '%'; } else { return fileClassToUpload.singular; } diff --git a/js/fetchers/ownership_fetcher.js b/js/fetchers/ownership_fetcher.js index fde66c7d..f9ce5f86 100644 --- a/js/fetchers/ownership_fetcher.js +++ b/js/fetchers/ownership_fetcher.js @@ -48,7 +48,7 @@ let OwnershipFetcher = { return requests.get(ApiUrls.ownership_loans_pieces_request); }, - makeContractPublic(contractObj){ + changeContract(contractObj){ return requests.put(ApiUrls.ownership_contract, { body: contractObj, contract_id: contractObj.id }); }, From d6bd4b4ac1914ced446795695f9efd85acd9f20d Mon Sep 17 00:00:00 2001 From: diminator Date: Wed, 16 Sep 2015 14:07:13 +0200 Subject: [PATCH 084/192] bug fix acl button form copyright association + account settings bug fix dispatch in form loan ikonotv slides --- js/actions/contract_agreement_list_actions.js | 11 +++ js/components/ascribe_buttons/acl_button.js | 33 +++---- .../ascribe_forms/form_contract_agreement.js | 89 +++++++++++-------- .../form_copyright_association.js | 75 ++++++++++++++++ js/components/ascribe_forms/form_loan.js | 23 ++--- .../ascribe_settings/account_settings.js | 3 + .../ikonotv_additional_data_form.js | 13 +-- .../ikonotv/ikonotv_contract_notifications.js | 83 +++++++++-------- js/constants/application_constants.js | 6 +- 9 files changed, 221 insertions(+), 115 deletions(-) create mode 100644 js/components/ascribe_forms/form_copyright_association.js diff --git a/js/actions/contract_agreement_list_actions.js b/js/actions/contract_agreement_list_actions.js index 86988f47..f2959901 100644 --- a/js/actions/contract_agreement_list_actions.js +++ b/js/actions/contract_agreement_list_actions.js @@ -89,6 +89,17 @@ class ContractAgreementListActions { }); } + flushContractAgreementList(){ + return Q.Promise((resolve, reject) => { + this.actions.updateContractAgreementList(null).then( + resolve() + ).catch((err) => { + console.logGlobal(err); + reject(err); + }); + }); + } + } export default alt.createActions(ContractAgreementListActions); diff --git a/js/components/ascribe_buttons/acl_button.js b/js/components/ascribe_buttons/acl_button.js index 084de194..e3c7fa1c 100644 --- a/js/components/ascribe_buttons/acl_button.js +++ b/js/components/ascribe_buttons/acl_button.js @@ -162,21 +162,24 @@ let AclButton = React.createClass({ }, render() { - 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} - - ); + 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; } }); diff --git a/js/components/ascribe_forms/form_contract_agreement.js b/js/components/ascribe_forms/form_contract_agreement.js index fb6793e6..94ab26d0 100644 --- a/js/components/ascribe_forms/form_contract_agreement.js +++ b/js/components/ascribe_forms/form_contract_agreement.js @@ -35,7 +35,7 @@ let ContractAgreementForm = React.createClass({ componentDidMount() { ContractListStore.listen(this.onChange); - ContractListActions.fetchContractList(true); + ContractListActions.fetchContractList(true, false); }, componentWillUnmount() { @@ -95,45 +95,56 @@ let ContractAgreementForm = React.createClass({ }, render() { + if (this.state.contractList && this.state.contractList.length > 0) { + return ( +
+ {getLangText('Send loan request')} + } + spinner={ + + + + }> +
+

{getLangText('Contract form')}

+
+ + + + {this.getContracts()} + + {getLangText('Appendix')} + + +
+ ); + } return ( -
- {getLangText('Send loan request')} - } - spinner={ - - - - }> -
-

{getLangText('Contract form')}

-
- - - - {this.getContracts()} - - {getLangText('Appendix')} - - -
+
); } }); diff --git a/js/components/ascribe_forms/form_copyright_association.js b/js/components/ascribe_forms/form_copyright_association.js new file mode 100644 index 00000000..451afb97 --- /dev/null +++ b/js/components/ascribe_forms/form_copyright_association.js @@ -0,0 +1,75 @@ +'use strict'; + +import React from 'react'; + +import GlobalNotificationModel from '../../models/global_notification_model'; +import GlobalNotificationActions from '../../actions/global_notification_actions'; + +import Form from './form'; +import Property from './property'; + +import apiUrls from '../../constants/api_urls'; +import appConstants from '../../constants/application_constants'; + +import { getLangText } from '../../utils/lang_utils'; + +let CopyrightAssociationForm = React.createClass({ + propTypes: { + currentUser: React.PropTypes.object + }, + + handleSubmitSuccess(){ + let notification = getLangText('Copyright association updated'); + notification = new GlobalNotificationModel(notification, 'success', 10000); + GlobalNotificationActions.appendGlobalNotification(notification); + }, + + getProfileFormData(){ + if (this.props.currentUser && this.props.currentUser.email){ + return {email: this.props.currentUser.email}; + } + return null; + }, + + render() { + let selectedState = -1; + if (this.props.currentUser + && this.props.currentUser.profile + && this.props.currentUser.profile.copyright_association) { + selectedState = appConstants.copyrightAssociations.indexOf(this.props.currentUser.profile.copyright_association); + } + return ( +
+ + + +
+
+ ); + } +}); + +export default CopyrightAssociationForm; \ No newline at end of file diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index dacbae77..a1c31330 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -61,7 +61,7 @@ let LoanForm = React.createClass({ // however, it can also be that at the time the component is mounting, // the email is not defined (because it's asynchronously fetched from the server). // Then we need to update it as soon as it is included into LoanForm's props. - if(nextProps && nextProps.email) { + if(nextProps && nextProps.email && this.props.email !== nextProps.email) { this.getContractAgreementsOrCreatePublic(nextProps.email); } }, @@ -75,16 +75,19 @@ let LoanForm = React.createClass({ }, getContractAgreementsOrCreatePublic(email){ - ContractAgreementListActions.flushContractAgreementList(); - if (email) { - ContractAgreementListActions.fetchAvailableContractAgreementList(email).then( - (contractAgreementList) => { - if (!contractAgreementList) { - ContractAgreementListActions.createContractAgreementFromPublicContract(email); + /* a more complex defer (with promises) otherwise we dispatch while an action is being dispatched) */ + window.setTimeout(() => { + ContractAgreementListActions.flushContractAgreementList(); + + if (email) { + ContractAgreementListActions.fetchAvailableContractAgreementList(email).then( + (contractAgreementList) => { + if (!contractAgreementList) { + ContractAgreementListActions.createContractAgreementFromPublicContract(email); + } } - } - ); - } + ); + }}, 0); }, getFormData(){ diff --git a/js/components/ascribe_settings/account_settings.js b/js/components/ascribe_settings/account_settings.js index b4d46b2d..93a419c2 100644 --- a/js/components/ascribe_settings/account_settings.js +++ b/js/components/ascribe_settings/account_settings.js @@ -13,6 +13,8 @@ import Property from '../ascribe_forms/property'; import InputCheckbox from '../ascribe_forms/input_checkbox'; import CollapsibleParagraph from '../ascribe_collapsible/collapsible_paragraph'; +import CopyrightAssociationForm from '../ascribe_forms/form_copyright_association'; + import ApiUrls from '../../constants/api_urls'; import AppConstants from '../../constants/application_constants'; @@ -117,6 +119,7 @@ let AccountSettings = React.createClass({ show={true} defaultExpanded={true}> {content} + {profile} {/*
diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_additional_data_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_additional_data_form.js index 6a2f8cc5..6f249c7b 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_additional_data_form.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_additional_data_form.js @@ -7,7 +7,7 @@ import Property from '../../../../../ascribe_forms/property'; import InputTextAreaToggable from '../../../../../ascribe_forms/input_textarea_toggable'; -import FurtherDetailsFileuploader from '../../../../../ascribe_detail/further_details_fileuploader'; +//import FurtherDetailsFileuploader from '../../../../../ascribe_detail/further_details_fileuploader'; import ApiUrls from '../../../../../../constants/api_urls'; import AppConstants from '../../../../../../constants/application_constants'; @@ -15,7 +15,7 @@ import AppConstants from '../../../../../../constants/application_constants'; import requests from '../../../../../../utils/requests'; import { getLangText } from '../../../../../../utils/lang_utils'; -import { formSubmissionValidation } from '../../../../../ascribe_uploader/react_s3_fine_uploader_utils'; +//import { formSubmissionValidation } from '../../../../../ascribe_uploader/react_s3_fine_uploader_utils'; let IkonotvAdditionalDataForm = React.createClass({ @@ -110,15 +110,6 @@ let IkonotvAdditionalDataForm = React.createClass({ placeholder={getLangText('Enter a conceptual overview...')} required="required"/> - ); } else { diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js index 6a63657c..beffe23a 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js @@ -6,17 +6,18 @@ import Router from 'react-router'; import Glyphicon from 'react-bootstrap/lib/Glyphicon'; import Button from 'react-bootstrap/lib/Button'; -import Form from '../../../../ascribe_forms/form'; -import Property from '../../../../ascribe_forms/property'; -import InputCheckbox from '../../../../ascribe_forms/input_checkbox'; - import NotificationActions from '../../../../../actions/notification_actions'; import NotificationStore from '../../../../../stores/notification_store'; + +import UserStore from '../../../../../stores/user_store'; + import WhitelabelStore from '../../../../../stores/whitelabel_store'; import GlobalNotificationModel from '../../../../../models/global_notification_model'; import GlobalNotificationActions from '../../../../../actions/global_notification_actions'; +import CopyrightAssociationForm from '../../../../ascribe_forms/form_copyright_association'; + import apiUrls from '../../../../../constants/api_urls'; import requests from '../../../../../utils/requests'; @@ -32,12 +33,14 @@ let IkonotvContractNotifications = React.createClass({ getInitialState() { return mergeOptions( NotificationStore.getState(), + UserStore.getState(), WhitelabelStore.getState() ); }, componentDidMount() { NotificationStore.listen(this.onChange); + UserStore.listen(this.onChange); WhitelabelStore.listen(this.onChange); if (this.state.contractAgreementListNotifications === null){ NotificationActions.fetchContractAgreementListNotifications(); @@ -88,7 +91,8 @@ let IkonotvContractNotifications = React.createClass({ let notifications = this.state.contractAgreementListNotifications[0]; let appendix = notifications.contract_agreement.appendix; if (appendix) { - return (
+ return ( +

{getLangText('Appendix')}

                         {appendix.default}
@@ -99,6 +103,13 @@ let IkonotvContractNotifications = React.createClass({
         return null;
     },
 
+    handleConfirm() {
+        let contractAgreement = this.state.contractAgreementListNotifications[0].contract_agreement;
+        requests.put(apiUrls.ownership_contract_agreements_confirm, {contract_agreement_id: contractAgreement.id}).then(
+            () => this.handleConfirmSuccess()
+        );
+    },
+
     handleConfirmSuccess() {
         let notification = new GlobalNotificationModel(getLangText('You have accepted the conditions'), 'success', 10000);
         GlobalNotificationActions.appendGlobalNotification(notification);
@@ -118,11 +129,29 @@ let IkonotvContractNotifications = React.createClass({
         this.transitionTo('pieces');
     },
 
+    getCopyrightAssociationForm(){
+        if (this.state.currentUser && this.state.currentUser.profile
+            && this.state.currentUser.profile.copyright_association){
+            return null;
+        }
+        return (
+            
+

{getLangText('Are you a member of any copyright societies?')}

+

+ ARS, DACS, Bildkunst, Pictoright, SODRAC, Copyright Agency/Viscopy, SAVA, Bildrecht GmbH, + SABAM, AUTVIS, CREAIMAGEN, SONECA, Copydan, EAU, Kuvasto, GCA, HUNGART, IVARO, SIAE, JASPAR-SPDA, + AKKA/LAA, LATGA-A, SOMAAP, ARTEGESTION, CARIER, BONO, APSAV, SPA, GESTOR, VISaRTA, RAO, LITA, + DALRO, VeGaP, BUS, ProLitteris, AGADU, AUTORARTE, BUBEDRA, BBDA, BCDA, BURIDA, ADAVIS, BSDA +

+ +
+ ); + }, + render() { if (this.state.contractAgreementListNotifications && this.state.contractAgreementListNotifications.length > 0) { - let contractAgreement = this.state.contractAgreementListNotifications[0].contract_agreement; return (
@@ -133,41 +162,17 @@ let IkonotvContractNotifications = React.createClass({
{this.getContract()} -
- {this.getAppendix} -

{getLangText('Are you a member of any copyright societies?')}

-

- ARS, DACS, Bildkunst, Pictoright, SODRAC, Copyright Agency/Viscopy, SAVA, Bildrecht GmbH, - SABAM, AUTVIS, CREAIMAGEN, SONECA, Copydan, EAU, Kuvasto, GCA, HUNGART, IVARO, SIAE, JASPAR-SPDA, - AKKA/LAA, LATGA-A, SOMAAP, ARTEGESTION, CARIER, BONO, APSAV, SPA, GESTOR, VISaRTA, RAO, LITA, - DALRO, VeGaP, BUS, ProLitteris, AGADU, AUTORARTE, BUBEDRA, BBDA, BCDA, BURIDA, ADAVIS, BSDA + {this.getAppendix()} + {this.getCopyrightAssociationForm()} +

+ +

-
- - -

- }> - - - - {' ' + getLangText('Yes') } - - - - -
diff --git a/js/constants/application_constants.js b/js/constants/application_constants.js index f1455029..3b3c4a9f 100644 --- a/js/constants/application_constants.js +++ b/js/constants/application_constants.js @@ -61,7 +61,11 @@ let constants = { 'whitelabel': {}, 'raven': { 'url': 'https://0955da3388c64ab29bd32c2a429f9ef4@app.getsentry.com/48351' - } + }, + 'copyrightAssociations': ['ARS', 'DACS', 'Bildkunst', 'Pictoright', 'SODRAC', 'Copyright Agency/Viscopy', 'SAVA', + 'Bildrecht GmbH', 'SABAM', 'AUTVIS', 'CREAIMAGEN', 'SONECA', 'Copydan', 'EAU', 'Kuvasto', 'GCA', 'HUNGART', + 'IVARO', 'SIAE', 'JASPAR-SPDA', 'AKKA/LAA', 'LATGA-A', 'SOMAAP', 'ARTEGESTION', 'CARIER', 'BONO', 'APSAV', + 'SPA', 'GESTOR', 'VISaRTA', 'RAO', 'LITA', 'DALRO', 'VeGaP', 'BUS', 'ProLitteris', 'AGADU', 'AUTORARTE', 'BUBEDRA', 'BBDA', 'BCDA', 'BURIDA', 'ADAVIS', 'BSDA'] }; export default constants; From b2a3c9545b5f6180125cb7847e6c306f49102536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Wed, 16 Sep 2015 14:07:55 +0200 Subject: [PATCH 085/192] minor corrections --- .../contract_settings_update_button.js | 4 ++++ .../file_drag_and_drop_preview.js | 1 + .../ascribe_upload_button/upload_button.js | 14 +------------- .../ascribe_uploader/react_s3_fine_uploader.js | 1 - 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/js/components/ascribe_settings/contract_settings_update_button.js b/js/components/ascribe_settings/contract_settings_update_button.js index 2fbfe15f..5712d441 100644 --- a/js/components/ascribe_settings/contract_settings_update_button.js +++ b/js/components/ascribe_settings/contract_settings_update_button.js @@ -33,12 +33,16 @@ let ContractSettingsUpdateButton = React.createClass({ ContractListActions .changeContract(contract) .then((res) => { + + // Display feedback to the user let notification = new GlobalNotificationModel(getLangText('Contract %s successfully updated', res.name), 'success', 5000); GlobalNotificationActions.appendGlobalNotification(notification); + // and refresh the contract list to get the updated contracs return ContractListActions.fetchContractList(true); }) .then(() => { + // Also, reset the fineuploader component so that the user can again 'update' his contract this.refs.fineuploader.reset(); }) .catch((err) => { diff --git a/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview.js b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview.js index 8f712061..86d4135e 100644 --- a/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview.js +++ b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview.js @@ -45,6 +45,7 @@ let FileDragAndDropPreview = React.createClass({ handleDownloadFile() { if(this.props.file.s3Url) { + // This simply opens a new browser tab with the url provided open(this.props.file.s3Url); } }, diff --git a/js/components/ascribe_uploader/ascribe_upload_button/upload_button.js b/js/components/ascribe_uploader/ascribe_upload_button/upload_button.js index 47347d46..1547272e 100644 --- a/js/components/ascribe_uploader/ascribe_upload_button/upload_button.js +++ b/js/components/ascribe_uploader/ascribe_upload_button/upload_button.js @@ -8,20 +8,8 @@ import { getLangText } from '../../../utils/lang_utils'; let UploadButton = React.createClass({ propTypes: { - onDragStart: React.PropTypes.func, onDrop: React.PropTypes.func.isRequired, - onDrag: React.PropTypes.func, - onDragEnter: React.PropTypes.func, - onLeave: React.PropTypes.func, - onDragLeave: React.PropTypes.func, - onDragOver: React.PropTypes.func, - onDragEnd: React.PropTypes.func, - onInactive: React.PropTypes.func, filesToUpload: React.PropTypes.array, - handleDeleteFile: React.PropTypes.func, - handleCancelFile: React.PropTypes.func, - handlePauseFile: React.PropTypes.func, - handleResumeFile: React.PropTypes.func, multiple: React.PropTypes.bool, // For simplification purposes we're just going to use this prop as a @@ -77,7 +65,7 @@ let UploadButton = React.createClass({ // Depending on wether there is an upload going on or not we // display the progress if(filesToUpload.length > 0) { - return getLangText('Upload progress') + ': ' + Math.ceil(filesToUpload[0].progress) + '%'; + return getLangText('Upload progress') + ': ' + Math.ceil(filesToUpload[0].progress) + '%'; } else { return fileClassToUpload.singular; } diff --git a/js/components/ascribe_uploader/react_s3_fine_uploader.js b/js/components/ascribe_uploader/react_s3_fine_uploader.js index 54434826..c7a5f9a7 100644 --- a/js/components/ascribe_uploader/react_s3_fine_uploader.js +++ b/js/components/ascribe_uploader/react_s3_fine_uploader.js @@ -3,7 +3,6 @@ import React from 'react/addons'; import fineUploader from 'fineUploader'; import Router from 'react-router'; -import fineUploader from 'fineUploader'; import Q from 'q'; import S3Fetcher from '../../fetchers/s3_fetcher'; From 7c376b7229694e942705ae13fbfd43cc10545395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Wed, 16 Sep 2015 15:14:08 +0200 Subject: [PATCH 086/192] PR Feedback: add getLangText and move itemLimit and sizeLimit to app constants --- .../ascribe_detail/further_details_fileuploader.js | 5 +---- js/components/ascribe_forms/form_create_contract.js | 5 ++--- js/components/ascribe_forms/form_register_piece.js | 5 +---- js/components/ascribe_settings/contract_settings.js | 12 ++++++------ .../contract_settings_update_button.js | 4 ++-- js/constants/application_constants.js | 13 +++++++++++++ 6 files changed, 25 insertions(+), 19 deletions(-) diff --git a/js/components/ascribe_detail/further_details_fileuploader.js b/js/components/ascribe_detail/further_details_fileuploader.js index bfbf9582..9bf0bd5b 100644 --- a/js/components/ascribe_detail/further_details_fileuploader.js +++ b/js/components/ascribe_detail/further_details_fileuploader.js @@ -55,10 +55,7 @@ let FurtherDetailsFileuploader = React.createClass({ url: ApiUrls.blob_otherdatas, pieceId: this.props.pieceId }} - validation={{ - itemLimit: 100000, - sizeLimit: '50000000' - }} + validation={AppConstants.fineUploader.validation.additionalData} submitFile={this.props.submitFile} setIsUploadReady={this.props.setIsUploadReady} isReadyForFormSubmission={this.props.isReadyForFormSubmission} diff --git a/js/components/ascribe_forms/form_create_contract.js b/js/components/ascribe_forms/form_create_contract.js index 26790269..b19cb050 100644 --- a/js/components/ascribe_forms/form_create_contract.js +++ b/js/components/ascribe_forms/form_create_contract.js @@ -78,13 +78,12 @@ let CreateContractForm = React.createClass({ url: ApiUrls.blob_contracts }} validation={{ - itemLimit: 100000, - sizeLimit: '50000000', + itemLimit: AppConstants.fineUploader.validation.additionalData.itemLimit, + sizeLimit: AppConstants.fineUploader.validation.additionalData.sizeLimit, allowedExtensions: ['pdf'] }} areAssetsDownloadable={true} areAssetsEditable={true} - submitFile={this.submitFile} setIsUploadReady={this.setIsUploadReady} isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile} fileClassToUpload={this.props.fileClassToUpload}/> diff --git a/js/components/ascribe_forms/form_register_piece.js b/js/components/ascribe_forms/form_register_piece.js index dab0b251..ed6fc701 100644 --- a/js/components/ascribe_forms/form_register_piece.js +++ b/js/components/ascribe_forms/form_register_piece.js @@ -107,10 +107,7 @@ let RegisterPieceForm = React.createClass({ createBlobRoutine={{ url: ApiUrls.blob_digitalworks }} - validation={{ - itemLimit: 100000, - sizeLimit: '25000000000' - }} + validation={AppConstants.fineUploader.validation.registerWork} setIsUploadReady={this.setIsUploadReady} isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile} isFineUploaderActive={this.props.isFineUploaderActive} diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 278c0f52..c7abc682 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -101,12 +101,12 @@ let ContractSettings = React.createClass({ className="btn btn-default btn-sm margin-left-2px" href={contract.blob.url_safe} target="_blank"> - PREVIEW + {getLangText('PREVIEW')}
} @@ -122,8 +122,8 @@ let ContractSettings = React.createClass({ {privateContracts.map((contract, i) => { return ( @@ -138,12 +138,12 @@ let ContractSettings = React.createClass({ className="btn btn-default btn-sm margin-left-2px" href={contract.blob.url_safe} target="_blank"> - PREVIEW + {getLangText('PREVIEW')} } diff --git a/js/components/ascribe_settings/contract_settings_update_button.js b/js/components/ascribe_settings/contract_settings_update_button.js index 5712d441..f2e54c50 100644 --- a/js/components/ascribe_settings/contract_settings_update_button.js +++ b/js/components/ascribe_settings/contract_settings_update_button.js @@ -65,8 +65,8 @@ let ContractSettingsUpdateButton = React.createClass({ url: ApiUrls.blob_contracts }} validation={{ - itemLimit: 100000, - sizeLimit: '50000000', + itemLimit: AppConstants.fineUploader.validation.registerWork.itemLimit, + sizeLimit: AppConstants.fineUploader.validation.additionalData.sizeLimit, allowedExtensions: ['pdf'] }} setIsUploadReady={() =>{/* So that ReactS3FineUploader is not complaining */}} diff --git a/js/constants/application_constants.js b/js/constants/application_constants.js index f1455029..a2726d73 100644 --- a/js/constants/application_constants.js +++ b/js/constants/application_constants.js @@ -57,6 +57,19 @@ let constants = { // Source: http://www.w3schools.com/tags/att_input_type.asp 'possibleInputTypes': ['button', 'checkbox', 'color', 'date', 'datetime', 'datetime-local', 'email', 'file', 'hidden', 'image', 'month', 'number', 'password', 'radio', 'range', 'reset', 'search', 'submit', 'tel', 'text', 'time', 'url', 'week'], + 'fineUploader': { + 'validation': { + 'additionalData': { + 'itemLimit': 100, + 'sizeLimit': '50000000' + }, + 'registerWork': { + 'itemLimit': 1, + 'sizeLimit': '25000000000' + } + } + }, + // in case of whitelabel customization, we store stuff here 'whitelabel': {}, 'raven': { From 3c3e32980c501509a33e5a301f181ac55d71598a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Wed, 16 Sep 2015 15:23:01 +0200 Subject: [PATCH 087/192] minor getLangText edition --- .../file_drag_and_drop_preview_progress.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview_progress.js b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview_progress.js index 1427fcb6..1f1fd421 100644 --- a/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview_progress.js +++ b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview_progress.js @@ -5,6 +5,7 @@ import React from 'react'; import ProgressBar from 'react-bootstrap/lib/ProgressBar'; import { displayValidProgressFilesFilter } from '../react_s3_fine_uploader_utils'; +import { getLangText } from '../../../utils/lang_utils'; let FileDragAndDropPreviewProgress = React.createClass({ @@ -54,7 +55,7 @@ let FileDragAndDropPreviewProgress = React.createClass({ return ( ); From d888bb8a5416f55eb3aeb863f4e2d81b9542b5dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Wed, 16 Sep 2015 15:52:54 +0200 Subject: [PATCH 088/192] PR Feedback: remove unnecessary DnD functions --- .../file_drag_and_drop.js | 42 +------------------ 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js index 1e21aeb8..4c9211c5 100644 --- a/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js +++ b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js @@ -12,14 +12,8 @@ import { getLangText } from '../../../utils/lang_utils'; // Taken from: https://github.com/fedosejev/react-file-drag-and-drop let FileDragAndDrop = React.createClass({ propTypes: { - onDragStart: React.PropTypes.func, onDrop: React.PropTypes.func.isRequired, - onDrag: React.PropTypes.func, - onDragEnter: React.PropTypes.func, - onLeave: React.PropTypes.func, - onDragLeave: React.PropTypes.func, onDragOver: React.PropTypes.func, - onDragEnd: React.PropTypes.func, onInactive: React.PropTypes.func, filesToUpload: React.PropTypes.array, handleDeleteFile: React.PropTypes.func, @@ -49,36 +43,6 @@ let FileDragAndDrop = React.createClass({ allowedExtensions: React.PropTypes.string }, - handleDragStart(event) { - if (typeof this.props.onDragStart === 'function') { - this.props.onDragStart(event); - } - }, - - handleDrag(event) { - if (typeof this.props.onDrag === 'function') { - this.props.onDrag(event); - } - }, - - handleDragEnd(event) { - if (typeof this.props.onDragEnd === 'function') { - this.props.onDragEnd(event); - } - }, - - handleDragEnter(event) { - if (typeof this.props.onDragEnter === 'function') { - this.props.onDragEnter(event); - } - }, - - handleDragLeave(event) { - if (typeof this.props.onDragLeave === 'function') { - this.props.onDragLeave(event); - } - }, - handleDragOver(event) { event.preventDefault(); @@ -207,13 +171,9 @@ let FileDragAndDrop = React.createClass({ return (
+ onDrop={this.handleDrop}> Date: Wed, 16 Sep 2015 18:31:46 +0200 Subject: [PATCH 089/192] implement ikonotv landing page according to mockups --- .../components/ikonotv/ikonotv_landing.js | 106 ++++++++++++++++++ .../whitelabel/wallet/wallet_routes.js | 4 +- sass/whitelabel/index.scss | 1 + .../wallet/ikonotv/ikonotv_landing.scss | 81 +++++++++++++ 4 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js create mode 100644 sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js new file mode 100644 index 00000000..81f52e5e --- /dev/null +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js @@ -0,0 +1,106 @@ +'use strict'; + +import React from 'react'; + +import ButtonLink from 'react-router-bootstrap/lib/ButtonLink'; + +import UserActions from '../../../../../actions/user_actions'; +import UserStore from '../../../../../stores/user_store'; + +import { getLangText } from '../../../../../utils/lang_utils'; + + +let IkonotvLanding = React.createClass({ + + getInitialState() { + return UserStore.getState(); + }, + + componentDidMount() { + UserStore.listen(this.onChange); + }, + + componentWillUnmount() { + UserStore.unlisten(this.onChange); + }, + + onChange(state) { + this.setState(state); + }, + + getEnterButton() { + console.log(this.state.currentUser); + if(this.state.currentUser && this.state.currentUser.email) { + return ( + + {getLangText('ENTER')} + + ); + } else { + return ( + + {getLangText('ENTER')} + + ); + } + }, + + render() { + return ( +
+
+ +
+

PROTECT

+ +

& SHARE

+
+

Welcome to the ikonoTV

+

Registration Page

+
+
+
+

+ ONLINE-ONLY FOR YOUR PROTECTION +

+

+ As an entirely digital broadcasting and licensing company we’re always keen to properly handle the content that artists, museums, and archives consign to us. The main concern with art online is the risk it will be misused. Thanks to our partnership with ascribe.io, we can address that issue in a way that is faster and more efficient for our users. + Using ascribe means we can do away with paper contracts and replace them with an online-only version. Partnering with ascribe also means we can encrypt digital work once it is uploaded. This revolutionary service will allow you to keep track of your works and share without worry. +

+
+
+

+ NEW SUBSCRIPTION SERVICE +

+

+ IkonoTV has developed an app that provides playlists on demand—soon to be available on all online devices and SmartTVs. The app is a paid service; in view of the interest in distributing this service in public spaces (hospitals, airports, hotels, etc.), we can now offer the possibility of a share in revenue to compensate for the artist’s work. +

+
+
+

+ THE RAPID GROWTH OF IkonoTV +

+

+ In October 2014, our first app was installed on Amazon Fire TV. During the first month it was downloaded 200 times, and jumped to 5,000 by the second month. Today, we’re well over the 175,000 mark, making us the number one app in our category in the US, Canada, UK and Germany. +

+
+
+

+ FULL TRANSPARENCY +

+

+ We expect a similar success with each SmartTV brand. For us, this marks the beginning of a new way to offer hassle-free licensing to visual artists—and we’re very proud to be an integral part of this virtual market. In the future, should we plan anything not directly mentioned in the contract, we will always make sure to secure the artist’s approval first. ikonoTV was developed to serve art and artists, and for this reason it’s of the utmost importance to us to respect this relationship. Thanks to you, we now look forward to our next big step. +

+
+
+

Elizabeth Markevitch

+

Founder & CEO Markevitch Media GmbH

+ {this.getEnterButton()} +
+
+
+ ); + } +}); + +export default IkonotvLanding; \ No newline at end of file diff --git a/js/components/whitelabel/wallet/wallet_routes.js b/js/components/whitelabel/wallet/wallet_routes.js index 25fc1d80..9434615f 100644 --- a/js/components/whitelabel/wallet/wallet_routes.js +++ b/js/components/whitelabel/wallet/wallet_routes.js @@ -19,6 +19,7 @@ import CylandPieceContainer from './components/cyland/ascribe_detail/cyland_piec import CylandRegisterPiece from './components/cyland/cyland_register_piece'; import CylandPieceList from './components/cyland/cyland_piece_list'; +import IkonotvLanding from './components/ikonotv/ikonotv_landing'; import IkonotvPieceList from './components/ikonotv/ikonotv_piece_list'; import IkonotvRequestLoan from './components/ikonotv/ikonotv_request_loan'; import IkonotvPieceContainer from './components/ikonotv/ascribe_detail/ikonotv_piece_container'; @@ -66,8 +67,7 @@ let ROUTES = { ), 'ikonotv': ( - - + diff --git a/sass/whitelabel/index.scss b/sass/whitelabel/index.scss index 54b9f41e..9fa1b68f 100644 --- a/sass/whitelabel/index.scss +++ b/sass/whitelabel/index.scss @@ -1 +1,2 @@ @import 'prize/index'; +@import 'wallet/ikonotv/ikonotv_landing'; \ No newline at end of file diff --git a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss new file mode 100644 index 00000000..b0d60983 --- /dev/null +++ b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss @@ -0,0 +1,81 @@ +.ikonotv-landing { + /* center all text on the page */ + text-align: center; + background-color: #c40050; + color: white; + + padding: 5em 5em 5em 5em; + + header { + /* center all images on the page */ + img { + display: block; + margin-left: auto; + margin-right: auto; + } + + /* Ikonotv logo */ + img:first-child { + width: 200px; + } + + > .tagline { + margin-top: 2em; + margin-bottom: 2em; + + > h1 { + font-size: 9em; + font-weight: bold; + + margin-top: 10px; + margin-bottom: 10px; + } + } + + > h2 { + font-weight: 600; + font-size: 2.75em; + } + + > h2 + h2 { + margin-top: 0; + } + } + + article { + > section { + width: 65%; + margin: 3em auto 1em auto; + + > h1 { + text-align: center; + font-size: 1.35em; + font-weight: 600; + } + + > p { + text-align: left; + font-size: 1.3em; + line-height: 1.8; + } + } + } + + footer { + margin-top: 5em; + margin-bottom: 3em; + + > p { + font-size: 1.3em; + } + + > p + p { + margin-bottom: 3em; + } + + > .btn-default { + font-size: 1.5em; + font-weight: 500; + } + } +} \ No newline at end of file From a36cc9d782a704ac412a1e38d365c770fb6537f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Wed, 16 Sep 2015 18:32:34 +0200 Subject: [PATCH 090/192] minor correction --- .../whitelabel/wallet/components/ikonotv/ikonotv_landing.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js index 81f52e5e..1e2d3803 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js @@ -29,7 +29,6 @@ let IkonotvLanding = React.createClass({ }, getEnterButton() { - console.log(this.state.currentUser); if(this.state.currentUser && this.state.currentUser.email) { return ( From a85447e94c3df3ac14e7aa044369c4b14302ffb0 Mon Sep 17 00:00:00 2001 From: diminator Date: Wed, 16 Sep 2015 19:00:59 +0200 Subject: [PATCH 091/192] bug fix user token on signup/login --- js/components/ascribe_forms/form_login.js | 6 ++++-- js/components/ascribe_forms/form_signup.js | 10 +++++++++- .../components/ikonotv/ikonotv_register_piece.js | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/js/components/ascribe_forms/form_login.js b/js/components/ascribe_forms/form_login.js index 86a20119..1c6fd0ad 100644 --- a/js/components/ascribe_forms/form_login.js +++ b/js/components/ascribe_forms/form_login.js @@ -27,7 +27,7 @@ let LoginForm = React.createClass({ onLogin: React.PropTypes.func }, - mixins: [Router.Navigation], + mixins: [Router.Navigation, Router.State], getDefaultProps() { return { @@ -95,6 +95,7 @@ let LoginForm = React.createClass({ }, render() { + let email = this.getQuery().email ? this.getQuery().email : null; return (
diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js index 6a2acbb8..6be9f9f6 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js @@ -178,7 +178,7 @@ let IkonotvRegisterPiece = React.createClass({ 0} enableLocalHashing={false} - headerMessage={getLangText('Submit to Cyland Archive')} + headerMessage={getLangText('Submit to IkonoTV')} submitMessage={getLangText('Submit')} isFineUploaderActive={this.state.isFineUploaderActive} handleSuccess={this.handleRegisterSuccess} From 48508d5756f96774c0ee7edd6b7ee1dad01f4bd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Wed, 16 Sep 2015 21:21:30 +0200 Subject: [PATCH 092/192] Implement filter display for piece list --- .../ascribe_accordion_list/accordion_list.js | 2 +- js/components/piece_list.js | 8 ++-- js/components/piece_list_filter_display.js | 45 +++++++++++++++++++ sass/ascribe_accordion_list.scss | 4 ++ sass/main.scss | 20 +++++++++ 5 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 js/components/piece_list_filter_display.js diff --git a/js/components/ascribe_accordion_list/accordion_list.js b/js/components/ascribe_accordion_list/accordion_list.js index 471ba9d5..fe300702 100644 --- a/js/components/ascribe_accordion_list/accordion_list.js +++ b/js/components/ascribe_accordion_list/accordion_list.js @@ -21,7 +21,7 @@ let AccordionList = React.createClass({ ); } else if(this.props.count === 0) { return ( -
+

{getLangText('We could not find any works related to you...')}

{getLangText('To register one, click')} {getLangText('here')}!

diff --git a/js/components/piece_list.js b/js/components/piece_list.js index 71304a63..c7cab0f4 100644 --- a/js/components/piece_list.js +++ b/js/components/piece_list.js @@ -15,6 +15,8 @@ import AccordionListItemTableEditions from './ascribe_accordion_list/accordion_l import Pagination from './ascribe_pagination/pagination'; +import PieceListFilterDisplay from './piece_list_filter_display'; + import GlobalAction from './global_action'; import PieceListBulkModal from './ascribe_piece_list_bulk_modal/piece_list_bulk_modal'; import PieceListToolbar from './ascribe_piece_list_toolbar/piece_list_toolbar'; @@ -22,6 +24,8 @@ import PieceListToolbar from './ascribe_piece_list_toolbar/piece_list_toolbar'; import AppConstants from '../constants/application_constants'; import { mergeOptions } from '../utils/general_utils'; +import { getLangText } from '../utils/lang_utils'; + let PieceList = React.createClass({ propTypes: { @@ -149,9 +153,6 @@ let PieceList = React.createClass({ let loadingElement = (); let AccordionListItemType = this.props.accordionListItemType; - // - - return (
+ filter.split('acl_')[1]).join(', '); + + // there are acls, like acl_create_editions that still have underscores in them, + // therefore we need to replace all underscores with spaces + return filterText.replace(/_/g, ' '); + }, + + render() { + let { filterBy } = this.props; + + // do not show the FilterDisplay if there are no filters applied + if(filterBy && Object.keys(filterBy).length === 0) { + return null; + } else { + return ( +
+
+ {this.getFilterText()} +
+
+
+ ); + } + } +}); + +export default PieceListFilterDisplay; \ No newline at end of file diff --git a/sass/ascribe_accordion_list.scss b/sass/ascribe_accordion_list.scss index 6412a598..86a519b5 100644 --- a/sass/ascribe_accordion_list.scss +++ b/sass/ascribe_accordion_list.scss @@ -5,6 +5,10 @@ $ascribe-accordion-list-item-height: 8em; padding-right: 15px; } +.ascribe-accordion-list-placeholder { + margin-top: 1em; +} + .ascribe-accordion-list-item { background-color: white; border: 1px solid black; diff --git a/sass/main.scss b/sass/main.scss index 5f5c0f23..39ea78bd 100644 --- a/sass/main.scss +++ b/sass/main.scss @@ -487,3 +487,23 @@ hr { .ascribe-progress-bar-xs { height: 12px; } + + +.ascribe-piece-list-filter-display { + padding-left: 0; + padding-right: 0; + + > span { + font-size: 1.1em; + font-weight: 600; + color: #616161; + + padding-left: .3em; + } + + > hr { + margin-top: .15em; + margin-bottom: .1em; + border-color: #ccc; + } +} \ No newline at end of file From 5c2ec3ffb0f2b558ca8f6a9d55303908e6d7e116 Mon Sep 17 00:00:00 2001 From: diminator Date: Wed, 16 Sep 2015 23:27:38 +0200 Subject: [PATCH 093/192] bug fix signup query landing page redirect ikono: user acl proxy on submit button ikono: further details + slides --- js/components/ascribe_forms/form_loan.js | 6 +- js/components/ascribe_forms/form_signup.js | 1 - .../slides_container.js | 4 +- js/components/signup_container.js | 9 + .../ikonotv_accordion_list_item.js | 14 +- .../ascribe_detail/ikonotv_piece_container.js | 137 +++++++-------- ...form.js => ikonotv_artist_details_form.js} | 44 +++-- .../ikonotv_artwork_details_form.js | 164 ++++++++++++++++++ .../ikonotv/ikonotv_contract_notifications.js | 4 +- .../components/ikonotv/ikonotv_landing.js | 31 ++-- .../ikonotv/ikonotv_register_piece.js | 128 ++++++++++---- js/components/whitelabel/wallet/wallet_app.js | 2 +- 12 files changed, 395 insertions(+), 149 deletions(-) rename js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/{ikonotv_additional_data_form.js => ikonotv_artist_details_form.js} (64%) create mode 100644 js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index a1c31330..0c60fd7b 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -35,6 +35,7 @@ let LoanForm = React.createClass({ url: React.PropTypes.string, id: React.PropTypes.object, message: React.PropTypes.string, + createPublicContractAgreement: React.PropTypes.bool, handleSuccess: React.PropTypes.func }, @@ -44,7 +45,8 @@ let LoanForm = React.createClass({ showPersonalMessage: true, showEndDate: true, showStartDate: true, - showPassword: true + showPassword: true, + createPublicContractAgreement: true }; }, @@ -82,7 +84,7 @@ let LoanForm = React.createClass({ if (email) { ContractAgreementListActions.fetchAvailableContractAgreementList(email).then( (contractAgreementList) => { - if (!contractAgreementList) { + if (!contractAgreementList && this.props.createPublicContractAgreement) { ContractAgreementListActions.createContractAgreementFromPublicContract(email); } } diff --git a/js/components/ascribe_forms/form_signup.js b/js/components/ascribe_forms/form_signup.js index 8b4e4cf7..928afe38 100644 --- a/js/components/ascribe_forms/form_signup.js +++ b/js/components/ascribe_forms/form_signup.js @@ -67,7 +67,6 @@ let SignupForm = React.createClass({ }, getFormData() { - console.log(this.getQuery()); if (this.getQuery().token){ return {token: this.getQuery().token}; } diff --git a/js/components/ascribe_slides_container/slides_container.js b/js/components/ascribe_slides_container/slides_container.js index 84dff61c..53092a38 100644 --- a/js/components/ascribe_slides_container/slides_container.js +++ b/js/components/ascribe_slides_container/slides_container.js @@ -178,7 +178,7 @@ let SlidesContainer = React.createClass({ let breadcrumbs = []; ReactAddons.Children.map(this.props.children, (child, i) => { - if(i >= this.state.startFrom && child.props['data-slide-title']) { + if(child && i >= this.state.startFrom && child.props['data-slide-title']) { breadcrumbs.push(child.props['data-slide-title']); } }); @@ -229,7 +229,7 @@ let SlidesContainer = React.createClass({ // since the default parameter of startFrom is -1, we do not need to check // if its actually present in the url bar, as it will just not match - if(i >= this.state.startFrom) { + if(child && i >= this.state.startFrom) { return ReactAddons.addons.cloneWithProps(child, { className: 'ascribe-slide', style: { diff --git a/js/components/signup_container.js b/js/components/signup_container.js index 46813b59..856e4af2 100644 --- a/js/components/signup_container.js +++ b/js/components/signup_container.js @@ -1,8 +1,12 @@ 'use strict'; import React from 'react'; +import Router from 'react-router'; import SignupForm from './ascribe_forms/form_signup'; +import { getLangText } from '../utils/lang_utils'; + +let Link = Router.Link; let SignupContainer = React.createClass({ getInitialState() { @@ -33,7 +37,12 @@ let SignupContainer = React.createClass({ return (
+
+ {getLangText('Already an ascribe user')}? {getLangText('Log in')}...
+ {getLangText('Forgot my password')}? {getLangText('Rescue me')}... +
+ ); } }); diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_accordion_list/ikonotv_accordion_list_item.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_accordion_list/ikonotv_accordion_list_item.js index b716914a..2dd3cc2f 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_accordion_list/ikonotv_accordion_list_item.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_accordion_list/ikonotv_accordion_list_item.js @@ -63,12 +63,16 @@ let IkonotvAccordionListItem = React.createClass({ return (
- + + + 0) { - return ( - ); - } - else { - - //We need to disable the normal acl_loan because we're inserting a custom acl_loan button - let availableAcls; - - if(this.state.piece && this.state.piece.acl && typeof this.state.piece.acl.acl_loan !== 'undefined') { - // make a copy to not have side effects - availableAcls = mergeOptions({}, this.state.piece.acl); - availableAcls.acl_loan = false; - } - - return ( - - - - - - - ); - } - }, - render() { if(this.state.piece && this.state.piece.title) { return ( @@ -152,14 +87,29 @@ let IkonotvPieceContainer = React.createClass({
- } - buttons={this.getActions()}> + }> + 0}> + + {return {'id': this.state.piece.id}; }} + label={getLangText('Personal note (private)')} + defaultValue={this.state.piece.private_note ? this.state.piece.private_note : null} + placeholder={getLangText('Enter your comments ...')} + editable={true} + successMessage={getLangText('Private note saved')} + url={ApiUrls.note_private_piece} + currentUser={this.state.currentUser}/> + + ); } else { @@ -172,4 +122,43 @@ let IkonotvPieceContainer = React.createClass({ } }); + +let IkonotvPieceDetails = React.createClass({ + propTypes: { + piece: React.PropTypes.object + }, + + render() { + if (this.props.piece && Object.keys(this.props.piece.extra_data).length !== 0){ + return ( + + + {Object.keys(this.props.piece.extra_data).map((data, i) => { + let label = data.replace('_', ' '); + return ( + ); + } + )} +
+ +
+ ); + } + return null; + } +}); + export default IkonotvPieceContainer; diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_additional_data_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js similarity index 64% rename from js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_additional_data_form.js rename to js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js index 6f249c7b..cd98a94c 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_additional_data_form.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js @@ -15,10 +15,9 @@ import AppConstants from '../../../../../../constants/application_constants'; import requests from '../../../../../../utils/requests'; import { getLangText } from '../../../../../../utils/lang_utils'; -//import { formSubmissionValidation } from '../../../../../ascribe_uploader/react_s3_fine_uploader_utils'; -let IkonotvAdditionalDataForm = React.createClass({ +let IkonotvArtistDetailsForm = React.createClass({ propTypes: { handleSuccess: React.PropTypes.func.isRequired, piece: React.PropTypes.object.isRequired, @@ -77,7 +76,7 @@ let IkonotvAdditionalDataForm = React.createClass({ type="submit" className="btn ascribe-btn ascribe-btn-login" disabled={!this.state.isUploadReady || this.props.disabled}> - {getLangText('Proceed to loan')} + {getLangText('Proceed to artwork details')} } spinner={ @@ -87,28 +86,49 @@ let IkonotvAdditionalDataForm = React.createClass({ }>

- {getLangText('Provide supporting materials')} + {getLangText('Artist Details')}

+ defaultValue={this.props.piece.extra_data.artist_website} + placeholder={getLangText('The artist\'s website if present...')}/> + + + + + + + defaultValue={this.props.piece.extra_data.conceptual_overview} + placeholder={getLangText('Enter a short bio about the Artist')} + /> ); @@ -122,4 +142,4 @@ let IkonotvAdditionalDataForm = React.createClass({ } }); -export default IkonotvAdditionalDataForm; \ No newline at end of file +export default IkonotvArtistDetailsForm; \ No newline at end of file diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js new file mode 100644 index 00000000..ffaa8fa5 --- /dev/null +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js @@ -0,0 +1,164 @@ +'use strict'; + +import React from 'react'; + +import Form from '../../../../../ascribe_forms/form'; +import Property from '../../../../../ascribe_forms/property'; + +import InputTextAreaToggable from '../../../../../ascribe_forms/input_textarea_toggable'; + +//import FurtherDetailsFileuploader from '../../../../../ascribe_detail/further_details_fileuploader'; + +import ApiUrls from '../../../../../../constants/api_urls'; +import AppConstants from '../../../../../../constants/application_constants'; + +import requests from '../../../../../../utils/requests'; + +import { getLangText } from '../../../../../../utils/lang_utils'; + + +let IkonotvArtworkDetailsForm = React.createClass({ + propTypes: { + handleSuccess: React.PropTypes.func.isRequired, + piece: React.PropTypes.object.isRequired, + + disabled: React.PropTypes.bool + }, + + getInitialState() { + return { + isUploadReady: true + }; + }, + + getFormData() { + let extradata = {}; + let formRefs = this.refs.form.refs; + + // Put additional fields in extra data object + Object + .keys(formRefs) + .forEach((fieldName) => { + extradata[fieldName] = formRefs[fieldName].state.value; + }); + + return { + extradata: extradata, + piece_id: this.props.piece.id + }; + + }, + + uploadStarted() { + this.setState({ + isUploadReady: false + }); + }, + + setIsUploadReady(isReady) { + this.setState({ + isUploadReady: isReady + }); + }, + + render() { + if(this.props.piece && this.props.piece.id) { + return ( +
+ {getLangText('Proceed to loan')} + + } + spinner={ +
+ +
+ }> +
+

+ {getLangText('Artwork Details')} +

+
+ + + + + + + + + + + + + + + + + + +
+ ); + } else { + return ( +
+ +
+ ); + } + } +}); + +export default IkonotvArtworkDetailsForm; \ No newline at end of file diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js index beffe23a..60ec2208 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js @@ -12,6 +12,7 @@ import NotificationStore from '../../../../../stores/notification_store'; import UserStore from '../../../../../stores/user_store'; import WhitelabelStore from '../../../../../stores/whitelabel_store'; +import WhitelabelActions from '../../../../../actions/whitelabel_actions'; import GlobalNotificationModel from '../../../../../models/global_notification_model'; import GlobalNotificationActions from '../../../../../actions/global_notification_actions'; @@ -42,6 +43,7 @@ let IkonotvContractNotifications = React.createClass({ NotificationStore.listen(this.onChange); UserStore.listen(this.onChange); WhitelabelStore.listen(this.onChange); + WhitelabelActions.fetchWhitelabel(); if (this.state.contractAgreementListNotifications === null){ NotificationActions.fetchContractAgreementListNotifications(); } @@ -90,7 +92,7 @@ let IkonotvContractNotifications = React.createClass({ getAppendix() { let notifications = this.state.contractAgreementListNotifications[0]; let appendix = notifications.contract_agreement.appendix; - if (appendix) { + if (appendix && appendix.default) { return (

{getLangText('Appendix')}

diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js index 1e2d3803..7abfd62c 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js @@ -1,10 +1,10 @@ 'use strict'; import React from 'react'; +import Router from 'react-router'; import ButtonLink from 'react-router-bootstrap/lib/ButtonLink'; -import UserActions from '../../../../../actions/user_actions'; import UserStore from '../../../../../stores/user_store'; import { getLangText } from '../../../../../utils/lang_utils'; @@ -12,6 +12,8 @@ import { getLangText } from '../../../../../utils/lang_utils'; let IkonotvLanding = React.createClass({ + mixins: [Router.Navigation, Router.State], + getInitialState() { return UserStore.getState(); }, @@ -29,19 +31,20 @@ let IkonotvLanding = React.createClass({ }, getEnterButton() { + let redirect = 'signup'; + if(this.state.currentUser && this.state.currentUser.email) { - return ( - - {getLangText('ENTER')} - - ); - } else { - return ( - - {getLangText('ENTER')} - - ); + redirect = 'pieces'; } + else if (this.getQuery() && this.getQuery().redirect) { + redirect = this.getQuery().redirect; + } + console.log(redirect); + return ( + + {getLangText('ENTER')} + + ); }, render() { @@ -52,7 +55,7 @@ let IkonotvLanding = React.createClass({

PROTECT

-

& SHARE

+

& SHARE

Welcome to the ikonoTV

Registration Page

@@ -93,7 +96,7 @@ let IkonotvLanding = React.createClass({

Elizabeth Markevitch

-

Founder & CEO Markevitch Media GmbH

+

Founder & CEO Markevitch Media GmbH

{this.getEnterButton()}
diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js index 6be9f9f6..ecb594c5 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js @@ -21,7 +21,9 @@ import GlobalNotificationActions from '../../../../../actions/global_notificatio import RegisterPieceForm from '../../../../ascribe_forms/form_register_piece'; import LoanForm from '../../../../ascribe_forms/form_loan'; -import IkonotvAdditionalDataForm from './ascribe_forms/ikonotv_additional_data_form'; + +import IkonotvArtistDetailsForm from './ascribe_forms/ikonotv_artist_details_form'; +import IkonotvArtworkDetailsForm from './ascribe_forms/ikonotv_artwork_details_form'; import SlidesContainer from '../../../../ascribe_slides_container/slides_container'; @@ -95,10 +97,14 @@ let IkonotvRegisterPiece = React.createClass({ if(response && response.piece) { PieceActions.updatePiece(response.piece); } + if (!this.canSubmit()) { + this.transitionTo('pieces'); + } + else { + this.incrementStep(); + this.refs.slidesContainer.nextSlide(); + } - this.incrementStep(); - - this.refs.slidesContainer.nextSlide(); }, handleAdditionalDataSuccess() { @@ -158,12 +164,83 @@ let IkonotvRegisterPiece = React.createClass({ this.transitionTo('login'); }, + canSubmit() { + if (this.state.currentUser && this.state.currentUser.acl) { + return ( + this.state.currentUser + && this.state.currentUser.acl + && !!this.state.currentUser.acl.acl_submit + ); + } + return false; + }, + + getSlideArtistDetails() { + if (this.canSubmit()) { + return ( +
+ + + 1} + handleSuccess={this.handleAdditionalDataSuccess} + piece={this.state.piece}/> + + +
+ ); + } + return null; + }, + + getSlideArtworkDetails() { + if (this.canSubmit()) { + return ( +
+ + + 1} + handleSuccess={this.handleAdditionalDataSuccess} + piece={this.state.piece}/> + + +
+ ); + } + return null; + }, + + getSlideLoan() { + if (this.canSubmit()) { + + let today = new Moment(); + let enddate = new Moment(); + enddate.add(1, 'years'); + return ( +
+ + + + + +
+ ); + } + return null; + }, + render() { - - let today = new Moment(); - let enddate = new Moment(); - enddate.add(1, 'years'); - return ( 0} enableLocalHashing={false} - headerMessage={getLangText('Submit to IkonoTV')} - submitMessage={getLangText('Submit')} + headerMessage={getLangText('Register work')} + submitMessage={getLangText('Register')} isFineUploaderActive={this.state.isFineUploaderActive} handleSuccess={this.handleRegisterSuccess} onLoggedOut={this.onLoggedOut} />
-
- - - 1} - handleSuccess={this.handleAdditionalDataSuccess} - piece={this.state.piece}/> - - -
-
- - - - - -
+ {this.getSlideArtistDetails()} + {this.getSlideArtworkDetails()} + {this.getSlideLoan()} ); } diff --git a/js/components/whitelabel/wallet/wallet_app.js b/js/components/whitelabel/wallet/wallet_app.js index 06bac15f..9a742f8b 100644 --- a/js/components/whitelabel/wallet/wallet_app.js +++ b/js/components/whitelabel/wallet/wallet_app.js @@ -19,7 +19,7 @@ let WalletApp = React.createClass({ let ROUTES = getRoutes(null, subdomain); let header = null; - if ((this.isActive('landing') || this.isActive('login') || this.isActive('signup')) + if ((this.isActive('landing') || this.isActive('login') || this.isActive('signup') || this.isActive('contract_notifications')) && (['ikonotv', 'cyland']).indexOf(subdomain) > -1) { header = (
); From a96aa1005fba0db7dd770ef2f0872e897adbcc83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Wed, 16 Sep 2015 23:36:21 +0200 Subject: [PATCH 094/192] Make PieceListToolbar filters generic --- .../piece_list_toolbar.js | 7 +- .../piece_list_toolbar_filter_widget.js | 71 +++++++++++-------- js/components/piece_list.js | 18 +++-- js/components/piece_list_filter_display.js | 66 ++++++++++++++--- sass/ascribe_piece_list_toolbar.scss | 10 ++- sass/main.scss | 4 +- 6 files changed, 126 insertions(+), 50 deletions(-) diff --git a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js index 233f4089..ea609155 100644 --- a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js +++ b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js @@ -14,7 +14,12 @@ let PieceListToolbar = React.createClass({ propTypes: { className: React.PropTypes.string, searchFor: React.PropTypes.func, - filterParams: React.PropTypes.array, + filterParams: React.PropTypes.arrayOf( + React.PropTypes.shape({ + label: React.PropTypes.string, + items: React.PropTypes.array + }) + ), filterBy: React.PropTypes.object, applyFilterBy: React.PropTypes.func, orderParams: React.PropTypes.array, diff --git a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js index 2520c499..9591f970 100644 --- a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js +++ b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js @@ -16,7 +16,12 @@ let PieceListToolbarFilterWidgetFilter = React.createClass({ // label: // } // - filterParams: React.PropTypes.arrayOf(React.PropTypes.any).isRequired, + filterParams: React.PropTypes.arrayOf( + React.PropTypes.shape({ + label: React.PropTypes.string, + items: React.PropTypes.array + }) + ).isRequired, filterBy: React.PropTypes.object, applyFilterBy: React.PropTypes.func }, @@ -79,35 +84,43 @@ let PieceListToolbarFilterWidgetFilter = React.createClass({ -
  • - {getLangText('Show works I can')}: -
  • - {this.props.filterParams.map((param, i) => { - let label; - - if(typeof param !== 'string') { - label = param.label; - param = param.key; - } else { - param = param; - label = param.split('_')[1]; - } - + {this.props.filterParams.map(({ label, items }, i) => { return ( - -
    - - {getLangText(label)} - - -
    -
    +
    +
  • + {label}: +
  • + {items.map((param, j) => { + let label; + + if(typeof param !== 'string') { + label = param.label; + param = param.key; + } else { + param = param; + label = param.split('_')[1]; + } + + return ( +
  • +
    + + {getLangText(label)} + + +
    +
  • + ); + })} +
    ); })}
    diff --git a/js/components/piece_list.js b/js/components/piece_list.js index c7cab0f4..dd8ee91e 100644 --- a/js/components/piece_list.js +++ b/js/components/piece_list.js @@ -35,7 +35,6 @@ let PieceList = React.createClass({ filterParams: React.PropTypes.array, orderParams: React.PropTypes.array, orderBy: React.PropTypes.string - }, mixins: [Router.Navigation, Router.State], @@ -44,13 +43,20 @@ let PieceList = React.createClass({ return { accordionListItemType: AccordionListItemWallet, orderParams: ['artist_name', 'title'], - filterParams: [ + filterParams: [{ + label: getLangText('Show works I can'), + items: [ 'acl_transfer', 'acl_consign', { key: 'acl_create_editions', label: 'create editions' }] + }, + { + label: getLangText('Show works I have'), + items: ['acl_loaned'] + }] }; }, getInitialState() { @@ -95,8 +101,8 @@ let PieceList = React.createClass({ // the site should go to the top document.body.scrollTop = document.documentElement.scrollTop = 0; PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search, - this.state.orderBy, this.state.orderAsc, - this.state.filterBy); + this.state.orderBy, this.state.orderAsc, + this.state.filterBy); }; }, @@ -167,7 +173,9 @@ let PieceList = React.createClass({ {this.props.customSubmitButton} - + filter.split('acl_')[1]).join(', '); + return filterParams.map((filterParam) => { + return { + label: filterParam.label, + items: filterParam.items.map((item) => { + if(typeof item !== 'string' && typeof item.key === 'string' && typeof item.label === 'string') { + return { + key: item.key, + label: item.label, + value: filterBy[item.key] ? filterBy[item.key] : false + }; + } else { + return { + key: item, + label: item.split('acl_')[1].replace(/_/g, ' '), + value: filterBy[item] ? filterBy[item] : false + } + } + }) + } + }); + }, - // there are acls, like acl_create_editions that still have underscores in them, - // therefore we need to replace all underscores with spaces - return filterText.replace(/_/g, ' '); + getFilterText(filtersWithLabel) { + let filterTextList = filtersWithLabel + .map((filterWithLabel) => { + let activeFilterWithLabel = filterWithLabel + .items + .map((filter) => { + if(filter.value) { + return filter.label; + } + }) + .filter((filterName) => !!filterName) + .join(', '); + + if(activeFilterWithLabel) { + return filterWithLabel.label + ': ' + activeFilterWithLabel + } + }) + .filter((filterText) => !!filterText) + // if there are multiple sentences, capitalize the first one and lowercase the others + .map((filterText, i) => i === 0 ? filterText.charAt(0).toUpperCase() + filterText.substr(1) : filterText.charAt(0).toLowerCase() + filterText.substr(1)) + .join(' and '); + + return filterTextList; }, render() { let { filterBy } = this.props; + let filtersWithLabel = this.transformFilterParamsItemsToBools(); // do not show the FilterDisplay if there are no filters applied if(filterBy && Object.keys(filterBy).length === 0) { @@ -33,7 +77,7 @@ let PieceListFilterDisplay = React.createClass({ return (
    - {this.getFilterText()} + {this.getFilterText(filtersWithLabel)}
    diff --git a/sass/ascribe_piece_list_toolbar.scss b/sass/ascribe_piece_list_toolbar.scss index aeec1bff..dde7f2f0 100644 --- a/sass/ascribe_piece_list_toolbar.scss +++ b/sass/ascribe_piece_list_toolbar.scss @@ -54,8 +54,7 @@ } .filter-widget-item { - - > a { + a { padding-left: 0; padding-right: 0; } @@ -64,6 +63,13 @@ .checkbox-line { height: 25px; position: relative; + color: #333333; + + /* Fuck you react-bootstrap */ + &:hover { + background-color: $dropdown-link-hover-bg; + cursor: pointer; + } span { cursor: pointer; diff --git a/sass/main.scss b/sass/main.scss index 39ea78bd..e7170b6d 100644 --- a/sass/main.scss +++ b/sass/main.scss @@ -490,8 +490,8 @@ hr { .ascribe-piece-list-filter-display { - padding-left: 0; - padding-right: 0; + padding-left: 10px; + padding-right: 10px; > span { font-size: 1.1em; From 67e0b3464089ac4f7586690f10aaf1290951cbad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Thu, 17 Sep 2015 10:06:47 +0200 Subject: [PATCH 095/192] integrate filtering into IkonoTv and Cyland whitelabel --- js/components/piece_list.js | 4 ---- .../wallet/components/cyland/cyland_piece_list.js | 9 +++++++++ .../wallet/components/ikonotv/ikonotv_piece_list.js | 11 ++++++++++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/js/components/piece_list.js b/js/components/piece_list.js index dd8ee91e..7ecbd0f0 100644 --- a/js/components/piece_list.js +++ b/js/components/piece_list.js @@ -52,10 +52,6 @@ let PieceList = React.createClass({ key: 'acl_create_editions', label: 'create editions' }] - }, - { - label: getLangText('Show works I have'), - items: ['acl_loaned'] }] }; }, diff --git a/js/components/whitelabel/wallet/components/cyland/cyland_piece_list.js b/js/components/whitelabel/wallet/components/cyland/cyland_piece_list.js index 018a3e55..3b1c70c0 100644 --- a/js/components/whitelabel/wallet/components/cyland/cyland_piece_list.js +++ b/js/components/whitelabel/wallet/components/cyland/cyland_piece_list.js @@ -8,6 +8,8 @@ import UserStore from '../../../../../stores/user_store'; import CylandAccordionListItem from './ascribe_accordion_list/cyland_accordion_list_item'; +import { getLangText } from '../../../../../utils/lang_utils'; + let CylandPieceList = React.createClass({ getInitialState() { @@ -33,6 +35,13 @@ let CylandPieceList = React.createClass({
    ); diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_piece_list.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_piece_list.js index 4c8766e4..33478fbf 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_piece_list.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_piece_list.js @@ -8,6 +8,9 @@ import UserStore from '../../../../../stores/user_store'; import IkonotvAccordionListItem from './ascribe_accordion_list/ikonotv_accordion_list_item'; +import { getLangText } from '../../../../../utils/lang_utils'; + + let IkonotvPieceList = React.createClass({ getInitialState() { return UserStore.getState(); @@ -32,7 +35,13 @@ let IkonotvPieceList = React.createClass({ + filterParams={[{ + label: getLangText('Show works I have'), + items: [{ + key: 'acl_loaned', + label: getLangText('loaned to IkonoTV') + }] + }]}/>
    ); } From ace465afad0b403206dc329ace1964475c954ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Thu, 17 Sep 2015 10:20:35 +0200 Subject: [PATCH 096/192] Improve PropTypes for PieceListToolbarFilterWidget --- .../piece_list_toolbar.js | 10 ++++++++- .../piece_list_toolbar_filter_widget.js | 21 +++++++++---------- js/components/piece_list_filter_display.js | 18 ++++++++++------ 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js index ea609155..0890db00 100644 --- a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js +++ b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar.js @@ -17,7 +17,15 @@ let PieceListToolbar = React.createClass({ filterParams: React.PropTypes.arrayOf( React.PropTypes.shape({ label: React.PropTypes.string, - items: React.PropTypes.array + items: React.PropTypes.arrayOf( + React.PropTypes.oneOfType([ + React.PropTypes.string, + React.PropTypes.shape({ + key: React.PropTypes.string, + label: React.PropTypes.string + }) + ]) + ) }) ), filterBy: React.PropTypes.object, diff --git a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js index 9591f970..eb36bbd5 100644 --- a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js +++ b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js @@ -3,23 +3,24 @@ import React from 'react'; import DropdownButton from 'react-bootstrap/lib/DropdownButton'; -import MenuItem from 'react-bootstrap/lib/MenuItem'; import { getLangText } from '../../utils/lang_utils.js'; + let PieceListToolbarFilterWidgetFilter = React.createClass({ propTypes: { - // An array of either strings (which represent acl enums) or objects of the form - // - // { - // key: , - // label: - // } - // filterParams: React.PropTypes.arrayOf( React.PropTypes.shape({ label: React.PropTypes.string, - items: React.PropTypes.array + items: React.PropTypes.arrayOf( + React.PropTypes.oneOfType([ + React.PropTypes.string, + React.PropTypes.shape({ + key: React.PropTypes.string, + label: React.PropTypes.string + }) + ]) + ) }) ).isRequired, filterBy: React.PropTypes.object, @@ -93,8 +94,6 @@ let PieceListToolbarFilterWidgetFilter = React.createClass({ {label}: {items.map((param, j) => { - let label; - if(typeof param !== 'string') { label = param.label; param = param.key; diff --git a/js/components/piece_list_filter_display.js b/js/components/piece_list_filter_display.js index 971adb82..e1cbf9bd 100644 --- a/js/components/piece_list_filter_display.js +++ b/js/components/piece_list_filter_display.js @@ -2,8 +2,6 @@ import React from 'react'; -import { getLangText } from '../utils/lang_utils'; - let PieceListFilterDisplay = React.createClass({ propTypes: { @@ -11,7 +9,15 @@ let PieceListFilterDisplay = React.createClass({ filterParams: React.PropTypes.arrayOf( React.PropTypes.shape({ label: React.PropTypes.string, - items: React.PropTypes.array + items: React.PropTypes.arrayOf( + React.PropTypes.oneOfType([ + React.PropTypes.string, + React.PropTypes.shape({ + key: React.PropTypes.string, + label: React.PropTypes.string + }) + ]) + ) }) ) }, @@ -34,10 +40,10 @@ let PieceListFilterDisplay = React.createClass({ key: item, label: item.split('acl_')[1].replace(/_/g, ' '), value: filterBy[item] ? filterBy[item] : false - } + }; } }) - } + }; }); }, @@ -55,7 +61,7 @@ let PieceListFilterDisplay = React.createClass({ .join(', '); if(activeFilterWithLabel) { - return filterWithLabel.label + ': ' + activeFilterWithLabel + return filterWithLabel.label + ': ' + activeFilterWithLabel; } }) .filter((filterText) => !!filterText) From ac09c721ca1fb2204478a231ee9a02df7ad0e669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Thu, 17 Sep 2015 10:41:23 +0200 Subject: [PATCH 097/192] Document PieceListToolbarFilterWidget and PieceListFilterDisplay --- .../piece_list_toolbar_filter_widget.js | 12 ++++++++++ js/components/piece_list_filter_display.js | 23 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js index eb36bbd5..07f66cd1 100644 --- a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js +++ b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js @@ -85,6 +85,8 @@ let PieceListToolbarFilterWidgetFilter = React.createClass({ + {/* We iterate over filterParams, to receive the label and then for each + label also iterate over its items, to get all filterable options */} {this.props.filterParams.map(({ label, items }, i) => { return (
    @@ -94,6 +96,16 @@ let PieceListToolbarFilterWidgetFilter = React.createClass({ {label}: {items.map((param, j) => { + + // As can be seen in the PropTypes, a param can either + // be a string or an object of the shape: + // + // { + // key: , + // label: + // } + // + // This is why we need to distinguish between both here. if(typeof param !== 'string') { label = param.label; param = param.key; diff --git a/js/components/piece_list_filter_display.js b/js/components/piece_list_filter_display.js index e1cbf9bd..e1c19bdd 100644 --- a/js/components/piece_list_filter_display.js +++ b/js/components/piece_list_filter_display.js @@ -22,6 +22,12 @@ let PieceListFilterDisplay = React.createClass({ ) }, + /** + * Takes the above described filterParams prop, + * assigns it it's true filterBy value that is derived from the filterBy prop + * and also - if there wasn't already one defined - generates a label + * @return {object} + */ transformFilterParamsItemsToBools() { let { filterParams, filterBy } = this.props; @@ -47,23 +53,40 @@ let PieceListFilterDisplay = React.createClass({ }); }, + /** + * Takes the list of filters generated in transformFilterParamsItemsToBools and + * transforms them into human readable text. + * @param {Object} filtersWithLabel An object of the shape {key: , label: , value: } + * @return {string} A human readable string + */ getFilterText(filtersWithLabel) { let filterTextList = filtersWithLabel + // Iterate over all provided filterLabels and generate a list + // of human readable strings .map((filterWithLabel) => { let activeFilterWithLabel = filterWithLabel .items + // If the filter is active (which it is when its value is true), + // we're going to include it's label into a list, + // otherwise we'll just return nothing .map((filter) => { if(filter.value) { return filter.label; } }) + // if nothing is returned, that index is 'undefined'. + // As we only want active filter, we filter out all falsy values e.g. undefined .filter((filterName) => !!filterName) + // and join the result to a string .join(', '); + // If this actually didn't generate an empty string, + // we take the label and concat it to the result. if(activeFilterWithLabel) { return filterWithLabel.label + ': ' + activeFilterWithLabel; } }) + // filter out strings that are undefined, as their filter's were not activated .filter((filterText) => !!filterText) // if there are multiple sentences, capitalize the first one and lowercase the others .map((filterText, i) => i === 0 ? filterText.charAt(0).toUpperCase() + filterText.substr(1) : filterText.charAt(0).toLowerCase() + filterText.substr(1)) From 32f38428f19e81a153addc6c1a06927725e98399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Thu, 17 Sep 2015 11:39:45 +0200 Subject: [PATCH 098/192] PR Feedback: Fix replacement of underscores in filterParams --- .../piece_list_toolbar_filter_widget.js | 2 +- js/components/piece_list.js | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js index 07f66cd1..9cb8b94f 100644 --- a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js +++ b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_filter_widget.js @@ -111,7 +111,7 @@ let PieceListToolbarFilterWidgetFilter = React.createClass({ param = param.key; } else { param = param; - label = param.split('_')[1]; + label = param.split('acl_')[1].replace(/_/g, ' '); } return ( diff --git a/js/components/piece_list.js b/js/components/piece_list.js index 7ecbd0f0..7978ffde 100644 --- a/js/components/piece_list.js +++ b/js/components/piece_list.js @@ -46,12 +46,10 @@ let PieceList = React.createClass({ filterParams: [{ label: getLangText('Show works I can'), items: [ - 'acl_transfer', - 'acl_consign', - { - key: 'acl_create_editions', - label: 'create editions' - }] + 'acl_transfer', + 'acl_consign', + 'acl_create_editions' + ] }] }; }, From 63fffc213260ba940e97266e59502f2e64cced33 Mon Sep 17 00:00:00 2001 From: diminator Date: Thu, 17 Sep 2015 11:39:55 +0200 Subject: [PATCH 099/192] PR comments fix --- js/actions/contract_agreement_list_actions.js | 7 +- js/components/ascribe_detail/edition.js | 2 +- .../ascribe_detail/piece_container.js | 2 +- .../form_copyright_association.js | 76 +++++++++---------- js/components/ascribe_forms/form_loan.js | 7 +- .../ascribe_detail/cyland_piece_container.js | 2 +- .../ascribe_detail/ikonotv_piece_container.js | 2 +- .../ikonotv_artist_details_form.js | 2 +- .../ikonotv_artwork_details_form.js | 4 +- .../ikonotv/ikonotv_contract_notifications.js | 38 +++++----- 10 files changed, 72 insertions(+), 70 deletions(-) diff --git a/js/actions/contract_agreement_list_actions.js b/js/actions/contract_agreement_list_actions.js index f2959901..52c055a6 100644 --- a/js/actions/contract_agreement_list_actions.js +++ b/js/actions/contract_agreement_list_actions.js @@ -91,12 +91,7 @@ class ContractAgreementListActions { flushContractAgreementList(){ return Q.Promise((resolve, reject) => { - this.actions.updateContractAgreementList(null).then( - resolve() - ).catch((err) => { - console.logGlobal(err); - reject(err); - }); + return this.actions.updateContractAgreementList(null); }); } diff --git a/js/components/ascribe_detail/edition.js b/js/components/ascribe_detail/edition.js index aa3d81ba..1e69a7ab 100644 --- a/js/components/ascribe_detail/edition.js +++ b/js/components/ascribe_detail/edition.js @@ -152,7 +152,7 @@ let Edition = React.createClass({ {return {'bitcoin_id': this.props.edition.bitcoin_id}; }} diff --git a/js/components/ascribe_detail/piece_container.js b/js/components/ascribe_detail/piece_container.js index 8642ee05..4f8d8d8d 100644 --- a/js/components/ascribe_detail/piece_container.js +++ b/js/components/ascribe_detail/piece_container.js @@ -237,7 +237,7 @@ let PieceContainer = React.createClass({ - - - -
    - - ); + if (this.props.currentUser && this.props.currentUser.email){ + return ( +
    + + + +
    +
    + ); + } + return null; } }); diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index 0c60fd7b..1b37a116 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -79,12 +79,17 @@ let LoanForm = React.createClass({ getContractAgreementsOrCreatePublic(email){ /* a more complex defer (with promises) otherwise we dispatch while an action is being dispatched) */ window.setTimeout(() => { - ContractAgreementListActions.flushContractAgreementList(); + ContractAgreementListActions.flushContractAgreementList() + .catch((err) => { + console.logGlobal(err); + }); if (email) { + // fetch the available contractagreements (pending/accepted) ContractAgreementListActions.fetchAvailableContractAgreementList(email).then( (contractAgreementList) => { if (!contractAgreementList && this.props.createPublicContractAgreement) { + // for public contracts: fetch the public contract and create a contractagreement if available ContractAgreementListActions.createContractAgreementFromPublicContract(email); } } diff --git a/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js b/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js index 395cd86e..5b605007 100644 --- a/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js +++ b/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js @@ -98,7 +98,7 @@ let CylandPieceContainer = React.createClass({
    {return {'id': this.state.piece.id}; }} diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js index 8368bd89..9ee94245 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js @@ -97,7 +97,7 @@ let IkonotvPieceContainer = React.createClass({ {return {'id': this.state.piece.id}; }} diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js index cd98a94c..e840173a 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js @@ -62,7 +62,7 @@ let IkonotvArtistDetailsForm = React.createClass({ }, render() { - if(this.props.piece && this.props.piece.id) { + if(this.props.piece && this.props.piece.id && this.props.piece.extra_data) { return (
    this.handleConfirmSuccess() ); }, handleConfirmSuccess() { - let notification = new GlobalNotificationModel(getLangText('You have accepted the conditions'), 'success', 10000); + let notification = new GlobalNotificationModel(getLangText('You have accepted the conditions'), 'success', 5000); GlobalNotificationActions.appendGlobalNotification(notification); this.transitionTo('pieces'); }, handleDeny() { let contractAgreement = this.state.contractAgreementListNotifications[0].contract_agreement; - requests.put(apiUrls.ownership_contract_agreements_deny, {contract_agreement_id: contractAgreement.id}).then( + requests.put(ApiUrls.ownership_contract_agreements_deny, {contract_agreement_id: contractAgreement.id}).then( () => this.handleDenySuccess() ); }, handleDenySuccess() { - let notification = new GlobalNotificationModel(getLangText('You have denied the conditions'), 'success', 10000); + let notification = new GlobalNotificationModel(getLangText('You have denied the conditions'), 'success', 5000); GlobalNotificationActions.appendGlobalNotification(notification); this.transitionTo('pieces'); }, @@ -136,18 +139,19 @@ let IkonotvContractNotifications = React.createClass({ && this.state.currentUser.profile.copyright_association){ return null; } - return ( -
    -

    {getLangText('Are you a member of any copyright societies?')}

    -

    - ARS, DACS, Bildkunst, Pictoright, SODRAC, Copyright Agency/Viscopy, SAVA, Bildrecht GmbH, - SABAM, AUTVIS, CREAIMAGEN, SONECA, Copydan, EAU, Kuvasto, GCA, HUNGART, IVARO, SIAE, JASPAR-SPDA, - AKKA/LAA, LATGA-A, SOMAAP, ARTEGESTION, CARIER, BONO, APSAV, SPA, GESTOR, VISaRTA, RAO, LITA, - DALRO, VeGaP, BUS, ProLitteris, AGADU, AUTORARTE, BUBEDRA, BBDA, BCDA, BURIDA, ADAVIS, BSDA -

    - -
    - ); + if (this.state.currentUser && this.state.currentUser.profile) { + return ( +
    +

    {getLangText('Are you a member of any copyright societies?')}

    + +

    + {AppConstants.copyrightAssociations.join(', ')} +

    + +
    + ); + } + return null; }, render() { From 780ab9f7f1d2e5a3eab5342296dbcee5315decd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Thu, 17 Sep 2015 13:28:59 +0200 Subject: [PATCH 100/192] Cleanup window.setTimeout --- js/actions/contract_agreement_list_actions.js | 4 +-- js/components/ascribe_forms/form_loan.js | 28 ++++++++----------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/js/actions/contract_agreement_list_actions.js b/js/actions/contract_agreement_list_actions.js index 52c055a6..a5059ff0 100644 --- a/js/actions/contract_agreement_list_actions.js +++ b/js/actions/contract_agreement_list_actions.js @@ -90,9 +90,7 @@ class ContractAgreementListActions { } flushContractAgreementList(){ - return Q.Promise((resolve, reject) => { - return this.actions.updateContractAgreementList(null); - }); + this.actions.updateContractAgreementList(null); } } diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index 1b37a116..f8946486 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -77,24 +77,18 @@ let LoanForm = React.createClass({ }, getContractAgreementsOrCreatePublic(email){ - /* a more complex defer (with promises) otherwise we dispatch while an action is being dispatched) */ - window.setTimeout(() => { - ContractAgreementListActions.flushContractAgreementList() - .catch((err) => { - console.logGlobal(err); - }); - - if (email) { - // fetch the available contractagreements (pending/accepted) - ContractAgreementListActions.fetchAvailableContractAgreementList(email).then( - (contractAgreementList) => { - if (!contractAgreementList && this.props.createPublicContractAgreement) { - // for public contracts: fetch the public contract and create a contractagreement if available - ContractAgreementListActions.createContractAgreementFromPublicContract(email); - } + ContractAgreementListActions.flushContractAgreementList(); + if (email) { + // fetch the available contractagreements (pending/accepted) + ContractAgreementListActions.fetchAvailableContractAgreementList(email).then( + (contractAgreementList) => { + if (!contractAgreementList && this.props.createPublicContractAgreement) { + // for public contracts: fetch the public contract and create a contractagreement if available + ContractAgreementListActions.createContractAgreementFromPublicContract(email); } - ); - }}, 0); + } + ); + } }, getFormData(){ From 297d30f21f3027e9e0cc0e44b5682b7ec518f7d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Thu, 17 Sep 2015 13:52:51 +0200 Subject: [PATCH 101/192] PR Feeback: Simplify statements --- js/components/piece_list_filter_display.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/components/piece_list_filter_display.js b/js/components/piece_list_filter_display.js index e1c19bdd..6ca5207a 100644 --- a/js/components/piece_list_filter_display.js +++ b/js/components/piece_list_filter_display.js @@ -39,13 +39,13 @@ let PieceListFilterDisplay = React.createClass({ return { key: item.key, label: item.label, - value: filterBy[item.key] ? filterBy[item.key] : false + value: filterBy[item.key] || false }; } else { return { key: item, label: item.split('acl_')[1].replace(/_/g, ' '), - value: filterBy[item] ? filterBy[item] : false + value: filterBy[item] || false }; } }) From ff163df61ebe8d8e92643fc2f72d1a800c6e48f5 Mon Sep 17 00:00:00 2001 From: diminator Date: Thu, 17 Sep 2015 14:20:46 +0200 Subject: [PATCH 102/192] PR update --- js/components/ascribe_detail/edition.js | 5 +++-- js/components/ascribe_detail/piece_container.js | 5 ++--- .../ascribe_forms/form_copyright_association.js | 2 +- js/components/ascribe_forms/form_login.js | 2 +- js/components/ascribe_forms/form_signup.js | 2 +- .../ascribe_detail/cyland_piece_container.js | 5 ++--- .../ascribe_detail/ikonotv_piece_container.js | 5 ++--- .../ikonotv/ikonotv_contract_notifications.js | 16 +++++++--------- .../wallet/components/ikonotv/ikonotv_landing.js | 3 +-- .../components/ikonotv/ikonotv_register_piece.js | 10 ++-------- js/fetchers/ownership_fetcher.js | 8 ++++++++ 11 files changed, 30 insertions(+), 33 deletions(-) diff --git a/js/components/ascribe_detail/edition.js b/js/components/ascribe_detail/edition.js index 1e69a7ab..f2dbf682 100644 --- a/js/components/ascribe_detail/edition.js +++ b/js/components/ascribe_detail/edition.js @@ -152,8 +152,9 @@ let Edition = React.createClass({ + show={!!(this.state.currentUser.username + || this.props.edition.acl.acl_edit + || this.props.edition.public_note)}> {return {'bitcoin_id': this.props.edition.bitcoin_id}; }} label={getLangText('Personal note (private)')} diff --git a/js/components/ascribe_detail/piece_container.js b/js/components/ascribe_detail/piece_container.js index 4f8d8d8d..f14cf743 100644 --- a/js/components/ascribe_detail/piece_container.js +++ b/js/components/ascribe_detail/piece_container.js @@ -237,12 +237,11 @@ let PieceContainer = React.createClass({ + show={!!(this.state.currentUser.username || this.state.piece.public_note)}> @@ -70,7 +55,7 @@ let AccountSettings = React.createClass({ editable={false}> @@ -87,7 +72,7 @@ let AccountSettings = React.createClass({ className="ascribe-settings-property-collapsible-toggle" style={{paddingBottom: 0}}> + defaultChecked={this.props.currentUser.profile.hash_locally}> {' ' + getLangText('Enable hash option, e.g. slow connections or to keep piece private')} diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index c7abc682..889932af 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -14,11 +14,14 @@ import ContractSettingsUpdateButton from './contract_settings_update_button'; import GlobalNotificationModel from '../../models/global_notification_model'; import GlobalNotificationActions from '../../actions/global_notification_actions'; +import AclProxy from '../acl_proxy'; + import { getLangText } from '../../utils/lang_utils'; let ContractSettings = React.createClass({ propTypes: { + currentUser: React.PropTypes.object, defaultExpanded: React.PropTypes.bool }, @@ -79,80 +82,92 @@ let ContractSettings = React.createClass({ } return ( - + - {createPublicContractForm} - {publicContracts.map((contract, i) => { - return ( - - -
    - {getLangText('PREVIEW')} - - -
    - } - leftColumnWidth="40%" - rightColumnWidth="60%"/> - ); - })} + + + {createPublicContractForm} + {publicContracts.map((contract, i) => { + return ( + + + + {getLangText('PREVIEW')} + + +
    + } + leftColumnWidth="40%" + rightColumnWidth="60%"/> + ); + })} + + + + + + {privateContracts.map((contract, i) => { + return ( + + + + {getLangText('PREVIEW')} + + +
    + } + leftColumnWidth="40%" + rightColumnWidth="60%"/> + ); + })} +
    +
    - - - {privateContracts.map((contract, i) => { - return ( - - - - {getLangText('PREVIEW')} - - - - } - leftColumnWidth="40%" - rightColumnWidth="60%"/> - ); - })} - - + ); } }); diff --git a/js/components/ascribe_settings/settings_container.js b/js/components/ascribe_settings/settings_container.js index 2d2440bf..9b08af43 100644 --- a/js/components/ascribe_settings/settings_container.js +++ b/js/components/ascribe_settings/settings_container.js @@ -3,6 +3,9 @@ import React from 'react'; import Router from 'react-router'; +import UserStore from '../../stores/user_store'; +import UserActions from '../../actions/user_actions'; + import AccountSettings from './account_settings'; import BitcoinWalletSettings from './bitcoin_wallet_settings'; import ContractSettings from './contract_settings'; @@ -18,14 +21,35 @@ let SettingsContainer = React.createClass({ mixins: [Router.Navigation], + getInitialState() { + return UserStore.getState(); + }, + + componentDidMount() { + UserStore.listen(this.onChange); + UserActions.fetchCurrentUser(); + }, + + componentWillUnmount() { + UserStore.unlisten(this.onChange); + }, + + loadUser(){ + UserActions.fetchCurrentUser(); + }, + + onChange(state) { + this.setState(state); + }, + render() { return (
    - + {this.props.children} - +
    ); } diff --git a/js/components/whitelabel/wallet/constants/wallet_api_urls.js b/js/components/whitelabel/wallet/constants/wallet_api_urls.js index e0d8a862..2cdc0054 100644 --- a/js/components/whitelabel/wallet/constants/wallet_api_urls.js +++ b/js/components/whitelabel/wallet/constants/wallet_api_urls.js @@ -8,7 +8,8 @@ function getWalletApiUrls(subdomain) { return { 'pieces_list': walletConstants.walletApiEndpoint + subdomain + '/pieces/', 'piece': walletConstants.walletApiEndpoint + subdomain + '/pieces/${piece_id}/', - 'piece_extradata': walletConstants.walletApiEndpoint + subdomain + '/pieces/${piece_id}/extradata/' + 'piece_extradata': walletConstants.walletApiEndpoint + subdomain + '/pieces/${piece_id}/extradata/', + 'user': walletConstants.walletApiEndpoint + subdomain + '/users/' }; } else if (subdomain === 'ikonotv'){ From c67c87f17b903e8ef5198d72c8e5b8bfb0bec62b Mon Sep 17 00:00:00 2001 From: diminator Date: Fri, 18 Sep 2015 10:11:35 +0200 Subject: [PATCH 104/192] WARNING: Based upon D-943, which hasnt been approved/merged yet after AD-943 has been approved, merge it in this branch and do PR actions + buttons in ikono piece detail --- .../ascribe_buttons/ikonotv_submit_button.js | 8 ++- .../ascribe_detail/ikonotv_piece_container.js | 53 ++++++++++++++++++- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js index be3bda77..7f1723cd 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js @@ -13,6 +13,12 @@ let IkonotvSubmitButton = React.createClass({ piece: React.PropTypes.object.isRequired }, + getDefaultProps() { + return { + className: 'btn-xs' + }; + }, + render() { let piece = this.props.piece; let startFrom = 1; @@ -34,7 +40,7 @@ let IkonotvSubmitButton = React.createClass({ 'start_from': startFrom, 'piece_id': piece.id }} - className={classNames('btn', 'btn-default', 'btn-xs', this.props.className)}> + className={classNames('btn', 'btn-default', this.props.className)}> {getLangText('Loan to IkonoTV')} ); diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js index 3efa2185..ac7d16da 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js @@ -11,6 +11,11 @@ import Piece from '../../../../../../components/ascribe_detail/piece'; import AppConstants from '../../../../../../constants/application_constants'; +import ListRequestActions from '../../../../../ascribe_forms/list_form_request_actions'; +import AclButtonList from '../../../../../ascribe_buttons/acl_button_list'; +import DeleteButton from '../../../../../ascribe_buttons/delete_button'; +import IkonotvSubmitButton from '../ascribe_buttons/ikonotv_submit_button'; + import Form from '../../../../../../components/ascribe_forms/form'; import Property from '../../../../../../components/ascribe_forms/property'; import InputTextAreaToggable from '../../../../../../components/ascribe_forms/input_textarea_toggable'; @@ -21,6 +26,8 @@ import Note from '../../../../../ascribe_detail/note'; import DetailProperty from '../../../../../ascribe_detail/detail_property'; +import AclProxy from '../../../../../acl_proxy'; + import ApiUrls from '../../../../../../constants/api_urls'; import { getLangText } from '../../../../../../utils/lang_utils'; @@ -66,6 +73,50 @@ let IkonotvPieceContainer = React.createClass({ PieceActions.fetchOne(this.props.params.pieceId); }, + getActions(){ + if (this.state.piece && + this.state.piece.notifications && + this.state.piece.notifications.length > 0) { + return ( + ); + } + else { + + //We need to disable the normal acl_loan because we're inserting a custom acl_loan button + let availableAcls; + + if(this.state.piece && this.state.piece.acl && typeof this.state.piece.acl.acl_loan !== 'undefined') { + // make a copy to not have side effects + availableAcls = mergeOptions({}, this.state.piece.acl); + availableAcls.acl_loan = false; + } + + return ( + + + + + + + ); + } + }, + render() { if(this.state.piece && this.state.piece.title) { return ( @@ -88,7 +139,7 @@ let IkonotvPieceContainer = React.createClass({
    }> - + {this.getActions()} 0}> From b76ffcde73cd941d0f8137c92818a1e373ba7602 Mon Sep 17 00:00:00 2001 From: vrde Date: Fri, 18 Sep 2015 13:46:15 +0200 Subject: [PATCH 105/192] Finish styling for landing page --- js/components/whitelabel/prize/prize_app.js | 2 +- .../components/ikonotv/ikonotv_landing.js | 14 +++--- js/components/whitelabel/wallet/wallet_app.js | 5 ++- .../wallet/ikonotv/ikonotv_landing.scss | 43 ++++++++++++++++--- 4 files changed, 50 insertions(+), 14 deletions(-) diff --git a/js/components/whitelabel/prize/prize_app.js b/js/components/whitelabel/prize/prize_app.js index 29763ab3..f187dd1c 100644 --- a/js/components/whitelabel/prize/prize_app.js +++ b/js/components/whitelabel/prize/prize_app.js @@ -27,7 +27,7 @@ let PrizeApp = React.createClass({ } return ( -
    +
    {header} diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js index 1e2d3803..293eecdd 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js @@ -32,13 +32,13 @@ let IkonotvLanding = React.createClass({ if(this.state.currentUser && this.state.currentUser.email) { return ( - {getLangText('ENTER')} + {getLangText('ENTER TO START')} ); } else { return ( - {getLangText('ENTER')} + {getLangText('ENTER TO START')} ); } @@ -51,11 +51,13 @@ let IkonotvLanding = React.createClass({

    PROTECT

    - +
    +
    +
    +

    & SHARE

    -

    Welcome to the ikonoTV

    -

    Registration Page

    +

    Welcome to the ikonoTV
    Registration Page

    @@ -102,4 +104,4 @@ let IkonotvLanding = React.createClass({ } }); -export default IkonotvLanding; \ No newline at end of file +export default IkonotvLanding; diff --git a/js/components/whitelabel/wallet/wallet_app.js b/js/components/whitelabel/wallet/wallet_app.js index 06bac15f..8aa15f59 100644 --- a/js/components/whitelabel/wallet/wallet_app.js +++ b/js/components/whitelabel/wallet/wallet_app.js @@ -8,9 +8,12 @@ import Footer from '../../footer'; import GlobalNotification from '../../global_notification'; import getRoutes from './wallet_routes'; +import classNames from 'classnames'; + let RouteHandler = Router.RouteHandler; + let WalletApp = React.createClass({ mixins: [Router.State], @@ -28,7 +31,7 @@ let WalletApp = React.createClass({ } return ( -
    +
    {header} diff --git a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss index b0d60983..7a54f20a 100644 --- a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss +++ b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss @@ -1,11 +1,20 @@ +.client--ikonotv.page--landing { + background-color: #c40050; + margin: 0; + width: 100%; + padding: 5em 1em; +} + + +.client--ikonotv.page--landing .ascribe-footer { + display: none; +} + .ikonotv-landing { /* center all text on the page */ text-align: center; - background-color: #c40050; color: white; - padding: 5em 5em 5em 5em; - header { /* center all images on the page */ img { @@ -16,7 +25,7 @@ /* Ikonotv logo */ img:first-child { - width: 200px; + max-width: 200px; } > .tagline { @@ -29,12 +38,30 @@ margin-top: 10px; margin-bottom: 10px; + + @media only screen and (max-width: 600px) { + font-size: 4em; + } + } + + > .poster { + max-width: 600px; + margin: 0 auto; + > .content { + width: 100%; + padding-bottom: 56.25%; + height: 0; + background-color: #ffff00; + } } } > h2 { font-weight: 600; font-size: 2.75em; + @media only screen and (max-width: 600px) { + font-size: 1.75em; + } } > h2 + h2 { @@ -44,7 +71,8 @@ article { > section { - width: 65%; + width: 100%; + max-width: 60em; margin: 3em auto 1em auto; > h1 { @@ -57,6 +85,9 @@ text-align: left; font-size: 1.3em; line-height: 1.8; + @media only screen and (max-width: 600px) { + font-size: 1.1em; + } } } } @@ -78,4 +109,4 @@ font-weight: 500; } } -} \ No newline at end of file +} From c99c3492fbb67a0b50609b89e0374577a5b20e97 Mon Sep 17 00:00:00 2001 From: vrde Date: Fri, 18 Sep 2015 14:02:31 +0200 Subject: [PATCH 106/192] Add margin top to ascribe-wallet-app class --- sass/whitelabel/index.scss | 3 ++- sass/whitelabel/wallet/index.scss | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 sass/whitelabel/wallet/index.scss diff --git a/sass/whitelabel/index.scss b/sass/whitelabel/index.scss index 9fa1b68f..fc7a6b3b 100644 --- a/sass/whitelabel/index.scss +++ b/sass/whitelabel/index.scss @@ -1,2 +1,3 @@ @import 'prize/index'; -@import 'wallet/ikonotv/ikonotv_landing'; \ No newline at end of file +@import 'wallet/index'; +@import 'wallet/ikonotv/ikonotv_landing'; diff --git a/sass/whitelabel/wallet/index.scss b/sass/whitelabel/wallet/index.scss new file mode 100644 index 00000000..4ec76076 --- /dev/null +++ b/sass/whitelabel/wallet/index.scss @@ -0,0 +1,5 @@ +.ascribe-wallet-app { + border-radius: 0; + padding-top: 70px; + min-height: 100vh; +} From 2cbf7d00959e396c71858ec52763470def7e9cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 18 Sep 2015 13:49:50 +0200 Subject: [PATCH 107/192] Implement PR Feedback --- js/actions/contract_agreement_list_actions.js | 5 ----- js/components/ascribe_forms/form_loan.js | 2 +- .../components/ikonotv/ikonotv_contract_notifications.js | 6 +++--- .../wallet/components/ikonotv/ikonotv_register_piece.js | 4 ++-- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/js/actions/contract_agreement_list_actions.js b/js/actions/contract_agreement_list_actions.js index a5059ff0..93bc35ac 100644 --- a/js/actions/contract_agreement_list_actions.js +++ b/js/actions/contract_agreement_list_actions.js @@ -88,11 +88,6 @@ class ContractAgreementListActions { }); }); } - - flushContractAgreementList(){ - this.actions.updateContractAgreementList(null); - } - } export default alt.createActions(ContractAgreementListActions); diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index f8946486..6aef1f56 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -77,7 +77,7 @@ let LoanForm = React.createClass({ }, getContractAgreementsOrCreatePublic(email){ - ContractAgreementListActions.flushContractAgreementList(); + ContractAgreementListActions.flushContractAgreementList.defer(); if (email) { // fetch the available contractagreements (pending/accepted) ContractAgreementListActions.fetchAvailableContractAgreementList(email).then( diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js index 0f631758..cfc80825 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js @@ -135,9 +135,9 @@ let IkonotvContractNotifications = React.createClass({ }, getCopyrightAssociationForm(){ - let c = this.state.currentUser; + let currentUser = this.state.currentUser; - if (c && c.profile && !c.profile.copyright_association) { + if (currentUser && currentUser.profile && !currentUser.profile.copyright_association) { return (

    {getLangText('Are you a member of any copyright societies?')}

    @@ -145,7 +145,7 @@ let IkonotvContractNotifications = React.createClass({

    {AppConstants.copyrightAssociations.join(', ')}

    - +
    ); } diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js index 700b5678..76880304 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js @@ -165,8 +165,8 @@ let IkonotvRegisterPiece = React.createClass({ }, canSubmit() { - let c = this.state.currentUser; - return c && c.acl && c.acl.acl_submit; + let currentUser = this.state.currentUser; + return currentUser && currentUser.acl && currentUser.acl.acl_submit; }, getSlideArtistDetails() { From 03803ca61a5e7220df5eb61a543ef1323315c9d4 Mon Sep 17 00:00:00 2001 From: vrde Date: Fri, 18 Sep 2015 14:25:31 +0200 Subject: [PATCH 108/192] Add active routes as css classes --- js/components/whitelabel/wallet/wallet_app.js | 3 ++- sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/js/components/whitelabel/wallet/wallet_app.js b/js/components/whitelabel/wallet/wallet_app.js index 8aa15f59..cb2a79d5 100644 --- a/js/components/whitelabel/wallet/wallet_app.js +++ b/js/components/whitelabel/wallet/wallet_app.js @@ -20,6 +20,7 @@ let WalletApp = React.createClass({ render() { let subdomain = window.location.host.split('.')[0]; let ROUTES = getRoutes(null, subdomain); + let activeRoutes = this.getRoutes().map(elem => 'route--' + elem.name); let header = null; if ((this.isActive('landing') || this.isActive('login') || this.isActive('signup')) @@ -31,7 +32,7 @@ let WalletApp = React.createClass({ } return ( -
    +
    {header} diff --git a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss index 7a54f20a..0dc69a84 100644 --- a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss +++ b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss @@ -1,12 +1,15 @@ -.client--ikonotv.page--landing { +.client--ikonotv.route--landing { background-color: #c40050; margin: 0; width: 100%; padding: 5em 1em; } +.client--ikonotv .ascribe-login-wrapper { -.client--ikonotv.page--landing .ascribe-footer { +} + +.client--ikonotv.route--landing .ascribe-footer { display: none; } From e05249eacb07c51f3137eb17ab1d2590d804a2ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 18 Sep 2015 14:50:08 +0200 Subject: [PATCH 109/192] WIP fix wrong input fields bug --- .../ascribe_forms/input_textarea_toggable.js | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/js/components/ascribe_forms/input_textarea_toggable.js b/js/components/ascribe_forms/input_textarea_toggable.js index ac3994a7..e6da5282 100644 --- a/js/components/ascribe_forms/input_textarea_toggable.js +++ b/js/components/ascribe_forms/input_textarea_toggable.js @@ -15,10 +15,32 @@ let InputTextAreaToggable = React.createClass({ getInitialState() { return { - value: this.props.defaultValue + value: null }; }, + componentDidUpdate(prevProps, prevState) { + if(this.state.value !== prevState.value) { + this.handleChange({ + target: { + value: this.state.value + } + }); + } + + if(!this.state.value && this.props.defaultValue) { + this.handleChange({ + target: { + value: this.props.defaultValue + } + }); + } + }, + + componentWillUnmount() { + this.setState({value: null}); + }, + handleChange(event) { this.setState({value: event.target.value}); this.props.onChange(event); From 63b375ade6013f6eda8811b536387a92c777ea66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 18 Sep 2015 15:17:24 +0200 Subject: [PATCH 110/192] fix separation --- .../ascribe_settings/contract_settings.js | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 889932af..34966304 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -75,8 +75,8 @@ let ContractSettings = React.createClass({ ); } @@ -92,10 +92,7 @@ let ContractSettings = React.createClass({ - +
    {createPublicContractForm} {publicContracts.map((contract, i) => { return ( @@ -123,21 +120,18 @@ let ContractSettings = React.createClass({ rightColumnWidth="60%"/> ); })} - +
    - +
    + isPublic={false} + fileClassToUpload={{ + singular: getLangText('new contract'), + plural: getLangText('new contracts') + }}/> {privateContracts.map((contract, i) => { return ( ); })} - +
    From eb43b18167f1bf39c3be4b2c3e4d375f522d0699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 18 Sep 2015 15:22:57 +0200 Subject: [PATCH 111/192] make remove in ContractSettings a secondary action --- js/components/ascribe_settings/contract_settings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 34966304..f85db29e 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -110,7 +110,7 @@ let ContractSettings = React.createClass({ {getLangText('PREVIEW')} @@ -148,7 +148,7 @@ let ContractSettings = React.createClass({ {getLangText('PREVIEW')} From 7be3c8b46920e9e66206deefaae4d3c84dec0a7d Mon Sep 17 00:00:00 2001 From: vrde Date: Fri, 18 Sep 2015 15:36:01 +0200 Subject: [PATCH 112/192] Add style for signup and login --- js/components/whitelabel/wallet/wallet_app.js | 14 ++-- .../wallet/ikonotv/ikonotv_landing.scss | 83 ++++++++++++++++++- 2 files changed, 89 insertions(+), 8 deletions(-) diff --git a/js/components/whitelabel/wallet/wallet_app.js b/js/components/whitelabel/wallet/wallet_app.js index cb2a79d5..b92656e2 100644 --- a/js/components/whitelabel/wallet/wallet_app.js +++ b/js/components/whitelabel/wallet/wallet_app.js @@ -32,12 +32,14 @@ let WalletApp = React.createClass({ } return ( -
    - {header} - - - -
    +
    +
    + {header} + + + +
    +
    ); } diff --git a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss index 0dc69a84..5e45e7f2 100644 --- a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss +++ b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss @@ -1,3 +1,7 @@ +.client--ikonotv { + font-family: 'Helvetica Neue', 'Helvetica', sans-serif; +} + .client--ikonotv.route--landing { background-color: #c40050; margin: 0; @@ -5,11 +9,86 @@ padding: 5em 1em; } -.client--ikonotv .ascribe-login-wrapper { +.client--ikonotv.route--login, +.client--ikonotv.route--signup { + background-color: #c40050; + + button[type='submit'] { + display: block; + margin: 50px auto 0; + width: auto; + padding: 10px 30px; + text-transform: uppercase; + font-weight: bold; + } + + .ascribe-form-header { + background-image: url(https://s3-us-west-2.amazonaws.com/ascribe0/whitelabel/ikonotv/ikono_tv.png); + background-color: transparent; + background-position: center 0; + background-repeat: no-repeat; + background-size: 300px; + margin-bottom: 30px; + height: 150px; + position: relative; + + h3 { + position: absolute; + bottom: 0; + left: 0; + right: 0; + color: white; + text-align: center; + font-size: 22px; + } + } + + .ascribe-settings-wrapper { + background-color: transparent; + + &:hover { + border-left: 3px solid transparent; + } + + &.is-focused { + border-left: 3px solid transparent !important; + } + } + + .ascribe-settings-property { + border: none; + } + + .ascribe-settings-property > span { + color: white; + } + + .ascribe-settings-property > input { + padding: 10px; + background-color: #fff; + margin-top: .1em; + + &:focus { + background-color: #ffff00; + } + } + + .checkbox, + .checkbox a { + color: white !important; + } } -.client--ikonotv.route--landing .ascribe-footer { + +.client--ikonotv .ascribe-form-bordered { + border: none; +} + +.client--ikonotv .ascribe-login-wrapper { +} + +.client--ikonotv .ascribe-footer { display: none; } From 2ba7eac1911d4a5bf21d60f84ab34e35877248f5 Mon Sep 17 00:00:00 2001 From: vrde Date: Fri, 18 Sep 2015 15:40:06 +0200 Subject: [PATCH 113/192] Add "already a user" link from signup to login --- js/components/signup_container.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/js/components/signup_container.js b/js/components/signup_container.js index 46813b59..8720da53 100644 --- a/js/components/signup_container.js +++ b/js/components/signup_container.js @@ -1,8 +1,13 @@ 'use strict'; import React from 'react'; +import Router from 'react-router'; + import SignupForm from './ascribe_forms/form_signup'; +import { getLangText } from '../utils/lang_utils'; + +let Link = Router.Link; let SignupContainer = React.createClass({ getInitialState() { @@ -33,6 +38,9 @@ let SignupContainer = React.createClass({ return (
    +
    + {getLangText('Already an ascribe user')}? {getLangText('Log in')}...
    +
    ); } From 7482c3f4489a0b11fa3e47db7318c9a6eef04d89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 18 Sep 2015 15:51:15 +0200 Subject: [PATCH 114/192] add user endpoint to cyland --- js/components/whitelabel/wallet/constants/wallet_api_urls.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/components/whitelabel/wallet/constants/wallet_api_urls.js b/js/components/whitelabel/wallet/constants/wallet_api_urls.js index e0d8a862..2cdc0054 100644 --- a/js/components/whitelabel/wallet/constants/wallet_api_urls.js +++ b/js/components/whitelabel/wallet/constants/wallet_api_urls.js @@ -8,7 +8,8 @@ function getWalletApiUrls(subdomain) { return { 'pieces_list': walletConstants.walletApiEndpoint + subdomain + '/pieces/', 'piece': walletConstants.walletApiEndpoint + subdomain + '/pieces/${piece_id}/', - 'piece_extradata': walletConstants.walletApiEndpoint + subdomain + '/pieces/${piece_id}/extradata/' + 'piece_extradata': walletConstants.walletApiEndpoint + subdomain + '/pieces/${piece_id}/extradata/', + 'user': walletConstants.walletApiEndpoint + subdomain + '/users/' }; } else if (subdomain === 'ikonotv'){ From dd965653d6fa0c07023c8be585bbca194b2bfbfd Mon Sep 17 00:00:00 2001 From: vrde Date: Fri, 18 Sep 2015 16:00:39 +0200 Subject: [PATCH 115/192] Add style to loading button --- .../wallet/ikonotv/ikonotv_landing.scss | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss index 5e45e7f2..d0708f5e 100644 --- a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss +++ b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss @@ -14,13 +14,18 @@ .client--ikonotv.route--signup { background-color: #c40050; - button[type='submit'] { + .ascribe-btn-login { display: block; margin: 50px auto 0; width: auto; padding: 10px 30px; text-transform: uppercase; font-weight: bold; + width: 180px; + } + + .ascribe-btn-login-spinner { + background-color: #02b6a3; } .ascribe-form-header { @@ -78,6 +83,16 @@ .checkbox a { color: white !important; } + + .ascribe-login-text { + color: white; + text-align: center; + + a { + color: white; + text-decoration: underline; + } + } } From afef1214f0d674680bd506d69c2111c9f71cbd0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 18 Sep 2015 16:04:48 +0200 Subject: [PATCH 116/192] contract expandedDefault to false --- js/components/ascribe_settings/contract_settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index f85db29e..39cb853d 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -88,7 +88,7 @@ let ContractSettings = React.createClass({ + defaultExpanded={false}> From 9d67d046d082f07e63263f1e163112f39a9718c6 Mon Sep 17 00:00:00 2001 From: diminator Date: Mon, 21 Sep 2015 10:32:35 +0200 Subject: [PATCH 117/192] fix currentUser bug --- .../ascribe_settings/account_settings.js | 2 +- .../ascribe_settings/settings_container.js | 21 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/js/components/ascribe_settings/account_settings.js b/js/components/ascribe_settings/account_settings.js index a613c3b4..aa50d719 100644 --- a/js/components/ascribe_settings/account_settings.js +++ b/js/components/ascribe_settings/account_settings.js @@ -104,7 +104,7 @@ let AccountSettings = React.createClass({ show={true} defaultExpanded={true}> {content} - + {profile} {/* diff --git a/js/components/ascribe_settings/settings_container.js b/js/components/ascribe_settings/settings_container.js index 9b08af43..2b3dc6a7 100644 --- a/js/components/ascribe_settings/settings_container.js +++ b/js/components/ascribe_settings/settings_container.js @@ -43,15 +43,18 @@ let SettingsContainer = React.createClass({ }, render() { - return ( -
    - - {this.props.children} - - - -
    - ); + if (this.state.currentUser && this.state.currentUser.username) { + return ( +
    + + {this.props.children} + + + +
    + ); + } + return null; } }); From 2486158c12dcfc7b0b79eacd47a0c0d1cada0f57 Mon Sep 17 00:00:00 2001 From: diminator Date: Mon, 21 Sep 2015 10:47:24 +0200 Subject: [PATCH 118/192] .required => .isRequired --- js/components/ascribe_forms/form_loan_request_answer.js | 2 +- js/components/ascribe_settings/account_settings.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/js/components/ascribe_forms/form_loan_request_answer.js b/js/components/ascribe_forms/form_loan_request_answer.js index 2ebdb439..1bfe90db 100644 --- a/js/components/ascribe_forms/form_loan_request_answer.js +++ b/js/components/ascribe_forms/form_loan_request_answer.js @@ -18,7 +18,7 @@ let LoanRequestAnswerForm = React.createClass({ url: React.PropTypes.string, id: React.PropTypes.object, message: React.PropTypes.string, - handleSuccess: React.PropTypes.func.required + handleSuccess: React.PropTypes.func.isRequired }, getDefaultProps() { diff --git a/js/components/ascribe_settings/account_settings.js b/js/components/ascribe_settings/account_settings.js index aa50d719..7c769c22 100644 --- a/js/components/ascribe_settings/account_settings.js +++ b/js/components/ascribe_settings/account_settings.js @@ -19,8 +19,8 @@ import { getLangText } from '../../utils/lang_utils'; let AccountSettings = React.createClass({ propTypes: { - currentUser: React.PropTypes.object.required, - loadUser: React.PropTypes.func.required + currentUser: React.PropTypes.object.isRequired, + loadUser: React.PropTypes.func.isRequired }, handleSuccess(){ From ec0208358d0a8933b2f5681a5e2cfb3d99d7c9a5 Mon Sep 17 00:00:00 2001 From: diminator Date: Mon, 21 Sep 2015 10:54:13 +0200 Subject: [PATCH 119/192] added appendix --- js/components/ascribe_forms/form_loan.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index 6aef1f56..aeb942ee 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -152,6 +152,23 @@ let LoanForm = React.createClass({ } }, + getAppendix() { + if(this.state.contractAgreementList && this.state.contractAgreementList.length > 0) { + let appendix = this.state.contractAgreementList[0].appendix; + if (appendix && appendix.default) { + return ( +
    +

    {getLangText('Appendix')}

    +
    +                            {appendix.default}
    +                        
    +
    + ); + } + } + return null; + }, + getButtons() { if(this.props.loanHeading) { return ( @@ -257,6 +274,7 @@ let LoanForm = React.createClass({ required={this.props.showPassword ? 'required' : ''}/> {this.getContractCheckbox()} + {this.getAppendix()} {this.props.children} ); From 0819724a10a57895526bffc4a0eea2e6a5ec22d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 21 Sep 2015 10:57:10 +0200 Subject: [PATCH 120/192] probably fix dispatch.dispatch error + showing wrong piece data bug --- js/actions/contract_agreement_list_actions.js | 3 ++- js/components/ascribe_forms/input_textarea_toggable.js | 4 ++++ js/components/ascribe_settings/account_settings.js | 4 ++-- .../wallet/components/ikonotv/ikonotv_register_piece.js | 4 ++++ 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/js/actions/contract_agreement_list_actions.js b/js/actions/contract_agreement_list_actions.js index 93bc35ac..fe089f24 100644 --- a/js/actions/contract_agreement_list_actions.js +++ b/js/actions/contract_agreement_list_actions.js @@ -15,8 +15,9 @@ class ContractAgreementListActions { } fetchContractAgreementList(issuer, accepted, pending) { + this.actions.updateContractAgreementList(null); + return Q.Promise((resolve, reject) => { - this.actions.updateContractAgreementList(null); OwnershipFetcher.fetchContractAgreementList(issuer, accepted, pending) .then((contractAgreementList) => { if (contractAgreementList.count > 0) { diff --git a/js/components/ascribe_forms/input_textarea_toggable.js b/js/components/ascribe_forms/input_textarea_toggable.js index e6da5282..39ef36fc 100644 --- a/js/components/ascribe_forms/input_textarea_toggable.js +++ b/js/components/ascribe_forms/input_textarea_toggable.js @@ -20,6 +20,8 @@ let InputTextAreaToggable = React.createClass({ }, componentDidUpdate(prevProps, prevState) { + // if the components state value was changed during an update, we want to refresh it + // in this component as well as in the parent Property if(this.state.value !== prevState.value) { this.handleChange({ target: { @@ -28,6 +30,8 @@ let InputTextAreaToggable = React.createClass({ }); } + // Otherwise, if state wasn't defined beforehand and defaultValue is defined from the outside + // we set it as the component's state and update Property by calling handleChange if(!this.state.value && this.props.defaultValue) { this.handleChange({ target: { diff --git a/js/components/ascribe_settings/account_settings.js b/js/components/ascribe_settings/account_settings.js index aa50d719..7c769c22 100644 --- a/js/components/ascribe_settings/account_settings.js +++ b/js/components/ascribe_settings/account_settings.js @@ -19,8 +19,8 @@ import { getLangText } from '../../utils/lang_utils'; let AccountSettings = React.createClass({ propTypes: { - currentUser: React.PropTypes.object.required, - loadUser: React.PropTypes.func.required + currentUser: React.PropTypes.object.isRequired, + loadUser: React.PropTypes.func.isRequired }, handleSuccess(){ diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js index 76880304..98d8a8e7 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js @@ -57,6 +57,10 @@ let IkonotvRegisterPiece = React.createClass({ PieceStore.listen(this.onChange); UserActions.fetchCurrentUser(); + // Before we load the new piece, we reset the piece store to delete old data that we do + // not want to display to the user. + PieceActions.updatePiece({}); + let queryParams = this.getQuery(); // Since every step of this register process is atomic, From 92f543490e8a3650e9490ccf020757131587a8aa Mon Sep 17 00:00:00 2001 From: diminator Date: Mon, 21 Sep 2015 11:26:36 +0200 Subject: [PATCH 121/192] buttonlink style --- .../components/ikonotv/ascribe_buttons/ikonotv_submit_button.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js index 7f1723cd..523f9fe2 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_buttons/ikonotv_submit_button.js @@ -40,7 +40,7 @@ let IkonotvSubmitButton = React.createClass({ 'start_from': startFrom, 'piece_id': piece.id }} - className={classNames('btn', 'btn-default', this.props.className)}> + className={classNames('ascribe-margin-1px', this.props.className)}> {getLangText('Loan to IkonoTV')} ); From c00e003aeb4454842be98aa712b5b1a551268898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 21 Sep 2015 12:05:42 +0200 Subject: [PATCH 122/192] refactor input textarea to use disabled instead of editable --- js/components/ascribe_detail/note.js | 9 ++++--- js/components/ascribe_forms/form_consign.js | 4 ++-- .../ascribe_forms/form_contract_agreement.js | 4 +++- js/components/ascribe_forms/form_loan.js | 2 +- .../ascribe_forms/form_piece_extradata.js | 7 +++--- .../ascribe_forms/form_register_piece.js | 2 +- .../ascribe_forms/form_share_email.js | 4 ++-- .../ascribe_forms/form_submit_to_prize.js | 8 +++---- js/components/ascribe_forms/form_transfer.js | 4 ++-- js/components/ascribe_forms/form_unconsign.js | 4 ++-- .../ascribe_forms/form_unconsign_request.js | 4 ++-- .../ascribe_forms/input_fineuploader.js | 10 ++++---- .../ascribe_forms/input_textarea_toggable.js | 4 ++-- js/components/coa_verify_container.js | 5 ++-- .../ascribe_detail/prize_piece_container.js | 4 ++-- .../prize/components/prize_register_piece.js | 8 +++---- .../ascribe_detail/cyland_piece_container.js | 4 ++-- .../cyland_additional_data_form.js | 9 ++----- .../ascribe_detail/ikonotv_piece_container.js | 8 +++---- .../ikonotv_artist_details_form.js | 16 ++++--------- .../ikonotv_artwork_details_form.js | 24 +++++-------------- 21 files changed, 61 insertions(+), 83 deletions(-) diff --git a/js/components/ascribe_detail/note.js b/js/components/ascribe_detail/note.js index 0f32e5da..b377ff5c 100644 --- a/js/components/ascribe_detail/note.js +++ b/js/components/ascribe_detail/note.js @@ -44,14 +44,13 @@ let Note = React.createClass({
    + handleSuccess={this.showNotification} + disabled={!this.props.editable}> + label={this.props.label}> @@ -63,4 +62,4 @@ let Note = React.createClass({ } }); -export default Note \ No newline at end of file +export default Note; \ No newline at end of file diff --git a/js/components/ascribe_forms/form_consign.js b/js/components/ascribe_forms/form_consign.js index 6f85adc2..de4a4788 100644 --- a/js/components/ascribe_forms/form_consign.js +++ b/js/components/ascribe_forms/form_consign.js @@ -56,10 +56,10 @@ let ConsignForm = React.createClass({ + editable={true} + overrideForm={true}> diff --git a/js/components/ascribe_forms/form_contract_agreement.js b/js/components/ascribe_forms/form_contract_agreement.js index 94ab26d0..85ed6b6a 100644 --- a/js/components/ascribe_forms/form_contract_agreement.js +++ b/js/components/ascribe_forms/form_contract_agreement.js @@ -129,9 +129,11 @@ let ContractAgreementForm = React.createClass({ name='appendix' checkboxLabel={getLangText('Add appendix to the contract')}> {getLangText('Appendix')} + {/* We're using disabled on a form here as PropertyCollapsible currently + does not support the disabled + overrideForm functionality */} diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index aeb942ee..b15ac909 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -256,10 +256,10 @@ let LoanForm = React.createClass({ name='loan_message' label={getLangText('Personal Message')} editable={true} + overrideForm={true} hidden={!this.props.showPersonalMessage}> diff --git a/js/components/ascribe_forms/form_piece_extradata.js b/js/components/ascribe_forms/form_piece_extradata.js index 293ca09e..45f684ad 100644 --- a/js/components/ascribe_forms/form_piece_extradata.js +++ b/js/components/ascribe_forms/form_piece_extradata.js @@ -41,14 +41,13 @@ let PieceExtraDataForm = React.createClass({ ref='form' url={url} handleSuccess={this.props.handleSuccess} - getFormData={this.getFormData}> + getFormData={this.getFormData} + disabled={!this.props.editable}> + label={this.props.title}> diff --git a/js/components/ascribe_forms/form_register_piece.js b/js/components/ascribe_forms/form_register_piece.js index 68902290..118b3968 100644 --- a/js/components/ascribe_forms/form_register_piece.js +++ b/js/components/ascribe_forms/form_register_piece.js @@ -112,7 +112,7 @@ let RegisterPieceForm = React.createClass({ isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile} isFineUploaderActive={this.props.isFineUploaderActive} onLoggedOut={this.props.onLoggedOut} - editable={this.props.isFineUploaderEditable} + disabled={!this.props.isFineUploaderEditable} enableLocalHashing={enableLocalHashing}/> + editable={true} + overrideForm={true}> diff --git a/js/components/ascribe_forms/form_submit_to_prize.js b/js/components/ascribe_forms/form_submit_to_prize.js index ff853c01..23075791 100644 --- a/js/components/ascribe_forms/form_submit_to_prize.js +++ b/js/components/ascribe_forms/form_submit_to_prize.js @@ -45,20 +45,20 @@ let PieceSubmitToPrizeForm = React.createClass({ + editable={true} + overrideForm={true}> + editable={true} + overrideForm={true}> diff --git a/js/components/ascribe_forms/form_transfer.js b/js/components/ascribe_forms/form_transfer.js index 6ec73d38..8bbcf110 100644 --- a/js/components/ascribe_forms/form_transfer.js +++ b/js/components/ascribe_forms/form_transfer.js @@ -61,10 +61,10 @@ let TransferForm = React.createClass({ + editable={true} + overrideForm={true}> diff --git a/js/components/ascribe_forms/form_unconsign.js b/js/components/ascribe_forms/form_unconsign.js index 9bc5b4bd..ed6362da 100644 --- a/js/components/ascribe_forms/form_unconsign.js +++ b/js/components/ascribe_forms/form_unconsign.js @@ -50,10 +50,10 @@ let UnConsignForm = React.createClass({ + editable={true} + overrideForm={true}> diff --git a/js/components/ascribe_forms/form_unconsign_request.js b/js/components/ascribe_forms/form_unconsign_request.js index c47b5411..750ee72d 100644 --- a/js/components/ascribe_forms/form_unconsign_request.js +++ b/js/components/ascribe_forms/form_unconsign_request.js @@ -50,10 +50,10 @@ let UnConsignRequestForm = React.createClass({ + editable={true} + overrideForm={true}> diff --git a/js/components/ascribe_forms/input_fineuploader.js b/js/components/ascribe_forms/input_fineuploader.js index 82d6bf92..915d915f 100644 --- a/js/components/ascribe_forms/input_fineuploader.js +++ b/js/components/ascribe_forms/input_fineuploader.js @@ -8,12 +8,14 @@ import AppConstants from '../../constants/application_constants'; import { getCookie } from '../../utils/fetch_api_utils'; -let InputFileUploader = React.createClass({ +let InputFineUploader = React.createClass({ propTypes: { setIsUploadReady: React.PropTypes.func, isReadyForFormSubmission: React.PropTypes.func, submitFileName: React.PropTypes.func, + areAssetsDownloadable: React.PropTypes.bool, + onClick: React.PropTypes.func, keyRoutine: React.PropTypes.shape({ url: React.PropTypes.string, @@ -33,7 +35,7 @@ let InputFileUploader = React.createClass({ // before login in isFineUploaderActive: React.PropTypes.bool, onLoggedOut: React.PropTypes.func, - editable: React.PropTypes.bool, + enableLocalHashing: React.PropTypes.bool, // provided by Property @@ -86,7 +88,7 @@ let InputFileUploader = React.createClass({ submitFile={this.submitFile} setIsUploadReady={this.props.setIsUploadReady} isReadyForFormSubmission={this.props.isReadyForFormSubmission} - areAssetsDownloadable={false} + areAssetsDownloadable={this.props.areAssetsDownloadable} areAssetsEditable={editable} signature={{ endpoint: AppConstants.serverUrl + 's3/signature/', @@ -109,4 +111,4 @@ let InputFileUploader = React.createClass({ } }); -export default InputFileUploader; \ No newline at end of file +export default InputFineUploader; \ 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 index 39ef36fc..97f880f3 100644 --- a/js/components/ascribe_forms/input_textarea_toggable.js +++ b/js/components/ascribe_forms/input_textarea_toggable.js @@ -7,7 +7,7 @@ import TextareaAutosize from 'react-textarea-autosize'; let InputTextAreaToggable = React.createClass({ propTypes: { - editable: React.PropTypes.bool.isRequired, + disabled: React.PropTypes.bool, rows: React.PropTypes.number.isRequired, required: React.PropTypes.string, defaultValue: React.PropTypes.string @@ -54,7 +54,7 @@ let InputTextAreaToggable = React.createClass({ let className = 'form-control ascribe-textarea'; let textarea = null; - if(this.props.editable) { + if(!this.props.disabled) { className = className + ' ascribe-textarea-editable'; textarea = ( + label="Signature" + editable={true} + overrideForm={true}> diff --git a/js/components/whitelabel/prize/components/ascribe_detail/prize_piece_container.js b/js/components/whitelabel/prize/components/ascribe_detail/prize_piece_container.js index 406b5827..44a727e4 100644 --- a/js/components/whitelabel/prize/components/ascribe_detail/prize_piece_container.js +++ b/js/components/whitelabel/prize/components/ascribe_detail/prize_piece_container.js @@ -426,10 +426,10 @@ let PrizePieceDetails = React.createClass({ + editable={false} + overrideForm={true}> ); } diff --git a/js/components/whitelabel/prize/components/prize_register_piece.js b/js/components/whitelabel/prize/components/prize_register_piece.js index e7a97541..0bd3fe75 100644 --- a/js/components/whitelabel/prize/components/prize_register_piece.js +++ b/js/components/whitelabel/prize/components/prize_register_piece.js @@ -41,20 +41,20 @@ let PrizeRegisterPiece = React.createClass({ + editable={true} + overrideForm={true}> + editable={true} + overrideForm={true}> diff --git a/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js b/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js index dab5eda4..f4a63ec8 100644 --- a/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js +++ b/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js @@ -143,10 +143,10 @@ let CylandPieceDetails = React.createClass({ key={i} name={data} label={label} - editable={false}> + editable={false} + overrideForm={true}> ); } diff --git a/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js b/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js index 123ad2b7..9214123c 100644 --- a/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js +++ b/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js @@ -92,21 +92,17 @@ let CylandAdditionalDataForm = React.createClass({
    + label={getLangText('Artist Biography')}> + label={getLangText('Conceptual Overview')}> @@ -115,7 +111,6 @@ let CylandAdditionalDataForm = React.createClass({ submitFile={this.submitFile} setIsUploadReady={this.setIsUploadReady} isReadyForFormSubmission={formSubmissionValidation.fileOptional} - editable={!this.props.disabled} pieceId={this.props.piece.id} otherData={this.props.piece.other_data} multiple={true}/> diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js index ac7d16da..2025c10b 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js @@ -185,7 +185,9 @@ let IkonotvPieceDetails = React.createClass({ title={getLangText('Further Details')} show={true} defaultExpanded={true}> -
    + {Object.keys(this.props.piece.extra_data).map((data, i) => { let label = data.replace('_', ' '); return ( @@ -193,11 +195,9 @@ let IkonotvPieceDetails = React.createClass({ key={i} name={data} label={label} - hidden={!this.props.piece.extra_data[data]} - editable={false}> + hidden={!this.props.piece.extra_data[data]}> ); } diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js index e840173a..ae7324b5 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js @@ -91,41 +91,33 @@ let IkonotvArtistDetailsForm = React.createClass({
    + label={getLangText('Artist Website')}> + label={getLangText('Website of related Gallery, Museum, etc.')}> + label={getLangText('Additional Websites/Publications')}> + label={getLangText('Short text about the Artist')}> diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js index 0ff3ae50..1a424011 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js @@ -89,61 +89,49 @@ let IkonotvArtworkDetailsForm = React.createClass({
    + label={getLangText('Medium')}> + label={getLangText('Size/Duration')}> + label={getLangText('Copyright')}> + label={getLangText('Courtesy of')}> + label={getLangText('Copyright of Photography')}> + label={getLangText('Additional Details about the artwork')}> From 652df66cb3175bbe6412b8ffae39130a92b2ec6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 21 Sep 2015 14:22:52 +0200 Subject: [PATCH 123/192] Fix some issues with smelly code --- js/actions/contract_agreement_list_actions.js | 1 - js/components/ascribe_forms/form.js | 2 +- .../ascribe_forms/input_textarea_toggable.js | 4 --- .../ascribe_detail/cyland_piece_container.js | 7 ----- .../ascribe_detail/ikonotv_piece_container.js | 27 ++++++++++++------- .../ikonotv_artist_details_form.js | 20 -------------- .../ikonotv_artwork_details_form.js | 18 ------------- 7 files changed, 18 insertions(+), 61 deletions(-) diff --git a/js/actions/contract_agreement_list_actions.js b/js/actions/contract_agreement_list_actions.js index fe089f24..cd78b52b 100644 --- a/js/actions/contract_agreement_list_actions.js +++ b/js/actions/contract_agreement_list_actions.js @@ -16,7 +16,6 @@ class ContractAgreementListActions { fetchContractAgreementList(issuer, accepted, pending) { this.actions.updateContractAgreementList(null); - return Q.Promise((resolve, reject) => { OwnershipFetcher.fetchContractAgreementList(issuer, accepted, pending) .then((contractAgreementList) => { diff --git a/js/components/ascribe_forms/form.js b/js/components/ascribe_forms/form.js index f7b1f76f..c5f60b76 100644 --- a/js/components/ascribe_forms/form.js +++ b/js/components/ascribe_forms/form.js @@ -203,7 +203,7 @@ let Form = React.createClass({ } let buttons = null; - if (this.state.edited){ + if (this.state.edited && !this.props.disabled){ buttons = (

    diff --git a/js/components/ascribe_forms/input_textarea_toggable.js b/js/components/ascribe_forms/input_textarea_toggable.js index 97f880f3..e789b61e 100644 --- a/js/components/ascribe_forms/input_textarea_toggable.js +++ b/js/components/ascribe_forms/input_textarea_toggable.js @@ -41,10 +41,6 @@ let InputTextAreaToggable = React.createClass({ } }, - componentWillUnmount() { - this.setState({value: null}); - }, - handleChange(event) { this.setState({value: event.target.value}); this.props.onChange(event); diff --git a/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js b/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js index f4a63ec8..3264c27e 100644 --- a/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js +++ b/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js @@ -42,13 +42,6 @@ let CylandPieceContainer = React.createClass({ UserStore.listen(this.onChange); }, - componentWillReceiveProps(nextProps) { - if(this.props.params.pieceId !== nextProps.params.pieceId) { - PieceActions.updatePiece({}); - PieceActions.fetchOne(nextProps.params.pieceId); - } - }, - componentWillUnmount() { // Every time we're leaving the piece detail page, // just reset the piece that is saved in the piece store diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js index 2025c10b..0425d5d8 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js @@ -21,6 +21,12 @@ import Property from '../../../../../../components/ascribe_forms/property'; import InputTextAreaToggable from '../../../../../../components/ascribe_forms/input_textarea_toggable'; import CollapsibleParagraph from '../../../../../../components/ascribe_collapsible/collapsible_paragraph'; +import IkonotvArtistDetailsForm from '../ascribe_forms/ikonotv_artist_details_form'; +import IkonotvArtworkDetailsForm from '../ascribe_forms/ikonotv_artwork_details_form'; + +import GlobalNotificationModel from '../../../../../../models/global_notification_model'; +import GlobalNotificationActions from '../../../../../../actions/global_notification_actions'; + import HistoryIterator from '../../../../../ascribe_detail/history_iterator'; import Note from '../../../../../ascribe_detail/note'; @@ -44,23 +50,18 @@ let IkonotvPieceContainer = React.createClass({ componentDidMount() { PieceStore.listen(this.onChange); - PieceActions.fetchOne(this.props.params.pieceId); UserStore.listen(this.onChange); - }, - componentWillReceiveProps(nextProps) { - if(this.props.params.pieceId !== nextProps.params.pieceId) { - PieceActions.updatePiece({}); - PieceActions.fetchOne(nextProps.params.pieceId); - } - }, - - componentWillUnmount() { // Every time we're leaving the piece detail page, // just reset the piece that is saved in the piece store // as it will otherwise display wrong/old data once the user loads // the piece detail a second time PieceActions.updatePiece({}); + + this.loadPiece(); + }, + + componentWillUnmount() { PieceStore.unlisten(this.onChange); UserStore.unlisten(this.onChange); }, @@ -159,6 +160,7 @@ let IkonotvPieceContainer = React.createClass({ url={ApiUrls.note_private_piece} currentUser={this.state.currentUser}/> + ); @@ -178,6 +180,11 @@ let IkonotvPieceDetails = React.createClass({ piece: React.PropTypes.object }, + handleSuccess() { + let notification = new GlobalNotificationModel('Artist details successfully updated', 'success', 10000); + GlobalNotificationActions.appendGlobalNotification(notification); + }, + render() { if (this.props.piece && Object.keys(this.props.piece.extra_data).length !== 0){ return ( diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js index ae7324b5..11f4d147 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js @@ -7,8 +7,6 @@ import Property from '../../../../../ascribe_forms/property'; import InputTextAreaToggable from '../../../../../ascribe_forms/input_textarea_toggable'; -//import FurtherDetailsFileuploader from '../../../../../ascribe_detail/further_details_fileuploader'; - import ApiUrls from '../../../../../../constants/api_urls'; import AppConstants from '../../../../../../constants/application_constants'; @@ -25,12 +23,6 @@ let IkonotvArtistDetailsForm = React.createClass({ disabled: React.PropTypes.bool }, - getInitialState() { - return { - isUploadReady: true - }; - }, - getFormData() { let extradata = {}; let formRefs = this.refs.form.refs; @@ -49,18 +41,6 @@ let IkonotvArtistDetailsForm = React.createClass({ }, - uploadStarted() { - this.setState({ - isUploadReady: false - }); - }, - - setIsUploadReady(isReady) { - this.setState({ - isUploadReady: isReady - }); - }, - render() { if(this.props.piece && this.props.piece.id && this.props.piece.extra_data) { return ( diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js index 1a424011..c4a3be37 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js @@ -23,12 +23,6 @@ let IkonotvArtworkDetailsForm = React.createClass({ disabled: React.PropTypes.bool }, - getInitialState() { - return { - isUploadReady: true - }; - }, - getFormData() { let extradata = {}; let formRefs = this.refs.form.refs; @@ -47,18 +41,6 @@ let IkonotvArtworkDetailsForm = React.createClass({ }, - uploadStarted() { - this.setState({ - isUploadReady: false - }); - }, - - setIsUploadReady(isReady) { - this.setState({ - isUploadReady: isReady - }); - }, - render() { if(this.props.piece && this.props.piece.id && this.props.piece.extra_data) { return ( From 9444cfb1bf5cf28ca90c23fe5f88bc9d447972c5 Mon Sep 17 00:00:00 2001 From: vrde Date: Mon, 21 Sep 2015 14:53:58 +0200 Subject: [PATCH 124/192] Add styles for header --- .../wallet/ikonotv/ikonotv_landing.scss | 97 ++++++++++++++++++- 1 file changed, 92 insertions(+), 5 deletions(-) diff --git a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss index d0708f5e..49c85f95 100644 --- a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss +++ b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss @@ -1,9 +1,94 @@ +$ikono--bg-color: #0066cc; +$ikono--button-color: #993399; +$ikono--logo: 'https://s3-us-west-2.amazonaws.com/ascribe0/whitelabel/ikonotv/ikono_tv.png'; + + .client--ikonotv { font-family: 'Helvetica Neue', 'Helvetica', sans-serif; } + +.navbar-default .navbar-nav > .active a:hover, .navbar-default .navbar-nav > .active a:focus { + +} + +.client--ikonotv .navbar-default { + background-color: $ikono--bg-color; + + // this is a horrible hack + .navbar-nav > li > a[href="https://www.ascribe.io/"] { + font-size: 11px; + text-transform: none; + font-weight: normal; + } + + .navbar-nav > li > a, + .navbar-nav > li > .active a { + text-transform: uppercase; + border-bottom-color: transparent; + font-size: 14px; + font-weight: bold; + } + + .navbar-nav > li > a { + color: white; + } + + .navbar-nav > .active a, + .navbar-nav > .active a:hover, + .navbar-nav > .active a:focus { + color: black; + border-bottom-color: transparent; + } + + .navbar-nav > .active { + background-color: white; + } + + .navbar-toggle .icon-bar { + background-color: white; + } + + .navbar-nav > .open > a, + .navbar-nav > .open > a:hover, + .navbar-nav > .open > a:focus, + .dropdown-menu > .active > a, + .dropdown-menu > .active > a:hover, + .dropdown-menu > .active > a:focus { + color: white; + background-color: $ikono--bg-color; + } + + .img-brand.navbar-brand { + width: 0; + height: 0; + padding-right: 120px; + padding-bottom: 36px; + padding-left: 30px; + background-image: url($ikono--logo); + background-color: transparent; + background-position: center 4px; + background-repeat: no-repeat; + background-size: 150px; + margin-bottom: 0; + position: relative; + } + +} + + + +.client--ikonotv.route--landing .btn-default, +.client--ikonotv.route--signup .ascribe-btn-login, +.client--ikonotv.route--login .ascribe-btn-login { + background-color: $ikono--button-color; + border: none; +} + + + .client--ikonotv.route--landing { - background-color: #c40050; + background-color: $ikono--bg-color; margin: 0; width: 100%; padding: 5em 1em; @@ -12,7 +97,7 @@ .client--ikonotv.route--login, .client--ikonotv.route--signup { - background-color: #c40050; + background-color: $ikono--bg-color; .ascribe-btn-login { display: block; @@ -25,16 +110,16 @@ } .ascribe-btn-login-spinner { - background-color: #02b6a3; + background-color: $ikono--button-color; } .ascribe-form-header { - background-image: url(https://s3-us-west-2.amazonaws.com/ascribe0/whitelabel/ikonotv/ikono_tv.png); + background-image: url($ikono--logo); background-color: transparent; background-position: center 0; background-repeat: no-repeat; background-size: 300px; - margin-bottom: 30px; + margin-bottom: 0; height: 150px; position: relative; @@ -46,6 +131,8 @@ color: white; text-align: center; font-size: 22px; + text-indent: -99999px; + font-size: 0; } } From d0c46d4ca22b8e83bbab42f449597d72422e2ebc Mon Sep 17 00:00:00 2001 From: vrde Date: Mon, 21 Sep 2015 14:58:07 +0200 Subject: [PATCH 125/192] Fix hover/focus status on hambuger icon --- sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss index 49c85f95..4e0ba619 100644 --- a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss +++ b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss @@ -74,6 +74,10 @@ $ikono--logo: 'https://s3-us-west-2.amazonaws.com/ascribe0/whitelabel/ikonotv/ik position: relative; } + .navbar-toggle:hover, + .navbar-toggle:focus { + background-color: rgba(255, 255, 255, 0.1); + } } From c7560247020718977f352a32429f548fbf49abde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 21 Sep 2015 15:08:24 +0200 Subject: [PATCH 126/192] Add whitelabel tailored extra_data forms to piece detail --- .../ascribe_forms/input_textarea_toggable.js | 8 +-- .../ascribe_detail/ikonotv_piece_container.js | 64 ++++------------- .../ikonotv_artist_details_form.js | 71 +++++++++++++------ .../ikonotv_artwork_details_form.js | 70 ++++++++++++------ 4 files changed, 116 insertions(+), 97 deletions(-) diff --git a/js/components/ascribe_forms/input_textarea_toggable.js b/js/components/ascribe_forms/input_textarea_toggable.js index e789b61e..1986cf24 100644 --- a/js/components/ascribe_forms/input_textarea_toggable.js +++ b/js/components/ascribe_forms/input_textarea_toggable.js @@ -22,7 +22,7 @@ let InputTextAreaToggable = React.createClass({ componentDidUpdate(prevProps, prevState) { // if the components state value was changed during an update, we want to refresh it // in this component as well as in the parent Property - if(this.state.value !== prevState.value) { + if(!this.state.value && this.state.value !== prevState.value) { this.handleChange({ target: { value: this.state.value @@ -33,10 +33,8 @@ let InputTextAreaToggable = React.createClass({ // Otherwise, if state wasn't defined beforehand and defaultValue is defined from the outside // we set it as the component's state and update Property by calling handleChange if(!this.state.value && this.props.defaultValue) { - this.handleChange({ - target: { - value: this.props.defaultValue - } + this.setState({ + value: this.props.defaultValue }); } }, diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js index 0425d5d8..bd0cd104 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js @@ -16,17 +16,11 @@ import AclButtonList from '../../../../../ascribe_buttons/acl_button_list'; import DeleteButton from '../../../../../ascribe_buttons/delete_button'; import IkonotvSubmitButton from '../ascribe_buttons/ikonotv_submit_button'; -import Form from '../../../../../../components/ascribe_forms/form'; -import Property from '../../../../../../components/ascribe_forms/property'; -import InputTextAreaToggable from '../../../../../../components/ascribe_forms/input_textarea_toggable'; import CollapsibleParagraph from '../../../../../../components/ascribe_collapsible/collapsible_paragraph'; import IkonotvArtistDetailsForm from '../ascribe_forms/ikonotv_artist_details_form'; import IkonotvArtworkDetailsForm from '../ascribe_forms/ikonotv_artwork_details_form'; -import GlobalNotificationModel from '../../../../../../models/global_notification_model'; -import GlobalNotificationActions from '../../../../../../actions/global_notification_actions'; - import HistoryIterator from '../../../../../ascribe_detail/history_iterator'; import Note from '../../../../../ascribe_detail/note'; @@ -161,7 +155,19 @@ let IkonotvPieceContainer = React.createClass({ currentUser={this.state.currentUser}/> - + + + + ); } else { @@ -174,48 +180,4 @@ let IkonotvPieceContainer = React.createClass({ } }); - -let IkonotvPieceDetails = React.createClass({ - propTypes: { - piece: React.PropTypes.object - }, - - handleSuccess() { - let notification = new GlobalNotificationModel('Artist details successfully updated', 'success', 10000); - GlobalNotificationActions.appendGlobalNotification(notification); - }, - - render() { - if (this.props.piece && Object.keys(this.props.piece.extra_data).length !== 0){ - return ( - - - {Object.keys(this.props.piece.extra_data).map((data, i) => { - let label = data.replace('_', ' '); - return ( - ); - } - )} -


    - - - ); - } - return null; - } -}); - export default IkonotvPieceContainer; diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js index 11f4d147..93c4ef63 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js @@ -7,6 +7,9 @@ import Property from '../../../../../ascribe_forms/property'; import InputTextAreaToggable from '../../../../../ascribe_forms/input_textarea_toggable'; +import GlobalNotificationModel from '../../../../../../models/global_notification_model'; +import GlobalNotificationActions from '../../../../../../actions/global_notification_actions'; + import ApiUrls from '../../../../../../constants/api_urls'; import AppConstants from '../../../../../../constants/application_constants'; @@ -20,7 +23,15 @@ let IkonotvArtistDetailsForm = React.createClass({ handleSuccess: React.PropTypes.func.isRequired, piece: React.PropTypes.object.isRequired, - disabled: React.PropTypes.bool + disabled: React.PropTypes.bool, + + isInline: React.PropTypes.bool + }, + + getDefaultProps() { + return { + isInline: false + }; }, getFormData() { @@ -41,7 +52,42 @@ let IkonotvArtistDetailsForm = React.createClass({ }, + handleSuccess() { + let notification = new GlobalNotificationModel('Artist details successfully updated', 'success', 10000); + GlobalNotificationActions.appendGlobalNotification(notification); + }, + + render() { + let buttons, spinner, heading; + let { isInline } = this.props; + + + if(!isInline) { + buttons = ( + + ); + + spinner = ( +
    + +
    + ); + + heading = ( +
    +

    + {getLangText('Artist Details')} +

    +
    + ); + } + if(this.props.piece && this.props.piece.id && this.props.piece.extra_data) { return (
    - {getLangText('Proceed to artwork details')} - - } - spinner={ -
    - -
    - }> -
    -

    - {getLangText('Artist Details')} -

    -
    + buttons={buttons} + spinner={spinner}> + {heading} diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js index c4a3be37..cfd51d5b 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js @@ -7,6 +7,9 @@ import Property from '../../../../../ascribe_forms/property'; import InputTextAreaToggable from '../../../../../ascribe_forms/input_textarea_toggable'; +import GlobalNotificationModel from '../../../../../../models/global_notification_model'; +import GlobalNotificationActions from '../../../../../../actions/global_notification_actions'; + import ApiUrls from '../../../../../../constants/api_urls'; import AppConstants from '../../../../../../constants/application_constants'; @@ -17,10 +20,17 @@ import { getLangText } from '../../../../../../utils/lang_utils'; let IkonotvArtworkDetailsForm = React.createClass({ propTypes: { - handleSuccess: React.PropTypes.func.isRequired, piece: React.PropTypes.object.isRequired, - disabled: React.PropTypes.bool + disabled: React.PropTypes.bool, + + isInline: React.PropTypes.bool + }, + + getDefaultProps() { + return { + isInline: false + }; }, getFormData() { @@ -41,7 +51,40 @@ let IkonotvArtworkDetailsForm = React.createClass({ }, + handleSuccess() { + let notification = new GlobalNotificationModel('Artwork details successfully updated', 'success', 10000); + GlobalNotificationActions.appendGlobalNotification(notification); + }, + render() { + let buttons, spinner, heading; + let { isInline } = this.props; + + if(!isInline) { + buttons = ( + + ); + + spinner = ( +
    + +
    + ); + + heading = ( +
    +

    + {getLangText('Artwork Details')} +

    +
    + ); + } + if(this.props.piece && this.props.piece.id && this.props.piece.extra_data) { return ( - {getLangText('Proceed to loan')} - - } - spinner={ -
    - -
    - }> -
    -

    - {getLangText('Artwork Details')} -

    -
    + buttons={buttons} + spinner={spinner}> + {heading} From 6c2bb041f9366060a66e6913e7e53c5ee1fff7d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 21 Sep 2015 15:46:24 +0200 Subject: [PATCH 127/192] finalize whitelabel custom fields --- .../ascribe_detail/cyland_piece_container.js | 55 +++--------- .../cyland_additional_data_form.js | 87 ++++++++++++------- .../ikonotv_artist_details_form.js | 7 +- .../ikonotv_artwork_details_form.js | 5 +- 4 files changed, 74 insertions(+), 80 deletions(-) diff --git a/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js b/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js index 3264c27e..51e65386 100644 --- a/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js +++ b/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js @@ -19,6 +19,8 @@ import CollapsibleParagraph from '../../../../../../components/ascribe_collapsib import HistoryIterator from '../../../../../ascribe_detail/history_iterator'; import Note from '../../../../../ascribe_detail/note'; +import CylandAdditionalDataForm from '../../cyland/ascribe_forms/cyland_additional_data_form'; + import FurtherDetailsFileuploader from '../../../../../ascribe_detail/further_details_fileuploader'; import DetailProperty from '../../../../../ascribe_detail/detail_property'; @@ -102,7 +104,15 @@ let CylandPieceContainer = React.createClass({ url={ApiUrls.note_private_piece} currentUser={this.state.currentUser}/> - + + + ); } else { @@ -115,47 +125,4 @@ let CylandPieceContainer = React.createClass({ } }); - -let CylandPieceDetails = React.createClass({ - propTypes: { - piece: React.PropTypes.object - }, - - render() { - if (this.props.piece && Object.keys(this.props.piece.extra_data).length !== 0){ - return ( - - - {Object.keys(this.props.piece.extra_data).map((data, i) => { - let label = data.replace('_', ' '); - return ( - - - ); - } - )} - -
    - -
    - ); - } - return null; - } -}); - export default CylandPieceContainer; diff --git a/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js b/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js index 9214123c..0fd023c2 100644 --- a/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js +++ b/js/components/whitelabel/wallet/components/cyland/ascribe_forms/cyland_additional_data_form.js @@ -9,6 +9,9 @@ import InputTextAreaToggable from '../../../../../ascribe_forms/input_textarea_t import FurtherDetailsFileuploader from '../../../../../ascribe_detail/further_details_fileuploader'; +import GlobalNotificationModel from '../../../../../../models/global_notification_model'; +import GlobalNotificationActions from '../../../../../../actions/global_notification_actions'; + import ApiUrls from '../../../../../../constants/api_urls'; import AppConstants from '../../../../../../constants/application_constants'; @@ -20,10 +23,21 @@ import { formSubmissionValidation } from '../../../../../ascribe_uploader/react_ let CylandAdditionalDataForm = React.createClass({ propTypes: { - handleSuccess: React.PropTypes.func.isRequired, + handleSuccess: React.PropTypes.func, piece: React.PropTypes.object.isRequired, + disabled: React.PropTypes.bool, + isInline: React.PropTypes.bool + }, - disabled: React.PropTypes.bool + getDefaultProps() { + return { + isInline: false + }; + }, + + handleSuccess() { + let notification = new GlobalNotificationModel('Further details successfully updated', 'success', 10000); + GlobalNotificationActions.appendGlobalNotification(notification); }, getInitialState() { @@ -63,56 +77,69 @@ let CylandAdditionalDataForm = React.createClass({ }, render() { - if(this.props.piece && this.props.piece.id) { + let { piece, isInline, disabled, handleSuccess } = this.props; + let buttons, spinner, heading; + + if(!isInline) { + buttons = ( + + ); + + spinner = ( +
    + +
    + ); + + heading = ( +
    +

    + {getLangText('Provide supporting materials')} +

    +
    + ); + } + + if(piece && piece.id) { return (
    - {getLangText('Proceed to loan')} - - } - spinner={ -
    - -
    - }> -
    -

    - {getLangText('Provide supporting materials')} -

    -
    + buttons={buttons} + spinner={spinner}> + {heading} + defaultValue={piece.extra_data.artist_bio} + placeholder={getLangText('Enter the artist\'s biography...')}/> + defaultValue={piece.extra_data.conceptual_overview} + placeholder={getLangText('Enter a conceptual overview...')}/> ); diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js index 93c4ef63..1fe5016d 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js @@ -20,7 +20,7 @@ import { getLangText } from '../../../../../../utils/lang_utils'; let IkonotvArtistDetailsForm = React.createClass({ propTypes: { - handleSuccess: React.PropTypes.func.isRequired, + handleSuccess: React.PropTypes.func, piece: React.PropTypes.object.isRequired, disabled: React.PropTypes.bool, @@ -57,10 +57,9 @@ let IkonotvArtistDetailsForm = React.createClass({ GlobalNotificationActions.appendGlobalNotification(notification); }, - render() { let buttons, spinner, heading; - let { isInline } = this.props; + let { isInline, handleSuccess } = this.props; if(!isInline) { @@ -95,7 +94,7 @@ let IkonotvArtistDetailsForm = React.createClass({ className="ascribe-form-bordered" ref='form' url={requests.prepareUrl(ApiUrls.piece_extradata, {piece_id: this.props.piece.id})} - handleSuccess={this.handleSuccess} + handleSuccess={handleSuccess || this.handleSuccess} getFormData={this.getFormData} buttons={buttons} spinner={spinner}> diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js index cfd51d5b..f091d860 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js @@ -20,6 +20,7 @@ import { getLangText } from '../../../../../../utils/lang_utils'; let IkonotvArtworkDetailsForm = React.createClass({ propTypes: { + handleSuccess: React.PropTypes.func, piece: React.PropTypes.object.isRequired, disabled: React.PropTypes.bool, @@ -58,7 +59,7 @@ let IkonotvArtworkDetailsForm = React.createClass({ render() { let buttons, spinner, heading; - let { isInline } = this.props; + let { isInline, handleSuccess } = this.props; if(!isInline) { buttons = ( @@ -92,7 +93,7 @@ let IkonotvArtworkDetailsForm = React.createClass({ className="ascribe-form-bordered" ref='form' url={requests.prepareUrl(ApiUrls.piece_extradata, {piece_id: this.props.piece.id})} - handleSuccess={this.handleSuccess} + handleSuccess={handleSuccess || this.handleSuccess} getFormData={this.getFormData} buttons={buttons} spinner={spinner}> From 04e331f4e5d65dda3a3edeee7e73c471fe13a0a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 21 Sep 2015 15:57:27 +0200 Subject: [PATCH 128/192] hide additional files when not defined and already loaned to whitelabel customer --- .../ikonotv_artist_details_form.js | 12 ++++++++---- .../ikonotv_artwork_details_form.js | 18 ++++++++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js index 1fe5016d..d198c7dd 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js @@ -101,7 +101,8 @@ let IkonotvArtistDetailsForm = React.createClass({ {heading} + label={getLangText('Artist Website')} + hidden={this.props.disabled && !this.props.piece.extra_data.artist_website}> + label={getLangText('Website of related Gallery, Museum, etc.')} + hidden={this.props.disabled && !this.props.piece.extra_data.gallery_website}> + label={getLangText('Additional Websites/Publications')} + hidden={this.props.disabled && !this.props.piece.extra_data.additional_websites}> + label={getLangText('Short text about the Artist')} + hidden={this.props.disabled && !this.props.piece.extra_data.conceptual_overview}> + label={getLangText('Medium')} + hidden={this.props.disabled && !this.props.piece.extra_data.medium}> + label={getLangText('Size/Duration')} + hidden={this.props.disabled && !this.props.piece.extra_data.size_duration}> + label={getLangText('Copyright')} + hidden={this.props.disabled && !this.props.piece.extra_data.copyright}> + label={getLangText('Courtesy of')} + hidden={this.props.disabled && !this.props.piece.extra_data.courtesy_of}> + label={getLangText('Copyright of Photography')} + hidden={this.props.disabled && !this.props.piece.extra_data.copyright_of_photography}> + label={getLangText('Additional Details about the artwork')} + hidden={this.props.disabled && !this.props.piece.extra_data.additional_details}> Date: Mon, 21 Sep 2015 16:10:25 +0200 Subject: [PATCH 129/192] update react textarea autosize --- js/components/ascribe_forms/form_loan.js | 2 +- .../wallet/components/ikonotv/ikonotv_register_piece.js | 2 -- package.json | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index b15ac909..5f7c5d78 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -158,7 +158,7 @@ let LoanForm = React.createClass({ if (appendix && appendix.default) { return (
    -

    {getLangText('Appendix')}

    +

    {getLangText('Appendix')}

                                 {appendix.default}
                             
    diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js index 98d8a8e7..91a62b3b 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js @@ -180,7 +180,6 @@ let IkonotvRegisterPiece = React.createClass({ 1} handleSuccess={this.handleAdditionalDataSuccess} piece={this.state.piece}/> @@ -198,7 +197,6 @@ let IkonotvRegisterPiece = React.createClass({ 1} handleSuccess={this.handleAdditionalDataSuccess} piece={this.state.piece}/> diff --git a/package.json b/package.json index 9160487b..0e41d714 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "react-router": "^0.13.3", "react-router-bootstrap": "~0.16.0", "react-star-rating": "~1.3.2", - "react-textarea-autosize": "^2.2.3", + "react-textarea-autosize": "^2.5.2", "reactify": "^1.1.0", "shmui": "^0.1.0", "spark-md5": "~1.0.0", From fdbae0316f1d1139e417115ad659c52535ab1d98 Mon Sep 17 00:00:00 2001 From: diminator Date: Mon, 21 Sep 2015 16:14:39 +0200 Subject: [PATCH 130/192] filter for submitted and accepted on ikonotv MIGRATE AND ./manage.py loaddata whitelabel/fixtures/settings.json --- .../ikonotv_accordion_list_item.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_accordion_list/ikonotv_accordion_list_item.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_accordion_list/ikonotv_accordion_list_item.js index b716914a..d063eace 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_accordion_list/ikonotv_accordion_list_item.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_accordion_list/ikonotv_accordion_list_item.js @@ -75,6 +75,16 @@ let IkonotvAccordionListItem = React.createClass({ aclName="acl_submitted"> + + + + + +
    ); }, From 904793269b7e886a9a172acd26dbff2d8d97728c Mon Sep 17 00:00:00 2001 From: diminator Date: Mon, 21 Sep 2015 18:04:15 +0200 Subject: [PATCH 134/192] refactored detail page for wallets --- .../ascribe_detail/wallet_action_panel.js | 70 ++++++++++++ .../ascribe_detail/wallet_piece_container.js | 85 ++++++++++++++ .../cyland_accordion_list_item.js | 1 - .../ascribe_detail/cyland_piece_container.js | 77 +++---------- .../ascribe_detail/ikonotv_piece_container.js | 106 ++---------------- 5 files changed, 181 insertions(+), 158 deletions(-) create mode 100644 js/components/whitelabel/wallet/components/ascribe_detail/wallet_action_panel.js create mode 100644 js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js 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 new file mode 100644 index 00000000..2a4ba61a --- /dev/null +++ b/js/components/whitelabel/wallet/components/ascribe_detail/wallet_action_panel.js @@ -0,0 +1,70 @@ +'use strict'; + +import React from 'react'; + + +import ListRequestActions from '../../../../ascribe_forms/list_form_request_actions'; +import AclButtonList from '../../../../ascribe_buttons/acl_button_list'; +import DeleteButton from '../../../../ascribe_buttons/delete_button'; + +import AclProxy from '../../../../acl_proxy'; + + +import { mergeOptions } from '../../../../../utils/general_utils'; + + +let WalletActionPanel = React.createClass({ + propTypes: { + piece: React.PropTypes.object.isRequired, + currentUser: React.PropTypes.object.isRequired, + loadPiece: React.PropTypes.func.isRequired, + submitButtonType: React.PropTypes.func.isRequired + }, + + render(){ + if (this.props.piece && + this.props.piece.notifications && + this.props.piece.notifications.length > 0) { + return ( + ); + } + else { + + //We need to disable the normal acl_loan because we're inserting a custom acl_loan button + let availableAcls; + + if (this.props.piece && this.props.piece.acl && typeof this.props.piece.acl.acl_loan !== 'undefined') { + // make a copy to not have side effects + availableAcls = mergeOptions({}, this.props.piece.acl); + availableAcls.acl_loan = false; + } + let SubmitButtonType = this.props.submitButtonType; + + return ( + + + + + + + ); + } + } +}); + +export default WalletActionPanel; \ No newline at end of file diff --git a/js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js b/js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js new file mode 100644 index 00000000..adbd3e95 --- /dev/null +++ b/js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js @@ -0,0 +1,85 @@ +'use strict'; + +import React from 'react'; + + +import Piece from '../../../../../components/ascribe_detail/piece'; + +import WalletActionPanel from './wallet_action_panel'; +import CollapsibleParagraph from '../../../../../components/ascribe_collapsible/collapsible_paragraph'; + +import HistoryIterator from '../../../../ascribe_detail/history_iterator'; +import Note from '../../../../ascribe_detail/note'; + +import DetailProperty from '../../../../ascribe_detail/detail_property'; + +import ApiUrls from '../../../../../constants/api_urls'; + +import { getLangText } from '../../../../../utils/lang_utils'; +import { mergeOptions } from '../../../../../utils/general_utils'; + + +let WalletPieceContainer = React.createClass({ + + propTypes: { + piece: React.PropTypes.object.isRequired, + currentUser: React.PropTypes.object.isRequired, + loadPiece: React.PropTypes.func.isRequired, + submitButtonType: React.PropTypes.func.isRequired + }, + + + render() { + return ( + +
    +

    {this.props.piece.title}

    + + +
    +
    + } + subheader={ +
    + + +
    +
    + }> + + 0}> + + + + {return {'id': this.props.piece.id}; }} + label={getLangText('Personal note (private)')} + defaultValue={this.props.piece.private_note || null} + placeholder={getLangText('Enter your comments ...')} + editable={true} + successMessage={getLangText('Private note saved')} + url={ApiUrls.note_private_piece} + currentUser={this.props.currentUser}/> + + + {this.props.children} + + ); + + } +}); + +export default WalletPieceContainer; diff --git a/js/components/whitelabel/wallet/components/cyland/ascribe_accordion_list/cyland_accordion_list_item.js b/js/components/whitelabel/wallet/components/cyland/ascribe_accordion_list/cyland_accordion_list_item.js index 9535e832..72357f48 100644 --- a/js/components/whitelabel/wallet/components/cyland/ascribe_accordion_list/cyland_accordion_list_item.js +++ b/js/components/whitelabel/wallet/components/cyland/ascribe_accordion_list/cyland_accordion_list_item.js @@ -1,7 +1,6 @@ 'use strict'; import React from 'react'; -import Router from 'react-router'; import AccordionListItemPiece from '../../../../../ascribe_accordion_list/accordion_list_item_piece'; diff --git a/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js b/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js index 51e65386..81c7a0cf 100644 --- a/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js +++ b/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js @@ -7,29 +7,19 @@ import PieceStore from '../../../../../../stores/piece_store'; import UserStore from '../../../../../../stores/user_store'; -import Piece from '../../../../../../components/ascribe_detail/piece'; +import CylandSubmitButton from '../ascribe_buttons/cyland_submit_button'; + +import CollapsibleParagraph from '../../../../../../components/ascribe_collapsible/collapsible_paragraph'; + +import CylandAdditionalDataForm from '../ascribe_forms/cyland_additional_data_form'; + +import WalletPieceContainer from '../../ascribe_detail/wallet_piece_container'; import AppConstants from '../../../../../../constants/application_constants'; -import Form from '../../../../../../components/ascribe_forms/form'; -import Property from '../../../../../../components/ascribe_forms/property'; -import InputTextAreaToggable from '../../../../../../components/ascribe_forms/input_textarea_toggable'; -import CollapsibleParagraph from '../../../../../../components/ascribe_collapsible/collapsible_paragraph'; - -import HistoryIterator from '../../../../../ascribe_detail/history_iterator'; -import Note from '../../../../../ascribe_detail/note'; - -import CylandAdditionalDataForm from '../../cyland/ascribe_forms/cyland_additional_data_form'; - -import FurtherDetailsFileuploader from '../../../../../ascribe_detail/further_details_fileuploader'; -import DetailProperty from '../../../../../ascribe_detail/detail_property'; - -import ApiUrls from '../../../../../../constants/api_urls'; - import { getLangText } from '../../../../../../utils/lang_utils'; import { mergeOptions } from '../../../../../../utils/general_utils'; - let CylandPieceContainer = React.createClass({ getInitialState() { return mergeOptions( @@ -40,16 +30,18 @@ let CylandPieceContainer = React.createClass({ componentDidMount() { PieceStore.listen(this.onChange); - PieceActions.fetchOne(this.props.params.pieceId); UserStore.listen(this.onChange); - }, - componentWillUnmount() { // Every time we're leaving the piece detail page, // just reset the piece that is saved in the piece store // as it will otherwise display wrong/old data once the user loads // the piece detail a second time PieceActions.updatePiece({}); + + this.loadPiece(); + }, + + componentWillUnmount() { PieceStore.unlisten(this.onChange); UserStore.unlisten(this.onChange); }, @@ -65,45 +57,11 @@ let CylandPieceContainer = React.createClass({ render() { if(this.state.piece && this.state.piece.title) { return ( - -
    -

    {this.state.piece.title}

    - - -
    -
    - } - subheader={ -
    - - -
    -
    - }> - - 0}> - - - - {return {'id': this.state.piece.id}; }} - label={getLangText('Personal note (private)')} - defaultValue={this.state.piece.private_note || null} - placeholder={getLangText('Enter your comments ...')} - editable={true} - successMessage={getLangText('Private note saved')} - url={ApiUrls.note_private_piece} - currentUser={this.state.currentUser}/> - + submitButtonType={CylandSubmitButton}> - + ); - } else { + } + else { return (
    diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js index bd0cd104..3c2a3e4b 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_detail/ikonotv_piece_container.js @@ -7,13 +7,7 @@ import PieceStore from '../../../../../../stores/piece_store'; import UserStore from '../../../../../../stores/user_store'; -import Piece from '../../../../../../components/ascribe_detail/piece'; -import AppConstants from '../../../../../../constants/application_constants'; - -import ListRequestActions from '../../../../../ascribe_forms/list_form_request_actions'; -import AclButtonList from '../../../../../ascribe_buttons/acl_button_list'; -import DeleteButton from '../../../../../ascribe_buttons/delete_button'; import IkonotvSubmitButton from '../ascribe_buttons/ikonotv_submit_button'; import CollapsibleParagraph from '../../../../../../components/ascribe_collapsible/collapsible_paragraph'; @@ -21,19 +15,13 @@ import CollapsibleParagraph from '../../../../../../components/ascribe_collapsib import IkonotvArtistDetailsForm from '../ascribe_forms/ikonotv_artist_details_form'; import IkonotvArtworkDetailsForm from '../ascribe_forms/ikonotv_artwork_details_form'; -import HistoryIterator from '../../../../../ascribe_detail/history_iterator'; -import Note from '../../../../../ascribe_detail/note'; +import WalletPieceContainer from '../../ascribe_detail/wallet_piece_container'; -import DetailProperty from '../../../../../ascribe_detail/detail_property'; - -import AclProxy from '../../../../../acl_proxy'; - -import ApiUrls from '../../../../../../constants/api_urls'; +import AppConstants from '../../../../../../constants/application_constants'; import { getLangText } from '../../../../../../utils/lang_utils'; import { mergeOptions } from '../../../../../../utils/general_utils'; - let IkonotvPieceContainer = React.createClass({ getInitialState() { return mergeOptions( @@ -68,93 +56,14 @@ let IkonotvPieceContainer = React.createClass({ PieceActions.fetchOne(this.props.params.pieceId); }, - getActions(){ - if (this.state.piece && - this.state.piece.notifications && - this.state.piece.notifications.length > 0) { - return ( - ); - } - else { - - //We need to disable the normal acl_loan because we're inserting a custom acl_loan button - let availableAcls; - - if(this.state.piece && this.state.piece.acl && typeof this.state.piece.acl.acl_loan !== 'undefined') { - // make a copy to not have side effects - availableAcls = mergeOptions({}, this.state.piece.acl); - availableAcls.acl_loan = false; - } - - return ( - - - - - - - ); - } - }, - render() { if(this.state.piece && this.state.piece.title) { return ( - -
    -

    {this.state.piece.title}

    - - -
    -
    - } - subheader={ -
    - - -
    -
    - }> - {this.getActions()} - 0}> - - - - {return {'id': this.state.piece.id}; }} - label={getLangText('Personal note (private)')} - defaultValue={this.state.piece.private_note || null} - placeholder={getLangText('Enter your comments ...')} - editable={true} - successMessage={getLangText('Private note saved')} - url={ApiUrls.note_private_piece} - currentUser={this.state.currentUser}/> - - + submitButtonType={IkonotvSubmitButton}> - + ); - } else { + } + else { return (
    From b4c7b864fd739bf4449e17249472df6912901bf5 Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 22 Sep 2015 09:20:10 +0200 Subject: [PATCH 135/192] check if piece exists in props in wallet details --- .../ascribe_detail/wallet_piece_container.js | 91 ++++++++++--------- 1 file changed, 50 insertions(+), 41 deletions(-) diff --git a/js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js b/js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js index adbd3e95..fa049a6f 100644 --- a/js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js +++ b/js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js @@ -17,7 +17,7 @@ import ApiUrls from '../../../../../constants/api_urls'; import { getLangText } from '../../../../../utils/lang_utils'; import { mergeOptions } from '../../../../../utils/general_utils'; - +import AppConstants from '../../../../../constants/application_constants'; let WalletPieceContainer = React.createClass({ @@ -30,54 +30,63 @@ let WalletPieceContainer = React.createClass({ render() { - return ( - -
    -

    {this.props.piece.title}

    - - -
    -
    + if(this.props.piece && this.props.piece.title) { + return ( + +
    +

    {this.props.piece.title}

    + + +
    +
    } - subheader={ + subheader={

    }> - - 0}> - - - - {return {'id': this.props.piece.id}; }} - label={getLangText('Personal note (private)')} - defaultValue={this.props.piece.private_note || null} - placeholder={getLangText('Enter your comments ...')} - editable={true} - successMessage={getLangText('Private note saved')} - url={ApiUrls.note_private_piece} - currentUser={this.props.currentUser}/> - + + 0}> + + + + {return {'id': this.props.piece.id}; }} + label={getLangText('Personal note (private)')} + defaultValue={this.props.piece.private_note || null} + placeholder={getLangText('Enter your comments ...')} + editable={true} + successMessage={getLangText('Private note saved')} + url={ApiUrls.note_private_piece} + currentUser={this.props.currentUser}/> + - {this.props.children} - - ); + {this.props.children} + + ); + } + else { + return ( +
    + +
    + ); + } } }); From b0b44718da9e844c0eae8b44303bd302b6f3ab1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 22 Sep 2015 10:29:23 +0200 Subject: [PATCH 136/192] Changes to landing page text according to Elisabeth --- .../whitelabel/wallet/components/ikonotv/ikonotv_landing.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js index 7184c605..e991233a 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js @@ -76,7 +76,7 @@ let IkonotvLanding = React.createClass({ NEW SUBSCRIPTION SERVICE

    - IkonoTV has developed an app that provides playlists on demand—soon to be available on all online devices and SmartTVs. The app is a paid service; in view of the interest in distributing this service in public spaces (hospitals, airports, hotels, etc.), we can now offer the possibility of a share in revenue to compensate for the artist’s work. + IkonoTV has developed an app that provides playlists on demand—soon to be available on all online devices and SmartTVs. We can now offer the possibility of a share in revenue to compensate for the artist’s work.

    @@ -84,7 +84,7 @@ let IkonotvLanding = React.createClass({ THE RAPID GROWTH OF IkonoTV

    - In October 2014, our first app was installed on Amazon Fire TV. During the first month it was downloaded 200 times, and jumped to 5,000 by the second month. Today, we’re well over the 175,000 mark, making us the number one app in our category in the US, Canada, UK and Germany. + In October 2014, our first app was installed on Amazon Fire TV. During the first month it was downloaded 200 times, and jumped to 5,000 by the second month. Today, we’re well over the 285,000 mark, making us the number one app in our category in the US, Canada, UK and Germany.

    From a0ff5af62bad657cfa1496bc4e7a13931a747e38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 22 Sep 2015 11:33:59 +0200 Subject: [PATCH 137/192] Make style changes --- .../wallet/components/ikonotv/ikonotv_contract_notifications.js | 2 +- .../wallet/components/ikonotv/ikonotv_register_piece.js | 2 +- sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js index cfc80825..9c184835 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_contract_notifications.js @@ -162,7 +162,7 @@ let IkonotvContractNotifications = React.createClass({
    - {getLangText('Production Contract')} + {getLangText('Contract')}
    {this.getContract()} diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js index 91a62b3b..b946d984 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_register_piece.js @@ -259,8 +259,8 @@ let IkonotvRegisterPiece = React.createClass({
    - {this.getSlideArtistDetails()} {this.getSlideArtworkDetails()} + {this.getSlideArtistDetails()} {this.getSlideLoan()} ); diff --git a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss index 4e0ba619..df1cf39c 100644 --- a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss +++ b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss @@ -221,7 +221,7 @@ $ikono--logo: 'https://s3-us-west-2.amazonaws.com/ascribe0/whitelabel/ikonotv/ik margin-bottom: 2em; > h1 { - font-size: 9em; + font-size: 7em; font-weight: bold; margin-top: 10px; From 31ffc4262a8d458429912427b89966211bdfaea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 22 Sep 2015 11:41:10 +0200 Subject: [PATCH 138/192] change text in signup form --- js/components/ascribe_forms/form_signup.js | 2 +- js/constants/languages.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/js/components/ascribe_forms/form_signup.js b/js/components/ascribe_forms/form_signup.js index 67097b42..bcc38007 100644 --- a/js/components/ascribe_forms/form_signup.js +++ b/js/components/ascribe_forms/form_signup.js @@ -127,7 +127,7 @@ let SignupForm = React.createClass({ style={{paddingBottom: 0}}> - {' ' + getLangText('I agree to the Terms of Service') + ' '} + {' ' + getLangText('I agree to the Terms of Service of ascribe') + ' '} ( {getLangText('read')} ) diff --git a/js/constants/languages.js b/js/constants/languages.js index db29166f..4a40d9a4 100644 --- a/js/constants/languages.js +++ b/js/constants/languages.js @@ -207,7 +207,7 @@ const languages = { 'Specify editions': 'Specify editions', 'Editions': 'Editions', 'Create editions': 'Create editions', - 'I agree to the Terms of Service': 'I agree to the Terms of Service', + 'I agree to the Terms of Service of ascribe': 'I agree to the Terms of Service of ascribe', 'read': 'read', 'If your email address exists in our database, you will receive a password recovery link in a few minutes.': 'If your email address exists in our database, you will receive a password recovery link in a few minutes.', 'REGISTREE': 'REGISTREE', From a8c436c40b3e47362dca0fee9dbed642dbbe87fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 22 Sep 2015 11:56:30 +0200 Subject: [PATCH 139/192] Change detail text in loan process --- .../ikonotv/ascribe_forms/ikonotv_artist_details_form.js | 2 +- .../ikonotv/ascribe_forms/ikonotv_artwork_details_form.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js index d198c7dd..fadeec59 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artist_details_form.js @@ -119,7 +119,7 @@ let IkonotvArtistDetailsForm = React.createClass({ Date: Tue, 22 Sep 2015 12:20:14 +0200 Subject: [PATCH 140/192] filter in frontend --- .../components/ikonotv/ikonotv_piece_list.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_piece_list.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_piece_list.js index 33478fbf..053d21b3 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_piece_list.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_piece_list.js @@ -37,11 +37,17 @@ let IkonotvPieceList = React.createClass({ accordionListItemType={IkonotvAccordionListItem} filterParams={[{ label: getLangText('Show works I have'), - items: [{ - key: 'acl_loaned', - label: getLangText('loaned to IkonoTV') - }] - }]}/> + items: [ + { + key: 'submitted', + label: getLangText('submitted') + }, + { + key: 'accepted', + label: getLangText('loaned') + } + ] + }]}/>
    ); } From 878a716262daebcc03bab2f1e8bec77fd9dd0860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 22 Sep 2015 13:20:55 +0200 Subject: [PATCH 141/192] Remove 'learn more' from contract form --- js/components/ascribe_forms/form_contract_agreement.js | 10 +--------- .../ascribe_forms/ikonotv_artwork_details_form.js | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/js/components/ascribe_forms/form_contract_agreement.js b/js/components/ascribe_forms/form_contract_agreement.js index 85ed6b6a..ddb261c4 100644 --- a/js/components/ascribe_forms/form_contract_agreement.js +++ b/js/components/ascribe_forms/form_contract_agreement.js @@ -68,15 +68,7 @@ let ContractAgreementForm = React.createClass({ - {getLangText('Learn more')} - - }> + onChange={this.onContractChange}> - + {this.getContractCheckbox()} + {this.getAppendix()} - {this.getContractCheckbox()} - {this.getAppendix()} {this.props.children} ); diff --git a/js/components/ascribe_forms/input_checkbox.js b/js/components/ascribe_forms/input_checkbox.js index 275b2374..38885441 100644 --- a/js/components/ascribe_forms/input_checkbox.js +++ b/js/components/ascribe_forms/input_checkbox.js @@ -25,7 +25,10 @@ let InputCheckbox = React.createClass({ // provided by Property disabled: React.PropTypes.bool, - onChange: React.PropTypes.func + onChange: React.PropTypes.func, + + // can be used to style the component from the outside + style: React.PropTypes.object }, // As HTML inputs, we're setting the default value for an input to checked === false @@ -98,6 +101,7 @@ let InputCheckbox = React.createClass({ return ( - - + ); } @@ -97,12 +94,11 @@ let IkonotvContractNotifications = React.createClass({ let appendix = notifications.contract_agreement.appendix; if (appendix && appendix.default) { return ( -
    -

    {getLangText('Appendix')}

    -
    -                        {appendix.default}
    -                    
    -
    + +
    {appendix.default}
    +
    ); } return null; @@ -153,9 +149,12 @@ let IkonotvContractNotifications = React.createClass({ }, render() { - if (this.state.contractAgreementListNotifications && this.state.contractAgreementListNotifications.length > 0) { + + let notifications = this.state.contractAgreementListNotifications[0]; + let blob = notifications.contract_agreement.contract.blob; + return (
    @@ -168,6 +167,14 @@ let IkonotvContractNotifications = React.createClass({ {this.getContract()}
    {this.getAppendix()} + {this.getCopyrightAssociationForm()}

    ); diff --git a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js index fb21c3a8..bab4ceca 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ascribe_forms/ikonotv_artwork_details_form.js @@ -67,7 +67,7 @@ let IkonotvArtworkDetailsForm = React.createClass({ type="submit" className="btn ascribe-btn ascribe-btn-login" disabled={this.props.disabled}> - {getLangText('Proceed to loan')} + {getLangText('Proceed to artist details')} ); From 172b5b7c5b1207c5298f367100025bad90f780cd Mon Sep 17 00:00:00 2001 From: vrde Date: Tue, 22 Sep 2015 17:11:38 +0200 Subject: [PATCH 151/192] Fix form borders --- sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss index c25517e1..d3dfb270 100644 --- a/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss +++ b/sass/whitelabel/wallet/ikonotv/ikonotv_landing.scss @@ -178,8 +178,13 @@ $ikono--logo: 'https://s3-us-west-2.amazonaws.com/ascribe0/whitelabel/ikonotv/ik } -.client--ikonotv .ascribe-form-bordered { - border: none; +.client--ikonotv { + .route--login, + .route--signup { + .ascribe-form-bordered { + border: none; + } + } } .client--ikonotv .ascribe-login-wrapper { From 3a11efb2fc4604082e2c66048f90c4fef5009f88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Tue, 22 Sep 2015 17:13:06 +0200 Subject: [PATCH 152/192] Improve input_textarea_toggleable --- .../ascribe_forms/input_textarea_toggable.js | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/js/components/ascribe_forms/input_textarea_toggable.js b/js/components/ascribe_forms/input_textarea_toggable.js index 1986cf24..a36f6ecc 100644 --- a/js/components/ascribe_forms/input_textarea_toggable.js +++ b/js/components/ascribe_forms/input_textarea_toggable.js @@ -19,20 +19,10 @@ let InputTextAreaToggable = React.createClass({ }; }, - componentDidUpdate(prevProps, prevState) { - // if the components state value was changed during an update, we want to refresh it - // in this component as well as in the parent Property - if(!this.state.value && this.state.value !== prevState.value) { - this.handleChange({ - target: { - value: this.state.value - } - }); - } - - // Otherwise, if state wasn't defined beforehand and defaultValue is defined from the outside - // we set it as the component's state and update Property by calling handleChange - if(!this.state.value && this.props.defaultValue) { + componentDidUpdate() { + // If the initial value of state.value is null, we want to set props.defaultValue + // as a value. In all other cases TextareaAutosize.onChange is updating.handleChange already + if(this.state.value === null && this.props.defaultValue) { this.setState({ value: this.props.defaultValue }); From f1bc400faf18df0a4942fb9a63f754ccc681702f Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 22 Sep 2015 17:23:19 +0200 Subject: [PATCH 153/192] acls on 3 levels whitelabel user piece the higher on the list, the more power (whitelabel overrides user and piece) --- js/components/ascribe_settings/contract_settings.js | 2 +- .../ascribe_accordion_list/accordion_list_item_prize.js | 2 +- .../components/ascribe_detail/wallet_action_panel.js | 2 +- .../ascribe_accordion_list/cyland_accordion_list_item.js | 6 +++--- .../ascribe_accordion_list/ikonotv_accordion_list_item.js | 8 ++++---- .../wallet/components/ikonotv/ikonotv_register_piece.js | 2 +- js/components/whitelabel/wallet/wallet_routes.js | 2 +- js/constants/application_constants.js | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 39cb853d..d0ded734 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -83,7 +83,7 @@ let ContractSettings = React.createClass({ return ( + aclName="acl_wallet_submit"> + aclName="acl_wallet_submit"> + aclName="acl_wallet_submit"> + aclName="acl_wallet_submitted"> -

    - } - leftColumnWidth="40%" - rightColumnWidth="60%"/> - ); - })} -
    - - -
    - - {privateContracts.map((contract, i) => { - return ( - - - - {getLangText('PREVIEW')} - - -
    - } - leftColumnWidth="40%" - rightColumnWidth="60%"/> - ); - })} -
    - -
    - +
    + + + +
    + {createPublicContractForm} + {publicContracts.map((contract, i) => { + return ( + + + + {getLangText('PREVIEW')} + + +
    + } + leftColumnWidth="40%" + rightColumnWidth="60%"/> + ); + })} +
    + + +
    + + {privateContracts.map((contract, i) => { + return ( + + + + {getLangText('PREVIEW')} + + +
    + } + leftColumnWidth="40%" + rightColumnWidth="60%"/> + ); + })} + +
    + + + ); } }); diff --git a/js/components/ascribe_settings/settings_container.js b/js/components/ascribe_settings/settings_container.js index 2b3dc6a7..12c406ad 100644 --- a/js/components/ascribe_settings/settings_container.js +++ b/js/components/ascribe_settings/settings_container.js @@ -50,7 +50,6 @@ let SettingsContainer = React.createClass({ {this.props.children} - ); } diff --git a/js/components/header.js b/js/components/header.js index 0309b748..307ba663 100644 --- a/js/components/header.js +++ b/js/components/header.js @@ -3,7 +3,6 @@ import React from 'react'; import Router from 'react-router'; - import Nav from 'react-bootstrap/lib/Nav'; import Navbar from 'react-bootstrap/lib/Navbar'; import CollapsibleNav from 'react-bootstrap/lib/CollapsibleNav'; @@ -12,6 +11,8 @@ import MenuItem from 'react-bootstrap/lib/MenuItem'; import MenuItemLink from 'react-router-bootstrap/lib/MenuItemLink'; import NavItemLink from 'react-router-bootstrap/lib/NavItemLink'; +import AclProxy from './acl_proxy'; + import UserActions from '../actions/user_actions'; import UserStore from '../stores/user_store'; @@ -96,7 +97,7 @@ let Header = React.createClass({ } }, - onMenuItemClick(event) { + onMenuItemClick() { /* This is a hack to make the dropdown close after clicking on an item The function just need to be defined @@ -137,6 +138,15 @@ let Header = React.createClass({ onClick={this.onMenuItemClick}> {getLangText('Account Settings')} + + + {getLangText('Contract Settings')} + + {getLangText('Log out')} diff --git a/js/components/whitelabel/wallet/wallet_routes.js b/js/components/whitelabel/wallet/wallet_routes.js index 075901bd..43b983aa 100644 --- a/js/components/whitelabel/wallet/wallet_routes.js +++ b/js/components/whitelabel/wallet/wallet_routes.js @@ -12,7 +12,7 @@ import PieceList from '../../../components/piece_list'; import PieceContainer from '../../../components/ascribe_detail/piece_container'; import EditionContainer from '../../../components/ascribe_detail/edition_container'; import SettingsContainer from '../../../components/ascribe_settings/settings_container'; -import RegisterPiece from '../../../components/register_piece'; +import ContractSettings from '../../../components/ascribe_settings/contract_settings'; import CylandLanding from './components/cyland/cyland_landing'; import CylandPieceContainer from './components/cyland/ascribe_detail/cyland_piece_container'; @@ -49,6 +49,7 @@ let ROUTES = { + ), 'cc': ( @@ -79,6 +80,7 @@ let ROUTES = { + ) diff --git a/js/routes.js b/js/routes.js index 1d521cab..7a869f41 100644 --- a/js/routes.js +++ b/js/routes.js @@ -17,6 +17,7 @@ import LogoutContainer from './components/logout_container'; import SignupContainer from './components/signup_container'; import PasswordResetContainer from './components/password_reset_container'; +import ContractSettings from './components/ascribe_settings/contract_settings'; import SettingsContainer from './components/ascribe_settings/settings_container'; import CoaVerifyContainer from './components/coa_verify_container'; @@ -43,6 +44,7 @@ const COMMON_ROUTES = ( + From 74e7c9a3d92b8aef983d47c65afbd41a3af5473b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Wed, 23 Sep 2015 15:41:12 +0200 Subject: [PATCH 158/192] Integrate new ACLOptions into settings --- .../ascribe_settings/contract_settings.js | 156 +++++++++--------- .../ascribe_settings/settings_container.js | 29 +++- js/components/header.js | 2 +- 3 files changed, 102 insertions(+), 85 deletions(-) diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 2ef600f0..2050120c 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -89,86 +89,82 @@ let ContractSettings = React.createClass({ return (
    - - - -
    - {createPublicContractForm} - {publicContracts.map((contract, i) => { - return ( - - - - {getLangText('PREVIEW')} - - -
    - } - leftColumnWidth="40%" - rightColumnWidth="60%"/> - ); - })} -
    - - -
    - - {privateContracts.map((contract, i) => { - return ( - - - - {getLangText('PREVIEW')} - - -
    - } - leftColumnWidth="40%" - rightColumnWidth="60%"/> - ); - })} - -
    - - + + +
    + {createPublicContractForm} + {publicContracts.map((contract, i) => { + return ( + + + + {getLangText('PREVIEW')} + + +
    + } + leftColumnWidth="40%" + rightColumnWidth="60%"/> + ); + })} + +
    + +
    + + {privateContracts.map((contract, i) => { + return ( + + + + {getLangText('PREVIEW')} + + +
    + } + leftColumnWidth="40%" + rightColumnWidth="60%"/> + ); + })} + +
    +
    ); } diff --git a/js/components/ascribe_settings/settings_container.js b/js/components/ascribe_settings/settings_container.js index 12c406ad..0957bb78 100644 --- a/js/components/ascribe_settings/settings_container.js +++ b/js/components/ascribe_settings/settings_container.js @@ -6,11 +6,17 @@ import Router from 'react-router'; import UserStore from '../../stores/user_store'; import UserActions from '../../actions/user_actions'; +import WhitelabelStore from '../../stores/whitelabel_store'; +import WhitelabelActions from '../../actions/whitelabel_actions'; + import AccountSettings from './account_settings'; import BitcoinWalletSettings from './bitcoin_wallet_settings'; -import ContractSettings from './contract_settings'; import APISettings from './api_settings'; +import AclProxy from '../acl_proxy'; + +import { mergeOptions } from '../../utils/general_utils'; + let SettingsContainer = React.createClass({ propTypes: { @@ -22,15 +28,22 @@ let SettingsContainer = React.createClass({ mixins: [Router.Navigation], getInitialState() { - return UserStore.getState(); + return mergeOptions( + UserStore.getState(), + WhitelabelStore.getState() + ); }, componentDidMount() { UserStore.listen(this.onChange); + WhitelabelStore.listen(this.onChange); + + WhitelabelActions.fetchWhitelabel(); UserActions.fetchCurrentUser(); }, componentWillUnmount() { + WhitelabelStore.unlisten(this.onChange); UserStore.unlisten(this.onChange); }, @@ -48,8 +61,16 @@ let SettingsContainer = React.createClass({
    {this.props.children} - - + + + + + +
    ); } diff --git a/js/components/header.js b/js/components/header.js index 307ba663..f227313f 100644 --- a/js/components/header.js +++ b/js/components/header.js @@ -139,7 +139,7 @@ let Header = React.createClass({ {getLangText('Account Settings')} Date: Wed, 23 Sep 2015 16:09:12 +0200 Subject: [PATCH 159/192] add acl for update button in ContractSettings --- .../ascribe_settings/contract_settings.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 2050120c..a2ff405e 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -11,6 +11,9 @@ import ContractListActions from '../../actions/contract_list_actions'; import UserStore from '../../stores/user_store'; import UserActions from '../../actions/user_actions'; +import WhitelabelStore from '../../stores/whitelabel_store'; +import WhitelabelActions from '../../actions/whitelabel_actions'; + import ActionPanel from '../ascribe_panel/action_panel'; import ContractSettingsUpdateButton from './contract_settings_update_button'; @@ -34,12 +37,15 @@ let ContractSettings = React.createClass({ componentDidMount() { ContractListStore.listen(this.onChange); UserStore.listen(this.onChange); + WhitelabelStore.listen(this.onChange); + WhitelabelActions.fetchWhitelabel(); UserActions.fetchCurrentUser(); ContractListActions.fetchContractList(true); }, componentWillUnmount() { + WhitelabelStore.unlisten(this.onChange); UserStore.unlisten(this.onChange); ContractListStore.unlisten(this.onChange); }, @@ -106,7 +112,11 @@ let ContractSettings = React.createClass({ content={contract.name} buttons={
    - + + + - + + + Date: Wed, 23 Sep 2015 16:27:32 +0200 Subject: [PATCH 160/192] Fix mobile menu --- sass/main.scss | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/sass/main.scss b/sass/main.scss index 56849cdb..8965eed7 100644 --- a/sass/main.scss +++ b/sass/main.scss @@ -103,34 +103,6 @@ hr { height: 60px; } -//http://stackoverflow.com/questions/22228239/bootstrap-navbar-static-top-menu-breaks-on-two-lines -@media (max-width: 990px) { - .navbar-header { - float: none; - } - .navbar-toggle { - display: block; - } - .navbar-collapse { - border-top: 1px solid transparent; - box-shadow: inset 0 1px 0 rgba(255,255,255,0.1); - } - .navbar-collapse.collapse { - display: none!important; - } - .navbar-nav { - float: none!important; - margin: 7.5px -15px; - } - .navbar-nav>li { - float: none; - } - .navbar-nav>li>a { - padding-top: 10px; - padding-bottom: 10px; - } -} - .truncate { white-space: nowrap; width: 4em; From 81aa052a8a4d80eae36fc3a59eef01ed9515d2a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 25 Sep 2015 09:53:52 +0200 Subject: [PATCH 161/192] Fix load piece method in WalletPieceContainer --- .../components/ascribe_detail/wallet_piece_container.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js b/js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js index fa049a6f..5503f68b 100644 --- a/js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js +++ b/js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js @@ -2,7 +2,6 @@ import React from 'react'; - import Piece from '../../../../../components/ascribe_detail/piece'; import WalletActionPanel from './wallet_action_panel'; @@ -14,10 +13,10 @@ import Note from '../../../../ascribe_detail/note'; import DetailProperty from '../../../../ascribe_detail/detail_property'; import ApiUrls from '../../../../../constants/api_urls'; +import AppConstants from '../../../../../constants/application_constants'; import { getLangText } from '../../../../../utils/lang_utils'; -import { mergeOptions } from '../../../../../utils/general_utils'; -import AppConstants from '../../../../../constants/application_constants'; + let WalletPieceContainer = React.createClass({ @@ -34,7 +33,7 @@ let WalletPieceContainer = React.createClass({ return (
    @@ -54,7 +53,7 @@ let WalletPieceContainer = React.createClass({ Date: Fri, 25 Sep 2015 10:10:27 +0200 Subject: [PATCH 162/192] Conditional header for + NEW WORK --- .../wallet/components/ascribe_detail/wallet_piece_container.js | 1 - js/components/whitelabel/wallet/wallet_routes.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js b/js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js index 5503f68b..8c0efece 100644 --- a/js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js +++ b/js/components/whitelabel/wallet/components/ascribe_detail/wallet_piece_container.js @@ -19,7 +19,6 @@ import { getLangText } from '../../../../../utils/lang_utils'; let WalletPieceContainer = React.createClass({ - propTypes: { piece: React.PropTypes.object.isRequired, currentUser: React.PropTypes.object.isRequired, diff --git a/js/components/whitelabel/wallet/wallet_routes.js b/js/components/whitelabel/wallet/wallet_routes.js index 075901bd..632c1e35 100644 --- a/js/components/whitelabel/wallet/wallet_routes.js +++ b/js/components/whitelabel/wallet/wallet_routes.js @@ -74,7 +74,7 @@ let ROUTES = { - + From 9080c84fa93d13041db7d7d007c9fb83237acce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 25 Sep 2015 11:20:12 +0200 Subject: [PATCH 163/192] Implement word wrap for ContractSettings --- .../ascribe_settings/contract_settings.js | 10 +++++----- js/utils/general_utils.js | 17 +++++++++++++++++ sass/ascribe_panel.scss | 4 ++++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index a2ff405e..298caaee 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -23,7 +23,7 @@ import GlobalNotificationActions from '../../actions/global_notification_actions import AclProxy from '../acl_proxy'; import { getLangText } from '../../utils/lang_utils'; -import { mergeOptions } from '../../utils/general_utils'; +import { mergeOptions, wrapTextAtCharIndex } from '../../utils/general_utils'; let ContractSettings = React.createClass({ @@ -109,7 +109,7 @@ let ContractSettings = React.createClass({
    } - leftColumnWidth="40%" - rightColumnWidth="60%"/> + leftColumnWidth="60%" + rightColumnWidth="40%"/> ); })} diff --git a/js/utils/general_utils.js b/js/utils/general_utils.js index 7717a96a..3565a271 100644 --- a/js/utils/general_utils.js +++ b/js/utils/general_utils.js @@ -204,4 +204,21 @@ export function excludePropFromObject(obj, propList){ } } return clonedObj; +} + +/** + * Takes a string and breaks it at the supplied index and replaces it + * with a (potentially) short string that also has been provided + * @param {string} text The string to wrap + * @param {number} charIndex The char number at which the text should be wrapped + * @param {String} replacement All text after charIndex will be replaced with this string + * @return {string} The wrapped text + */ +export function wrapTextAtCharIndex(text, charIndex, replacement = '...') { + let wrappedText = ''; + + wrappedText = text.slice(0, charIndex); + wrappedText += text.length > charIndex ? replacement : ''; + + return wrappedText; } \ No newline at end of file diff --git a/sass/ascribe_panel.scss b/sass/ascribe_panel.scss index 9d53b911..0d156d7f 100644 --- a/sass/ascribe_panel.scss +++ b/sass/ascribe_panel.scss @@ -24,6 +24,10 @@ > .ascribe-panel-content { display: table-cell; vertical-align: middle; + + &:first-child { + font-size: .9em; + } } @media(max-width:767px) { From 16e7a54b2707bfcb47b6be12bc02e516551545d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 25 Sep 2015 11:50:55 +0200 Subject: [PATCH 164/192] add coa_verify route to wallet_routes to avoid crash --- js/components/whitelabel/wallet/wallet_routes.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/components/whitelabel/wallet/wallet_routes.js b/js/components/whitelabel/wallet/wallet_routes.js index 40f092d6..8d149d2e 100644 --- a/js/components/whitelabel/wallet/wallet_routes.js +++ b/js/components/whitelabel/wallet/wallet_routes.js @@ -4,6 +4,7 @@ import React from 'react'; import Router from 'react-router'; // general components +import CoaVerifyContainer from '../../../components/coa_verify_container'; import LoginContainer from '../../../components/login_container'; import LogoutContainer from '../../../components/logout_container'; import SignupContainer from '../../../components/signup_container'; @@ -45,6 +46,7 @@ let ROUTES = { + ), @@ -60,6 +62,7 @@ let ROUTES = { + ), @@ -76,6 +79,7 @@ let ROUTES = { + ) From e20e3785334f91dc1ec6ec34b8b1d9182449f1af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 25 Sep 2015 11:54:12 +0200 Subject: [PATCH 165/192] Remove PrizeDashboard from codebase, add coa_verify to prize app --- .../prizes_dashboard.js | 82 ------------------- .../whitelabel/prize/prize_routes.js | 2 + js/routes.js | 3 - 3 files changed, 2 insertions(+), 85 deletions(-) delete mode 100644 js/components/ascribe_prizes_dashboard/prizes_dashboard.js diff --git a/js/components/ascribe_prizes_dashboard/prizes_dashboard.js b/js/components/ascribe_prizes_dashboard/prizes_dashboard.js deleted file mode 100644 index b4c695f4..00000000 --- a/js/components/ascribe_prizes_dashboard/prizes_dashboard.js +++ /dev/null @@ -1,82 +0,0 @@ -'use strict'; - -import React from 'react'; - -import PrizeListActions from '../../actions/prize_list_actions'; -import PrizeListStore from '../../stores/prize_list_store'; - -import Table from '../ascribe_table/table'; -import TableItem from '../ascribe_table/table_item'; -import TableItemText from '../ascribe_table/table_item_text'; - -import { ColumnModel} from '../ascribe_table/models/table_models'; -import { getLangText } from '../../utils/lang_utils'; - -let PrizesDashboard = React.createClass({ - - getInitialState() { - return PrizeListStore.getState(); - }, - - componentDidMount() { - PrizeListStore.listen(this.onChange); - PrizeListActions.fetchPrizeList(); - }, - - componentWillUnmount() { - PrizeListStore.unlisten(this.onChange); - }, - - onChange(state) { - this.setState(state); - }, - - getColumnList() { - return [ - new ColumnModel( - (item) => { - return { - 'content': item.name - }; }, - 'name', - getLangText('Name'), - TableItemText, - 6, - false, - null - ), - new ColumnModel( - (item) => { - return { - 'content': item.domain - }; }, - 'domain', - getLangText('Domain'), - TableItemText, - 1, - false, - null - ) - ]; - }, - - render() { - return ( - - {this.state.prizeList.map((item, i) => { - return ( - - ); - })} -
    - ); - } -}); - -export default PrizesDashboard; \ No newline at end of file diff --git a/js/components/whitelabel/prize/prize_routes.js b/js/components/whitelabel/prize/prize_routes.js index a389cb83..d3031774 100644 --- a/js/components/whitelabel/prize/prize_routes.js +++ b/js/components/whitelabel/prize/prize_routes.js @@ -13,6 +13,7 @@ import PrizePieceList from './components/prize_piece_list'; import PrizePieceContainer from './components/ascribe_detail/prize_piece_container'; import EditionContainer from '../../ascribe_detail/edition_container'; import SettingsContainer from './components/prize_settings_container'; +import CoaVerifyContainer from '../../../components/coa_verify_container'; import App from './prize_app'; import AppConstants from '../../../constants/application_constants'; @@ -34,6 +35,7 @@ function getRoutes() { + ); } diff --git a/js/routes.js b/js/routes.js index f76e4b45..12e5c1f4 100644 --- a/js/routes.js +++ b/js/routes.js @@ -22,8 +22,6 @@ import CoaVerifyContainer from './components/coa_verify_container'; import RegisterPiece from './components/register_piece'; -import PrizesDashboard from './components/ascribe_prizes_dashboard/prizes_dashboard'; - import AppConstants from './constants/application_constants'; let Route = Router.Route; @@ -45,7 +43,6 @@ const COMMON_ROUTES = ( - ); From cb452ce7bf675781a42806c9e42e2a5755e85e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 25 Sep 2015 15:22:16 +0200 Subject: [PATCH 166/192] PR Feedback: rename wrapTextAtCharIndex to truncateTextAtCharIndex --- js/components/ascribe_settings/contract_settings.js | 6 +++--- js/utils/general_utils.js | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index 298caaee..ad329143 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -23,7 +23,7 @@ import GlobalNotificationActions from '../../actions/global_notification_actions import AclProxy from '../acl_proxy'; import { getLangText } from '../../utils/lang_utils'; -import { mergeOptions, wrapTextAtCharIndex } from '../../utils/general_utils'; +import { mergeOptions, truncateTextAtCharIndex } from '../../utils/general_utils'; let ContractSettings = React.createClass({ @@ -109,7 +109,7 @@ let ContractSettings = React.createClass({ Date: Fri, 25 Sep 2015 15:25:34 +0200 Subject: [PATCH 167/192] Minor renaming fix --- js/utils/general_utils.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/utils/general_utils.js b/js/utils/general_utils.js index 3f610168..ba2b7752 100644 --- a/js/utils/general_utils.js +++ b/js/utils/general_utils.js @@ -215,10 +215,10 @@ export function excludePropFromObject(obj, propList){ * @return {string} The truncated text */ export function truncateTextAtCharIndex(text, charIndex, replacement = '...') { - let wrappedText = ''; + let truncatedText = ''; - wrappedText = text.slice(0, charIndex); - wrappedText += text.length > charIndex ? replacement : ''; + truncatedText = text.slice(0, charIndex); + truncatedText += text.length > charIndex ? replacement : ''; - return wrappedText; + return truncatedText; } \ No newline at end of file From e6a6c2c2a38ef42167e830ee8495b4ca3325f2d2 Mon Sep 17 00:00:00 2001 From: diminator Date: Fri, 25 Sep 2015 15:33:01 +0200 Subject: [PATCH 168/192] set collapsible default show=true --- js/components/ascribe_collapsible/collapsible_paragraph.js | 2 +- js/components/ascribe_settings/account_settings.js | 1 - js/components/ascribe_settings/api_settings.js | 1 - js/components/ascribe_settings/bitcoin_wallet_settings.js | 1 - js/components/ascribe_settings/contract_settings.js | 1 - .../prize/components/ascribe_detail/prize_piece_container.js | 4 ---- .../whitelabel/prize/components/prize_settings_container.js | 4 ---- .../cyland/ascribe_detail/cyland_piece_container.js | 1 - .../ikonotv/ascribe_detail/ikonotv_piece_container.js | 2 -- 9 files changed, 1 insertion(+), 16 deletions(-) diff --git a/js/components/ascribe_collapsible/collapsible_paragraph.js b/js/components/ascribe_collapsible/collapsible_paragraph.js index a5c884e5..e146b42b 100644 --- a/js/components/ascribe_collapsible/collapsible_paragraph.js +++ b/js/components/ascribe_collapsible/collapsible_paragraph.js @@ -17,7 +17,7 @@ const CollapsibleParagraph = React.createClass({ getDefaultProps() { return { - show: false + show: true }; }, diff --git a/js/components/ascribe_settings/account_settings.js b/js/components/ascribe_settings/account_settings.js index 7c769c22..562cd48f 100644 --- a/js/components/ascribe_settings/account_settings.js +++ b/js/components/ascribe_settings/account_settings.js @@ -101,7 +101,6 @@ let AccountSettings = React.createClass({ return ( {content} diff --git a/js/components/ascribe_settings/api_settings.js b/js/components/ascribe_settings/api_settings.js index 7908b42a..0f638675 100644 --- a/js/components/ascribe_settings/api_settings.js +++ b/js/components/ascribe_settings/api_settings.js @@ -97,7 +97,6 @@ let APISettings = React.createClass({ return (
    {content} diff --git a/js/components/ascribe_settings/contract_settings.js b/js/components/ascribe_settings/contract_settings.js index d0ded734..a11256c0 100644 --- a/js/components/ascribe_settings/contract_settings.js +++ b/js/components/ascribe_settings/contract_settings.js @@ -87,7 +87,6 @@ let ContractSettings = React.createClass({ aclObject={this.props.currentUser.acl}>
    @@ -329,7 +328,6 @@ let PrizePieceRatings = React.createClass({
    {Object.keys(this.props.piece.extra_data).map((data) => { diff --git a/js/components/whitelabel/prize/components/prize_settings_container.js b/js/components/whitelabel/prize/components/prize_settings_container.js index e6a53bbb..3e274b57 100644 --- a/js/components/whitelabel/prize/components/prize_settings_container.js +++ b/js/components/whitelabel/prize/components/prize_settings_container.js @@ -79,7 +79,6 @@ let PrizeSettings = React.createClass({ return ( {this.getMembersActive()} {this.getMembersPending()} {this.getMembersInactive()} diff --git a/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js b/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js index 81c7a0cf..1be98cfc 100644 --- a/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js +++ b/js/components/whitelabel/wallet/components/cyland/ascribe_detail/cyland_piece_container.js @@ -64,7 +64,6 @@ let CylandPieceContainer = React.createClass({ submitButtonType={CylandSubmitButton}> {getLangText('This piece has been loaned before we started to collect further details.')} @@ -78,7 +77,6 @@ let IkonotvPieceContainer = React.createClass({ furtherDetails = ( Date: Fri, 25 Sep 2015 15:39:36 +0200 Subject: [PATCH 169/192] forward to collection after contract sent --- .../ascribe_forms/form_contract_agreement.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/js/components/ascribe_forms/form_contract_agreement.js b/js/components/ascribe_forms/form_contract_agreement.js index 6d47d8e0..ec4a5a81 100644 --- a/js/components/ascribe_forms/form_contract_agreement.js +++ b/js/components/ascribe_forms/form_contract_agreement.js @@ -1,6 +1,7 @@ 'use strict'; import React from 'react'; +import Router from 'react-router'; import ContractListActions from '../../actions/contract_list_actions'; import ContractListStore from '../../stores/contract_list_store'; @@ -20,11 +21,13 @@ import { mergeOptions } from '../../utils/general_utils'; let ContractAgreementForm = React.createClass({ - propTypes: { + propTypes: { handleSuccess: React.PropTypes.func - }, + }, - getInitialState() { + mixins: [Router.Navigation, Router.State], + + getInitialState() { return mergeOptions( ContractListStore.getState(), { @@ -54,7 +57,7 @@ let ContractAgreementForm = React.createClass({ let notification = 'Contract agreement send'; notification = new GlobalNotificationModel(notification, 'success', 10000); GlobalNotificationActions.appendGlobalNotification(notification); - this.refs.form.reset(); + this.transitionTo('pieces'); }, getFormData(){ From 827e734b6ae46a7a2e58e6e5b2e557df9162133b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Fri, 25 Sep 2015 16:26:47 +0200 Subject: [PATCH 170/192] remove .gitignore~ --- .gitignore~ | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 .gitignore~ diff --git a/.gitignore~ b/.gitignore~ deleted file mode 100644 index 41b217c2..00000000 --- a/.gitignore~ +++ /dev/null @@ -1,24 +0,0 @@ -lib-cov -*.seed -*.log -*.csv -*.dat -*.out -*.pid -*.gz -*.sublime-project -.idea -spool-project.sublime-project -*.sublime-workspace -*.sublime-workspace -webapp-dependencies.txt - -pids -logs -results -README.md~ -node_modules/* - -build - -.DS_Store From 2e6acff56d45d4495683a63b7f077d333302d3da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 28 Sep 2015 10:02:07 +0200 Subject: [PATCH 171/192] Make user email uneditable --- js/components/ascribe_settings/account_settings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/components/ascribe_settings/account_settings.js b/js/components/ascribe_settings/account_settings.js index 562cd48f..28eca49f 100644 --- a/js/components/ascribe_settings/account_settings.js +++ b/js/components/ascribe_settings/account_settings.js @@ -54,6 +54,7 @@ let AccountSettings = React.createClass({ Date: Mon, 28 Sep 2015 10:07:17 +0200 Subject: [PATCH 172/192] Center dialog text for hashing files in file_drag_and_drop --- sass/ascribe_uploader.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/sass/ascribe_uploader.scss b/sass/ascribe_uploader.scss index 331b6b00..809bbeca 100644 --- a/sass/ascribe_uploader.scss +++ b/sass/ascribe_uploader.scss @@ -53,6 +53,7 @@ } .file-drag-and-drop-hashing-dialog { + text-align: center; margin: 1.5em 0 0 0; } From afef5db150d31e03be25e4ffb0d5ae2e07826880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 28 Sep 2015 10:19:12 +0200 Subject: [PATCH 173/192] Add proper button to create editions form --- .../accordion_list_item_edition_widget.js | 2 +- js/components/ascribe_forms/create_editions_form.js | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/js/components/ascribe_accordion_list/accordion_list_item_edition_widget.js b/js/components/ascribe_accordion_list/accordion_list_item_edition_widget.js index e4ba0d2b..709160b9 100644 --- a/js/components/ascribe_accordion_list/accordion_list_item_edition_widget.js +++ b/js/components/ascribe_accordion_list/accordion_list_item_edition_widget.js @@ -6,7 +6,6 @@ import classNames from 'classnames'; import EditionListActions from '../../actions/edition_list_actions'; import EditionListStore from '../../stores/edition_list_store'; -import PieceListActions from '../../actions/piece_list_actions'; import PieceListStore from '../../stores/piece_list_store'; import Button from 'react-bootstrap/lib/Button'; @@ -16,6 +15,7 @@ import CreateEditionsButton from '../ascribe_buttons/create_editions_button'; import { mergeOptions } from '../../utils/general_utils'; import { getLangText } from '../../utils/lang_utils'; + let AccordionListItemEditionWidget = React.createClass({ propTypes: { className: React.PropTypes.string, diff --git a/js/components/ascribe_forms/create_editions_form.js b/js/components/ascribe_forms/create_editions_form.js index a078feeb..cd5a22d3 100644 --- a/js/components/ascribe_forms/create_editions_form.js +++ b/js/components/ascribe_forms/create_editions_form.js @@ -40,6 +40,12 @@ let CreateEditionsForm = React.createClass({ url={ApiUrls.editions} getFormData={this.getFormData} handleSuccess={this.handleSuccess} + buttons={ + } spinner={ } spinner={ From 5b41e368ac21f1c8ce24d1131a9cf9e1a454a1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 28 Sep 2015 12:00:13 +0200 Subject: [PATCH 175/192] Implement AclProxy for hash work in account settings --- .../ascribe_settings/account_settings.js | 74 ++++++------------- .../ascribe_settings/settings_container.js | 5 +- 2 files changed, 28 insertions(+), 51 deletions(-) diff --git a/js/components/ascribe_settings/account_settings.js b/js/components/ascribe_settings/account_settings.js index 28eca49f..1898c599 100644 --- a/js/components/ascribe_settings/account_settings.js +++ b/js/components/ascribe_settings/account_settings.js @@ -10,6 +10,8 @@ import Property from '../ascribe_forms/property'; import InputCheckbox from '../ascribe_forms/input_checkbox'; import CollapsibleParagraph from '../ascribe_collapsible/collapsible_paragraph'; +import AclProxy from '../acl_proxy'; + import CopyrightAssociationForm from '../ascribe_forms/form_copyright_association'; import ApiUrls from '../../constants/api_urls'; @@ -20,7 +22,8 @@ import { getLangText } from '../../utils/lang_utils'; let AccountSettings = React.createClass({ propTypes: { currentUser: React.PropTypes.object.isRequired, - loadUser: React.PropTypes.func.isRequired + loadUser: React.PropTypes.func.isRequired, + whitelabel: React.PropTypes.object.isRequired }, handleSuccess(){ @@ -66,37 +69,26 @@ let AccountSettings = React.createClass({ ); profile = ( -
    - - - - {' ' + getLangText('Enable hash option, e.g. slow connections or to keep piece private')} - - - -
    - {/* - - */} -
    + +
    + + + + {' ' + getLangText('Enable hash option, e.g. slow connections or to keep piece private')} + + + +
    +
    ); } return ( @@ -106,24 +98,6 @@ let AccountSettings = React.createClass({ {content} {profile} - {/*
    - - - -
    -
    */}
    ); } diff --git a/js/components/ascribe_settings/settings_container.js b/js/components/ascribe_settings/settings_container.js index 0957bb78..2b9ae2a1 100644 --- a/js/components/ascribe_settings/settings_container.js +++ b/js/components/ascribe_settings/settings_container.js @@ -59,7 +59,10 @@ let SettingsContainer = React.createClass({ if (this.state.currentUser && this.state.currentUser.username) { return (
    - + {this.props.children} Date: Mon, 28 Sep 2015 15:14:45 +0200 Subject: [PATCH 176/192] Corrections on loan form --- js/components/ascribe_forms/form_loan.js | 3 ++- sass/ascribe_notification_page.scss | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/js/components/ascribe_forms/form_loan.js b/js/components/ascribe_forms/form_loan.js index b9942ea8..ef2fbd13 100644 --- a/js/components/ascribe_forms/form_loan.js +++ b/js/components/ascribe_forms/form_loan.js @@ -107,7 +107,7 @@ let LoanForm = React.createClass({ if (this.state.contractAgreementList && this.state.contractAgreementList.length > 0) { return {'contract_agreement_id': this.state.contractAgreementList[0].id}; } - return null; + return {}; }, getContractCheckbox() { @@ -122,6 +122,7 @@ let LoanForm = React.createClass({ return (
    ); From 9045b9ec01034b598363f21c017256a78cba76fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 28 Sep 2015 16:32:59 +0200 Subject: [PATCH 180/192] refresh piece list on every major acl action --- js/components/ascribe_detail/edition.js | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/js/components/ascribe_detail/edition.js b/js/components/ascribe_detail/edition.js index f2dbf682..115805ec 100644 --- a/js/components/ascribe_detail/edition.js +++ b/js/components/ascribe_detail/edition.js @@ -88,10 +88,8 @@ let Edition = React.createClass({ }, handleDeleteSuccess(response) { - PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search, - this.state.orderBy, this.state.orderAsc, this.state.filterBy); + this.refreshCollection(); - EditionListActions.refreshEditionList({pieceId: this.props.edition.parent}); EditionListActions.closeAllEditionLists(); EditionListActions.clearAllEditionSelections(); @@ -101,6 +99,13 @@ let Edition = React.createClass({ this.transitionTo('pieces'); }, + refreshCollection() { + console.log('freshing'); + PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search, + this.state.orderBy, this.state.orderAsc, this.state.filterBy); + EditionListActions.refreshEditionList({pieceId: this.props.edition.parent}); + }, + render() { return ( @@ -118,6 +123,7 @@ let Edition = React.createClass({
    @@ -206,14 +212,22 @@ let EditionSummary = React.createClass({ edition: React.PropTypes.object, handleSuccess: React.PropTypes.func, currentUser: React.PropTypes.object, - handleDeleteSuccess: React.PropTypes.func + handleDeleteSuccess: React.PropTypes.func, + refreshCollection: React.PropTypes.func }, getTransferWithdrawData(){ return {'bitcoin_id': this.props.edition.bitcoin_id}; }, + + handleSuccess() { + this.props.refreshCollection(); + this.props.handleSuccess(); + }, + showNotification(response){ this.props.handleSuccess(); + if (response){ let notification = new GlobalNotificationModel(response.notification, 'success'); GlobalNotificationActions.appendGlobalNotification(notification); @@ -278,7 +292,7 @@ let EditionSummary = React.createClass({ className="text-center ascribe-button-list" availableAcls={this.props.edition.acl} editions={[this.props.edition]} - handleSuccess={this.props.handleSuccess}> + handleSuccess={this.handleSuccess}> {withdrawButton} Date: Mon, 28 Sep 2015 16:57:35 +0200 Subject: [PATCH 181/192] fix: ikonotv redirect to collection if logged in --- .../whitelabel/wallet/components/ikonotv/ikonotv_landing.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js index e991233a..0f5d129a 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js @@ -6,6 +6,7 @@ import Router from 'react-router'; import ButtonLink from 'react-router-bootstrap/lib/ButtonLink'; import UserStore from '../../../../../stores/user_store'; +import UserActions from '../../../../../actions/user_actions'; import { getLangText } from '../../../../../utils/lang_utils'; @@ -20,6 +21,7 @@ let IkonotvLanding = React.createClass({ componentDidMount() { UserStore.listen(this.onChange); + UserActions.fetchCurrentUser(); }, componentWillUnmount() { @@ -32,7 +34,7 @@ let IkonotvLanding = React.createClass({ getEnterButton() { let redirect = 'login'; - + console.log(this.state) if(this.state.currentUser && this.state.currentUser.email) { redirect = 'pieces'; } From 2dda22d84816c0d0432a1835b3e4dd9adc370620 Mon Sep 17 00:00:00 2001 From: diminator Date: Mon, 28 Sep 2015 16:57:46 +0200 Subject: [PATCH 182/192] fix: ikonotv redirect to collection if logged in --- .../whitelabel/wallet/components/ikonotv/ikonotv_landing.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js index 0f5d129a..57abc5db 100644 --- a/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js +++ b/js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js @@ -34,7 +34,7 @@ let IkonotvLanding = React.createClass({ getEnterButton() { let redirect = 'login'; - console.log(this.state) + if(this.state.currentUser && this.state.currentUser.email) { redirect = 'pieces'; } From 9bb5a51fed1cf2f169928a737306fd65e7b4fa5e Mon Sep 17 00:00:00 2001 From: diminator Date: Mon, 28 Sep 2015 17:11:15 +0200 Subject: [PATCH 183/192] bug fix show public note for anonymous --- js/components/ascribe_detail/note.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/components/ascribe_detail/note.js b/js/components/ascribe_detail/note.js index b377ff5c..c739b937 100644 --- a/js/components/ascribe_detail/note.js +++ b/js/components/ascribe_detail/note.js @@ -39,7 +39,7 @@ let Note = React.createClass({ }, render() { - if (!!this.props.currentUser.username && this.props.show) { + if ((!!this.props.currentUser.username && this.props.editable || !this.props.editable ) && this.props.show) { return (
    Date: Mon, 28 Sep 2015 17:21:34 +0200 Subject: [PATCH 184/192] Instead of transition from logout to login, we replace the state --- js/components/logout_container.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/components/logout_container.js b/js/components/logout_container.js index 096fa490..c7769867 100644 --- a/js/components/logout_container.js +++ b/js/components/logout_container.js @@ -19,7 +19,7 @@ let LogoutContainer = React.createClass({ Alt.flush(); // kill intercom (with fire) window.Intercom('shutdown'); - this.transitionTo(baseUrl); + this.replaceWith(baseUrl); }) .catch((err) => { console.logGlobal(err); From 6a5b66bda5956526ea7270ba31688e5856543a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 28 Sep 2015 17:25:45 +0200 Subject: [PATCH 185/192] fix alignment of download button and file type in fineuploader --- sass/ascribe_uploader.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sass/ascribe_uploader.scss b/sass/ascribe_uploader.scss index 809bbeca..f6c5ab9c 100644 --- a/sass/ascribe_uploader.scss +++ b/sass/ascribe_uploader.scss @@ -143,6 +143,10 @@ text-align: center; vertical-align: middle; + p { + margin-top: 5px; + } + .action-file { color: white; cursor: pointer; From e1ac3ca4c61a38a9813c30d57b69455bbda9fbe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Mon, 28 Sep 2015 17:39:58 +0200 Subject: [PATCH 186/192] Add multi level ACLs for loan piece detail loan button --- .../ascribe_detail/wallet_action_panel.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) 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 7d9286f0..b00d10cc 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 @@ -51,12 +51,16 @@ let WalletActionPanel = React.createClass({ editions={this.props.piece} handleSuccess={this.loadPiece}> - + + + Date: Tue, 29 Sep 2015 13:22:24 +0200 Subject: [PATCH 187/192] debug console log --- js/components/piece_list.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/components/piece_list.js b/js/components/piece_list.js index 35dcaba0..3050d590 100644 --- a/js/components/piece_list.js +++ b/js/components/piece_list.js @@ -144,6 +144,7 @@ let PieceList = React.createClass({ }, applyOrderBy(orderBy) { + console.log(orderBy); PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search, orderBy, this.state.orderAsc, this.state.filterBy); }, From 33ba4ce07f2f028514dec9e0ea97020d1ffae9a7 Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 29 Sep 2015 14:13:15 +0200 Subject: [PATCH 188/192] li instead of menuitem --- .../piece_list_toolbar_order_widget.js | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_order_widget.js b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_order_widget.js index 38b92b6d..a44b8ca2 100644 --- a/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_order_widget.js +++ b/js/components/ascribe_piece_list_toolbar/piece_list_toolbar_order_widget.js @@ -3,7 +3,6 @@ import React from 'react'; import DropdownButton from 'react-bootstrap/lib/DropdownButton'; -import MenuItem from 'react-bootstrap/lib/MenuItem'; import { getLangText } from '../../utils/lang_utils.js'; @@ -62,20 +61,22 @@ let PieceListToolbarOrderWidget = React.createClass({ {this.props.orderParams.map((param) => { return ( - -
    - - {getLangText(param.replace('_', ' '))} - - -1} /> -
    -
    +
    +
  • +
    + + {getLangText(param.replace('_', ' '))} + + -1} /> +
    +
  • +
    ); })} From ec0a458189127361a62cc4fcf0cce82278dc81ba Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 29 Sep 2015 14:14:59 +0200 Subject: [PATCH 189/192] removed console log --- js/components/piece_list.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/components/piece_list.js b/js/components/piece_list.js index 3050d590..35dcaba0 100644 --- a/js/components/piece_list.js +++ b/js/components/piece_list.js @@ -144,7 +144,6 @@ let PieceList = React.createClass({ }, applyOrderBy(orderBy) { - console.log(orderBy); PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search, orderBy, this.state.orderAsc, this.state.filterBy); }, From f64fb73aa6fd1487cce35e52743e93c5d7c428e5 Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 29 Sep 2015 15:58:24 +0200 Subject: [PATCH 190/192] cc fixes in licenses, collection and details --- js/components/ascribe_detail/edition.js | 3 +- .../ascribe_detail/license_detail.js | 31 +++++++++++++++++++ .../ascribe_detail/piece_container.js | 2 ++ .../wallet/components/cc/cc_register_piece.js | 21 ++++++++----- 4 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 js/components/ascribe_detail/license_detail.js diff --git a/js/components/ascribe_detail/edition.js b/js/components/ascribe_detail/edition.js index 115805ec..51884751 100644 --- a/js/components/ascribe_detail/edition.js +++ b/js/components/ascribe_detail/edition.js @@ -25,7 +25,7 @@ import CollapsibleParagraph from './../ascribe_collapsible/collapsible_paragraph import Form from './../ascribe_forms/form'; import Property from './../ascribe_forms/property'; import EditionDetailProperty from './detail_property'; - +import LicenseDetail from './license_detail'; import EditionFurtherDetails from './further_details'; import ListRequestActions from './../ascribe_forms/list_form_request_actions'; @@ -317,6 +317,7 @@ let EditionSummary = React.createClass({ + {this.getStatus()} {this.getActions()}
    diff --git a/js/components/ascribe_detail/license_detail.js b/js/components/ascribe_detail/license_detail.js new file mode 100644 index 00000000..c3cc9f62 --- /dev/null +++ b/js/components/ascribe_detail/license_detail.js @@ -0,0 +1,31 @@ +'use strict'; + +import React from 'react'; + +import DetailProperty from './detail_property'; + +/** + * This is the component that implements display-specific functionality + */ +let LicenseDetail = React.createClass({ + propTypes: { + license: React.PropTypes.object + }, + render () { + if (this.props.license.code === 'default') { + return null; + } + return ( + + { this.props.license.code.toUpperCase() + ': ' + this.props.license.name} +
    + } + /> + ); + } +}); + +export default LicenseDetail; diff --git a/js/components/ascribe_detail/piece_container.js b/js/components/ascribe_detail/piece_container.js index f14cf743..c2eb1759 100644 --- a/js/components/ascribe_detail/piece_container.js +++ b/js/components/ascribe_detail/piece_container.js @@ -19,6 +19,7 @@ import CollapsibleParagraph from './../ascribe_collapsible/collapsible_paragraph import FurtherDetails from './further_details'; import DetailProperty from './detail_property'; +import LicenseDetail from './license_detail'; import HistoryIterator from './history_iterator'; import AclButtonList from './../ascribe_buttons/acl_button_list'; @@ -224,6 +225,7 @@ let PieceContainer = React.createClass({
    +
    } buttons={this.getActions()}> diff --git a/js/components/whitelabel/wallet/components/cc/cc_register_piece.js b/js/components/whitelabel/wallet/components/cc/cc_register_piece.js index 129c1b0a..c9690477 100644 --- a/js/components/whitelabel/wallet/components/cc/cc_register_piece.js +++ b/js/components/whitelabel/wallet/components/cc/cc_register_piece.js @@ -46,12 +46,19 @@ let CCRegisterPiece = React.createClass({ label={getLangText('Copyright license%s', '...')} onChange={this.onLicenseChange} footer={ - - {getLangText('Learn more')} - + + + {getLangText('Learn more about ') + this.state.licenses[this.state.selectedLicense].code} + +  ( + + {getLangText('ascribe faq')} + ) + }>