1
0
mirror of https://github.com/ascribe/onion.git synced 2024-11-15 01:25:17 +01:00

Merge remote-tracking branch 'origin/master' into AD-538-users-and-even-devs-are-unsure-wh

Conflicts:
	js/components/ascribe_detail/edition.js
	js/utils/general_utils.js
	sass/main.scss
This commit is contained in:
Tim Daubenschütz 2015-10-15 10:06:39 +02:00
commit a1f159fc2d
84 changed files with 500 additions and 262 deletions

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import ApplicationFetcher from '../fetchers/application_fetcher'; import ApplicationFetcher from '../fetchers/application_fetcher';

View File

@ -1,8 +1,9 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import CoaFetcher from '../fetchers/coa_fetcher'; import CoaFetcher from '../fetchers/coa_fetcher';
import Q from 'q';
class CoaActions { class CoaActions {
constructor() { constructor() {
@ -12,23 +13,38 @@ class CoaActions {
); );
} }
fetchOne(id) { fetchOrCreate(id, bitcoinId) {
CoaFetcher.fetchOne(id) return Q.Promise((resolve, reject) => {
.then((res) => { CoaFetcher.fetchOne(id)
this.actions.updateCoa(res.coa); .then((res) => {
}) if (res.coa) {
.catch((err) => { this.actions.updateCoa(res.coa);
console.logGlobal(err); resolve(res.coa);
}); }
else {
this.actions.create(bitcoinId);
}
})
.catch((err) => {
console.logGlobal(err);
this.actions.updateCoa(null);
reject(err);
});
});
} }
create(edition) {
CoaFetcher.create(edition.bitcoin_id) create(bitcoinId) {
.then((res) => { return Q.Promise((resolve, reject) => {
this.actions.updateCoa(res.coa); CoaFetcher.create(bitcoinId)
}) .then((res) => {
.catch((err) => { this.actions.updateCoa(res.coa);
console.logGlobal(err); })
}); .catch((err) => {
console.logGlobal(err);
this.actions.updateCoa(null);
reject(err);
});
});
} }
} }

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import Q from 'q'; import Q from 'q';
import OwnershipFetcher from '../fetchers/ownership_fetcher'; import OwnershipFetcher from '../fetchers/ownership_fetcher';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import OwnershipFetcher from '../fetchers/ownership_fetcher'; import OwnershipFetcher from '../fetchers/ownership_fetcher';
import Q from 'q'; import Q from 'q';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import EditionFetcher from '../fetchers/edition_fetcher'; import EditionFetcher from '../fetchers/edition_fetcher';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import Q from 'q'; import Q from 'q';
import EditionListFetcher from '../fetchers/edition_list_fetcher.js'; import EditionListFetcher from '../fetchers/edition_list_fetcher.js';
@ -33,6 +33,10 @@ class EditionListActions {
EditionListFetcher EditionListFetcher
.fetch(pieceId, page, pageSize, orderBy, orderAsc, filterBy) .fetch(pieceId, page, pageSize, orderBy, orderAsc, filterBy)
.then((res) => { .then((res) => {
if(res && !res.editions) {
throw new Error('Piece has no editions to fetch.');
}
this.actions.updateEditionList({ this.actions.updateEditionList({
pieceId, pieceId,
page, page,
@ -46,6 +50,7 @@ class EditionListActions {
resolve(res); resolve(res);
}) })
.catch((err) => { .catch((err) => {
console.logGlobal(err);
reject(err); reject(err);
}); });
}); });

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { altThirdParty } from '../alt';
class EventActions { class EventActions {
@ -16,4 +16,4 @@ class EventActions {
} }
} }
export default alt.createActions(EventActions); export default altThirdParty.createActions(EventActions);

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
class GlobalNotificationActions { class GlobalNotificationActions {

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import LicenseFetcher from '../fetchers/license_fetcher'; import LicenseFetcher from '../fetchers/license_fetcher';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import Q from 'q'; import Q from 'q';
import NotificationFetcher from '../fetchers/notification_fetcher'; import NotificationFetcher from '../fetchers/notification_fetcher';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import OwnershipFetcher from '../fetchers/ownership_fetcher'; import OwnershipFetcher from '../fetchers/ownership_fetcher';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import PieceFetcher from '../fetchers/piece_fetcher'; import PieceFetcher from '../fetchers/piece_fetcher';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import Q from 'q'; import Q from 'q';
import PieceListFetcher from '../fetchers/piece_list_fetcher'; import PieceListFetcher from '../fetchers/piece_list_fetcher';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import Q from 'q'; import Q from 'q';
import PrizeListFetcher from '../fetchers/prize_list_fetcher'; import PrizeListFetcher from '../fetchers/prize_list_fetcher';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { altUser } from '../alt';
import UserFetcher from '../fetchers/user_fetcher'; import UserFetcher from '../fetchers/user_fetcher';
@ -34,4 +34,4 @@ class UserActions {
} }
} }
export default alt.createActions(UserActions); export default altUser.createActions(UserActions);

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import WalletSettingsFetcher from '../fetchers/wallet_settings_fetcher'; import WalletSettingsFetcher from '../fetchers/wallet_settings_fetcher';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { altWhitelabel } from '../alt';
import WhitelabelFetcher from '../fetchers/whitelabel_fetcher'; import WhitelabelFetcher from '../fetchers/whitelabel_fetcher';
@ -26,4 +26,4 @@ class WhitelabelActions {
} }
} }
export default alt.createActions(WhitelabelActions); export default altWhitelabel.createActions(WhitelabelActions);

View File

@ -2,4 +2,7 @@
import Alt from 'alt'; import Alt from 'alt';
export default new Alt(); export let alt = new Alt();
export let altThirdParty = new Alt();
export let altUser = new Alt();
export let altWhitelabel = new Alt();

View File

