1
0
mirror of https://github.com/ascribe/onion.git synced 2024-12-22 17:33:14 +01:00

Merge remote-tracking branch 'origin/master' into AD-744-search-filter-not-working-i-type-

This commit is contained in:
Tim Daubenschütz 2015-10-12 17:35:48 +02:00
commit f57125184d
67 changed files with 445 additions and 215 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
'use strict';
import alt from '../alt';
import { altThirdParty } from '../alt';
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';
import alt from '../alt';
import { alt } from '../alt';
class GlobalNotificationActions {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
'use strict';
import alt from '../alt';
import { altUser } from '../alt';
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';
import alt from '../alt';
import { alt } from '../alt';
import WalletSettingsFetcher from '../fetchers/wallet_settings_fetcher';

View File

@ -1,6 +1,6 @@
'use strict';
import alt from '../alt';
import { altWhitelabel } from '../alt';
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';
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 */
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 requests from './utils/requests';
import { updateApiUrls } from './constants/api_urls';
import { getSubdomainSettings } from './utils/constants_utils';
import { initLogging } from './utils/error_utils';
import { getSubdomain } from './utils/general_utils';
import EventActions from './actions/event_actions';
@ -48,11 +50,11 @@ requests.defaults({
class AppGateway {
start() {
let settings;
let subdomain = window.location.host.split('.')[0];
let subdomain = getSubdomain();
try {
settings = getSubdomainSettings(subdomain);
appConstants.whitelabel = settings;
AppConstants.whitelabel = settings;
updateApiUrls(settings.type, subdomain);
this.load(settings);
} catch(err) {

View File

@ -6,15 +6,11 @@ import Router from 'react-router';
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
import Button from 'react-bootstrap/lib/Button';
import UserActions from '../../actions/user_actions';
import UserStore from '../../stores/user_store';
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 HistoryIterator from './history_iterator';
@ -28,13 +24,7 @@ import EditionDetailProperty from './detail_property';
import LicenseDetail from './license_detail';
import EditionFurtherDetails from './further_details';
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 EditionActionPanel from './edition_action_panel';
import Note from './note';
@ -42,7 +32,6 @@ 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 Link = Router.Link;
/**
@ -57,15 +46,11 @@ let Edition = React.createClass({
mixins: [Router.Navigation],
getInitialState() {
return mergeOptions(
UserStore.getState(),
PieceListStore.getState()
);
return UserStore.getState();
},
componentDidMount() {
UserStore.listen(this.onChange);
PieceListStore.listen(this.onChange);
UserActions.fetchCurrentUser();
},
@ -80,31 +65,12 @@ let Edition = React.createClass({
CoaActions.flushCoa();
UserStore.unlisten(this.onChange);
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});
},
render() {
return (
<Row>
@ -121,12 +87,9 @@ let Edition = React.createClass({
<hr/>
</div>
<EditionSummary
handleSuccess={this.props.loadEdition}
refreshCollection={this.refreshCollection}
currentUser={this.state.currentUser}
edition={this.props.edition}
handleDeleteSuccess={this.handleDeleteSuccess}/>
currentUser={this.state.currentUser}
handleSuccess={this.props.loadEdition}/>
<CollapsibleParagraph
title={getLangText('Certificate of Authenticity')}
show={this.props.edition.acl.acl_coa === true}>
@ -209,29 +172,14 @@ let Edition = React.createClass({
let EditionSummary = React.createClass({
propTypes: {
edition: React.PropTypes.object,
handleSuccess: React.PropTypes.func,
currentUser: React.PropTypes.object,
handleDeleteSuccess: React.PropTypes.func,
refreshCollection: React.PropTypes.func
},
getTransferWithdrawData(){
return {'bitcoin_id': this.props.edition.bitcoin_id};
handleSuccess: React.PropTypes.func
},
handleSuccess() {
this.props.refreshCollection();
this.props.handleSuccess();
},
showNotification(response){
this.props.handleSuccess();
if (response){
let notification = new GlobalNotificationModel(response.notification, 'success');
GlobalNotificationActions.appendGlobalNotification(notification);
}
},
getStatus(){
let status = null;
if (this.props.edition.status.length > 0){
@ -246,79 +194,26 @@ let EditionSummary = React.createClass({
return status;
},
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={12}>
<AclButtonList
className="text-center ascribe-button-list"
availableAcls={this.props.edition.acl}
editions={[this.props.edition]}
handleSuccess={this.handleSuccess}>
{withdrawButton}
<DeleteButton
handleSuccess={this.props.handleDeleteSuccess}
editions={[this.props.edition]}/>
{unconsignRequestButton}
</AclButtonList>
</Col>
</Row>);
}
return actions;
},
render() {
let { edition, currentUser } = this.props;
return (
<div className="ascribe-detail-header">
<EditionDetailProperty
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
label={getLangText('ID')}
value={ this.props.edition.bitcoin_id }
value={ edition.bitcoin_id }
ellipsis={true} />
<EditionDetailProperty
label={getLangText('OWNER')}
value={ this.props.edition.owner } />
<LicenseDetail license={this.props.edition.license_type}/>
value={ edition.owner } />
<LicenseDetail license={edition.license_type}/>
{this.getStatus()}
{this.getActions()}
<EditionActionPanel
edition={edition}
currentUser={currentUser}
handleSuccess={this.handleSuccess} />
<hr/>
</div>
);
@ -336,12 +231,13 @@ let CoaDetails = React.createClass({
},
componentDidMount() {
let { edition } = this.props;
CoaStore.listen(this.onChange);
if(this.props.edition.coa) {
CoaActions.fetchOne(this.props.edition.coa);
if(edition.coa) {
CoaActions.fetchOrCreate(edition.coa, edition.bitcoin_id);
}
else {
CoaActions.create(this.props.edition);
CoaActions.create(edition.bitcoin_id);
}
},

View File

@ -0,0 +1,169 @@
'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 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);
}
},
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]}/>
</AclButtonList>
</Col>
</Row>
);
}
}
});
export default EditionActionPanel;

View File

@ -44,6 +44,10 @@ let LoginForm = React.createClass({
componentDidMount() {
UserStore.listen(this.onChange);
let { redirect } = this.getQuery();
if (redirect && redirect !== 'login'){
this.transitionTo(redirect, null, this.getQuery());
}
},
componentWillUnmount() {
@ -56,6 +60,15 @@ let LoginForm = React.createClass({
// if user is already logged in, redirect him to piece list
if(this.state.currentUser && this.state.currentUser.email && this.props.redirectOnLoggedIn) {
// 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);
}
},
@ -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.
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) {
// 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.

View File

@ -14,6 +14,7 @@ import Form from './form';
import Property from './property';
import InputCheckbox from './input_checkbox';
import AppConstants from '../../constants/application_constants';
import ApiUrls from '../../constants/api_urls';
@ -40,6 +41,10 @@ let SignupForm = React.createClass({
componentDidMount() {
UserStore.listen(this.onChange);
let { redirect } = this.getQuery();
if (redirect && redirect !== 'signup'){
this.transitionTo(redirect, null, this.getQuery());
}
},
componentWillUnmount() {
@ -51,7 +56,16 @@ let SignupForm = React.createClass({
// if user is already logged in, redirect him to piece list
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') + '.');
}
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');
}
},

View File

@ -33,21 +33,28 @@ let PieceListBulkModal = React.createClass({
);
},
onChange(state) {
this.setState(state);
},
componentDidMount() {
EditionListStore.listen(this.onChange);
UserStore.listen(this.onChange);
PieceListStore.listen(this.onChange);
UserActions.fetchCurrentUser();
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search,
this.state.orderBy, this.state.orderAsc, this.state.filterBy);
},
componentWillUnmount() {
EditionListStore.unlisten(this.onChange);
PieceListStore.unlisten(this.onChange);
UserStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
fetchSelectedPieceEditionList() {
let filteredPieceIdList = Object.keys(this.state.editionList)
.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 UserActions from '../actions/user_actions';
import Alt from '../alt';
import { alt, altWhitelabel, altUser, altThirdParty } from '../alt';
import AppConstants from '../constants/application_constants';
let baseUrl = AppConstants.baseUrl;
@ -16,7 +16,10 @@ let LogoutContainer = React.createClass({
componentDidMount() {
UserActions.logoutCurrentUser()
.then(() => {
Alt.flush();
alt.flush();
altWhitelabel.flush();
altUser.flush();
altThirdParty.flush();
// kill intercom (with fire)
window.Intercom('shutdown');
this.replaceWith(baseUrl);

View File

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

View File

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

View File

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

View File

@ -9,6 +9,9 @@ import GlobalNotification from '../../global_notification';
import getRoutes from './prize_routes';
import { getSubdomain } from '../../../utils/general_utils';
let RouteHandler = Router.RouteHandler;
let PrizeApp = React.createClass({
@ -16,7 +19,7 @@ let PrizeApp = React.createClass({
render() {
let header = null;
let subdomain = window.location.host.split('.')[0];
let subdomain = getSubdomain();
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 SettingsContainer from './components/prize_settings_container';
import CoaVerifyContainer from '../../../components/coa_verify_container';
import ErrorNotFoundPage from '../../../components/error_not_found_page';
import App from './prize_app';
import AppConstants from '../../../constants/application_constants';
let Route = Router.Route;
let NotFoundRoute = Router.NotFoundRoute;
let baseUrl = AppConstants.baseUrl;
@ -36,6 +38,7 @@ function getRoutes() {
<Route name="edition" path="editions/:editionId" handler={EditionContainer} />
<Route name="settings" path="settings" handler={SettingsContainer} />
<Route name="coa_verify" path="verify" handler={CoaVerifyContainer} />
<NotFoundRoute name="notFound" handler={ErrorNotFoundPage} />
</Route>
);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -21,6 +21,10 @@ import { getLangText } from '../../../../../../utils/lang_utils';
import { mergeOptions } from '../../../../../../utils/general_utils';
let CylandPieceContainer = React.createClass({
propTypes: {
params: React.PropTypes.object
},
getInitialState() {
return mergeOptions(
PieceStore.getState(),

View File

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

View File

@ -22,7 +22,12 @@ import AppConstants from '../../../../../../constants/application_constants';
import { getLangText } from '../../../../../../utils/lang_utils';
import { mergeOptions } from '../../../../../../utils/general_utils';
let IkonotvPieceContainer = React.createClass({
propTypes: {
params: React.PropTypes.object
},
getInitialState() {
return mergeOptions(
PieceStore.getState(),

View File

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

View File

@ -14,6 +14,7 @@ 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 ContractSettings from '../../../components/ascribe_settings/contract_settings';
import ErrorNotFoundPage from '../../../components/error_not_found_page';
import CylandLanding from './components/cyland/cyland_landing';
import CylandPieceContainer from './components/cyland/ascribe_detail/cyland_piece_container';
@ -33,6 +34,7 @@ import WalletApp from './wallet_app';
import AppConstants from '../../../constants/application_constants';
let Route = Router.Route;
let NotFoundRoute = Router.NotFoundRoute;
let Redirect = Router.Redirect;
let baseUrl = AppConstants.baseUrl;
@ -52,6 +54,7 @@ let ROUTES = {
<Route name="coa_verify" path="verify" handler={CoaVerifyContainer} />
<Route name="settings" path="settings" handler={SettingsContainer} />
<Route name="contract_settings" path="contract_settings" handler={ContractSettings} />
<NotFoundRoute name="notFound" handler={ErrorNotFoundPage} />
</Route>
),
'cc': (
@ -68,6 +71,7 @@ let ROUTES = {
<Route name="edition" path="editions/:editionId" handler={EditionContainer} />
<Route name="coa_verify" path="verify" handler={CoaVerifyContainer} />
<Route name="settings" path="settings" handler={SettingsContainer} />
<NotFoundRoute name="notFound" handler={ErrorNotFoundPage} />
</Route>
),
'ikonotv': (
@ -86,6 +90,7 @@ let ROUTES = {
<Route name="settings" path="settings" handler={SettingsContainer} />
<Route name="contract_settings" path="contract_settings" handler={ContractSettings} />
<Route name="contract_notifications" path="contract_notifications" handler={IkonotvContractNotifications} />
<NotFoundRoute name="notFound" handler={ErrorNotFoundPage} />
</Route>
)
};

View File

@ -38,6 +38,7 @@ let ApiUrls = {
'ownership_consigns': AppConstants.apiEndpoint + 'ownership/consigns/',
'ownership_consigns_confirm': AppConstants.apiEndpoint + 'ownership/consigns/confirm/',
'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_confirm': AppConstants.apiEndpoint + 'ownership/loans/pieces/confirm/',
'ownership_loans_pieces_deny': AppConstants.apiEndpoint + 'ownership/loans/pieces/deny/',

View File

@ -2,12 +2,15 @@
import requests from '../utils/requests';
import { getSubdomain } from '../utils/general_utils';
let LicenseFetcher = {
/**
* Fetch the available licenses from the API (might be bound to the subdomain e.g. cc.ascribe.io).
*/
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 { getSubdomain } from '../utils/general_utils';
let WhitelabelFetcher = {
/**
* Fetch the custom whitelabel data from the API.
*/
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 CoaVerifyContainer from './components/coa_verify_container';
import ErrorNotFoundPage from './components/error_not_found_page';
import RegisterPiece from './components/register_piece';
import AppConstants from './constants/application_constants';
let Route = Router.Route;
let NotFoundRoute = Router.NotFoundRoute;
let Redirect = Router.Redirect;
let baseUrl = AppConstants.baseUrl;
@ -45,6 +48,7 @@ const COMMON_ROUTES = (
<Route name="settings" path="settings" handler={SettingsContainer} />
<Route name="contract_settings" path="contract_settings" handler={ContractSettings} />
<Route name="coa_verify" path="verify" handler={CoaVerifyContainer} />
<NotFoundRoute name="notFound" handler={ErrorNotFoundPage} />
</Route>
);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
'use strict';
import alt from '../alt';
import { altUser } from '../alt';
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';
import alt from '../alt';
import { alt } from '../alt';
import WalletSettingsActions from '../actions/wallet_settings_actions';

View File

@ -1,6 +1,6 @@
'use strict';
import alt from '../alt';
import { altWhitelabel } from '../alt';
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';
import alt from '../alt';
import { altThirdParty } from '../alt';
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';
import alt from '../alt';
import { altThirdParty } from '../alt';
import EventActions from '../actions/event_actions';
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';
import alt from '../alt';
import { altThirdParty } from '../alt';
import EventActions from '../actions/event_actions';
import { getSubdomain } from '../utils/general_utils';
class IntercomHandler {
constructor() {
@ -20,7 +22,7 @@ class IntercomHandler {
/* eslint-enable */
app_id: 'oboxh5w1',
email: profile.email,
subdomain: window.location.host.split('.')[0],
subdomain: getSubdomain(),
widget: {
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';
import alt from '../alt';
import { altThirdParty } from '../alt';
import EventActions from '../actions/event_actions';
import NotificationActions from '../actions/notification_actions';
import { getSubdomain } from '../utils/general_utils';
class NotificationsHandler {
@ -13,11 +15,11 @@ class NotificationsHandler {
this.loaded = false;
}
onProfileDidLoad(profile) {
onProfileDidLoad() {
if (this.loaded) {
return;
}
let subdomain = window.location.host.split('.')[0];
let subdomain = getSubdomain();
if (subdomain === 'ikonotv') {
NotificationActions.fetchContractAgreementListNotifications().then(
(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';
import alt from '../alt';
import { altThirdParty } from '../alt';
import EventActions from '../actions/event_actions';
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

@ -221,4 +221,15 @@ export function truncateTextAtCharIndex(text, charIndex, replacement = '...') {
truncatedText += text.length > charIndex ? replacement : '';
return truncatedText;
}
/**
* 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

@ -480,3 +480,20 @@ hr {
border-color: #ccc;
}
}
.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;
}
}