@ -10,13 +10,15 @@ import fetch from 'isomorphic-fetch';
/* eslint-enable */ /* eslint-enable */
import ApiUrls from './constants/api_urls'; import ApiUrls from './constants/api_urls';
import { updateApiUrls } from './constants/api_urls';
import appConstants from './constants/application_constants'; import AppConstants from './constants/application_constants';
import getRoutes from './routes'; import getRoutes from './routes';
import requests from './utils/requests'; import requests from './utils/requests';
import { updateApiUrls } from './constants/api_urls';
import { getSubdomainSettings } from './utils/constants_utils'; import { getSubdomainSettings } from './utils/constants_utils';
import { initLogging } from './utils/error_utils'; import { initLogging } from './utils/error_utils';
import { getSubdomain } from './utils/general_utils';
import EventActions from './actions/event_actions'; import EventActions from './actions/event_actions';
@ -48,11 +50,11 @@ requests.defaults({
class AppGateway { class AppGateway {
start() { start() {
let settings; let settings;
let subdomain = window.location.host.split('.')[0]; let subdomain = getSubdomain();
try { try {
settings = getSubdomainSettings(subdomain); settings = getSubdomainSettings(subdomain);
appConstants.whitelabel = settings; AppConstants.whitelabel = settings;
updateApiUrls(settings.type, subdomain); updateApiUrls(settings.type, subdomain);
this.load(settings); this.load(settings);
} catch(err) { } catch(err) {

View File

@ -6,7 +6,7 @@ import UserActions from '../../actions/user_actions';
import UserStore from '../../stores/user_store'; import UserStore from '../../stores/user_store';
import AclButton from '../ascribe_buttons/acl_button'; import AclButton from '../ascribe_buttons/acl_button';
import {getLangText} from '../../utils/lang_utils';
let AclButtonList = React.createClass({ let AclButtonList = React.createClass({
propTypes: { propTypes: {
@ -16,7 +16,6 @@ let AclButtonList = React.createClass({
React.PropTypes.array React.PropTypes.array
]), ]),
availableAcls: React.PropTypes.object, availableAcls: React.PropTypes.object,
actionsLabelStyle: React.PropTypes.object,
buttonsStyle: React.PropTypes.object, buttonsStyle: React.PropTypes.object,
handleSuccess: React.PropTypes.func, handleSuccess: React.PropTypes.func,
children: React.PropTypes.oneOfType([ children: React.PropTypes.oneOfType([

View File

@ -6,15 +6,11 @@ import Router from 'react-router';
import Row from 'react-bootstrap/lib/Row'; import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col'; import Col from 'react-bootstrap/lib/Col';
import Glyphicon from 'react-bootstrap/lib/Glyphicon'; import Glyphicon from 'react-bootstrap/lib/Glyphicon';
import Button from 'react-bootstrap/lib/Button';
import UserActions from '../../actions/user_actions'; import UserActions from '../../actions/user_actions';
import UserStore from '../../stores/user_store'; import UserStore from '../../stores/user_store';
import CoaActions from '../../actions/coa_actions'; import CoaActions from '../../actions/coa_actions';
import CoaStore from '../../stores/coa_store'; 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 HistoryIterator from './history_iterator'; import HistoryIterator from './history_iterator';
@ -28,14 +24,7 @@ import EditionDetailProperty from './detail_property';
import LicenseDetail from './license_detail'; import LicenseDetail from './license_detail';
import EditionFurtherDetails from './further_details'; import EditionFurtherDetails from './further_details';
import ListRequestActions from './../ascribe_forms/list_form_request_actions'; import EditionActionPanel from './edition_action_panel';
import AclButtonList from './../ascribe_buttons/acl_button_list';
import UnConsignRequestButton from './../ascribe_buttons/unconsign_request_button';
import DeleteButton from './../ascribe_buttons/delete_button';
import AclInformationButton from './../ascribe_buttons/acl_information_button';
import GlobalNotificationModel from '../../models/global_notification_model';
import GlobalNotificationActions from '../../actions/global_notification_actions';
import Note from './note'; import Note from './note';
@ -43,7 +32,6 @@ import ApiUrls from '../../constants/api_urls';
import AppConstants from '../../constants/application_constants'; import AppConstants from '../../constants/application_constants';
import { getLangText } from '../../utils/lang_utils'; import { getLangText } from '../../utils/lang_utils';
import { mergeOptions } from '../../utils/general_utils';
let Link = Router.Link; let Link = Router.Link;
/** /**
@ -58,15 +46,11 @@ let Edition = React.createClass({
mixins: [Router.Navigation], mixins: [Router.Navigation],
getInitialState() { getInitialState() {
return mergeOptions( return UserStore.getState();
UserStore.getState(),
PieceListStore.getState()
);
}, },
componentDidMount() { componentDidMount() {
UserStore.listen(this.onChange); UserStore.listen(this.onChange);
PieceListStore.listen(this.onChange);
UserActions.fetchCurrentUser(); UserActions.fetchCurrentUser();
}, },
@ -81,31 +65,12 @@ let Edition = React.createClass({
CoaActions.flushCoa(); CoaActions.flushCoa();
UserStore.unlisten(this.onChange); UserStore.unlisten(this.onChange);
PieceListStore.unlisten(this.onChange);
}, },
onChange(state) { onChange(state) {
this.setState(state); this.setState(state);
}, },
handleDeleteSuccess(response) {
this.refreshCollection();
EditionListActions.closeAllEditionLists();
EditionListActions.clearAllEditionSelections();
let notification = new GlobalNotificationModel(response.notification, 'success');
GlobalNotificationActions.appendGlobalNotification(notification);
this.transitionTo('pieces');
},
refreshCollection() {
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() { render() {
return ( return (
<Row> <Row>
@ -122,12 +87,9 @@ let Edition = React.createClass({
<hr/> <hr/>
</div> </div>
<EditionSummary <EditionSummary
handleSuccess={this.props.loadEdition}
refreshCollection={this.refreshCollection}
currentUser={this.state.currentUser}
edition={this.props.edition} edition={this.props.edition}
handleDeleteSuccess={this.handleDeleteSuccess}/> currentUser={this.state.currentUser}
handleSuccess={this.props.loadEdition}/>
<CollapsibleParagraph <CollapsibleParagraph
title={getLangText('Certificate of Authenticity')} title={getLangText('Certificate of Authenticity')}
show={this.props.edition.acl.acl_coa === true}> show={this.props.edition.acl.acl_coa === true}>
@ -208,29 +170,14 @@ let Edition = React.createClass({
let EditionSummary = React.createClass({ let EditionSummary = React.createClass({
propTypes: { propTypes: {
edition: React.PropTypes.object, edition: React.PropTypes.object,
handleSuccess: React.PropTypes.func,
currentUser: React.PropTypes.object, currentUser: React.PropTypes.object,
handleDeleteSuccess: React.PropTypes.func, handleSuccess: React.PropTypes.func
refreshCollection: React.PropTypes.func
},
getTransferWithdrawData(){
return {'bitcoin_id': this.props.edition.bitcoin_id};
}, },
handleSuccess() { handleSuccess() {
this.props.refreshCollection();
this.props.handleSuccess(); this.props.handleSuccess();
}, },
showNotification(response){
this.props.handleSuccess();
if (response){
let notification = new GlobalNotificationModel(response.notification, 'success');
GlobalNotificationActions.appendGlobalNotification(notification);
}
},
getStatus(){ getStatus(){
let status = null; let status = null;
if (this.props.edition.status.length > 0){ if (this.props.edition.status.length > 0){
@ -244,92 +191,27 @@ let EditionSummary = React.createClass({
} }
return status; return status;
}, },
getVerbList(){
let verbsToCheck = ['acl_transfer', 'acl_consign', 'acl_loan', 'acl_share', 'acl_delete'];
let verbListIndices = [];
let acl = this.props.edition.acl;
Object.keys(acl).forEach((key) => {
let index = verbsToCheck.indexOf(key);
if (acl[key] === true && index !== -1) {
verbListIndices.push(verbsToCheck[index].slice(4));
}
});
return verbListIndices;
},
getActions(){
let actions = null;
if (this.props.edition &&
this.props.edition.notifications &&
this.props.edition.notifications.length > 0){
actions = (
<ListRequestActions
pieceOrEditions={[this.props.edition]}
currentUser={this.props.currentUser}
handleSuccess={this.showNotification}
notifications={this.props.edition.notifications}/>);
}
else {
let withdrawButton = null;
if (this.props.edition.status.length > 0 && this.props.edition.pending_new_owner && this.props.edition.acl.acl_withdraw_transfer) {
withdrawButton = (
<Form
url={ApiUrls.ownership_transfers_withdraw}
getFormData={this.getTransferWithdrawData}
handleSuccess={this.showNotification}
className='inline'
isInline={true}>
<Button bsStyle="danger" className="btn-delete pull-center" bsSize="small" type="submit">
WITHDRAW TRANSFER
</Button>
</Form>
);
}
let unconsignRequestButton = null;
if (this.props.edition.acl.acl_request_unconsign) {
unconsignRequestButton = (
<UnConsignRequestButton
currentUser={this.props.currentUser}
edition={this.props.edition}
handleSuccess={this.props.handleSuccess} />
);
}
actions = (
<Row>
<Col md={11}>
<AclButtonList
className="ascribe-button-list ascribe-button-list-detail"
availableAcls={this.props.edition.acl}
editions={[this.props.edition]}
handleSuccess={this.handleSuccess}>
{withdrawButton}
<DeleteButton
handleSuccess={this.props.handleDeleteSuccess}
editions={[this.props.edition]}/>
{unconsignRequestButton}
<AclInformationButton verbs = {this.getVerbList()}/>
</AclButtonList>
</Col>
</Row>);
}
return actions;
},
render() { render() {
let { edition, currentUser } = this.props;
return ( return (
<div className="ascribe-detail-header"> <div className="ascribe-detail-header">
<EditionDetailProperty <EditionDetailProperty
label={getLangText('EDITION')} label={getLangText('EDITION')}
value={this.props.edition.edition_number + ' ' + getLangText('of') + ' ' + this.props.edition.num_editions} /> value={ edition.edition_number + ' ' + getLangText('of') + ' ' + edition.num_editions} />
<EditionDetailProperty <EditionDetailProperty
label={getLangText('ID')} label={getLangText('ID')}
value={ this.props.edition.bitcoin_id } value={ edition.bitcoin_id }
ellipsis={true} /> ellipsis={true} />
<EditionDetailProperty <EditionDetailProperty
label={getLangText('OWNER')} label={getLangText('OWNER')}
value={ this.props.edition.owner } /> value={ edition.owner } />
<LicenseDetail license={this.props.edition.license_type}/> <LicenseDetail license={edition.license_type}/>
{this.getStatus()} {this.getStatus()}
<hr /> <EditionActionPanel
{this.getActions()} edition={edition}
currentUser={currentUser}
handleSuccess={this.handleSuccess} />
<hr/> <hr/>
</div> </div>
); );
@ -347,12 +229,13 @@ let CoaDetails = React.createClass({
}, },
componentDidMount() { componentDidMount() {
let { edition } = this.props;
CoaStore.listen(this.onChange); CoaStore.listen(this.onChange);
if(this.props.edition.coa) { if(edition.coa) {
CoaActions.fetchOne(this.props.edition.coa); CoaActions.fetchOrCreate(edition.coa, edition.bitcoin_id);
} }
else { else {
CoaActions.create(this.props.edition); CoaActions.create(edition.bitcoin_id);
} }
}, },

View File

@ -0,0 +1,185 @@
'use strict';
import React from 'react';
import Router from 'react-router';
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';
import Button from 'react-bootstrap/lib/Button';
import EditionListActions from '../../actions/edition_list_actions';
import PieceListActions from '../../actions/piece_list_actions';
import PieceListStore from '../../stores/piece_list_store';
import Form from './../ascribe_forms/form';
import Property from './../ascribe_forms/property';
import ListRequestActions from './../ascribe_forms/list_form_request_actions';
import AclButtonList from './../ascribe_buttons/acl_button_list';
import UnConsignRequestButton from './../ascribe_buttons/unconsign_request_button';
import DeleteButton from '../ascribe_buttons/delete_button';
import GlobalNotificationModel from '../../models/global_notification_model';
import GlobalNotificationActions from '../../actions/global_notification_actions';
import AclInformationButton from '../ascribe_buttons/acl_information_button';
import AclProxy from '../acl_proxy';
import ApiUrls from '../../constants/api_urls';
import { getLangText } from '../../utils/lang_utils';
/*
A component that handles all the actions inside of the edition detail
handleSuccess requires a loadEdition action (could be refactored)
*/
let EditionActionPanel = React.createClass({
propTypes: {
edition: React.PropTypes.object,
currentUser: React.PropTypes.object,
handleSuccess: React.PropTypes.func
},
mixins: [Router.Navigation],
getInitialState() {
return PieceListStore.getState();
},
componentDidMount() {
PieceListStore.listen(this.onChange);
},
componentWillUnmount() {
PieceListStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
handleDeleteSuccess(response) {
this.refreshCollection();
EditionListActions.closeAllEditionLists();
EditionListActions.clearAllEditionSelections();
let notification = new GlobalNotificationModel(response.notification, 'success');
GlobalNotificationActions.appendGlobalNotification(notification);
this.transitionTo('pieces');
},
refreshCollection() {
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});
},
handleSuccess(response){
this.refreshCollection();
this.props.handleSuccess();
if (response){
let notification = new GlobalNotificationModel(response.notification, 'success');
GlobalNotificationActions.appendGlobalNotification(notification);
}
},
getVerbList(){
let verbsToCheck = ['acl_transfer', 'acl_consign', 'acl_loan', 'acl_share', 'acl_delete'];
let verbListIndices = [];
let acl = this.props.edition.acl;
Object.keys(acl).forEach((key) => {
let index = verbsToCheck.indexOf(key);
if (acl[key] && index !== -1) {
verbListIndices.push(verbsToCheck[index].slice(4));
}
});
return verbListIndices;
},
render(){
let {edition, currentUser} = this.props;
if (edition &&
edition.notifications &&
edition.notifications.length > 0){
return (
<ListRequestActions
pieceOrEditions={[edition]}
currentUser={currentUser}
handleSuccess={this.handleSuccess}
notifications={edition.notifications}/>);
}
else {
return (
<Row>
<Col md={12}>
<AclButtonList
className="text-center ascribe-button-list"
availableAcls={edition.acl}
editions={[edition]}
handleSuccess={this.handleSuccess}>
<AclProxy
aclObject={edition.acl}
aclName="acl_withdraw_transfer">
<Form
url={ApiUrls.ownership_transfers_withdraw}
handleSuccess={this.handleSuccess}
className='inline'
isInline={true}>
<Property
name="bitcoin_id"
hidden={true}>
<input
type="text"
value={edition.bitcoin_id} />
</Property>
<Button bsStyle="danger" className="btn-delete pull-center" bsSize="small" type="submit">
{getLangText('WITHDRAW TRANSFER')}
</Button>
</Form>
</AclProxy>
<AclProxy
aclObject={edition.acl}
aclName="acl_withdraw_consign">
<Form
url={ApiUrls.ownership_consigns_withdraw}
handleSuccess={this.handleSuccess}
className='inline'
isInline={true}>
<Property
name="bitcoin_id"
hidden={true}>
<input
type="text"
value={edition.bitcoin_id} />
</Property>
<Button bsStyle="danger" className="btn-delete pull-center" bsSize="small" type="submit">
{getLangText('WITHDRAW CONSIGN')}
</Button>
</Form>
</AclProxy>
<AclProxy
aclObject={edition.acl}
aclName="acl_request_unconsign">
<UnConsignRequestButton
currentUser={currentUser}
edition={edition}
handleSuccess={this.handleSuccess} />
</AclProxy>
<DeleteButton
handleSuccess={this.handleDeleteSuccess}
editions={[edition]}/>
<AclInformationButton aim="button" verbs = {this.getVerbList()}/>
</AclButtonList>
</Col>
</Row>
);
}
}
});
export default EditionActionPanel;

View File

@ -43,7 +43,7 @@ let FurtherDetailsFileuploader = React.createClass({
return ( return (
<Property <Property
label="Additional files (max. 50MB per file)"> label="Additional files">
<ReactS3FineUploader <ReactS3FineUploader
uploadStarted={this.props.uploadStarted} uploadStarted={this.props.uploadStarted}
keyRoutine={{ keyRoutine={{

View File

@ -44,6 +44,10 @@ let LoginForm = React.createClass({
componentDidMount() { componentDidMount() {
UserStore.listen(this.onChange); UserStore.listen(this.onChange);
let { redirect } = this.getQuery();
if (redirect && redirect !== 'login'){
this.transitionTo(redirect, null, this.getQuery());
}
}, },
componentWillUnmount() { componentWillUnmount() {
@ -56,6 +60,15 @@ let LoginForm = React.createClass({
// if user is already logged in, redirect him to piece list // if user is already logged in, redirect him to piece list
if(this.state.currentUser && this.state.currentUser.email && this.props.redirectOnLoggedIn) { if(this.state.currentUser && this.state.currentUser.email && this.props.redirectOnLoggedIn) {
// FIXME: hack to redirect out of the dispatch cycle // FIXME: hack to redirect out of the dispatch cycle
let { redirectAuthenticated } = this.getQuery();
if ( redirectAuthenticated) {
/*
* redirectAuthenticated contains an arbirary path
* eg pieces/<id>, editions/<bitcoin_id>, collection, settings, ...
* hence transitionTo cannot be used directly
*/
window.location = AppConstants.baseUrl + redirectAuthenticated;
}
window.setTimeout(() => this.transitionTo('pieces'), 0); window.setTimeout(() => this.transitionTo('pieces'), 0);
} }
}, },
@ -79,7 +92,13 @@ let LoginForm = React.createClass({
Users on Stack Overflow claim this is a bug in chrome and should be fixed in the future. Users on Stack Overflow claim this is a bug in chrome and should be fixed in the future.
Until then, we redirect the HARD way, but reloading the whole page using window.location Until then, we redirect the HARD way, but reloading the whole page using window.location
*/ */
window.location = AppConstants.baseUrl + 'collection'; let { redirectAuthenticated } = this.getQuery();
if ( redirectAuthenticated) {
window.location = AppConstants.baseUrl + redirectAuthenticated;
}
else {
window.location = AppConstants.baseUrl + 'collection';
}
} else if(this.props.onLogin) { } else if(this.props.onLogin) {
// In some instances we want to give a callback to an outer container, // In some instances we want to give a callback to an outer container,
// to show that the one login action the user triggered actually went through. // to show that the one login action the user triggered actually went through.

View File

@ -14,6 +14,7 @@ import Form from './form';
import Property from './property'; import Property from './property';
import InputCheckbox from './input_checkbox'; import InputCheckbox from './input_checkbox';
import AppConstants from '../../constants/application_constants';
import ApiUrls from '../../constants/api_urls'; import ApiUrls from '../../constants/api_urls';
@ -40,6 +41,10 @@ let SignupForm = React.createClass({
componentDidMount() { componentDidMount() {
UserStore.listen(this.onChange); UserStore.listen(this.onChange);
let { redirect } = this.getQuery();
if (redirect && redirect !== 'signup'){
this.transitionTo(redirect, null, this.getQuery());
}
}, },
componentWillUnmount() { componentWillUnmount() {
@ -51,7 +56,16 @@ let SignupForm = React.createClass({
// if user is already logged in, redirect him to piece list // if user is already logged in, redirect him to piece list
if(this.state.currentUser && this.state.currentUser.email) { if(this.state.currentUser && this.state.currentUser.email) {
this.transitionTo('pieces'); let { redirectAuthenticated } = this.getQuery();
if ( redirectAuthenticated) {
/*
* redirectAuthenticated contains an arbirary path
* eg pieces/<id>, editions/<bitcoin_id>, collection, settings, ...
* hence transitionTo cannot be used directly
*/
window.location = AppConstants.baseUrl + redirectAuthenticated;
}
window.setTimeout(() => this.transitionTo('pieces'));
} }
}, },
@ -62,6 +76,15 @@ let SignupForm = React.createClass({
this.props.handleSuccess(getLangText('We sent an email to your address') + ' ' + response.user.email + ', ' + getLangText('please confirm') + '.'); this.props.handleSuccess(getLangText('We sent an email to your address') + ' ' + response.user.email + ', ' + getLangText('please confirm') + '.');
} }
else if (response.redirect) { else if (response.redirect) {
let { redirectAuthenticated } = this.getQuery();
if ( redirectAuthenticated) {
/*
* redirectAuthenticated contains an arbirary path
* eg pieces/<id>, editions/<bitcoin_id>, collection, settings, ...
* hence transitionTo cannot be used directly
*/
window.location = AppConstants.baseUrl + redirectAuthenticated;
}
this.transitionTo('pieces'); this.transitionTo('pieces');
} }
}, },

View File

@ -22,6 +22,7 @@ let InputCheckbox = React.createClass({
React.PropTypes.arrayOf(React.PropTypes.element), React.PropTypes.arrayOf(React.PropTypes.element),
React.PropTypes.element React.PropTypes.element
]), ]),
name: React.PropTypes.string,
// provided by Property // provided by Property
disabled: React.PropTypes.bool, disabled: React.PropTypes.bool,
@ -50,7 +51,7 @@ let InputCheckbox = React.createClass({
// Developer's are used to define defaultValues for inputs via defaultValue, but since this is a // Developer's are used to define defaultValues for inputs via defaultValue, but since this is a
// input of type checkbox we warn the dev to not do that. // input of type checkbox we warn the dev to not do that.
if(this.props.defaultValue) { if(this.props.defaultValue) { //eslint-disable-line react/prop-types
console.warn('InputCheckbox is of type checkbox. Therefore its value is represented by checked and defaultChecked. defaultValue will do nothing!'); console.warn('InputCheckbox is of type checkbox. Therefore its value is represented by checked and defaultChecked. defaultValue will do nothing!');
} }
@ -102,8 +103,10 @@ let InputCheckbox = React.createClass({
return ( return (
<span <span
style={this.props.style} style={this.props.style}
onClick={this.onChange}> onClick={this.onChange}
name={this.props.name}>
<input <input
name={this.props.name}
type="checkbox" type="checkbox"
ref="checkbox" ref="checkbox"
onChange={this.onChange} onChange={this.onChange}
@ -119,4 +122,4 @@ let InputCheckbox = React.createClass({
} }
}); });
export default InputCheckbox; export default InputCheckbox;

View File

@ -31,6 +31,7 @@ let Property = React.createClass({
footer: React.PropTypes.element, footer: React.PropTypes.element,
handleChange: React.PropTypes.func, handleChange: React.PropTypes.func,
ignoreFocus: React.PropTypes.bool, ignoreFocus: React.PropTypes.bool,
name: React.PropTypes.string.isRequired,
className: React.PropTypes.string, className: React.PropTypes.string,
onClick: React.PropTypes.func, onClick: React.PropTypes.func,
@ -210,7 +211,8 @@ let Property = React.createClass({
onFocus: this.handleFocus, onFocus: this.handleFocus,
onBlur: this.handleBlur, onBlur: this.handleBlur,
disabled: !this.props.editable, disabled: !this.props.editable,
ref: 'input' ref: 'input',
name: this.props.name
}); });
}); });
}, },
@ -260,4 +262,4 @@ let Property = React.createClass({
} }
}); });
export default Property; export default Property;

View File

@ -33,21 +33,28 @@ let PieceListBulkModal = React.createClass({
); );
}, },
onChange(state) {
this.setState(state);
},
componentDidMount() { componentDidMount() {
EditionListStore.listen(this.onChange); EditionListStore.listen(this.onChange);
UserStore.listen(this.onChange); UserStore.listen(this.onChange);
PieceListStore.listen(this.onChange);
UserActions.fetchCurrentUser(); UserActions.fetchCurrentUser();
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search,
this.state.orderBy, this.state.orderAsc, this.state.filterBy);
}, },
componentWillUnmount() { componentWillUnmount() {
EditionListStore.unlisten(this.onChange); EditionListStore.unlisten(this.onChange);
PieceListStore.unlisten(this.onChange);
UserStore.unlisten(this.onChange); UserStore.unlisten(this.onChange);
}, },
onChange(state) {
this.setState(state);
},
fetchSelectedPieceEditionList() { fetchSelectedPieceEditionList() {
let filteredPieceIdList = Object.keys(this.state.editionList) let filteredPieceIdList = Object.keys(this.state.editionList)
.filter((pieceId) => { .filter((pieceId) => {

View File

@ -0,0 +1,25 @@
'use strict';
import React from 'react';
import { getLangText } from '../utils/lang_utils';
let ErrorNotFoundPage = React.createClass({
render() {
return (
<div className="row">
<div className="col-md-12">
<div className="error-wrapper">
<h1>404</h1>
<p>
{getLangText('Ups, the page you are looking for does not exist.')}
</p>
</div>
</div>
</div>
);
}
});
export default ErrorNotFoundPage;

View File

@ -4,7 +4,7 @@ import React from 'react';
import Router from 'react-router'; import Router from 'react-router';
import UserActions from '../actions/user_actions'; import UserActions from '../actions/user_actions';
import Alt from '../alt'; import { alt, altWhitelabel, altUser, altThirdParty } from '../alt';
import AppConstants from '../constants/application_constants'; import AppConstants from '../constants/application_constants';
let baseUrl = AppConstants.baseUrl; let baseUrl = AppConstants.baseUrl;
@ -16,7 +16,10 @@ let LogoutContainer = React.createClass({
componentDidMount() { componentDidMount() {
UserActions.logoutCurrentUser() UserActions.logoutCurrentUser()
.then(() => { .then(() => {
Alt.flush(); alt.flush();
altWhitelabel.flush();
altUser.flush();
altThirdParty.flush();
// kill intercom (with fire) // kill intercom (with fire)
window.Intercom('shutdown'); window.Intercom('shutdown');
this.replaceWith(baseUrl); this.replaceWith(baseUrl);

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../../../../alt'; import { alt } from '../../../../alt';
import Q from 'q'; import Q from 'q';
import PrizeFetcher from '../fetchers/prize_fetcher'; import PrizeFetcher from '../fetchers/prize_fetcher';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../../../../alt'; import { alt } from '../../../../alt';
import Q from 'q'; import Q from 'q';
import PrizeJuryFetcher from '../fetchers/prize_jury_fetcher'; import PrizeJuryFetcher from '../fetchers/prize_jury_fetcher';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../../../../alt'; import { alt } from '../../../../alt';
import Q from 'q'; import Q from 'q';
import PrizeRatingFetcher from '../fetchers/prize_rating_fetcher'; import PrizeRatingFetcher from '../fetchers/prize_rating_fetcher';

View File

@ -9,6 +9,9 @@ import GlobalNotification from '../../global_notification';
import getRoutes from './prize_routes'; import getRoutes from './prize_routes';
import { getSubdomain } from '../../../utils/general_utils';
let RouteHandler = Router.RouteHandler; let RouteHandler = Router.RouteHandler;
let PrizeApp = React.createClass({ let PrizeApp = React.createClass({
@ -16,7 +19,7 @@ let PrizeApp = React.createClass({
render() { render() {
let header = null; let header = null;
let subdomain = window.location.host.split('.')[0]; let subdomain = getSubdomain();
let ROUTES = getRoutes(null, subdomain); let ROUTES = getRoutes(null, subdomain);

View File

@ -14,11 +14,13 @@ import PrizePieceContainer from './components/ascribe_detail/prize_piece_contain
import EditionContainer from '../../ascribe_detail/edition_container'; import EditionContainer from '../../ascribe_detail/edition_container';
import SettingsContainer from './components/prize_settings_container'; import SettingsContainer from './components/prize_settings_container';
import CoaVerifyContainer from '../../../components/coa_verify_container'; import CoaVerifyContainer from '../../../components/coa_verify_container';
import ErrorNotFoundPage from '../../../components/error_not_found_page';
import App from './prize_app'; import App from './prize_app';
import AppConstants from '../../../constants/application_constants'; import AppConstants from '../../../constants/application_constants';
let Route = Router.Route; let Route = Router.Route;
let NotFoundRoute = Router.NotFoundRoute;
let baseUrl = AppConstants.baseUrl; let baseUrl = AppConstants.baseUrl;
@ -36,6 +38,7 @@ function getRoutes() {
<Route name="edition" path="editions/:editionId" handler={EditionContainer} /> <Route name="edition" path="editions/:editionId" handler={EditionContainer} />
<Route name="settings" path="settings" handler={SettingsContainer} /> <Route name="settings" path="settings" handler={SettingsContainer} />
<Route name="coa_verify" path="verify" handler={CoaVerifyContainer} /> <Route name="coa_verify" path="verify" handler={CoaVerifyContainer} />
<NotFoundRoute name="notFound" handler={ErrorNotFoundPage} />
</Route> </Route>
); );
} }

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../../../../alt'; import { alt } from '../../../../alt';
import PrizeJuryActions from '../actions/prize_jury_actions'; import PrizeJuryActions from '../actions/prize_jury_actions';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../../../../alt'; import { alt } from '../../../../alt';
import PrizeRatingActions from '../actions/prize_rating_actions'; import PrizeRatingActions from '../actions/prize_rating_actions';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../../../../alt'; import { alt } from '../../../../alt';
import PrizeActions from '../actions/prize_actions'; import PrizeActions from '../actions/prize_actions';

View File

@ -49,7 +49,7 @@ let WalletActionPanel = React.createClass({
className="text-center ascribe-button-list" className="text-center ascribe-button-list"
availableAcls={availableAcls} availableAcls={availableAcls}
editions={this.props.piece} editions={this.props.piece}
handleSuccess={this.loadPiece}> handleSuccess={this.props.loadPiece}>
<AclProxy <AclProxy
aclObject={this.props.currentUser.acl} aclObject={this.props.currentUser.acl}
aclName="acl_wallet_submit"> aclName="acl_wallet_submit">
@ -58,7 +58,6 @@ let WalletActionPanel = React.createClass({
aclName="acl_wallet_submit"> aclName="acl_wallet_submit">
<SubmitButtonType <SubmitButtonType
className="btn-sm" className="btn-sm"
handleSuccess={this.handleSubmitSuccess}
piece={this.props.piece}/> piece={this.props.piece}/>
</AclProxy> </AclProxy>
</AclProxy> </AclProxy>

View File

@ -12,7 +12,7 @@ import UserStore from '../../../../../../stores/user_store';
import GlobalNotificationModel from '../../../../../../models/global_notification_model'; import GlobalNotificationModel from '../../../../../../models/global_notification_model';
import GlobalNotificationActions from '../../../../../../actions/global_notification_actions'; import GlobalNotificationActions from '../../../../../../actions/global_notification_actions';
import CylandSubmitButton from '../ascribe_buttons/cyland_submit_button'; import CylandSubmitButton from '../cyland_buttons/cyland_submit_button';
import AclProxy from '../../../../../acl_proxy'; import AclProxy from '../../../../../acl_proxy';
import { getLangText } from '../../../../../../utils/lang_utils'; import { getLangText } from '../../../../../../utils/lang_utils';

View File

@ -10,6 +10,7 @@ import WhitelabelStore from '../../../../../../stores/whitelabel_store';
import { getLangText } from '../../../../../../utils/lang_utils'; import { getLangText } from '../../../../../../utils/lang_utils';
let CylandSubmitButton = React.createClass({ let CylandSubmitButton = React.createClass({
propTypes: { propTypes: {
className: React.PropTypes.string, className: React.PropTypes.string,

View File

@ -7,11 +7,11 @@ import PieceStore from '../../../../../../stores/piece_store';
import UserStore from '../../../../../../stores/user_store'; import UserStore from '../../../../../../stores/user_store';
import CylandSubmitButton from '../ascribe_buttons/cyland_submit_button'; import CylandSubmitButton from '../cyland_buttons/cyland_submit_button';
import CollapsibleParagraph from '../../../../../../components/ascribe_collapsible/collapsible_paragraph'; import CollapsibleParagraph from '../../../../../../components/ascribe_collapsible/collapsible_paragraph';
import CylandAdditionalDataForm from '../ascribe_forms/cyland_additional_data_form'; import CylandAdditionalDataForm from '../cyland_forms/cyland_additional_data_form';
import WalletPieceContainer from '../../ascribe_detail/wallet_piece_container'; import WalletPieceContainer from '../../ascribe_detail/wallet_piece_container';
@ -21,6 +21,10 @@ import { getLangText } from '../../../../../../utils/lang_utils';
import { mergeOptions } from '../../../../../../utils/general_utils'; import { mergeOptions } from '../../../../../../utils/general_utils';
let CylandPieceContainer = React.createClass({ let CylandPieceContainer = React.createClass({
propTypes: {
params: React.PropTypes.object
},
getInitialState() { getInitialState() {
return mergeOptions( return mergeOptions(
PieceStore.getState(), PieceStore.getState(),

View File

@ -35,17 +35,17 @@ let CylandAdditionalDataForm = React.createClass({
}; };
}, },
handleSuccess() {
let notification = new GlobalNotificationModel('Further details successfully updated', 'success', 10000);
GlobalNotificationActions.appendGlobalNotification(notification);
},
getInitialState() { getInitialState() {
return { return {
isUploadReady: true isUploadReady: true
}; };
}, },
handleSuccess() {
let notification = new GlobalNotificationModel(getLangText('Further details successfully updated'), 'success', 10000);
GlobalNotificationActions.appendGlobalNotification(notification);
},
getFormData() { getFormData() {
let extradata = {}; let extradata = {};
let formRefs = this.refs.form.refs; let formRefs = this.refs.form.refs;

View File

@ -1,7 +1,7 @@
'use strict'; 'use strict';
import React from 'react'; import React from 'react';
import constants from '../../../../constants/application_constants'; import AppConstants from '../../../../constants/application_constants';
let Hero = React.createClass({ let Hero = React.createClass({
@ -9,7 +9,7 @@ let Hero = React.createClass({
return ( return (
<div className="hero"> <div className="hero">
<img <img
className="logo" src={constants.whitelabel.logo} className="logo" src={AppConstants.whitelabel.logo}
alt="Sluice Art Prize" alt="Sluice Art Prize"
height="200px"/> height="200px"/>
</div> </div>

View File

@ -3,7 +3,6 @@
import React from 'react'; import React from 'react';
import Router from 'react-router'; import Router from 'react-router';
import WhitelabelActions from '../../../../../actions/whitelabel_actions'; import WhitelabelActions from '../../../../../actions/whitelabel_actions';
import WhitelabelStore from '../../../../../stores/whitelabel_store'; import WhitelabelStore from '../../../../../stores/whitelabel_store';

View File

@ -6,7 +6,7 @@ import PieceList from '../../../../piece_list';
import UserActions from '../../../../../actions/user_actions'; import UserActions from '../../../../../actions/user_actions';
import UserStore from '../../../../../stores/user_store'; import UserStore from '../../../../../stores/user_store';
import CylandAccordionListItem from './ascribe_accordion_list/cyland_accordion_list_item'; import CylandAccordionListItem from './cyland_accordion_list/cyland_accordion_list_item';
import { getLangText } from '../../../../../utils/lang_utils'; import { getLangText } from '../../../../../utils/lang_utils';

View File

@ -25,7 +25,7 @@ import PieceActions from '../../../../../actions/piece_actions';
import GlobalNotificationModel from '../../../../../models/global_notification_model'; import GlobalNotificationModel from '../../../../../models/global_notification_model';
import GlobalNotificationActions from '../../../../../actions/global_notification_actions'; import GlobalNotificationActions from '../../../../../actions/global_notification_actions';
import CylandAdditionalDataForm from './ascribe_forms/cyland_additional_data_form'; import CylandAdditionalDataForm from './cyland_forms/cyland_additional_data_form';
import LoanForm from '../../../../ascribe_forms/form_loan'; import LoanForm from '../../../../ascribe_forms/form_loan';

View File

@ -12,7 +12,7 @@ import UserStore from '../../../../../../stores/user_store';
import GlobalNotificationModel from '../../../../../../models/global_notification_model'; import GlobalNotificationModel from '../../../../../../models/global_notification_model';
import GlobalNotificationActions from '../../../../../../actions/global_notification_actions'; import GlobalNotificationActions from '../../../../../../actions/global_notification_actions';
import IkonotvSubmitButton from '../ascribe_buttons/ikonotv_submit_button'; import IkonotvSubmitButton from '../ikonotv_buttons/ikonotv_submit_button';
import AclProxy from '../../../../../acl_proxy'; import AclProxy from '../../../../../acl_proxy';

View File

@ -9,7 +9,6 @@ import { getLangText } from '../../../../../../utils/lang_utils';
let IkonotvSubmitButton = React.createClass({ let IkonotvSubmitButton = React.createClass({
propTypes: { propTypes: {
className: React.PropTypes.string, className: React.PropTypes.string,
handleSuccess: React.PropTypes.func,
piece: React.PropTypes.object.isRequired piece: React.PropTypes.object.isRequired
}, },

View File

@ -7,13 +7,12 @@ import PieceStore from '../../../../../../stores/piece_store';
import UserStore from '../../../../../../stores/user_store'; import UserStore from '../../../../../../stores/user_store';
import IkonotvSubmitButton from '../ikonotv_buttons/ikonotv_submit_button';
import IkonotvSubmitButton from '../ascribe_buttons/ikonotv_submit_button';
import CollapsibleParagraph from '../../../../../../components/ascribe_collapsible/collapsible_paragraph'; import CollapsibleParagraph from '../../../../../../components/ascribe_collapsible/collapsible_paragraph';
import IkonotvArtistDetailsForm from '../ascribe_forms/ikonotv_artist_details_form'; import IkonotvArtistDetailsForm from '../ikonotv_forms/ikonotv_artist_details_form';
import IkonotvArtworkDetailsForm from '../ascribe_forms/ikonotv_artwork_details_form'; import IkonotvArtworkDetailsForm from '../ikonotv_forms/ikonotv_artwork_details_form';
import WalletPieceContainer from '../../ascribe_detail/wallet_piece_container'; import WalletPieceContainer from '../../ascribe_detail/wallet_piece_container';
@ -22,7 +21,12 @@ import AppConstants from '../../../../../../constants/application_constants';
import { getLangText } from '../../../../../../utils/lang_utils'; import { getLangText } from '../../../../../../utils/lang_utils';
import { mergeOptions } from '../../../../../../utils/general_utils'; import { mergeOptions } from '../../../../../../utils/general_utils';
let IkonotvPieceContainer = React.createClass({ let IkonotvPieceContainer = React.createClass({
propTypes: {
params: React.PropTypes.object
},
getInitialState() { getInitialState() {
return mergeOptions( return mergeOptions(
PieceStore.getState(), PieceStore.getState(),

View File

@ -6,7 +6,7 @@ import PieceList from '../../../../piece_list';
import UserActions from '../../../../../actions/user_actions'; import UserActions from '../../../../../actions/user_actions';
import UserStore from '../../../../../stores/user_store'; import UserStore from '../../../../../stores/user_store';
import IkonotvAccordionListItem from './ascribe_accordion_list/ikonotv_accordion_list_item'; import IkonotvAccordionListItem from './ikonotv_accordion_list/ikonotv_accordion_list_item';
import { getLangText } from '../../../../../utils/lang_utils'; import { getLangText } from '../../../../../utils/lang_utils';

View File

@ -22,8 +22,8 @@ import GlobalNotificationActions from '../../../../../actions/global_notificatio
import RegisterPieceForm from '../../../../ascribe_forms/form_register_piece'; import RegisterPieceForm from '../../../../ascribe_forms/form_register_piece';
import LoanForm from '../../../../ascribe_forms/form_loan'; import LoanForm from '../../../../ascribe_forms/form_loan';
import IkonotvArtistDetailsForm from './ascribe_forms/ikonotv_artist_details_form'; import IkonotvArtistDetailsForm from './ikonotv_forms/ikonotv_artist_details_form';
import IkonotvArtworkDetailsForm from './ascribe_forms/ikonotv_artwork_details_form'; import IkonotvArtworkDetailsForm from './ikonotv_forms/ikonotv_artwork_details_form';
import SlidesContainer from '../../../../ascribe_slides_container/slides_container'; import SlidesContainer from '../../../../ascribe_slides_container/slides_container';

View File

@ -10,6 +10,8 @@ import GlobalNotification from '../../global_notification';
import getRoutes from './wallet_routes'; import getRoutes from './wallet_routes';
import classNames from 'classnames'; import classNames from 'classnames';
import { getSubdomain } from '../../../utils/general_utils';
let RouteHandler = Router.RouteHandler; let RouteHandler = Router.RouteHandler;
@ -18,7 +20,7 @@ let WalletApp = React.createClass({
mixins: [Router.State], mixins: [Router.State],
render() { render() {
let subdomain = window.location.host.split('.')[0]; let subdomain = getSubdomain();
let ROUTES = getRoutes(null, subdomain); let ROUTES = getRoutes(null, subdomain);
let activeRoutes = this.getRoutes().map(elem => 'route--' + elem.name); let activeRoutes = this.getRoutes().map(elem => 'route--' + elem.name);

View File

@ -14,9 +14,10 @@ import PieceContainer from '../../../components/ascribe_detail/piece_container';
import EditionContainer from '../../../components/ascribe_detail/edition_container'; import EditionContainer from '../../../components/ascribe_detail/edition_container';
import SettingsContainer from '../../../components/ascribe_settings/settings_container'; import SettingsContainer from '../../../components/ascribe_settings/settings_container';
import ContractSettings from '../../../components/ascribe_settings/contract_settings'; import ContractSettings from '../../../components/ascribe_settings/contract_settings';
import ErrorNotFoundPage from '../../../components/error_not_found_page';
import CylandLanding from './components/cyland/cyland_landing'; import CylandLanding from './components/cyland/cyland_landing';
import CylandPieceContainer from './components/cyland/ascribe_detail/cyland_piece_container'; import CylandPieceContainer from './components/cyland/cyland_detail/cyland_piece_container';
import CylandRegisterPiece from './components/cyland/cyland_register_piece'; import CylandRegisterPiece from './components/cyland/cyland_register_piece';
import CylandPieceList from './components/cyland/cyland_piece_list'; import CylandPieceList from './components/cyland/cyland_piece_list';
@ -24,7 +25,7 @@ import IkonotvLanding from './components/ikonotv/ikonotv_landing';
import IkonotvPieceList from './components/ikonotv/ikonotv_piece_list'; import IkonotvPieceList from './components/ikonotv/ikonotv_piece_list';
import IkonotvRequestLoan from './components/ikonotv/ikonotv_request_loan'; import IkonotvRequestLoan from './components/ikonotv/ikonotv_request_loan';
import IkonotvRegisterPiece from './components/ikonotv/ikonotv_register_piece'; import IkonotvRegisterPiece from './components/ikonotv/ikonotv_register_piece';
import IkonotvPieceContainer from './components/ikonotv/ascribe_detail/ikonotv_piece_container'; import IkonotvPieceContainer from './components/ikonotv/ikonotv_detail/ikonotv_piece_container';
import IkonotvContractNotifications from './components/ikonotv/ikonotv_contract_notifications'; import IkonotvContractNotifications from './components/ikonotv/ikonotv_contract_notifications';
import CCRegisterPiece from './components/cc/cc_register_piece'; import CCRegisterPiece from './components/cc/cc_register_piece';
@ -33,6 +34,7 @@ import WalletApp from './wallet_app';
import AppConstants from '../../../constants/application_constants'; import AppConstants from '../../../constants/application_constants';
let Route = Router.Route; let Route = Router.Route;
let NotFoundRoute = Router.NotFoundRoute;
let Redirect = Router.Redirect; let Redirect = Router.Redirect;
let baseUrl = AppConstants.baseUrl; let baseUrl = AppConstants.baseUrl;
@ -52,6 +54,7 @@ let ROUTES = {
<Route name="coa_verify" path="verify" handler={CoaVerifyContainer} /> <Route name="coa_verify" path="verify" handler={CoaVerifyContainer} />
<Route name="settings" path="settings" handler={SettingsContainer} /> <Route name="settings" path="settings" handler={SettingsContainer} />
<Route name="contract_settings" path="contract_settings" handler={ContractSettings} /> <Route name="contract_settings" path="contract_settings" handler={ContractSettings} />
<NotFoundRoute name="notFound" handler={ErrorNotFoundPage} />
</Route> </Route>
), ),
'cc': ( 'cc': (
@ -68,6 +71,7 @@ let ROUTES = {
<Route name="edition" path="editions/:editionId" handler={EditionContainer} /> <Route name="edition" path="editions/:editionId" handler={EditionContainer} />
<Route name="coa_verify" path="verify" handler={CoaVerifyContainer} /> <Route name="coa_verify" path="verify" handler={CoaVerifyContainer} />
<Route name="settings" path="settings" handler={SettingsContainer} /> <Route name="settings" path="settings" handler={SettingsContainer} />
<NotFoundRoute name="notFound" handler={ErrorNotFoundPage} />
</Route> </Route>
), ),
'ikonotv': ( 'ikonotv': (
@ -86,6 +90,7 @@ let ROUTES = {
<Route name="settings" path="settings" handler={SettingsContainer} /> <Route name="settings" path="settings" handler={SettingsContainer} />
<Route name="contract_settings" path="contract_settings" handler={ContractSettings} /> <Route name="contract_settings" path="contract_settings" handler={ContractSettings} />
<Route name="contract_notifications" path="contract_notifications" handler={IkonotvContractNotifications} /> <Route name="contract_notifications" path="contract_notifications" handler={IkonotvContractNotifications} />
<NotFoundRoute name="notFound" handler={ErrorNotFoundPage} />
</Route> </Route>
) )
}; };

View File

@ -38,6 +38,7 @@ let ApiUrls = {
'ownership_consigns': AppConstants.apiEndpoint + 'ownership/consigns/', 'ownership_consigns': AppConstants.apiEndpoint + 'ownership/consigns/',
'ownership_consigns_confirm': AppConstants.apiEndpoint + 'ownership/consigns/confirm/', 'ownership_consigns_confirm': AppConstants.apiEndpoint + 'ownership/consigns/confirm/',
'ownership_consigns_deny': AppConstants.apiEndpoint + 'ownership/consigns/deny/', 'ownership_consigns_deny': AppConstants.apiEndpoint + 'ownership/consigns/deny/',
'ownership_consigns_withdraw': AppConstants.apiEndpoint + 'ownership/consigns/withdraw/',
'ownership_loans_pieces': AppConstants.apiEndpoint + 'ownership/loans/pieces/', 'ownership_loans_pieces': AppConstants.apiEndpoint + 'ownership/loans/pieces/',
'ownership_loans_pieces_confirm': AppConstants.apiEndpoint + 'ownership/loans/pieces/confirm/', 'ownership_loans_pieces_confirm': AppConstants.apiEndpoint + 'ownership/loans/pieces/confirm/',
'ownership_loans_pieces_deny': AppConstants.apiEndpoint + 'ownership/loans/pieces/deny/', 'ownership_loans_pieces_deny': AppConstants.apiEndpoint + 'ownership/loans/pieces/deny/',

View File

@ -61,7 +61,7 @@ let constants = {
'validation': { 'validation': {
'additionalData': { 'additionalData': {
'itemLimit': 100, 'itemLimit': 100,
'sizeLimit': '50000000' 'sizeLimit': '25000000000'
}, },
'registerWork': { 'registerWork': {
'itemLimit': 1, 'itemLimit': 1,

View File

@ -2,12 +2,15 @@
import requests from '../utils/requests'; import requests from '../utils/requests';
import { getSubdomain } from '../utils/general_utils';
let LicenseFetcher = { let LicenseFetcher = {
/** /**
* Fetch the available licenses from the API (might be bound to the subdomain e.g. cc.ascribe.io). * Fetch the available licenses from the API (might be bound to the subdomain e.g. cc.ascribe.io).
*/ */
fetch() { fetch() {
return requests.get('licenses', {'subdomain': window.location.host.split('.')[0]}); return requests.get('licenses', {'subdomain': getSubdomain()});
} }
}; };

View File

@ -2,12 +2,15 @@
import requests from '../utils/requests'; import requests from '../utils/requests';
import { getSubdomain } from '../utils/general_utils';
let WhitelabelFetcher = { let WhitelabelFetcher = {
/** /**
* Fetch the custom whitelabel data from the API. * Fetch the custom whitelabel data from the API.
*/ */
fetch() { fetch() {
return requests.get('whitelabel_settings', {'subdomain': window.location.host.split('.')[0]}); return requests.get('whitelabel_settings', {'subdomain': getSubdomain()});
} }
}; };

View File

@ -21,11 +21,14 @@ import ContractSettings from './components/ascribe_settings/contract_settings';
import SettingsContainer from './components/ascribe_settings/settings_container'; import SettingsContainer from './components/ascribe_settings/settings_container';
import CoaVerifyContainer from './components/coa_verify_container'; import CoaVerifyContainer from './components/coa_verify_container';
import ErrorNotFoundPage from './components/error_not_found_page';
import RegisterPiece from './components/register_piece'; import RegisterPiece from './components/register_piece';
import AppConstants from './constants/application_constants'; import AppConstants from './constants/application_constants';
let Route = Router.Route; let Route = Router.Route;
let NotFoundRoute = Router.NotFoundRoute;
let Redirect = Router.Redirect; let Redirect = Router.Redirect;
let baseUrl = AppConstants.baseUrl; let baseUrl = AppConstants.baseUrl;
@ -45,6 +48,7 @@ const COMMON_ROUTES = (
<Route name="settings" path="settings" handler={SettingsContainer} /> <Route name="settings" path="settings" handler={SettingsContainer} />
<Route name="contract_settings" path="contract_settings" handler={ContractSettings} /> <Route name="contract_settings" path="contract_settings" handler={ContractSettings} />
<Route name="coa_verify" path="verify" handler={CoaVerifyContainer} /> <Route name="coa_verify" path="verify" handler={CoaVerifyContainer} />
<NotFoundRoute name="notFound" handler={ErrorNotFoundPage} />
</Route> </Route>
); );

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import ApplicationActions from '../actions/application_actions'; import ApplicationActions from '../actions/application_actions';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import CoaActions from '../actions/coa_actions'; import CoaActions from '../actions/coa_actions';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import ContractAgreementListActions from '../actions/contract_agreement_list_actions'; import ContractAgreementListActions from '../actions/contract_agreement_list_actions';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import ContractListActions from '../actions/contract_list_actions'; import ContractListActions from '../actions/contract_list_actions';

View File

@ -2,7 +2,7 @@
import React from 'react'; import React from 'react';
import alt from '../alt'; import { alt } from '../alt';
import EditionsListActions from '../actions/edition_list_actions'; import EditionsListActions from '../actions/edition_list_actions';
class EditionListStore { class EditionListStore {
@ -13,7 +13,6 @@ class EditionListStore {
} }
onUpdateEditionList({pieceId, editionListOfPiece, page, pageSize, orderBy, orderAsc, count, filterBy}) { onUpdateEditionList({pieceId, editionListOfPiece, page, pageSize, orderBy, orderAsc, count, filterBy}) {
/* /*
Basically there are two modes an edition list can be updated. Basically there are two modes an edition list can be updated.

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import EditionActions from '../actions/edition_actions'; import EditionActions from '../actions/edition_actions';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import GlobalNotificationActions from '../actions/global_notification_actions'; import GlobalNotificationActions from '../actions/global_notification_actions';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import LicenseActions from '../actions/license_actions'; import LicenseActions from '../actions/license_actions';

View File

@ -1,7 +1,7 @@
'use strict'; 'use strict';
import React from 'react'; import React from 'react';
import alt from '../alt'; import { alt } from '../alt';
import NotificationActions from '../actions/notification_actions'; import NotificationActions from '../actions/notification_actions';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import OwnershipActions from '../actions/ownership_actions'; import OwnershipActions from '../actions/ownership_actions';

View File

@ -1,7 +1,7 @@
'use strict'; 'use strict';
import React from 'react'; import React from 'react';
import alt from '../alt'; import { alt } from '../alt';
import PieceListActions from '../actions/piece_list_actions'; import PieceListActions from '../actions/piece_list_actions';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import PieceActions from '../actions/piece_actions'; import PieceActions from '../actions/piece_actions';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import PrizeListActions from '../actions/prize_list_actions'; import PrizeListActions from '../actions/prize_list_actions';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { altUser } from '../alt';
import UserActions from '../actions/user_actions'; import UserActions from '../actions/user_actions';
@ -18,4 +18,4 @@ class UserStore {
} }
} }
export default alt.createStore(UserStore, 'UserStore'); export default altUser.createStore(UserStore, 'UserStore');

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { alt } from '../alt';
import WalletSettingsActions from '../actions/wallet_settings_actions'; import WalletSettingsActions from '../actions/wallet_settings_actions';

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { altWhitelabel } from '../alt';
import WhitelabelActions from '../actions/whitelabel_actions'; import WhitelabelActions from '../actions/whitelabel_actions';
@ -15,4 +15,4 @@ class WhitelabelStore {
} }
} }
export default alt.createStore(WhitelabelStore, 'WhitelabelStore'); export default altWhitelabel.createStore(WhitelabelStore, 'WhitelabelStore');

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { altThirdParty } from '../alt';
import EventActions from '../actions/event_actions'; import EventActions from '../actions/event_actions';
@ -27,4 +27,4 @@ class DebugHandler {
} }
} }
export default alt.createStore(DebugHandler, 'DebugHandler'); export default altThirdParty.createStore(DebugHandler, 'DebugHandler');

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { altThirdParty } from '../alt';
import EventActions from '../actions/event_actions'; import EventActions from '../actions/event_actions';
class GoogleAnalyticsHandler { class GoogleAnalyticsHandler {
@ -23,4 +23,4 @@ class GoogleAnalyticsHandler {
} }
export default alt.createStore(GoogleAnalyticsHandler, 'GoogleAnalyticsHandler'); export default altThirdParty.createStore(GoogleAnalyticsHandler, 'GoogleAnalyticsHandler');

View File

@ -1,8 +1,10 @@
'use strict'; 'use strict';
import alt from '../alt'; import { altThirdParty } from '../alt';
import EventActions from '../actions/event_actions'; import EventActions from '../actions/event_actions';
import { getSubdomain } from '../utils/general_utils';
class IntercomHandler { class IntercomHandler {
constructor() { constructor() {
@ -20,7 +22,7 @@ class IntercomHandler {
/* eslint-enable */ /* eslint-enable */
app_id: 'oboxh5w1', app_id: 'oboxh5w1',
email: profile.email, email: profile.email,
subdomain: window.location.host.split('.')[0], subdomain: getSubdomain(),
widget: { widget: {
activator: '#IntercomDefaultWidget' activator: '#IntercomDefaultWidget'
} }
@ -31,4 +33,4 @@ class IntercomHandler {
} }
export default alt.createStore(IntercomHandler, 'IntercomHandler'); export default altThirdParty.createStore(IntercomHandler, 'IntercomHandler');

View File

@ -1,10 +1,12 @@
'use strict'; 'use strict';
import alt from '../alt'; import { altThirdParty } from '../alt';
import EventActions from '../actions/event_actions'; import EventActions from '../actions/event_actions';
import NotificationActions from '../actions/notification_actions'; import NotificationActions from '../actions/notification_actions';
import { getSubdomain } from '../utils/general_utils';
class NotificationsHandler { class NotificationsHandler {
@ -13,11 +15,11 @@ class NotificationsHandler {
this.loaded = false; this.loaded = false;
} }
onProfileDidLoad(profile) { onProfileDidLoad() {
if (this.loaded) { if (this.loaded) {
return; return;
} }
let subdomain = window.location.host.split('.')[0]; let subdomain = getSubdomain();
if (subdomain === 'ikonotv') { if (subdomain === 'ikonotv') {
NotificationActions.fetchContractAgreementListNotifications().then( NotificationActions.fetchContractAgreementListNotifications().then(
(res) => { (res) => {
@ -33,4 +35,4 @@ class NotificationsHandler {
} }
} }
export default alt.createStore(NotificationsHandler, 'NotificationsHandler'); export default altThirdParty.createStore(NotificationsHandler, 'NotificationsHandler');

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
import alt from '../alt'; import { altThirdParty } from '../alt';
import EventActions from '../actions/event_actions'; import EventActions from '../actions/event_actions';
import Raven from 'raven-js'; import Raven from 'raven-js';
@ -25,4 +25,4 @@ class RavenHandler {
} }
} }
export default alt.createStore(RavenHandler, 'RavenHandler'); export default altThirdParty.createStore(RavenHandler, 'RavenHandler');

View File

@ -231,4 +231,15 @@ export function truncateTextAtCharIndex(text, charIndex, replacement = '...') {
export function replaceSubstringAtIndex(baseString, substrToReplace, stringToBePut) { export function replaceSubstringAtIndex(baseString, substrToReplace, stringToBePut) {
let index = baseString.indexOf(substrToReplace); let index = baseString.indexOf(substrToReplace);
return baseString.substr(0, index) + stringToBePut + baseString.substr(index + substrToReplace.length); return baseString.substr(0, index) + stringToBePut + baseString.substr(index + substrToReplace.length);
}
/**
* Extracts the user's subdomain from the browser's window.
* If no subdomain is found (for example on a naked domain), the default "www" is just assumed.
* @return {string} subdomain as a string
*/
export function getSubdomain() {
let { host } = window.location;
let tokens = host.split('.');
return tokens.length > 2 ? tokens[0] : 'www';
} }

View File

@ -7,6 +7,7 @@ $BASE_URL: '<%= BASE_URL %>';
@import 'ascribe_variables'; @import 'ascribe_variables';
@import 'variables'; @import 'variables';
@import '../node_modules/bootstrap-sass/assets/stylesheets/bootstrap'; @import '../node_modules/bootstrap-sass/assets/stylesheets/bootstrap';
@import '../node_modules/react-star-rating/dist/css/react-star-rating.min';
@import '../node_modules/react-datepicker/dist/react-datepicker'; @import '../node_modules/react-datepicker/dist/react-datepicker';
@import 'glyphicons-social'; @import 'glyphicons-social';
@import 'ascribe_theme'; @import 'ascribe_theme';
@ -487,4 +488,22 @@ hr {
.modal-header-ascribe { .modal-header-ascribe {
padding: 15px; padding: 15px;
border-bottom: none; border-bottom: none;
min-height: 16.42857px; } min-height: 16.42857px;
}
.error-wrapper {
width: 100%;
text-align: center;
padding: 5% 20% 5% 20%;
> h1 {
font-size: 10em;
font-weight: 600;
margin-bottom: .25em;
}
> p {
font-size: 2em;
}
}