mirror of
https://github.com/ascribe/onion.git
synced 2025-02-14 21:10:27 +01:00
Merge pull request #202 from ascribe/upgrade-react
Upgrade react and react-router
This commit is contained in:
commit
6eeac85012
24
js/app.js
24
js/app.js
@ -4,16 +4,20 @@ import 'classlist-polyfill';
|
||||
import 'isomorphic-fetch';
|
||||
|
||||
import React from 'react';
|
||||
import { Router } from 'react-router';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Router from 'react-router/es6/Router';
|
||||
|
||||
import AppResolver from './app_resolver';
|
||||
import history from './history';
|
||||
|
||||
import AppConstants from './constants/application_constants';
|
||||
|
||||
import { getDefaultSubdomainSettings, getSubdomainSettings } from './utils/constants_utils';
|
||||
import { initLogging } from './utils/error_utils';
|
||||
import { getSubdomain } from './utils/general_utils';
|
||||
import requests from './utils/requests';
|
||||
|
||||
|
||||
// FIXME: rename these event actions
|
||||
import EventActions from './actions/event_actions';
|
||||
|
||||
@ -50,10 +54,22 @@ const AppGateway = {
|
||||
|
||||
// `history.listen` is called on every route change, which is perfect for routeDidChange
|
||||
// events.
|
||||
history.listen(EventActions.routeDidChange);
|
||||
// For history <= 3.0, history.listen will synchronously invoke the callback once
|
||||
// immediately after registration.
|
||||
history.listen((location) => {
|
||||
const { locationQueue } = history;
|
||||
locationQueue.unshift(location);
|
||||
|
||||
// Limit the number of locations to keep in memory to avoid too much memory usage
|
||||
if (locationQueue.length > AppConstants.locationThreshold) {
|
||||
locationQueue.length = AppConstants.locationThreshold;
|
||||
}
|
||||
|
||||
EventActions.routeDidChange(location);
|
||||
});
|
||||
|
||||
// Adds a client specific class to the body for whitelabel styling
|
||||
window.document.body.classList.add(`client--${settings.subdomain}`);
|
||||
window.document.body.classList.add(`client--${settings.subdomain || 'ascribe'}`);
|
||||
|
||||
AppResolver
|
||||
.resolve(settings)
|
||||
@ -70,7 +86,7 @@ const AppGateway = {
|
||||
}
|
||||
});
|
||||
|
||||
React.render((
|
||||
ReactDOM.render((
|
||||
<Router history={history}>
|
||||
{redirectRoute}
|
||||
{routes}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Redirect } from 'react-router';
|
||||
import Redirect from 'react-router/es6/Redirect';
|
||||
|
||||
import Routes from './routes';
|
||||
|
||||
|
@ -1,8 +1,4 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import UserActions from '../actions/user_actions';
|
||||
import UserStore from '../stores/user_store';
|
||||
@ -11,8 +7,7 @@ import WhitelabelActions from '../actions/whitelabel_actions';
|
||||
import WhitelabelStore from '../stores/whitelabel_store';
|
||||
|
||||
import GlobalNotification from './global_notification';
|
||||
|
||||
import AppConstants from '../constants/application_constants';
|
||||
import { currentUserShape, locationShape, whitelabelShape } from './prop_types';
|
||||
|
||||
import { mergeOptions } from '../utils/general_utils';
|
||||
|
||||
@ -23,11 +18,16 @@ export default function AppBase(App) {
|
||||
|
||||
propTypes: {
|
||||
children: React.PropTypes.element.isRequired,
|
||||
history: React.PropTypes.object.isRequired,
|
||||
location: React.PropTypes.object.isRequired,
|
||||
location: locationShape.isRequired,
|
||||
routes: React.PropTypes.arrayOf(React.PropTypes.object).isRequired
|
||||
},
|
||||
|
||||
childContextTypes: {
|
||||
currentUser: currentUserShape,
|
||||
location: locationShape,
|
||||
whitelabel: whitelabelShape
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return mergeOptions(
|
||||
UserStore.getState(),
|
||||
@ -35,7 +35,15 @@ export default function AppBase(App) {
|
||||
);
|
||||
},
|
||||
|
||||
mixins: [History],
|
||||
getChildContext() {
|
||||
const { currentUser, whitelabel } = this.state;
|
||||
|
||||
return {
|
||||
currentUser,
|
||||
whitelabel,
|
||||
location: this.props.location
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
UserStore.listen(this.onChange);
|
||||
@ -43,18 +51,6 @@ export default function AppBase(App) {
|
||||
|
||||
UserActions.fetchCurrentUser();
|
||||
WhitelabelActions.fetchWhitelabel();
|
||||
|
||||
this.history.locationQueue.push(this.props.location);
|
||||
},
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { locationQueue } = this.history;
|
||||
locationQueue.unshift(nextProps.location);
|
||||
|
||||
// Limit the number of locations to keep in memory to avoid too much memory usage
|
||||
if (locationQueue.length > AppConstants.locationThreshold) {
|
||||
locationQueue.length = AppConstants.locationThreshold;
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -68,7 +64,6 @@ export default function AppBase(App) {
|
||||
|
||||
render() {
|
||||
const { routes } = this.props;
|
||||
const { currentUser, whitelabel } = this.state;
|
||||
|
||||
// The second element of the routes prop given to us by react-router is always the
|
||||
// active second-level component object (ie. after App).
|
||||
@ -78,13 +73,11 @@ export default function AppBase(App) {
|
||||
<div>
|
||||
<App
|
||||
{...this.props}
|
||||
activeRoute={activeRoute}
|
||||
currentUser={currentUser}
|
||||
whitelabel={whitelabel} />
|
||||
activeRoute={activeRoute} />
|
||||
<GlobalNotification />
|
||||
<div id="modal" className="container" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -1,34 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { omitFromObject } from '../utils/general_utils';
|
||||
|
||||
const AppRouteWrapper = React.createClass({
|
||||
propTypes: {
|
||||
children: React.PropTypes.oneOfType([
|
||||
React.PropTypes.arrayOf(React.PropTypes.element),
|
||||
React.PropTypes.element
|
||||
]).isRequired
|
||||
},
|
||||
|
||||
render() {
|
||||
const propsToPropagate = omitFromObject(this.props, ['children']);
|
||||
|
||||
let childrenWithProps = this.props.children;
|
||||
// If there are more props given, propagate them into the child routes by cloning the routes
|
||||
if (Object.keys(propsToPropagate).length) {
|
||||
childrenWithProps = React.Children.map(this.props.children, (child) => {
|
||||
return React.cloneElement(child, propsToPropagate);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container ascribe-body">
|
||||
{childrenWithProps}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default AppRouteWrapper;
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import Link from 'react-router/es6/Link';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import Link from 'react-router/es6/Link';
|
||||
|
||||
|
||||
let AccordionListItem = React.createClass({
|
||||
|
@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
import AccordionListItem from './accordion_list_item';
|
||||
import AccordionListItemThumbnailPlacholder from './accordion_list_item_thumbnail_placeholder';
|
||||
|
@ -19,24 +19,27 @@ import AccordionListItemPiece from './accordion_list_item_piece';
|
||||
import AccordionListItemEditionWidget from './accordion_list_item_edition_widget';
|
||||
import CreateEditionsForm from '../ascribe_forms/create_editions_form';
|
||||
|
||||
|
||||
import AclProxy from '../acl_proxy';
|
||||
import withContext from '../context/with_context';
|
||||
import { whitelabelShape } from '../prop_types';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
import { mergeOptions } from '../../utils/general_utils';
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
|
||||
let AccordionListItemWallet = React.createClass({
|
||||
propTypes: {
|
||||
content: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
children: React.PropTypes.oneOfType([
|
||||
React.PropTypes.arrayOf(React.PropTypes.element),
|
||||
React.PropTypes.element
|
||||
]),
|
||||
className: React.PropTypes.string,
|
||||
thumbnailPlaceholder: React.PropTypes.func
|
||||
thumbnailPlaceholder: React.PropTypes.func,
|
||||
|
||||
// Injected through HOCs
|
||||
whitelabel: whitelabelShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
@ -162,4 +165,4 @@ let AccordionListItemWallet = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default AccordionListItemWallet;
|
||||
export default withContext(AccordionListItemWallet, 'whitelabel');
|
||||
|
@ -1,41 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import AppBase from './app_base';
|
||||
import AppRouteWrapper from './app_route_wrapper';
|
||||
import Footer from './footer';
|
||||
import Header from './header';
|
||||
|
||||
|
||||
let AscribeApp = React.createClass({
|
||||
const AscribeApp = React.createClass({
|
||||
propTypes: {
|
||||
activeRoute: React.PropTypes.object.isRequired,
|
||||
children: React.PropTypes.element.isRequired,
|
||||
routes: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
|
||||
|
||||
// Provided from AppBase
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object
|
||||
routes: React.PropTypes.arrayOf(React.PropTypes.object).isRequired
|
||||
},
|
||||
|
||||
render() {
|
||||
const { activeRoute, children, currentUser, routes, whitelabel } = this.props;
|
||||
const Footer = activeRoute && activeRoute.footer;
|
||||
const { activeRoute, children, routes } = this.props;
|
||||
const RouteFooterType = activeRoute && activeRoute.footer;
|
||||
|
||||
return (
|
||||
<div className="ascribe-app ascribe-default-app">
|
||||
<Header
|
||||
currentUser={currentUser}
|
||||
routes={routes}
|
||||
whitelabel={whitelabel} />
|
||||
<AppRouteWrapper
|
||||
currentUser={currentUser}
|
||||
whitelabel={whitelabel}>
|
||||
<Header routes={routes} />
|
||||
<div className="container ascribe-body">
|
||||
{/* Routes are injected here */}
|
||||
{children}
|
||||
</AppRouteWrapper>
|
||||
{Footer ? <Footer /> : null}
|
||||
</div>
|
||||
{RouteFooterType ? <RouteFooterType /> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react/addons';
|
||||
import React from 'react';
|
||||
|
||||
import ConsignButton from './acls/consign_button';
|
||||
import EmailButton from './acls/email_button';
|
||||
@ -14,7 +14,6 @@ import { selectFromObject } from '../../utils/general_utils';
|
||||
let AclButtonList = React.createClass({
|
||||
propTypes: {
|
||||
availableAcls: React.PropTypes.object.isRequired,
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
handleSuccess: React.PropTypes.func.isRequired,
|
||||
pieceOrEditions: React.PropTypes.oneOfType([
|
||||
React.PropTypes.object,
|
||||
@ -52,7 +51,7 @@ let AclButtonList = React.createClass({
|
||||
|
||||
handleResize() {
|
||||
this.setState({
|
||||
buttonListSize: this.refs.buttonList.getDOMNode().offsetWidth
|
||||
buttonListSize: this.refs.buttonList.offsetWidth
|
||||
});
|
||||
},
|
||||
|
||||
@ -61,7 +60,7 @@ let AclButtonList = React.createClass({
|
||||
const { buttonListSize } = this.state;
|
||||
|
||||
return React.Children.map(children, (child) => {
|
||||
return React.addons.cloneWithProps(child, { buttonListSize });
|
||||
return React.cloneElement(child, { buttonListSize });
|
||||
});
|
||||
},
|
||||
|
||||
@ -69,13 +68,11 @@ let AclButtonList = React.createClass({
|
||||
const { availableAcls,
|
||||
buttonsStyle,
|
||||
className,
|
||||
currentUser,
|
||||
handleSuccess,
|
||||
pieceOrEditions } = this.props;
|
||||
|
||||
const buttonProps = selectFromObject(this.props, [
|
||||
'availableAcls',
|
||||
'currentUser',
|
||||
'handleSuccess',
|
||||
'pieceOrEditions'
|
||||
]);
|
||||
|
@ -37,13 +37,13 @@ let AclInformation = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
getInfoText(title, info, example){
|
||||
getInfoText(title, info, example) {
|
||||
const aim = this.props.aim;
|
||||
|
||||
if(aim) {
|
||||
if(aim === 'form') {
|
||||
return (
|
||||
<p>
|
||||
<p key={title}>
|
||||
<span className="info">
|
||||
{replaceSubstringAtIndex(info.slice(2), 's ', ' ')}
|
||||
</span>
|
||||
@ -55,7 +55,7 @@ let AclInformation = React.createClass({
|
||||
}
|
||||
else if(aim === 'button') {
|
||||
return (
|
||||
<p>
|
||||
<p key={title}>
|
||||
<span className="title">
|
||||
{title}
|
||||
</span>
|
||||
|
@ -31,7 +31,6 @@ export default function AclButton({ action, displayName, title, tooltip }) {
|
||||
|
||||
buttonAcceptName: React.PropTypes.string,
|
||||
buttonAcceptClassName: React.PropTypes.string,
|
||||
currentUser: React.PropTypes.object,
|
||||
email: React.PropTypes.string,
|
||||
handleSuccess: React.PropTypes.func
|
||||
},
|
||||
@ -43,7 +42,6 @@ export default function AclButton({ action, displayName, title, tooltip }) {
|
||||
render() {
|
||||
const { availableAcls,
|
||||
buttonAcceptClassName,
|
||||
currentUser,
|
||||
email,
|
||||
pieceOrEditions,
|
||||
handleSuccess } = this.props;
|
||||
@ -63,7 +61,6 @@ export default function AclButton({ action, displayName, title, tooltip }) {
|
||||
title={title}>
|
||||
<AclFormFactory
|
||||
action={action}
|
||||
currentUser={currentUser}
|
||||
email={email}
|
||||
pieceOrEditions={pieceOrEditions}
|
||||
showNotification />
|
||||
|
@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react/addons';
|
||||
import React from 'react';
|
||||
import update from 'react-addons-update';
|
||||
|
||||
const { string, object } = React.PropTypes;
|
||||
|
||||
@ -30,7 +31,7 @@ const FormSubmitButton = React.createClass({
|
||||
},
|
||||
|
||||
setReadyStateForKey(key, state) {
|
||||
const readyStates = React.addons.update(this.state.readyStates, { [key]: { $set: state } });
|
||||
const readyStates = update(this.state.readyStates, { [key]: { $set: state } });
|
||||
this.setState({ readyStates });
|
||||
},
|
||||
|
||||
|
@ -5,21 +5,26 @@ import React from 'react';
|
||||
import Button from 'react-bootstrap/lib/Button';
|
||||
|
||||
import ModalWrapper from '../ascribe_modal/modal_wrapper';
|
||||
import UnConsignRequestForm from './../ascribe_forms/form_unconsign_request';
|
||||
import UnConsignRequestForm from '../ascribe_forms/form_unconsign_request';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils.js';
|
||||
import withContext from '../context/with_context';
|
||||
import { currentUserShape } from '../prop_types';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
|
||||
|
||||
let UnConsignRequestButton = React.createClass({
|
||||
const UnConsignRequestButton = React.createClass({
|
||||
propTypes: {
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
edition: React.PropTypes.object.isRequired,
|
||||
|
||||
handleSuccess: React.PropTypes.func
|
||||
handleSuccess: React.PropTypes.func,
|
||||
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
render: function () {
|
||||
render() {
|
||||
const { currentUser, edition, handleSuccess } = this.props;
|
||||
return (
|
||||
<ModalWrapper
|
||||
@ -45,5 +50,4 @@ ${currentUser.username}`
|
||||
}
|
||||
});
|
||||
|
||||
export default UnConsignRequestButton;
|
||||
|
||||
export default withContext(UnConsignRequestButton, 'currentUser');
|
||||
|
@ -1,15 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import Link from 'react-router/es6/Link';
|
||||
import Moment from 'moment';
|
||||
|
||||
import Row from 'react-bootstrap/lib/Row';
|
||||
import Col from 'react-bootstrap/lib/Col';
|
||||
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
|
||||
|
||||
import EditionActions from '../../actions/edition_actions';
|
||||
|
||||
import DetailProperty from './detail_property';
|
||||
import EditionActionPanel from './edition_action_panel';
|
||||
import FurtherDetails from './further_details';
|
||||
@ -24,6 +22,7 @@ import Form from '../ascribe_forms/form';
|
||||
import Property from '../ascribe_forms/property';
|
||||
|
||||
import AclProxy from '../acl_proxy';
|
||||
import withContext from '../context/with_context';
|
||||
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
import AscribeSpinner from '../ascribe_spinner';
|
||||
@ -34,16 +33,17 @@ import { getLangText } from '../../utils/lang_utils';
|
||||
/**
|
||||
* This is the component that implements display-specific functionality
|
||||
*/
|
||||
let Edition = React.createClass({
|
||||
const Edition = React.createClass({
|
||||
propTypes: {
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
edition: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
actionPanelButtonListType: React.PropTypes.func,
|
||||
coaError: React.PropTypes.object,
|
||||
furtherDetailsType: React.PropTypes.func,
|
||||
loadEdition: React.PropTypes.func
|
||||
loadEdition: React.PropTypes.func,
|
||||
|
||||
// Injected through HOCs
|
||||
isLoggedIn: React.PropTypes.bool.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
getDefaultProps() {
|
||||
@ -53,20 +53,20 @@ let Edition = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { actionPanelButtonListType,
|
||||
const {
|
||||
actionPanelButtonListType,
|
||||
coaError,
|
||||
currentUser,
|
||||
edition,
|
||||
furtherDetailsType: FurtherDetailsType,
|
||||
isLoggedIn,
|
||||
loadEdition,
|
||||
whitelabel } = this.props;
|
||||
furtherDetailsType: FurtherDetailsType
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Row>
|
||||
<Col md={6} className="ascribe-print-col-left">
|
||||
<MediaContainer
|
||||
content={edition}
|
||||
currentUser={currentUser}
|
||||
refreshObject={loadEdition} />
|
||||
</Col>
|
||||
<Col md={6} className="ascribe-edition-details ascribe-print-col-right">
|
||||
@ -82,9 +82,7 @@ let Edition = React.createClass({
|
||||
<EditionSummary
|
||||
actionPanelButtonListType={actionPanelButtonListType}
|
||||
edition={edition}
|
||||
currentUser={currentUser}
|
||||
handleSuccess={loadEdition}
|
||||
whitelabel={whitelabel} />
|
||||
handleSuccess={loadEdition} />
|
||||
<CollapsibleParagraph
|
||||
title={getLangText('Certificate of Authenticity')}
|
||||
show={edition.acl.acl_coa === true}>
|
||||
@ -114,7 +112,7 @@ let Edition = React.createClass({
|
||||
|
||||
<CollapsibleParagraph
|
||||
title={getLangText('Notes')}
|
||||
show={!!(currentUser.username || edition.acl.acl_edit || edition.public_note)}>
|
||||
show={!!(isLoggedIn || edition.acl.acl_edit || edition.public_note)}>
|
||||
<Note
|
||||
id={() => {return {'bitcoin_id': edition.bitcoin_id}; }}
|
||||
label={getLangText('Personal note (private)')}
|
||||
@ -122,8 +120,7 @@ let Edition = React.createClass({
|
||||
placeholder={getLangText('Enter your comments ...')}
|
||||
editable={true}
|
||||
successMessage={getLangText('Private note saved')}
|
||||
url={ApiUrls.note_private_edition}
|
||||
currentUser={currentUser} />
|
||||
url={ApiUrls.note_private_edition} />
|
||||
<Note
|
||||
id={() => {return {'bitcoin_id': edition.bitcoin_id}; }}
|
||||
label={getLangText('Personal note (public)')}
|
||||
@ -132,8 +129,7 @@ let Edition = React.createClass({
|
||||
editable={!!edition.acl.acl_edit}
|
||||
show={!!(edition.public_note || edition.acl.acl_edit)}
|
||||
successMessage={getLangText('Public edition note saved')}
|
||||
url={ApiUrls.note_public_edition}
|
||||
currentUser={currentUser} />
|
||||
url={ApiUrls.note_public_edition} />
|
||||
</CollapsibleParagraph>
|
||||
<CollapsibleParagraph
|
||||
title={getLangText('Further Details')}
|
||||
@ -155,14 +151,15 @@ let Edition = React.createClass({
|
||||
});
|
||||
|
||||
|
||||
let EditionSummary = React.createClass({
|
||||
let EditionSummary = withContext(React.createClass({
|
||||
propTypes: {
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
edition: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
actionPanelButtonListType: React.PropTypes.func,
|
||||
handleSuccess: React.PropTypes.func
|
||||
handleSuccess: React.PropTypes.func,
|
||||
|
||||
// Injected through HOCs
|
||||
isLoggedIn: React.PropTypes.bool.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
getStatus() {
|
||||
@ -176,7 +173,12 @@ let EditionSummary = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { actionPanelButtonListType, currentUser, edition, handleSuccess, whitelabel } = this.props;
|
||||
const {
|
||||
actionPanelButtonListType,
|
||||
edition,
|
||||
handleSuccess,
|
||||
isLoggedIn,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div className="ascribe-detail-header">
|
||||
@ -200,23 +202,21 @@ let EditionSummary = React.createClass({
|
||||
no more than 1 key, we're hiding the `DetailProperty` actions as otherwise
|
||||
`AclInformation` would show up
|
||||
*/}
|
||||
<AclProxy show={currentUser.email && Object.keys(edition.acl).length > 1}>
|
||||
<AclProxy show={isLoggedIn && Object.keys(edition.acl).length > 1}>
|
||||
<DetailProperty
|
||||
label={getLangText('ACTIONS')}
|
||||
className="hidden-print">
|
||||
<EditionActionPanel
|
||||
actionPanelButtonListType={actionPanelButtonListType}
|
||||
currentUser={currentUser}
|
||||
edition={edition}
|
||||
handleSuccess={handleSuccess}
|
||||
whitelabel={whitelabel} />
|
||||
handleSuccess={handleSuccess} />
|
||||
</DetailProperty>
|
||||
</AclProxy>
|
||||
<hr/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
}), 'isLoggedIn');
|
||||
|
||||
|
||||
let CoaDetails = React.createClass({
|
||||
@ -277,7 +277,7 @@ let CoaDetails = React.createClass({
|
||||
coaDetailElement = coa;
|
||||
} else {
|
||||
coaDetailElement = [
|
||||
<AscribeSpinner color='dark-blue' size='md'/>,
|
||||
<AscribeSpinner color='dark-blue' size='md' />,
|
||||
<p>{getLangText("Just a sec, we're generating your COA")}</p>,
|
||||
<p>{getLangText('(you may leave the page)')}</p>
|
||||
];
|
||||
@ -354,9 +354,9 @@ let SpoolDetails = React.createClass({
|
||||
<pre className="ascribe-pre">{ownerAddress}</pre>
|
||||
</Property>
|
||||
<hr />
|
||||
</Form>);
|
||||
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default Edition;
|
||||
export default withContext(Edition, 'isLoggedIn');
|
||||
|
@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import Row from 'react-bootstrap/lib/Row';
|
||||
import Col from 'react-bootstrap/lib/Col';
|
||||
@ -11,20 +10,21 @@ 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 Form from './../ascribe_forms/form';
|
||||
import ListRequestActions from './../ascribe_forms/list_form_request_actions';
|
||||
import Property from './../ascribe_forms/property';
|
||||
|
||||
import AclButtonList from './../ascribe_buttons/acl_button_list';
|
||||
import AclInformation from '../ascribe_buttons/acl_information';
|
||||
import DeleteButton from '../ascribe_buttons/delete_button';
|
||||
import UnConsignRequestButton from './../ascribe_buttons/unconsign_request_button';
|
||||
|
||||
import AclProxy from '../acl_proxy';
|
||||
import withContext from '../context/with_context';
|
||||
import { routerShape } from '../prop_types';
|
||||
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
|
||||
@ -34,17 +34,16 @@ 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({
|
||||
const EditionActionPanel = React.createClass({
|
||||
propTypes: {
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
edition: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
actionPanelButtonListType: React.PropTypes.func,
|
||||
handleSuccess: React.PropTypes.func
|
||||
},
|
||||
handleSuccess: React.PropTypes.func,
|
||||
|
||||
mixins: [History],
|
||||
// Injected through HOCs
|
||||
router: routerShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
@ -77,7 +76,7 @@ let EditionActionPanel = React.createClass({
|
||||
const notification = new GlobalNotificationModel(response.notification, 'success');
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
|
||||
this.history.push('/collection');
|
||||
this.props.router.push('/collection');
|
||||
},
|
||||
|
||||
refreshCollection() {
|
||||
@ -101,15 +100,11 @@ let EditionActionPanel = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { actionPanelButtonListType: ActionPanelButtonListType,
|
||||
currentUser,
|
||||
edition,
|
||||
whitelabel } = this.props;
|
||||
const { edition, actionPanelButtonListType: ActionPanelButtonListType } = this.props;
|
||||
|
||||
if (edition.notifications && edition.notifications.length) {
|
||||
return (
|
||||
<ListRequestActions
|
||||
currentUser={currentUser}
|
||||
notifications={edition.notifications}
|
||||
pieceOrEditions={[edition]}
|
||||
handleSuccess={this.handleSuccess} />);
|
||||
@ -120,10 +115,8 @@ let EditionActionPanel = React.createClass({
|
||||
<ActionPanelButtonListType
|
||||
availableAcls={edition.acl}
|
||||
className="ascribe-button-list"
|
||||
currentUser={currentUser}
|
||||
handleSuccess={this.handleSuccess}
|
||||
pieceOrEditions={[edition]}
|
||||
whitelabel={whitelabel}>
|
||||
pieceOrEditions={[edition]} >
|
||||
<AclProxy
|
||||
aclObject={edition.acl}
|
||||
aclName="acl_withdraw_transfer">
|
||||
@ -170,7 +163,6 @@ let EditionActionPanel = React.createClass({
|
||||
aclObject={edition.acl}
|
||||
aclName="acl_request_unconsign">
|
||||
<UnConsignRequestButton
|
||||
currentUser={currentUser}
|
||||
edition={edition}
|
||||
handleSuccess={this.handleSuccess} />
|
||||
</AclProxy>
|
||||
@ -189,4 +181,4 @@ let EditionActionPanel = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default EditionActionPanel;
|
||||
export default withContext(EditionActionPanel, 'router');
|
||||
|
@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import ReactError from '../../mixins/react_error';
|
||||
import { ResourceNotFoundError } from '../../models/errors';
|
||||
@ -25,16 +24,11 @@ let EditionContainer = React.createClass({
|
||||
actionPanelButtonListType: React.PropTypes.func,
|
||||
furtherDetailsType: React.PropTypes.func,
|
||||
|
||||
// Provided from AscribeApp
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object,
|
||||
params: React.PropTypes.object
|
||||
},
|
||||
|
||||
mixins: [History, ReactError],
|
||||
mixins: [ReactError],
|
||||
|
||||
getInitialState() {
|
||||
return EditionStore.getInitialState();
|
||||
@ -77,7 +71,7 @@ let EditionContainer = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { actionPanelButtonListType, currentUser, furtherDetailsType, whitelabel } = this.props;
|
||||
const { actionPanelButtonListType, furtherDetailsType } = this.props;
|
||||
const { edition, coaMeta } = this.state;
|
||||
|
||||
if (edition.id) {
|
||||
@ -87,11 +81,9 @@ let EditionContainer = React.createClass({
|
||||
<Edition
|
||||
actionPanelButtonListType={actionPanelButtonListType}
|
||||
coaError={coaMeta.err}
|
||||
currentUser={currentUser}
|
||||
edition={edition}
|
||||
furtherDetailsType={furtherDetailsType}
|
||||
loadEdition={this.loadEdition}
|
||||
whitelabel={whitelabel} />
|
||||
loadEdition={this.loadEdition} />
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
|
@ -17,12 +17,13 @@ import CollapsibleButton from './../ascribe_collapsible/collapsible_button';
|
||||
import AscribeSpinner from '../ascribe_spinner';
|
||||
|
||||
import AclProxy from '../acl_proxy';
|
||||
import withContext from '../context/with_context';
|
||||
import { currentUserShape } from '../prop_types';
|
||||
|
||||
import AppConstants from '../../constants/application_constants';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
import { extractFileExtensionFromUrl } from '../../utils/file_utils';
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
|
||||
const EMBED_IFRAME_HEIGHT = {
|
||||
@ -36,7 +37,8 @@ let MediaContainer = React.createClass({
|
||||
content: React.PropTypes.object.isRequired,
|
||||
refreshObject: React.PropTypes.func.isRequired,
|
||||
|
||||
currentUser: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
@ -118,7 +120,7 @@ let MediaContainer = React.createClass({
|
||||
// the information in content will be updated if a user updates their username.
|
||||
// We also force uniqueness of usernames, so this check is safe to dtermine if the
|
||||
// content was registered by the current user.
|
||||
const didUserRegisterContent = currentUser && (currentUser.username === content.user_registered);
|
||||
const didUserRegisterContent = currentUser.username === content.user_registered;
|
||||
const thumbnail = content.thumbnail.thumbnail_sizes && content.thumbnail.thumbnail_sizes['600x600'] ? content.thumbnail.thumbnail_sizes['600x600']
|
||||
: content.thumbnail.url_safe;
|
||||
|
||||
@ -181,4 +183,4 @@ let MediaContainer = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default MediaContainer;
|
||||
export default withContext(MediaContainer, 'currentUser');
|
||||
|
@ -5,15 +5,16 @@ import React from 'react';
|
||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||
|
||||
import Form from './../ascribe_forms/form';
|
||||
import Property from './../ascribe_forms/property';
|
||||
import InputTextAreaToggable from './../ascribe_forms/input_textarea_toggable';
|
||||
import Form from '../ascribe_forms/form';
|
||||
import Property from '../ascribe_forms/property';
|
||||
import InputTextAreaToggable from '../ascribe_forms/input_textarea_toggable';
|
||||
|
||||
import withContext from '../context/with_context';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
let Note = React.createClass({
|
||||
propTypes: {
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
id: React.PropTypes.func.isRequired,
|
||||
url: React.PropTypes.string.isRequired,
|
||||
|
||||
@ -22,7 +23,10 @@ let Note = React.createClass({
|
||||
label: React.PropTypes.string,
|
||||
placeholder: React.PropTypes.string,
|
||||
show: React.PropTypes.bool,
|
||||
successMessage: React.PropTypes.string
|
||||
successMessage: React.PropTypes.string,
|
||||
|
||||
// Injected through HOCs
|
||||
isLoggedIn: React.PropTypes.bool.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
getDefaultProps() {
|
||||
@ -40,9 +44,18 @@ let Note = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { currentUser, defaultValue, editable, id, label, placeholder, show, url } = this.props;
|
||||
const {
|
||||
defaultValue,
|
||||
editable,
|
||||
id,
|
||||
isLoggedIn,
|
||||
label,
|
||||
placeholder,
|
||||
show,
|
||||
url
|
||||
} = this.props;
|
||||
|
||||
if ((currentUser.username && editable || !editable) && show) {
|
||||
if ((isLoggedIn && editable || !editable) && show) {
|
||||
return (
|
||||
<Form
|
||||
url={url}
|
||||
@ -66,4 +79,4 @@ let Note = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default Note;
|
||||
export default withContext(Note, 'isLoggedIn');
|
||||
|
@ -18,7 +18,6 @@ let Piece = React.createClass({
|
||||
piece: React.PropTypes.object.isRequired,
|
||||
|
||||
buttons: React.PropTypes.object,
|
||||
currentUser: React.PropTypes.object,
|
||||
header: React.PropTypes.object,
|
||||
subheader: React.PropTypes.object,
|
||||
children: React.PropTypes.oneOfType([
|
||||
@ -32,14 +31,13 @@ let Piece = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { buttons, children, currentUser, header, piece, subheader } = this.props;
|
||||
const { buttons, children, header, piece, subheader } = this.props;
|
||||
|
||||
return (
|
||||
<Row>
|
||||
<Col md={6} className="ascribe-print-col-left">
|
||||
<MediaContainer
|
||||
content={piece}
|
||||
currentUser={currentUser}
|
||||
refreshObject={this.updatePiece} />
|
||||
</Col>
|
||||
<Col md={6} className="ascribe-edition-details ascribe-print-col-right">
|
||||
|
@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
import Moment from 'moment';
|
||||
|
||||
import ReactError from '../../mixins/react_error';
|
||||
@ -25,7 +24,7 @@ import LicenseDetail from './license_detail';
|
||||
import Note from './note';
|
||||
import Piece from './piece';
|
||||
|
||||
import AclButtonList from './../ascribe_buttons/acl_button_list';
|
||||
import AclButtonList from '../ascribe_buttons/acl_button_list';
|
||||
import AclInformation from '../ascribe_buttons/acl_information';
|
||||
import CreateEditionsButton from '../ascribe_buttons/create_editions_button';
|
||||
import DeleteButton from '../ascribe_buttons/delete_button';
|
||||
@ -36,31 +35,32 @@ import CreateEditionsForm from '../ascribe_forms/create_editions_form';
|
||||
import ListRequestActions from '../ascribe_forms/list_form_request_actions';
|
||||
|
||||
import AclProxy from '../acl_proxy';
|
||||
import AscribeSpinner from '../ascribe_spinner';
|
||||
import withContext from '../context/with_context';
|
||||
import { routerShape } from '../prop_types';
|
||||
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
import AscribeSpinner from '../ascribe_spinner';
|
||||
|
||||
import { setDocumentTitle } from '../../utils/dom_utils';
|
||||
import { mergeOptions } from '../../utils/general_utils';
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
import { setDocumentTitle } from '../../utils/dom_utils';
|
||||
|
||||
/**
|
||||
* This is the component that implements resource/data specific functionality
|
||||
*/
|
||||
let PieceContainer = React.createClass({
|
||||
const PieceContainer = React.createClass({
|
||||
propTypes: {
|
||||
furtherDetailsType: React.PropTypes.func,
|
||||
|
||||
// Provided from AscribeApp
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object,
|
||||
// Injected through HOCs
|
||||
isLoggedIn: React.PropTypes.bool.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
router: routerShape.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object,
|
||||
params: React.PropTypes.object
|
||||
},
|
||||
|
||||
mixins: [History, ReactError],
|
||||
mixins: [ReactError],
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
@ -164,7 +164,7 @@ let PieceContainer = React.createClass({
|
||||
const notification = new GlobalNotificationModel(response.notification, 'success');
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
|
||||
this.history.push('/collection');
|
||||
this.props.router.push('/collection');
|
||||
},
|
||||
|
||||
getCreateEditionsDialog() {
|
||||
@ -207,12 +207,11 @@ let PieceContainer = React.createClass({
|
||||
|
||||
getActions() {
|
||||
const { piece } = this.state;
|
||||
const { currentUser } = this.props;
|
||||
const { isLoggedIn } = this.props;
|
||||
|
||||
if (piece.notifications && piece.notifications.length > 0) {
|
||||
return (
|
||||
<ListRequestActions
|
||||
currentUser={currentUser}
|
||||
handleSuccess={this.loadPiece}
|
||||
notifications={piece.notifications}
|
||||
pieceOrEditions={piece} />
|
||||
@ -220,7 +219,7 @@ let PieceContainer = React.createClass({
|
||||
} else {
|
||||
return (
|
||||
<AclProxy
|
||||
show={currentUser && currentUser.email && Object.keys(piece.acl).length > 1}>
|
||||
show={isLoggedIn && Object.keys(piece.acl).length > 1}>
|
||||
{/*
|
||||
`acl_view` is always available in `edition.acl`, therefore if it has
|
||||
no more than 1 key, we're hiding the `DetailProperty` actions as otherwise
|
||||
@ -232,7 +231,6 @@ let PieceContainer = React.createClass({
|
||||
<AclButtonList
|
||||
availableAcls={piece.acl}
|
||||
className="ascribe-button-list"
|
||||
currentUser={currentUser}
|
||||
pieceOrEditions={piece}
|
||||
handleSuccess={this.loadPiece}>
|
||||
<CreateEditionsButton
|
||||
@ -257,7 +255,7 @@ let PieceContainer = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { currentUser, furtherDetailsType: FurtherDetailsType } = this.props;
|
||||
const { isLoggedIn, furtherDetailsType: FurtherDetailsType } = this.props;
|
||||
const { piece } = this.state;
|
||||
|
||||
if (piece.id) {
|
||||
@ -266,7 +264,6 @@ let PieceContainer = React.createClass({
|
||||
return (
|
||||
<Piece
|
||||
piece={piece}
|
||||
currentUser={currentUser}
|
||||
header={
|
||||
<div className="ascribe-detail-header">
|
||||
<hr className="hidden-print" style={{marginTop: 0}} />
|
||||
@ -297,7 +294,7 @@ let PieceContainer = React.createClass({
|
||||
</CollapsibleParagraph>
|
||||
<CollapsibleParagraph
|
||||
title={getLangText('Notes')}
|
||||
show={!!(currentUser.username || piece.acl.acl_edit || piece.public_note)}>
|
||||
show={!!(isLoggedIn || piece.acl.acl_edit || piece.public_note)}>
|
||||
<Note
|
||||
id={this.getId}
|
||||
label={getLangText('Personal note (private)')}
|
||||
@ -305,8 +302,7 @@ let PieceContainer = React.createClass({
|
||||
placeholder={getLangText('Enter your comments ...')}
|
||||
editable={true}
|
||||
successMessage={getLangText('Private note saved')}
|
||||
url={ApiUrls.note_private_piece}
|
||||
currentUser={currentUser} />
|
||||
url={ApiUrls.note_private_piece} />
|
||||
<Note
|
||||
id={this.getId}
|
||||
label={getLangText('Personal note (public)')}
|
||||
@ -315,8 +311,7 @@ let PieceContainer = React.createClass({
|
||||
editable={!!piece.acl.acl_edit}
|
||||
show={!!(piece.public_note || piece.acl.acl_edit)}
|
||||
successMessage={getLangText('Public note saved')}
|
||||
url={ApiUrls.note_public_piece}
|
||||
currentUser={currentUser} />
|
||||
url={ApiUrls.note_public_piece} />
|
||||
</CollapsibleParagraph>
|
||||
<CollapsibleParagraph
|
||||
title={getLangText('Further Details')}
|
||||
@ -344,4 +339,4 @@ let PieceContainer = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default PieceContainer;
|
||||
export default withContext(PieceContainer, 'isLoggedIn', 'router');
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||
|
||||
import ConsignForm from '../ascribe_forms/form_consign';
|
||||
import UnConsignForm from '../ascribe_forms/form_unconsign';
|
||||
import TransferForm from '../ascribe_forms/form_transfer';
|
||||
@ -9,12 +12,12 @@ import LoanForm from '../ascribe_forms/form_loan';
|
||||
import LoanRequestAnswerForm from '../ascribe_forms/form_loan_request_answer';
|
||||
import ShareForm from '../ascribe_forms/form_share_email';
|
||||
|
||||
import withContext from '../context/with_context';
|
||||
import { currentUserShape } from '../prop_types';
|
||||
|
||||
import AppConstants from '../../constants/application_constants';
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
|
||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||
|
||||
import { getAclFormMessage, getAclFormDataId } from '../../utils/form_utils';
|
||||
|
||||
let AclFormFactory = React.createClass({
|
||||
@ -26,12 +29,14 @@ let AclFormFactory = React.createClass({
|
||||
]).isRequired,
|
||||
|
||||
autoFocusProperty: React.PropTypes.string,
|
||||
currentUser: React.PropTypes.object,
|
||||
email: React.PropTypes.string,
|
||||
handleSuccess: React.PropTypes.func,
|
||||
message: React.PropTypes.string,
|
||||
labels: React.PropTypes.object,
|
||||
showNotification: React.PropTypes.bool
|
||||
message: React.PropTypes.string,
|
||||
showNotification: React.PropTypes.bool,
|
||||
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
isPiece() {
|
||||
@ -54,21 +59,23 @@ let AclFormFactory = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { action,
|
||||
const {
|
||||
action,
|
||||
autoFocusProperty,
|
||||
pieceOrEditions,
|
||||
currentUser,
|
||||
email,
|
||||
message,
|
||||
labels,
|
||||
handleSuccess,
|
||||
showNotification } = this.props;
|
||||
showNotification,
|
||||
currentUser: { username: senderName }
|
||||
} = this.props;
|
||||
|
||||
const formMessage = message || getAclFormMessage({
|
||||
senderName,
|
||||
aclName: action,
|
||||
entities: pieceOrEditions,
|
||||
isPiece: this.isPiece(),
|
||||
senderName: currentUser && currentUser.username
|
||||
isPiece: this.isPiece()
|
||||
});
|
||||
|
||||
if (action === 'acl_consign') {
|
||||
@ -131,4 +138,4 @@ let AclFormFactory = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default AclFormFactory;
|
||||
export default withContext(AclFormFactory, 'currentUser');
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import ReactAddons from 'react/addons';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
@ -257,7 +257,7 @@ let Form = React.createClass({
|
||||
},
|
||||
|
||||
renderChildren() {
|
||||
return ReactAddons.Children.map(this.props.children, (child, i) => {
|
||||
return React.Children.map(this.props.children, (child, i) => {
|
||||
if (child) {
|
||||
// Since refs will be overwritten by this functions return statement,
|
||||
// we still want to be able to define refs for nested `Form` or `Property`
|
||||
@ -355,7 +355,7 @@ let Form = React.createClass({
|
||||
let refToValidate = {};
|
||||
const property = this.refs[refName];
|
||||
const input = property.refs.input;
|
||||
const value = input.getDOMNode().value || input.state.value;
|
||||
const value = ReactDOM.findDOMNode(input).value || input.state.value;
|
||||
const { max,
|
||||
min,
|
||||
pattern,
|
||||
|
@ -8,14 +8,22 @@ import GlobalNotificationActions from '../../actions/global_notification_actions
|
||||
import Form from './form';
|
||||
import Property from './property';
|
||||
|
||||
import withContext from '../context/with_context';
|
||||
import { currentUserShape } from '../prop_types';
|
||||
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
import AppConstants from '../../constants/application_constants';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
let CopyrightAssociationForm = React.createClass({
|
||||
|
||||
const { bool } = React.PropTypes;
|
||||
|
||||
const CopyrightAssociationForm = React.createClass({
|
||||
propTypes: {
|
||||
currentUser: React.PropTypes.object.isRequired
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired,
|
||||
isLoggedIn: bool.isRequired
|
||||
},
|
||||
|
||||
handleSubmitSuccess() {
|
||||
@ -28,7 +36,7 @@ let CopyrightAssociationForm = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { currentUser } = this.props;
|
||||
const { currentUser, isLoggedIn } = this.props;
|
||||
const selectDefaultValue = ' -- ' + getLangText('select an association') + ' -- ';
|
||||
|
||||
let selectedState = selectDefaultValue;
|
||||
@ -38,7 +46,7 @@ let CopyrightAssociationForm = React.createClass({
|
||||
}
|
||||
}
|
||||
|
||||
if (currentUser.email) {
|
||||
if (isLoggedIn) {
|
||||
return (
|
||||
<Form
|
||||
ref='form'
|
||||
@ -77,4 +85,4 @@ let CopyrightAssociationForm = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default CopyrightAssociationForm;
|
||||
export default withContext(CopyrightAssociationForm, 'currentUser', 'isLoggedIn');
|
||||
|
@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||
@ -11,9 +10,11 @@ import UserActions from '../../actions/user_actions';
|
||||
import Form from './form';
|
||||
import Property from './property';
|
||||
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
import AppConstants from '../../constants/application_constants';
|
||||
import AscribeSpinner from '../ascribe_spinner';
|
||||
import withContext from '../context/with_context';
|
||||
import { locationShape } from '../prop_types';
|
||||
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
@ -22,11 +23,11 @@ let LoginForm = React.createClass({
|
||||
propTypes: {
|
||||
headerMessage: React.PropTypes.string,
|
||||
submitMessage: React.PropTypes.string,
|
||||
location: React.PropTypes.object,
|
||||
whitelabelName: React.PropTypes.string
|
||||
},
|
||||
whitelabelName: React.PropTypes.string,
|
||||
|
||||
mixins: [History],
|
||||
// Injected through HOCs
|
||||
location: locationShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
@ -93,4 +94,4 @@ let LoginForm = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default LoginForm;
|
||||
export default withContext(LoginForm, 'location');
|
||||
|
@ -8,23 +8,22 @@ import InputFineUploader from './input_fineuploader';
|
||||
|
||||
import FormSubmitButton from '../ascribe_buttons/form_submit_button';
|
||||
|
||||
import { FileStatus } from '../ascribe_uploader/react_s3_fine_uploader_utils';
|
||||
import UploadButton from '../ascribe_uploader/ascribe_upload_button/upload_button';
|
||||
|
||||
import AscribeSpinner from '../ascribe_spinner';
|
||||
import withContext from '../context/with_context';
|
||||
import { currentUserShape, locationShape } from '../prop_types';
|
||||
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
import AppConstants from '../../constants/application_constants';
|
||||
import { validationParts, validationTypes } from '../../constants/uploader_constants';
|
||||
|
||||
import { FileStatus, formSubmissionValidation } from '../ascribe_uploader/react_s3_fine_uploader_utils';
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
import { formSubmissionValidation } from '../ascribe_uploader/react_s3_fine_uploader_utils';
|
||||
|
||||
|
||||
let RegisterPieceForm = React.createClass({
|
||||
propTypes: {
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
|
||||
headerMessage: React.PropTypes.string,
|
||||
submitMessage: React.PropTypes.string,
|
||||
enableLocalHashing: React.PropTypes.bool,
|
||||
@ -36,11 +35,14 @@ let RegisterPieceForm = React.createClass({
|
||||
// For this form to work with SlideContainer, we sometimes have to disable it
|
||||
disabled: React.PropTypes.bool,
|
||||
|
||||
location: React.PropTypes.object,
|
||||
children: React.PropTypes.oneOfType([
|
||||
React.PropTypes.arrayOf(React.PropTypes.element),
|
||||
React.PropTypes.element
|
||||
])
|
||||
]),
|
||||
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
location: locationShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
getDefaultProps() {
|
||||
@ -128,7 +130,7 @@ let RegisterPieceForm = React.createClass({
|
||||
location,
|
||||
submitMessage } = this.props;
|
||||
|
||||
const profileHashLocally = currentUser && currentUser.profile ? currentUser.profile.hash_locally : false;
|
||||
const profileHashLocally = currentUser.profile ? currentUser.profile.hash_locally : false;
|
||||
const hashLocally = profileHashLocally && enableLocalHashing;
|
||||
|
||||
return (
|
||||
@ -238,4 +240,4 @@ let RegisterPieceForm = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default RegisterPieceForm;
|
||||
export default withContext(RegisterPieceForm, 'currentUser', 'location');
|
||||
|
@ -27,7 +27,6 @@ let RequestActionForm = React.createClass({
|
||||
React.PropTypes.array
|
||||
]).isRequired,
|
||||
|
||||
currentUser: React.PropTypes.object,
|
||||
handleSuccess: React.PropTypes.func
|
||||
},
|
||||
|
||||
@ -99,7 +98,6 @@ let RequestActionForm = React.createClass({
|
||||
availableAcls={{'acl_unconsign': true}}
|
||||
buttonAcceptClassName='inline pull-right btn-sm ascribe-margin-1px'
|
||||
pieceOrEditions={this.props.pieceOrEditions}
|
||||
currentUser={this.props.currentUser}
|
||||
handleSuccess={this.handleSuccess} />
|
||||
);
|
||||
} else if (this.props.notifications.action === 'loan_request') {
|
||||
@ -109,7 +107,6 @@ let RequestActionForm = React.createClass({
|
||||
buttonAcceptName="LOAN"
|
||||
buttonAcceptClassName='inline pull-right btn-sm ascribe-margin-1px'
|
||||
pieceOrEditions={this.props.pieceOrEditions}
|
||||
currentUser={this.props.currentUser}
|
||||
handleSuccess={this.handleSuccess} />
|
||||
);
|
||||
} else {
|
||||
|
@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import ContractListActions from '../../actions/contract_list_actions';
|
||||
import ContractListStore from '../../stores/contract_list_store';
|
||||
@ -13,19 +12,23 @@ import Form from './form';
|
||||
import Property from './property';
|
||||
import InputTextAreaToggable from './input_textarea_toggable';
|
||||
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
import AscribeSpinner from '../ascribe_spinner';
|
||||
import withContext from '../context/with_context';
|
||||
import { routerShape } from '../prop_types';
|
||||
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
import { mergeOptions } from '../../utils/general_utils';
|
||||
|
||||
|
||||
let SendContractAgreementForm = React.createClass({
|
||||
const SendContractAgreementForm = React.createClass({
|
||||
propTypes: {
|
||||
handleSuccess: React.PropTypes.func
|
||||
},
|
||||
handleSuccess: React.PropTypes.func,
|
||||
|
||||
mixins: [History],
|
||||
// Injected through HOCs
|
||||
router: routerShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return mergeOptions(
|
||||
@ -57,7 +60,7 @@ let SendContractAgreementForm = React.createClass({
|
||||
const notification = new GlobalNotificationModel(getLangText('Contract agreement sent'), 'success', 10000);
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
|
||||
this.history.push('/collection');
|
||||
this.props.router.push('/collection');
|
||||
},
|
||||
|
||||
getFormData() {
|
||||
@ -151,4 +154,4 @@ let SendContractAgreementForm = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default SendContractAgreementForm;
|
||||
export default withContext(SendContractAgreementForm, 'router');
|
||||
|
@ -21,7 +21,6 @@ let ShareForm = React.createClass({
|
||||
id: React.PropTypes.object,
|
||||
message: React.PropTypes.string,
|
||||
editions: React.PropTypes.array,
|
||||
currentUser: React.PropTypes.object,
|
||||
handleSuccess: React.PropTypes.func
|
||||
},
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||
@ -12,8 +11,11 @@ import Form from './form';
|
||||
import Property from './property';
|
||||
import InputCheckbox from './input_checkbox';
|
||||
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
import AscribeSpinner from '../ascribe_spinner';
|
||||
import withContext from '../context/with_context';
|
||||
import { locationShape } from '../prop_types';
|
||||
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
@ -23,16 +25,16 @@ let SignupForm = React.createClass({
|
||||
headerMessage: React.PropTypes.string,
|
||||
submitMessage: React.PropTypes.string,
|
||||
handleSuccess: React.PropTypes.func,
|
||||
location: React.PropTypes.object,
|
||||
children: React.PropTypes.oneOfType([
|
||||
React.PropTypes.arrayOf(React.PropTypes.element),
|
||||
React.PropTypes.element,
|
||||
React.PropTypes.string
|
||||
]),
|
||||
whitelabelName: React.PropTypes.string
|
||||
},
|
||||
whitelabelName: React.PropTypes.string,
|
||||
|
||||
mixins: [History],
|
||||
// Injected through HOCs
|
||||
isLoggedIn: locationShape.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
@ -132,4 +134,4 @@ let SignupForm = React.createClass({
|
||||
});
|
||||
|
||||
|
||||
export default SignupForm;
|
||||
export default withContext(SignupForm, 'location');
|
||||
|
@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
/**
|
||||
* This component can be used as a custom input element for form properties.
|
||||
@ -71,7 +72,7 @@ let InputCheckbox = React.createClass({
|
||||
}
|
||||
|
||||
// On every change, we're inversing the input's value
|
||||
let inverseValue = !this.refs.checkbox.getDOMNode().checked;
|
||||
let inverseValue = !ReactDOM.findDOMNode(this.refs.checkbox).checked;
|
||||
|
||||
// pass it to the state
|
||||
this.setState({value: inverseValue});
|
||||
|
@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react/addons';
|
||||
import React from 'react';
|
||||
import update from 'react-addons-update';
|
||||
|
||||
import InputCheckbox from './input_checkbox';
|
||||
|
||||
@ -101,7 +102,7 @@ const InputContractAgreementCheckbox = React.createClass({
|
||||
// so the parent `Property` is able to get the correct value of this component
|
||||
// when the `Form` queries it.
|
||||
this.setState({
|
||||
value: React.addons.update(this.state.value, {
|
||||
value: update(this.state.value, {
|
||||
terms: { $set: event.target.value }
|
||||
})
|
||||
});
|
||||
|
@ -11,19 +11,17 @@ let ListRequestActions = React.createClass({
|
||||
React.PropTypes.array
|
||||
]).isRequired,
|
||||
|
||||
currentUser: React.PropTypes.object,
|
||||
handleSuccess: React.PropTypes.func
|
||||
},
|
||||
|
||||
render () {
|
||||
const { currentUser, handleSuccess, notifications, pieceOrEditions } = this.props;
|
||||
const { handleSuccess, notifications, pieceOrEditions } = this.props;
|
||||
|
||||
if (notifications.length) {
|
||||
return (
|
||||
<div>
|
||||
{notifications.map((notification) =>
|
||||
<RequestActionForm
|
||||
currentUser={currentUser}
|
||||
handleSuccess={handleSuccess}
|
||||
notifications={notification}
|
||||
pieceOrEditions={pieceOrEditions} />
|
||||
|
@ -1,14 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import ReactAddons from 'react/addons';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import Panel from 'react-bootstrap/lib/Panel';
|
||||
|
||||
import AppConstants from '../../constants/application_constants';
|
||||
|
||||
import { mergeOptions } from '../../utils/general_utils';
|
||||
|
||||
|
||||
const { bool, element, string, oneOfType, func, object, arrayOf } = React.PropTypes;
|
||||
|
||||
@ -101,9 +99,9 @@ const Property = React.createClass({
|
||||
// In order to set this.state.value from another component
|
||||
// the state of value should only be set if its not undefined and
|
||||
// actually references something
|
||||
if(childInput && typeof childInput.getDOMNode().value !== 'undefined') {
|
||||
if(childInput && typeof ReactDOM.findDOMNode(childInput).value !== 'undefined') {
|
||||
this.setState({
|
||||
value: childInput.getDOMNode().value
|
||||
value: ReactDOM.findDOMNode(childInput).value
|
||||
});
|
||||
|
||||
// When implementing custom input components, their value isn't exposed like the one
|
||||
@ -116,9 +114,9 @@ const Property = React.createClass({
|
||||
});
|
||||
}
|
||||
|
||||
if(!this.state.initialValue && childInput && childInput.props.defaultValue) {
|
||||
if(!this.state.initialValue && childInput && childInput.defaultValue) {
|
||||
this.setState({
|
||||
initialValue: childInput.props.defaultValue
|
||||
initialValue: childInput.defaultValue
|
||||
});
|
||||
}
|
||||
},
|
||||
@ -140,7 +138,7 @@ const Property = React.createClass({
|
||||
// Therefore we have to make sure only to reset the initial value
|
||||
// of HTML inputs (which we determine by checking if there 'type' attribute matches
|
||||
// the ones included in AppConstants.possibleInputTypes).
|
||||
let inputDOMNode = input.getDOMNode();
|
||||
let inputDOMNode = ReactDOM.findDOMNode(input);
|
||||
if(inputDOMNode.type && typeof inputDOMNode.type === 'string' &&
|
||||
AppConstants.possibleInputTypes.indexOf(inputDOMNode.type.toLowerCase()) > -1) {
|
||||
inputDOMNode.value = this.state.initialValue;
|
||||
@ -180,10 +178,10 @@ const Property = React.createClass({
|
||||
// skip the focus of non-input elements
|
||||
let nonInputHTMLElements = ['pre', 'div'];
|
||||
if (this.refs.input &&
|
||||
nonInputHTMLElements.indexOf(this.refs.input.getDOMNode().nodeName.toLowerCase()) > -1 ) {
|
||||
nonInputHTMLElements.indexOf(ReactDOM.findDOMNode(this.refs.input).nodeName.toLowerCase()) > -1 ) {
|
||||
return;
|
||||
}
|
||||
this.refs.input.getDOMNode().focus();
|
||||
ReactDOM.findDOMNode(this.refs.input).focus();
|
||||
this.setState({
|
||||
isFocused: true
|
||||
});
|
||||
@ -205,7 +203,7 @@ const Property = React.createClass({
|
||||
errors: null,
|
||||
|
||||
// also update initialValue in case of the user updating and canceling its actions again
|
||||
initialValue: this.refs.input.getDOMNode().value
|
||||
initialValue: ReactDOM.findDOMNode(this.refs.input).value
|
||||
});
|
||||
},
|
||||
|
||||
@ -261,7 +259,7 @@ const Property = React.createClass({
|
||||
// Input's props should only be cloned and propagated down the tree,
|
||||
// if the component is actually being shown (!== 'expanded === false')
|
||||
if((this.state.expanded && this.props.checkboxLabel) || !this.props.checkboxLabel) {
|
||||
return ReactAddons.Children.map(this.props.children, (child) => {
|
||||
return React.Children.map(this.props.children, (child) => {
|
||||
// Since refs will be overriden by this functions return statement,
|
||||
// we still want to be able to define refs for nested `Form` or `Property`
|
||||
// children, which is why we're upfront simply invoking the callback-ref-
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import Link from 'react-router/es6/Link';
|
||||
|
||||
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
@ -1,66 +1,39 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
|
||||
let ActionPanel = React.createClass({
|
||||
propTypes: {
|
||||
title: React.PropTypes.string,
|
||||
buttons: React.PropTypes.element,
|
||||
content: React.PropTypes.oneOfType([
|
||||
React.PropTypes.string,
|
||||
React.PropTypes.element
|
||||
]),
|
||||
buttons: React.PropTypes.element,
|
||||
onClick: React.PropTypes.func,
|
||||
ignoreFocus: React.PropTypes.bool,
|
||||
|
||||
leftColumnWidth: React.PropTypes.string,
|
||||
onClick: React.PropTypes.func,
|
||||
rightColumnWidth: React.PropTypes.string
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
isFocused: false
|
||||
};
|
||||
},
|
||||
|
||||
handleFocus() {
|
||||
// if ignoreFocus (bool) is defined, then just ignore focusing on
|
||||
// the property and input
|
||||
if(this.props.ignoreFocus) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if onClick is defined from the outside,
|
||||
// just call it
|
||||
if(this.props.onClick) {
|
||||
this.props.onClick();
|
||||
}
|
||||
|
||||
this.refs.input.getDOMNode().focus();
|
||||
this.setState({
|
||||
isFocused: true
|
||||
});
|
||||
},
|
||||
|
||||
render() {
|
||||
|
||||
let { leftColumnWidth, rightColumnWidth } = this.props;
|
||||
const { buttons, content, leftColumnWidth, onClick, rightColumnWidth } = this.props;
|
||||
|
||||
return (
|
||||
<div className={classnames('ascribe-panel-wrapper', {'is-focused': this.state.isFocused})}>
|
||||
<div
|
||||
className={'ascribe-panel-wrapper'}
|
||||
onClick={onClick}>
|
||||
<div
|
||||
className="ascribe-panel-table"
|
||||
style={{width: leftColumnWidth}}>
|
||||
<div className="ascribe-panel-content">
|
||||
{this.props.content}
|
||||
{content}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="ascribe-panel-table"
|
||||
style={{width: rightColumnWidth}}>
|
||||
<div className="ascribe-panel-content">
|
||||
{this.props.buttons}
|
||||
{buttons}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,15 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { RouteContext } from 'react-router';
|
||||
import history from '../../history';
|
||||
|
||||
import UserStore from '../../stores/user_store';
|
||||
|
||||
import withContext from '../context/with_context';
|
||||
import { currentUserShape, locationShape, routerShape, whitelabelShape } from '../prop_types';
|
||||
|
||||
import AppConstants from '../../constants/application_constants';
|
||||
|
||||
|
||||
const { object } = React.PropTypes;
|
||||
const { bool, object } = React.PropTypes;
|
||||
const WHEN_ENUM = ['loggedIn', 'loggedOut'];
|
||||
|
||||
/**
|
||||
@ -25,7 +26,7 @@ export function AuthRedirect({ to, when }) {
|
||||
throw new Error(`"when" must be one of: [${whenValues}] got "${when}" instead`);
|
||||
}
|
||||
|
||||
return function(currentUser, query) {
|
||||
return function redirectRoute(router, { query }, { isLoggedIn }) {
|
||||
const { redirectAuthenticated, redirect } = query;
|
||||
|
||||
// The user of this handler specifies with `when`, what kind of status
|
||||
@ -34,19 +35,18 @@ export function AuthRedirect({ to, when }) {
|
||||
//
|
||||
// So if when === 'loggedIn', we're checking if the user is logged in (and
|
||||
// vice versa)
|
||||
const isLoggedIn = Object.keys(currentUser).length && currentUser.email;
|
||||
const exprToValidate = when === 'loggedIn' ? isLoggedIn : !isLoggedIn;
|
||||
|
||||
// and redirect if `true`.
|
||||
if (exprToValidate) {
|
||||
window.setTimeout(() => history.replace({ query, pathname: to }));
|
||||
window.setTimeout(() => router.replace({ query, pathname: to }));
|
||||
return true;
|
||||
|
||||
// Otherwise there can also be the case that the backend
|
||||
// wants to redirect the user to a specific route when the user is logged out already
|
||||
} else if (!exprToValidate && when === 'loggedIn' && redirect) {
|
||||
delete query.redirect;
|
||||
window.setTimeout(() => history.replace({ query, pathname: '/' + redirect }));
|
||||
window.setTimeout(() => router.replace({ query, pathname: `/${redirect}` }));
|
||||
return true;
|
||||
|
||||
} else if (!exprToValidate && when === 'loggedOut' && redirectAuthenticated) {
|
||||
@ -77,22 +77,19 @@ export function AuthRedirect({ to, when }) {
|
||||
*/
|
||||
export function ProxyHandler(...redirectFunctions) {
|
||||
return (Component) => {
|
||||
return React.createClass({
|
||||
displayName: 'ProxyHandler',
|
||||
|
||||
// Don't worry about shadowing the HOC here; using a declaration like this allows
|
||||
// babel-plugin-react-display-name to automatically generate the displayName.
|
||||
// eslint-disable-next-line no-shadow
|
||||
const ProxyHandler = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from AscribeApp, after the routes have been initialized
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object,
|
||||
|
||||
// Provided from router
|
||||
location: object
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired,
|
||||
isLoggedIn: bool.isRequired,
|
||||
location: locationShape.isRequired,
|
||||
router: routerShape.isRequired,
|
||||
whitelabel: whitelabelShape.isRequired
|
||||
},
|
||||
|
||||
// We need insert `RouteContext` here in order to be able
|
||||
// to use the `Lifecycle` widget in further down nested components
|
||||
mixins: [RouteContext],
|
||||
|
||||
componentDidMount() {
|
||||
this.evaluateRedirectFunctions();
|
||||
},
|
||||
@ -102,15 +99,15 @@ export function ProxyHandler(...redirectFunctions) {
|
||||
},
|
||||
|
||||
evaluateRedirectFunctions(props = this.props) {
|
||||
const { currentUser, location: { query } } = props;
|
||||
const { currentUser, isLoggedIn, location, router, whitelabel } = props;
|
||||
|
||||
if (UserStore.hasLoaded() && !UserStore.isLoading()) {
|
||||
const context = { currentUser, isLoggedIn, whitelabel };
|
||||
|
||||
for (let i = 0; i < redirectFunctions.length; i++) {
|
||||
// if a redirectFunction redirects the user,
|
||||
// it should return `true` and therefore
|
||||
// stop/avoid the execution of all functions
|
||||
// that follow
|
||||
if (redirectFunctions[i](currentUser, query)) {
|
||||
// if a redirectFunction redirects the user, it should return `true` and
|
||||
// therefore stop/avoid the execution of all functions that follow
|
||||
if (redirectFunctions[i](router, location, context)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -123,5 +120,12 @@ export function ProxyHandler(...redirectFunctions) {
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return withContext(ProxyHandler,
|
||||
'currentUser',
|
||||
'isLoggedIn',
|
||||
'location',
|
||||
'router',
|
||||
'whitelabel');
|
||||
};
|
||||
}
|
||||
|
@ -5,25 +5,29 @@ import React from 'react';
|
||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||
|
||||
import CopyrightAssociationForm from '../ascribe_forms/form_copyright_association';
|
||||
import Form from '../ascribe_forms/form';
|
||||
import Property from '../ascribe_forms/property';
|
||||
import InputCheckbox from '../ascribe_forms/input_checkbox';
|
||||
import Property from '../ascribe_forms/property';
|
||||
|
||||
import CollapsibleParagraph from '../ascribe_collapsible/collapsible_paragraph';
|
||||
|
||||
import AclProxy from '../acl_proxy';
|
||||
|
||||
import CopyrightAssociationForm from '../ascribe_forms/form_copyright_association';
|
||||
import AscribeSpinner from '../ascribe_spinner';
|
||||
import withContext from '../context/with_context';
|
||||
import { currentUserShape, whitelabelShape } from '../prop_types';
|
||||
|
||||
import ApiUrls from '../../constants/api_urls';
|
||||
import AscribeSpinner from '../ascribe_spinner';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
let AccountSettings = React.createClass({
|
||||
propTypes: {
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
loadUser: React.PropTypes.func.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired
|
||||
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
whitelabel: whitelabelShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
handleSuccess() {
|
||||
@ -100,7 +104,7 @@ let AccountSettings = React.createClass({
|
||||
<AclProxy
|
||||
aclObject={whitelabel}
|
||||
aclName="acl_view_settings_copyright_association">
|
||||
<CopyrightAssociationForm currentUser={currentUser} />
|
||||
<CopyrightAssociationForm />
|
||||
</AclProxy>
|
||||
{profile}
|
||||
</CollapsibleParagraph>
|
||||
@ -108,4 +112,4 @@ let AccountSettings = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default AccountSettings;
|
||||
export default withContext(AccountSettings, 'currentUser', 'whitelabel');
|
||||
|
@ -2,33 +2,33 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import CollapsibleParagraph from '../ascribe_collapsible/collapsible_paragraph';
|
||||
import CreateContractForm from '../ascribe_forms/form_create_contract';
|
||||
|
||||
import ContractListStore from '../../stores/contract_list_store';
|
||||
import ContractListActions from '../../actions/contract_list_actions';
|
||||
|
||||
import ActionPanel from '../ascribe_panel/action_panel';
|
||||
import ContractSettingsUpdateButton from './contract_settings_update_button';
|
||||
|
||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||
|
||||
import AclProxy from '../acl_proxy';
|
||||
import ContractSettingsUpdateButton from './contract_settings_update_button';
|
||||
|
||||
import CollapsibleParagraph from '../ascribe_collapsible/collapsible_paragraph';
|
||||
import CreateContractForm from '../ascribe_forms/form_create_contract';
|
||||
|
||||
import ActionPanel from '../ascribe_panel/action_panel';
|
||||
|
||||
import AclProxy from '../acl_proxy';
|
||||
import withContext from '../context/with_context';
|
||||
import { currentUserShape, whitelabelShape } from '../prop_types';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
import { setDocumentTitle } from '../../utils/dom_utils';
|
||||
import { truncateTextAtCharIndex } from '../../utils/general_utils';
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
|
||||
let ContractSettings = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from AscribeApp
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired,
|
||||
whitelabel: whitelabelShape.isRequired
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
@ -72,7 +72,7 @@ let ContractSettings = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { currentUser, location, whitelabel } = this.props;
|
||||
const { currentUser, whitelabel } = this.props;
|
||||
const publicContracts = this.getPublicContracts();
|
||||
const privateContracts = this.getPrivateContracts();
|
||||
let createPublicContractForm = null;
|
||||
@ -180,4 +180,4 @@ let ContractSettings = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default ContractSettings;
|
||||
export default withContext(ContractSettings, 'currentUser', 'whitelabel');
|
||||
|
@ -5,15 +5,16 @@ import React from 'react';
|
||||
import UserActions from '../../actions/user_actions';
|
||||
|
||||
import AccountSettings from './account_settings';
|
||||
import ApiSettings from './api_settings';
|
||||
import BitcoinWalletSettings from './bitcoin_wallet_settings';
|
||||
import APISettings from './api_settings';
|
||||
import WebhookSettings from './webhook_settings';
|
||||
|
||||
import AclProxy from '../acl_proxy';
|
||||
import withContext from '../context/with_context';
|
||||
import { whitelabelShape } from '../prop_types';
|
||||
|
||||
import { mergeOptions } from '../../utils/general_utils';
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
import { setDocumentTitle } from '../../utils/dom_utils';
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
|
||||
let SettingsContainer = React.createClass({
|
||||
@ -23,12 +24,9 @@ let SettingsContainer = React.createClass({
|
||||
React.PropTypes.element
|
||||
]),
|
||||
|
||||
// Provided from AscribeApp
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
isLoggedIn: React.PropTypes.bool.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
whitelabel: whitelabelShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
loadUser(invalidateCache) {
|
||||
@ -36,22 +34,19 @@ let SettingsContainer = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { children, currentUser, whitelabel } = this.props;
|
||||
const { children, isLoggedIn, whitelabel } = this.props;
|
||||
|
||||
setDocumentTitle(getLangText('Account settings'));
|
||||
|
||||
if (currentUser.username) {
|
||||
if (isLoggedIn) {
|
||||
return (
|
||||
<div className="settings-container">
|
||||
<AccountSettings
|
||||
currentUser={currentUser}
|
||||
loadUser={this.loadUser}
|
||||
whitelabel={whitelabel} />
|
||||
<AccountSettings loadUser={this.loadUser} />
|
||||
{children}
|
||||
<AclProxy
|
||||
aclObject={whitelabel}
|
||||
aclName="acl_view_settings_api">
|
||||
<APISettings />
|
||||
<ApiSettings />
|
||||
</AclProxy>
|
||||
<WebhookSettings />
|
||||
<AclProxy
|
||||
@ -66,4 +61,4 @@ let SettingsContainer = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default SettingsContainer;
|
||||
export default withContext(SettingsContainer, 'isLoggedIn', 'whitelabel');
|
||||
|
@ -1,32 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react/addons';
|
||||
import { History, Lifecycle } from 'react-router';
|
||||
import React from 'react';
|
||||
|
||||
import SlidesContainerBreadcrumbs from './slides_container_breadcrumbs';
|
||||
|
||||
import withContext from '../context/with_context';
|
||||
import { locationShape, routerShape } from '../prop_types';
|
||||
|
||||
|
||||
const { arrayOf, element, bool, shape, string, object } = React.PropTypes;
|
||||
|
||||
const SlidesContainer = React.createClass({
|
||||
propTypes: {
|
||||
children: arrayOf(element),
|
||||
forwardProcess: bool.isRequired,
|
||||
|
||||
children: arrayOf(element),
|
||||
glyphiconClassNames: shape({
|
||||
pending: string,
|
||||
complete: string
|
||||
}),
|
||||
location: object,
|
||||
pageExitWarning: string
|
||||
},
|
||||
|
||||
mixins: [History, Lifecycle],
|
||||
// Injected through HOCs
|
||||
location: locationShape.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
router: routerShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
containerWidth: 0,
|
||||
pageExitWarning: null
|
||||
containerWidth: 0
|
||||
};
|
||||
},
|
||||
|
||||
@ -37,20 +38,17 @@ const SlidesContainer = React.createClass({
|
||||
|
||||
// Initially, we need to dispatch 'resize' once to render correctly
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('resize', this.handleContainerResize);
|
||||
},
|
||||
|
||||
routerWillLeave() {
|
||||
return this.props.pageExitWarning;
|
||||
},
|
||||
|
||||
handleContainerResize() {
|
||||
this.setState({
|
||||
// +30 to get rid of the padding of the container which is 15px + 15px left and right
|
||||
containerWidth: this.refs.containerWrapper.getDOMNode().offsetWidth + 30
|
||||
containerWidth: this.refs.containerWrapper.offsetWidth + 30
|
||||
});
|
||||
},
|
||||
|
||||
@ -61,10 +59,10 @@ const SlidesContainer = React.createClass({
|
||||
},
|
||||
|
||||
setSlideNum(nextSlideNum, additionalQueryParams = {}) {
|
||||
const { location: { pathname } } = this.props;
|
||||
const query = Object.assign({}, this.props.location.query, additionalQueryParams, { slide_num: nextSlideNum });
|
||||
const { location: { pathname, query }, router } = this.props;
|
||||
const slideQuery = Object.assign({}, query, additionalQueryParams, { slide_num: nextSlideNum });
|
||||
|
||||
this.history.push({ pathname, query });
|
||||
router.push({ pathname, query: slideQuery });
|
||||
},
|
||||
|
||||
// breadcrumbs are defined as attributes of the slides.
|
||||
@ -120,7 +118,7 @@ const SlidesContainer = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
// Since we need to give the slides a width, we need to call ReactAddons.addons.cloneWithProps
|
||||
// Since we need to give the slides a width, we need to call React.cloneElement
|
||||
// Also, a key is nice to have!
|
||||
renderChildren() {
|
||||
const startFrom = parseInt(this.props.location.query.start_from, 10) || -1;
|
||||
@ -129,7 +127,7 @@ const SlidesContainer = React.createClass({
|
||||
// since the default parameter of startFrom is -1, we do not need to check
|
||||
// if its actually present in the url bar, as it will just not match
|
||||
if(child && i >= startFrom) {
|
||||
return React.addons.cloneWithProps(child, {
|
||||
return React.cloneElement(child, {
|
||||
className: 'ascribe-slide',
|
||||
style: {
|
||||
width: this.state.containerWidth
|
||||
@ -179,4 +177,4 @@ const SlidesContainer = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default SlidesContainer;
|
||||
export default withContext(SlidesContainer, 'location', 'router');
|
||||
|
@ -50,7 +50,7 @@ let FacebookShareButton = React.createClass({
|
||||
.inject(AppConstants.facebook.sdkUrl)
|
||||
.then(() => {
|
||||
if (this.state.loaded) {
|
||||
FB.XFBML.parse(this.refs.fbShareButton.getDOMNode().parent)
|
||||
window.FB.XFBML.parse(this.refs.fbShareButton.parent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -31,7 +31,7 @@ let TwitterShareButton = React.createClass({
|
||||
loadTwitterButton() {
|
||||
const { count, counturl, hashtags, size, text, url, via } = this.props;
|
||||
|
||||
twttr.widgets.createShareButton(url, this.refs.twitterShareButton.getDOMNode(), {
|
||||
window.twttr.widgets.createShareButton(url, this.refs.twitterShareButton, {
|
||||
count,
|
||||
counturl,
|
||||
hashtags,
|
||||
|
@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import ReactAddons from 'react/addons';
|
||||
|
||||
import TableHeader from './table_header';
|
||||
import { ColumnModel } from './models/table_models';
|
||||
@ -20,8 +19,8 @@ let Table = React.createClass({
|
||||
},
|
||||
|
||||
renderChildren() {
|
||||
return ReactAddons.Children.map(this.props.children, (child, i) => {
|
||||
return ReactAddons.addons.cloneWithProps(child, {
|
||||
return React.Children.map(this.props.children, (child, i) => {
|
||||
return React.cloneElement(child, {
|
||||
columnList: this.props.columnList,
|
||||
columnContent: this.props.itemList[i],
|
||||
key: i
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import Link from 'react-router/es6/Link';
|
||||
|
||||
import { ColumnModel } from './models/table_models';
|
||||
|
||||
|
@ -55,7 +55,7 @@ let FileDragAndDrop = React.createClass({
|
||||
},
|
||||
|
||||
clearSelection() {
|
||||
this.refs.fileSelector.getDOMNode().value = '';
|
||||
this.refs.fileSelector.value = '';
|
||||
},
|
||||
|
||||
handleDragOver(event) {
|
||||
@ -132,7 +132,7 @@ let FileDragAndDrop = React.createClass({
|
||||
evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null);
|
||||
}
|
||||
|
||||
this.refs.fileSelector.getDOMNode().dispatchEvent(evt);
|
||||
this.refs.fileSelector.dispatchEvent(evt);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -34,11 +34,13 @@ let FileDragAndDropDialog = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { enableLocalHashing,
|
||||
const {
|
||||
enableLocalHashing,
|
||||
fileClassToUpload,
|
||||
multipleFiles,
|
||||
onClick,
|
||||
uploadMethod } = this.props;
|
||||
uploadMethod
|
||||
} = this.props;
|
||||
let dialogElement;
|
||||
|
||||
if (enableLocalHashing && !uploadMethod) {
|
||||
@ -66,9 +68,7 @@ let FileDragAndDropDialog = React.createClass({
|
||||
{getLangText('Hash your work')}
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
<span> {getLangText('or')} </span>
|
||||
|
||||
<Link
|
||||
to={`/${window.location.pathname.split('/').pop()}`}
|
||||
query={queryParamsUpload}>
|
||||
|
@ -66,7 +66,7 @@ export default function UploadButton({ className = 'btn btn-default btn-sm', sho
|
||||
},
|
||||
|
||||
clearSelection() {
|
||||
this.refs.fileSelector.getDOMNode().value = '';
|
||||
this.refs.fileSelector.value = '';
|
||||
},
|
||||
|
||||
handleOnClick() {
|
||||
@ -88,7 +88,7 @@ export default function UploadButton({ className = 'btn btn-default btn-sm', sho
|
||||
evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null);
|
||||
}
|
||||
evt.stopPropagation();
|
||||
this.refs.fileSelector.getDOMNode().dispatchEvent(evt);
|
||||
this.refs.fileSelector.dispatchEvent(evt);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react/addons';
|
||||
import React from 'react';
|
||||
import update from 'react-addons-update';
|
||||
// FIXME: remove once using react-components
|
||||
import fineUploader from 'exports?qq!./vendor/s3.fine-uploader';
|
||||
import Q from 'q';
|
||||
@ -536,7 +537,7 @@ const ReactS3FineUploader = React.createClass({
|
||||
|
||||
changeSet.status = { $set: status };
|
||||
|
||||
let filesToUpload = React.addons.update(this.state.filesToUpload, { [fileId]: changeSet });
|
||||
let filesToUpload = update(this.state.filesToUpload, { [fileId]: changeSet });
|
||||
|
||||
this.setState({ filesToUpload }, resolve);
|
||||
});
|
||||
@ -547,7 +548,7 @@ const ReactS3FineUploader = React.createClass({
|
||||
|
||||
if(fileId < filesToUpload.length) {
|
||||
const changeSet = { $set: url };
|
||||
const newFilesToUpload = React.addons.update(filesToUpload, {
|
||||
const newFilesToUpload = update(filesToUpload, {
|
||||
[fileId]: { thumbnailUrl: changeSet }
|
||||
});
|
||||
|
||||
@ -574,7 +575,7 @@ const ReactS3FineUploader = React.createClass({
|
||||
completed: false
|
||||
};
|
||||
|
||||
let startedChunks = React.addons.update(this.state.startedChunks, { $set: chunks });
|
||||
let startedChunks = update(this.state.startedChunks, { $set: chunks });
|
||||
|
||||
this.setState({ startedChunks });
|
||||
},
|
||||
@ -588,7 +589,7 @@ const ReactS3FineUploader = React.createClass({
|
||||
chunks[chunkKey].responseJson = responseJson;
|
||||
chunks[chunkKey].xhr = xhr;
|
||||
|
||||
let startedChunks = React.addons.update(this.state.startedChunks, { $set: chunks });
|
||||
let startedChunks = update(this.state.startedChunks, { $set: chunks });
|
||||
|
||||
this.setState({ startedChunks });
|
||||
}
|
||||
@ -619,7 +620,7 @@ const ReactS3FineUploader = React.createClass({
|
||||
files[id].status = FileStatus.UPLOAD_SUCCESSFUL;
|
||||
files[id].key = this.state.uploader.getKey(id);
|
||||
|
||||
let filesToUpload = React.addons.update(this.state.filesToUpload, { $set: files });
|
||||
let filesToUpload = update(this.state.filesToUpload, { $set: files });
|
||||
this.setState({ filesToUpload });
|
||||
|
||||
// Only after the blob has been created server-side, we can make the form submittable.
|
||||
@ -667,7 +668,7 @@ const ReactS3FineUploader = React.createClass({
|
||||
if (!this.state.errorState.errorClass) {
|
||||
notificationMessage = errorNotificationMessage;
|
||||
|
||||
const errorState = React.addons.update(this.state.errorState, {
|
||||
const errorState = update(this.state.errorState, {
|
||||
errorClass: {
|
||||
$set: this.getUploadErrorClass({
|
||||
reason: errorReason,
|
||||
@ -720,7 +721,7 @@ const ReactS3FineUploader = React.createClass({
|
||||
},
|
||||
|
||||
onProgress(id, name, uploadedBytes, totalBytes) {
|
||||
let filesToUpload = React.addons.update(this.state.filesToUpload, {
|
||||
let filesToUpload = update(this.state.filesToUpload, {
|
||||
[id]: {
|
||||
progress: { $set: (uploadedBytes / totalBytes) * 100}
|
||||
}
|
||||
@ -747,7 +748,7 @@ const ReactS3FineUploader = React.createClass({
|
||||
return file;
|
||||
});
|
||||
|
||||
let filesToUpload = React.addons.update(this.state.filesToUpload, {$set: updatedFilesToUpload});
|
||||
let filesToUpload = update(this.state.filesToUpload, {$set: updatedFilesToUpload});
|
||||
|
||||
this.setState({filesToUpload });
|
||||
} else {
|
||||
@ -846,7 +847,7 @@ const ReactS3FineUploader = React.createClass({
|
||||
|
||||
fileIds.forEach((fileId) => {
|
||||
this.state.uploader.retry(fileId);
|
||||
filesToUpload = React.addons.update(filesToUpload, { [fileId]: { status: { $set: FileStatus.UPLOADING } } });
|
||||
filesToUpload = update(filesToUpload, { [fileId]: { status: { $set: FileStatus.UPLOADING } } });
|
||||
});
|
||||
|
||||
this.setState({
|
||||
@ -1041,7 +1042,7 @@ const ReactS3FineUploader = React.createClass({
|
||||
}
|
||||
|
||||
// set the new file array
|
||||
let filesToUpload = React.addons.update(this.state.filesToUpload, { $set: oldAndNewFiles });
|
||||
let filesToUpload = update(this.state.filesToUpload, { $set: oldAndNewFiles });
|
||||
|
||||
this.setState({ filesToUpload }, () => {
|
||||
// when files have been dropped or selected by a user, we want to propagate that
|
||||
|
@ -6,24 +6,23 @@ import GlobalNotificationModel from '../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../actions/global_notification_actions';
|
||||
|
||||
import Form from './ascribe_forms/form';
|
||||
import Property from './ascribe_forms/property';
|
||||
import InputTextAreaToggable from './ascribe_forms/input_textarea_toggable';
|
||||
import Property from './ascribe_forms/property';
|
||||
|
||||
import AscribeSpinner from './ascribe_spinner';
|
||||
import withContext from './context/with_context';
|
||||
import { locationShape } from './prop_types';
|
||||
|
||||
import ApiUrls from '../constants/api_urls';
|
||||
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
import { setDocumentTitle } from '../utils/dom_utils';
|
||||
|
||||
|
||||
let CoaVerifyContainer = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from AscribeApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
location: locationShape.isRequired
|
||||
},
|
||||
|
||||
render() {
|
||||
@ -117,5 +116,4 @@ let CoaVerifyForm = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default CoaVerifyContainer;
|
||||
export default withContext(CoaVerifyContainer, 'location');
|
||||
|
138
js/components/context/with_context.js
Normal file
138
js/components/context/with_context.js
Normal file
@ -0,0 +1,138 @@
|
||||
import React from 'react';
|
||||
import { currentUserShape, locationShape, routerShape, whitelabelShape } from '../prop_types';
|
||||
|
||||
import { selectFromObject } from '../../utils/general_utils';
|
||||
import { getDisplayName } from '../../utils/react_utils';
|
||||
|
||||
/**
|
||||
* ContextPropDefinitions
|
||||
* ======================
|
||||
* contextType definitions for `contextProp`s.
|
||||
*
|
||||
* Each definition is of the form:
|
||||
*
|
||||
* contextProp = {
|
||||
* 'contextTypes': {
|
||||
* 'contextType': contextType used by the contextProp,
|
||||
* ...
|
||||
* },
|
||||
* transformToProps: (optional) function that will receive the contextTypes from the component's
|
||||
* context and should return an object containing the props to inject.
|
||||
* }
|
||||
*
|
||||
* In the common case where your `contextProp` maps directly to the `contextType` used
|
||||
* (eg. using `currentUser` as a `contextProp` to get the `currentUser` from context), you can omit
|
||||
* the object definition and simply assign the `contextType` to the `contextProp`:
|
||||
*
|
||||
* contextProp = contextType
|
||||
*
|
||||
* as opposed to:
|
||||
*
|
||||
* contextProp = {
|
||||
* 'contextTypes': {
|
||||
* contextProp: contextType
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
const ContextPropDefinitions = {
|
||||
currentUser: currentUserShape.isRequired,
|
||||
isLoggedIn: {
|
||||
contextTypes: {
|
||||
currentUser: currentUserShape.isRequired
|
||||
},
|
||||
transformToProps: ({ currentUser }) => ({ isLoggedIn: !!currentUser.email })
|
||||
},
|
||||
location: locationShape.isRequired,
|
||||
router: routerShape.isRequired,
|
||||
whitelabel: whitelabelShape.isRequired
|
||||
};
|
||||
|
||||
// Expand any shortform definitions in ContextPropDefinitions into a normalized form that's
|
||||
// easier for withContext to work with
|
||||
Object.entries(ContextPropDefinitions).forEach(([prop, def]) => {
|
||||
if (!def.hasOwnProperty('contextTypes')) {
|
||||
ContextPropDefinitions[prop] = {
|
||||
contextTypes: {
|
||||
[prop]: def
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Generalized version of react-router's `withRouter`.
|
||||
* This injects the given `contextProp`s from the WrappedComponent's context into the component as
|
||||
* a prop.
|
||||
*
|
||||
* Given `contextProp`s must have a matching definition in `ContextPropDefinitions`.
|
||||
*
|
||||
* @param {Component} WrappedComponent Component to inject context into
|
||||
* @param {...string} contextProps Argument list of `contextProp`s (that must be registered in
|
||||
* `ContextPropDefinitions`) to be injected into component as
|
||||
* props
|
||||
* @return {Component} Wrapped component
|
||||
*/
|
||||
export default function withContext(WrappedComponent, ...contextProps) {
|
||||
const wrappedComponentName = getDisplayName(WrappedComponent);
|
||||
|
||||
if (!contextProps.length) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`Used withContext on ${wrappedComponentName} without supplying any ` +
|
||||
"items to inject from the component's context. Ignoring...");
|
||||
}
|
||||
|
||||
return WrappedComponent;
|
||||
}
|
||||
|
||||
const contextTypes = contextProps.reduce((types, contextProp) => {
|
||||
const contextDef = ContextPropDefinitions[contextProp];
|
||||
|
||||
if (contextDef) {
|
||||
Object.assign(types, contextDef.contextTypes);
|
||||
} else if (process.env.NODE_ENV !== 'production') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`No context types were found for '${contextProp}' when adding context ` +
|
||||
`to ${wrappedComponentName}. Make sure to add the context information ` +
|
||||
'with_context.js.');
|
||||
}
|
||||
|
||||
return types;
|
||||
}, {});
|
||||
|
||||
const WithContext = (props, context) => {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
// Check if the expected context was available
|
||||
Object.keys(contextTypes).forEach((contextType) => {
|
||||
if (!context[contextType]) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`Expected '${contextType}' did not exist in ` +
|
||||
`${wrappedComponentName}'s context during mounting`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const injectedProps = Object.assign({}, ...contextProps.map((contextProp) => {
|
||||
const contextDef = ContextPropDefinitions[contextProp];
|
||||
|
||||
if (contextDef) {
|
||||
const contextForProp = selectFromObject(context, Object.keys(contextDef.contextTypes));
|
||||
return typeof contextDef.transformToProps === 'function'
|
||||
? contextDef.transformToProps(contextForProp)
|
||||
: contextForProp;
|
||||
} else {
|
||||
// Will be ignored by Object.assign()
|
||||
return undefined;
|
||||
}
|
||||
}));
|
||||
|
||||
return (
|
||||
<WrappedComponent {...props} {...injectedProps} />
|
||||
);
|
||||
};
|
||||
|
||||
WithContext.displayName = `WithContext(${wrappedComponentName}): [${contextProps.join(', ')}]`;
|
||||
WithContext.contextTypes = contextTypes;
|
||||
|
||||
return WithContext;
|
||||
}
|
@ -1,25 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import history from '../history';
|
||||
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
|
||||
|
||||
let ErrorNotFoundPage = React.createClass({
|
||||
const ErrorNotFoundPage = React.createClass({
|
||||
propTypes: {
|
||||
message: React.PropTypes.string,
|
||||
|
||||
// Provided from AscribeApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
},
|
||||
|
||||
mixins: [History],
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
message: getLangText("Oops, the page you are looking for doesn't exist.")
|
||||
@ -28,7 +18,7 @@ let ErrorNotFoundPage = React.createClass({
|
||||
|
||||
componentDidMount() {
|
||||
// The previous page, if any, is the second item in the locationQueue
|
||||
const { locationQueue: [ , previousPage ] } = this.history;
|
||||
const { locationQueue: [, previousPage] } = history;
|
||||
|
||||
if (previousPage) {
|
||||
console.logGlobal('Page not found', {
|
||||
|
@ -48,7 +48,7 @@ let GlobalNotification = React.createClass({
|
||||
|
||||
handleContainerResize() {
|
||||
this.setState({
|
||||
containerWidth: this.refs.notificationWrapper.getDOMNode().offsetWidth
|
||||
containerWidth: this.refs.notificationWrapper.offsetWidth
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -3,35 +3,35 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
import history from '../history';
|
||||
|
||||
import Nav from 'react-bootstrap/lib/Nav';
|
||||
import Navbar from 'react-bootstrap/lib/Navbar';
|
||||
import CollapsibleNav from 'react-bootstrap/lib/CollapsibleNav';
|
||||
import DropdownButton from 'react-bootstrap/lib/DropdownButton';
|
||||
import MenuItem from 'react-bootstrap/lib/MenuItem';
|
||||
import NavItem from 'react-bootstrap/lib/NavItem';
|
||||
|
||||
import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
|
||||
|
||||
import EventActions from '../actions/event_actions';
|
||||
|
||||
import PieceListStore from '../stores/piece_list_store';
|
||||
|
||||
import AclProxy from './acl_proxy';
|
||||
import withContext from './context/with_context';
|
||||
import HeaderNotifications from './header_notifications';
|
||||
import HeaderNotificationDebug from './header_notification_debug';
|
||||
import NavRoutesLinks from './nav_routes_links';
|
||||
import { currentUserShape, whitelabelShape } from './prop_types';
|
||||
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
import { constructHead } from '../utils/dom_utils';
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
|
||||
|
||||
let Header = React.createClass({
|
||||
propTypes: {
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
routes: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired
|
||||
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
isLoggedIn: React.PropTypes.bool.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
whitelabel: whitelabelShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
@ -42,16 +42,10 @@ let Header = React.createClass({
|
||||
// Listen to the piece list store, but don't fetch immediately to avoid
|
||||
// conflicts with routes that may need to wait to load the piece list
|
||||
PieceListStore.listen(this.onChange);
|
||||
|
||||
// react-bootstrap 0.25.1 has a bug in which it doesn't
|
||||
// close the mobile expanded navigation after a click by itself.
|
||||
// To get rid of this, we set the state of the component ourselves.
|
||||
history.listen(this.onRouteChange);
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
PieceListStore.unlisten(this.onChange);
|
||||
//history.unlisten(this.onRouteChange);
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
@ -116,24 +110,15 @@ let Header = React.createClass({
|
||||
this.refs.dropdownbutton.setDropdownState(false);
|
||||
},
|
||||
|
||||
// On route change, close expanded navbar again since react-bootstrap doesn't close
|
||||
// the collapsibleNav by itself on click. setState() isn't available on a ref so
|
||||
// doing this explicitly is the only way for now.
|
||||
onRouteChange() {
|
||||
if (this.refs.navbar) {
|
||||
this.refs.navbar.state.navExpanded = false;
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
const { currentUser, routes, whitelabel } = this.props;
|
||||
const { currentUser, isLoggedIn, routes, whitelabel } = this.props;
|
||||
const { unfilteredPieceListCount } = this.state;
|
||||
|
||||
let account;
|
||||
let signup;
|
||||
let navRoutesLinks;
|
||||
|
||||
if (currentUser.username) {
|
||||
if (isLoggedIn) {
|
||||
account = (
|
||||
<DropdownButton
|
||||
ref='dropdownbutton'
|
||||
@ -175,7 +160,7 @@ let Header = React.createClass({
|
||||
navRoutesLinks = (
|
||||
<NavRoutesLinks
|
||||
navbar
|
||||
right
|
||||
pullRight
|
||||
hasPieces={!!unfilteredPieceListCount}
|
||||
routes={routes}
|
||||
userAcl={currentUser.acl} />
|
||||
@ -201,26 +186,30 @@ let Header = React.createClass({
|
||||
<div>
|
||||
<Navbar
|
||||
ref="navbar"
|
||||
brand={this.getLogo()}
|
||||
toggleNavKey={0}
|
||||
fixedTop={true}
|
||||
className="hidden-print">
|
||||
<CollapsibleNav eventKey={0}>
|
||||
<Nav navbar left>
|
||||
<Navbar.Header>
|
||||
<Navbar.Brand>
|
||||
{this.getLogo()}
|
||||
</Navbar.Brand>
|
||||
</Navbar.Header>
|
||||
<Navbar.Collapse
|
||||
eventKey={0}>
|
||||
<Nav navbar pullLeft>
|
||||
<AclProxy
|
||||
aclObject={whitelabel}
|
||||
aclName="acl_view_powered_by">
|
||||
{this.getPoweredBy()}
|
||||
</AclProxy>
|
||||
</Nav>
|
||||
<Nav navbar right>
|
||||
<HeaderNotificationDebug show={false} />
|
||||
<Nav navbar pullRight>
|
||||
<HeaderNotificationDebug show={false}/>
|
||||
{account}
|
||||
{signup}
|
||||
</Nav>
|
||||
<HeaderNotifications currentUser={currentUser} />
|
||||
<HeaderNotifications />
|
||||
{navRoutesLinks}
|
||||
</CollapsibleNav>
|
||||
</Navbar.Collapse>
|
||||
</Navbar>
|
||||
<p className="ascribe-print-header visible-print">
|
||||
<span className="icon-ascribe-logo" />
|
||||
@ -230,4 +219,4 @@ let Header = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default Header;
|
||||
export default withContext(Header, 'currentUser', 'isLoggedIn', 'whitelabel');
|
||||
|
@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import DropdownButton from 'react-bootstrap/lib/DropdownButton';
|
||||
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
|
||||
import MenuItem from 'react-bootstrap/lib/MenuItem';
|
||||
@ -11,12 +10,17 @@ import Nav from 'react-bootstrap/lib/Nav';
|
||||
import NotificationActions from '../actions/notification_actions';
|
||||
import NotificationStore from '../stores/notification_store';
|
||||
|
||||
import withContext from './context/with_context';
|
||||
import { currentUserShape } from './prop_types';
|
||||
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
|
||||
|
||||
let HeaderNotifications = React.createClass({
|
||||
propTypes: {
|
||||
currentUser: React.PropTypes.object.isRequired
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
isLoggedIn: React.PropTypes.bool.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
@ -26,7 +30,7 @@ let HeaderNotifications = React.createClass({
|
||||
componentDidMount() {
|
||||
NotificationStore.listen(this.onChange);
|
||||
|
||||
if (this.props.currentUser.email) {
|
||||
if (this.props.isLoggedIn) {
|
||||
this.refreshNotifications();
|
||||
}
|
||||
},
|
||||
@ -45,31 +49,6 @@ let HeaderNotifications = React.createClass({
|
||||
this.setState(state);
|
||||
},
|
||||
|
||||
onMenuItemClick() {
|
||||
/*
|
||||
This is a hack to make the dropdown close after clicking on an item
|
||||
The function just need to be defined
|
||||
|
||||
from https://github.com/react-bootstrap/react-bootstrap/issues/368:
|
||||
|
||||
@jvillasante - Have you tried to use onSelect with the DropdownButton?
|
||||
I don't have a working example that is exactly like yours,
|
||||
but I just noticed that the Dropdown closes when I've attached an event handler to OnSelect:
|
||||
|
||||
<DropdownButton eventKey={3} title="Admin" onSelect={ this.OnSelected } >
|
||||
|
||||
onSelected: function(e) {
|
||||
// doesn't need to have functionality (necessarily) ... just wired up
|
||||
}
|
||||
Internally, a call to DropdownButton.setDropDownState(false) is made which will hide the dropdown menu.
|
||||
So, you should be able to call that directly on the DropdownButton instance as well if needed.
|
||||
|
||||
NOW, THAT DIDN'T WORK - the onSelect routine isnt triggered in all cases
|
||||
Hence, we do this manually
|
||||
*/
|
||||
this.refs.dropdownbutton.setDropdownState(false);
|
||||
},
|
||||
|
||||
refreshNotifications() {
|
||||
NotificationActions.fetchPieceListNotifications();
|
||||
NotificationActions.fetchEditionListNotifications();
|
||||
@ -83,12 +62,18 @@ let HeaderNotifications = React.createClass({
|
||||
{`${(isPiece ? 'Artworks' : 'Editions')} (${notifications.length})`}
|
||||
</div>
|
||||
{notifications.map((notification, i) => {
|
||||
const pieceOrEdition = isPiece ? notification.piece : notification.edition;
|
||||
const href = isPiece ? `/pieces/${pieceOrEdition.id}`
|
||||
: `/editions/${pieceOrEdition.bitcoin_id}`;
|
||||
|
||||
return (
|
||||
<MenuItem eventKey={i + 2}>
|
||||
<MenuItem
|
||||
key={href}
|
||||
eventKey={i + 2}
|
||||
href={href}>
|
||||
<NotificationListItem
|
||||
notification={notification.notification}
|
||||
pieceOrEdition={isPiece ? notification.piece : notification.edition}
|
||||
onClick={this.onMenuItemClick}/>
|
||||
pieceOrEdition={pieceOrEdition} />
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
@ -112,7 +97,7 @@ let HeaderNotifications = React.createClass({
|
||||
}
|
||||
|
||||
return (
|
||||
<Nav navbar right>
|
||||
<Nav navbar pullRight>
|
||||
<DropdownButton
|
||||
ref='dropdownButton'
|
||||
id="header-notification-dropdown"
|
||||
@ -138,25 +123,6 @@ let NotificationListItem = React.createClass({
|
||||
propTypes: {
|
||||
notification: React.PropTypes.array,
|
||||
pieceOrEdition: React.PropTypes.object,
|
||||
onClick: React.PropTypes.func
|
||||
},
|
||||
|
||||
isPiece() {
|
||||
return !(this.props.pieceOrEdition && this.props.pieceOrEdition.parent);
|
||||
},
|
||||
|
||||
getLinkData() {
|
||||
let { pieceOrEdition } = this.props;
|
||||
|
||||
if (this.isPiece()) {
|
||||
return `/pieces/${pieceOrEdition.id}`;
|
||||
} else {
|
||||
return `/editions/${pieceOrEdition.bitcoin_id}`;
|
||||
}
|
||||
},
|
||||
|
||||
onClick(event){
|
||||
this.props.onClick(event);
|
||||
},
|
||||
|
||||
getNotificationText(){
|
||||
@ -174,7 +140,6 @@ let NotificationListItem = React.createClass({
|
||||
render() {
|
||||
if (this.props.pieceOrEdition) {
|
||||
return (
|
||||
<Link to={this.getLinkData()} onClick={this.onClick}>
|
||||
<div className="row notification-wrapper">
|
||||
<div className="col-xs-4 clear-paddings">
|
||||
<div className="thumbnail-wrapper">
|
||||
@ -187,10 +152,10 @@ let NotificationListItem = React.createClass({
|
||||
{this.getNotificationText()}
|
||||
</div>
|
||||
</div>
|
||||
</Link>);
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
export default HeaderNotifications;
|
||||
export default withContext(HeaderNotifications, 'currentUser', 'isLoggedIn');
|
||||
|
@ -1,35 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import Link from 'react-router/es6/Link';
|
||||
|
||||
import LoginForm from './ascribe_forms/form_login';
|
||||
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
import withContext from './context/with_context';
|
||||
import { whitelabelShape } from './prop_types';
|
||||
|
||||
import { setDocumentTitle } from '../utils/dom_utils';
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
|
||||
|
||||
let LoginContainer = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from AscribeApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
whitelabel: whitelabelShape.isRequired
|
||||
},
|
||||
|
||||
render() {
|
||||
const { whitelabel: { name: whitelabelName },
|
||||
location } = this.props;
|
||||
const { whitelabel: { name: whitelabelName } } = this.props;
|
||||
|
||||
setDocumentTitle(getLangText('Log in'));
|
||||
|
||||
return (
|
||||
<div className="ascribe-login-wrapper">
|
||||
<LoginForm
|
||||
location={location}
|
||||
whitelabelName={whitelabelName} />
|
||||
<LoginForm whitelabelName={whitelabelName} />
|
||||
<div className="ascribe-login-text">
|
||||
{getLangText(`Not a ${whitelabelName || 'ascribe'} user`)}? <Link to="/signup">{getLangText('Sign up')}...</Link><br/>
|
||||
{getLangText('Forgot my password')}? <Link to="/password_reset">{getLangText('Rescue me')}...</Link>
|
||||
@ -39,6 +35,4 @@ let LoginContainer = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
export default LoginContainer;
|
||||
export default withContext(LoginContainer, 'whitelabel');
|
||||
|
@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import AscribeSpinner from './ascribe_spinner';
|
||||
|
||||
@ -12,17 +11,6 @@ import { setDocumentTitle } from '../utils/dom_utils';
|
||||
|
||||
|
||||
let LogoutContainer = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from AscribeApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
},
|
||||
|
||||
mixins: [History],
|
||||
|
||||
componentDidMount() {
|
||||
UserActions.logoutCurrentUser();
|
||||
},
|
||||
|
@ -1,27 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import Form from './ascribe_forms/form';
|
||||
import Property from './ascribe_forms/property';
|
||||
import ApiUrls from '../constants/api_urls';
|
||||
import AscribeSpinner from './ascribe_spinner';
|
||||
|
||||
import GlobalNotificationModel from '../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../actions/global_notification_actions';
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
|
||||
import Form from './ascribe_forms/form';
|
||||
import Property from './ascribe_forms/property';
|
||||
|
||||
import AscribeSpinner from './ascribe_spinner';
|
||||
import withContext from './context/with_context';
|
||||
import { locationShape, routerShape } from './prop_types';
|
||||
|
||||
import ApiUrls from '../constants/api_urls';
|
||||
|
||||
import { setDocumentTitle } from '../utils/dom_utils';
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
|
||||
|
||||
let PasswordResetContainer = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from AscribeApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
location: locationShape.isRequired,
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
@ -108,13 +108,14 @@ let PasswordRequestResetForm = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
let PasswordResetForm = React.createClass({
|
||||
let PasswordResetForm = withContext(React.createClass({
|
||||
propTypes: {
|
||||
email: React.PropTypes.string,
|
||||
token: React.PropTypes.string
|
||||
},
|
||||
token: React.PropTypes.string,
|
||||
|
||||
mixins: [History],
|
||||
// Injected through HOCs
|
||||
router: routerShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
getFormData() {
|
||||
return {
|
||||
@ -124,7 +125,7 @@ let PasswordResetForm = React.createClass({
|
||||
},
|
||||
|
||||
handleSuccess() {
|
||||
this.history.push('/collection');
|
||||
this.props.router.push('/collection');
|
||||
|
||||
const notification = new GlobalNotificationModel(getLangText('Password successfully updated'), 'success', 10000);
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
@ -175,6 +176,6 @@ let PasswordResetForm = React.createClass({
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
});
|
||||
}), 'router');
|
||||
|
||||
export default PasswordResetContainer;
|
||||
export default withContext(PasswordResetContainer, 'location');
|
||||
|
@ -1,7 +1,4 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import PieceListStore from '../stores/piece_list_store';
|
||||
import PieceListActions from '../actions/piece_list_actions';
|
||||
@ -24,14 +21,16 @@ import PieceListBulkModal from './ascribe_piece_list_bulk_modal/piece_list_bulk_
|
||||
import PieceListToolbar from './ascribe_piece_list_toolbar/piece_list_toolbar';
|
||||
|
||||
import AscribeSpinner from './ascribe_spinner';
|
||||
import withContext from './context/with_context';
|
||||
import { locationShape, routerShape } from './prop_types';
|
||||
|
||||
import { getAvailableAcls } from '../utils/acl_utils';
|
||||
import { setDocumentTitle } from '../utils/dom_utils';
|
||||
import { mergeOptions, isShallowEqual } from '../utils/general_utils';
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
import { setDocumentTitle } from '../utils/dom_utils';
|
||||
|
||||
|
||||
let PieceList = React.createClass({
|
||||
const PieceList = React.createClass({
|
||||
propTypes: {
|
||||
accordionListItemType: React.PropTypes.func,
|
||||
bulkModalButtonListType: React.PropTypes.func,
|
||||
@ -47,16 +46,11 @@ let PieceList = React.createClass({
|
||||
orderParams: React.PropTypes.array,
|
||||
orderBy: React.PropTypes.string,
|
||||
|
||||
// Provided from AscribeApp
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
location: locationShape.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
router: routerShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
mixins: [History],
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
accordionListItemType: AccordionListItemWallet,
|
||||
@ -129,18 +123,18 @@ let PieceList = React.createClass({
|
||||
},
|
||||
|
||||
componentDidUpdate() {
|
||||
const { location: { query }, redirectTo, shouldRedirect } = this.props;
|
||||
const { location: { query }, redirectTo, router, shouldRedirect } = this.props;
|
||||
const { unfilteredPieceListCount } = this.state;
|
||||
|
||||
if (redirectTo && redirectTo.pathname &&
|
||||
(typeof shouldRedirect === 'function' && shouldRedirect(unfilteredPieceListCount))) {
|
||||
// FIXME: hack to redirect out of the dispatch cycle
|
||||
window.setTimeout(() => this.history.push({
|
||||
window.setTimeout(() => router.push({
|
||||
// Occasionally, the back end also sets query parameters for Onion.
|
||||
// We need to consider this by merging all passed query parameters, as we'll
|
||||
// otherwise end up in a 404 screen
|
||||
query: Object.assign({}, query, redirectTo.query),
|
||||
pathname: redirectTo.pathname
|
||||
pathname: redirectTo.pathname,
|
||||
query: Object.assign({}, query, redirectTo.query)
|
||||
}), 0);
|
||||
}
|
||||
},
|
||||
@ -195,14 +189,14 @@ let PieceList = React.createClass({
|
||||
},
|
||||
|
||||
searchFor(search) {
|
||||
const { location: { pathname } } = this.props;
|
||||
const { location: { pathname }, router } = this.props;
|
||||
|
||||
this.loadPieceList({ search, page: 1 });
|
||||
this.history.push({ pathname, query: { page: 1 } });
|
||||
router.push({ pathname, query: { page: 1 } });
|
||||
},
|
||||
|
||||
applyFilterBy(filterBy) {
|
||||
const { location: { pathname } } = this.props;
|
||||
const { location: { pathname }, router } = this.props;
|
||||
|
||||
this.setState({
|
||||
isFilterDirty: true
|
||||
@ -228,7 +222,7 @@ let PieceList = React.createClass({
|
||||
|
||||
// we have to redirect the user always to page one as it could be that there is no page two
|
||||
// for filtered pieces
|
||||
this.history.push({ pathname, query: { page: 1 } });
|
||||
router.push({ pathname, query: { page: 1 } });
|
||||
},
|
||||
|
||||
applyOrderBy(orderBy) {
|
||||
@ -277,14 +271,14 @@ let PieceList = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { accordionListItemType: AccordionListItemType,
|
||||
bulkModalButtonListType: BulkModalButtonListType,
|
||||
currentUser,
|
||||
const {
|
||||
customSubmitButton,
|
||||
customThumbnailPlaceholder,
|
||||
filterParams,
|
||||
orderParams,
|
||||
whitelabel } = this.props;
|
||||
accordionListItemType: AccordionListItemType,
|
||||
bulkModalButtonListType: BulkModalButtonListType
|
||||
} = this.props;
|
||||
|
||||
const loadingElement = <AscribeSpinner color='dark-blue' size='lg'/>;
|
||||
|
||||
@ -313,10 +307,8 @@ let PieceList = React.createClass({
|
||||
className="ascribe-piece-list-bulk-modal">
|
||||
<BulkModalButtonListType
|
||||
availableAcls={availableAcls}
|
||||
currentUser={currentUser}
|
||||
handleSuccess={this.handleAclSuccess}
|
||||
pieceOrEditions={selectedEditions}
|
||||
whitelabel={whitelabel}
|
||||
className="text-center ascribe-button-list collapse-group">
|
||||
<DeleteButton
|
||||
handleSuccess={this.handleAclSuccess}
|
||||
@ -344,9 +336,7 @@ let PieceList = React.createClass({
|
||||
key={piece.id}
|
||||
className="col-xs-12 col-sm-10 col-md-8 col-lg-8 col-sm-offset-1 col-md-offset-2 col-lg-offset-2 ascribe-accordion-list-item"
|
||||
content={piece}
|
||||
currentUser={currentUser}
|
||||
thumbnailPlaceholder={customThumbnailPlaceholder}
|
||||
whitelabel={whitelabel}>
|
||||
thumbnailPlaceholder={customThumbnailPlaceholder}>
|
||||
<AccordionListItemTableEditions
|
||||
className="ascribe-accordion-list-item-table col-xs-12 col-sm-10 col-md-8 col-lg-8 col-sm-offset-1 col-md-offset-2 col-lg-offset-2"
|
||||
parentId={piece.id} />
|
||||
@ -360,4 +350,4 @@ let PieceList = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default PieceList;
|
||||
export default withContext(PieceList, 'location', 'router');
|
||||
|
12
js/components/prop_types/current_user_shape.js
Normal file
12
js/components/prop_types/current_user_shape.js
Normal file
@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
|
||||
|
||||
const { number, object, shape, string } = React.PropTypes;
|
||||
|
||||
export default shape({
|
||||
acl: object,
|
||||
email: string,
|
||||
id: number,
|
||||
profile: object,
|
||||
username: string
|
||||
});
|
5
js/components/prop_types/index.js
Normal file
5
js/components/prop_types/index.js
Normal file
@ -0,0 +1,5 @@
|
||||
export { default as currentUserShape } from './current_user_shape';
|
||||
export { default as whitelabelShape } from './whitelabel_shape';
|
||||
|
||||
// Re-export PropTypes from react-router
|
||||
export { locationShape, routerShape } from 'react-router/es6/PropTypes';
|
11
js/components/prop_types/whitelabel_shape.js
Normal file
11
js/components/prop_types/whitelabel_shape.js
Normal file
@ -0,0 +1,11 @@
|
||||
import React from 'react';
|
||||
|
||||
|
||||
const { shape, string } = React.PropTypes;
|
||||
|
||||
export default shape({
|
||||
name: string,
|
||||
subdomain: string,
|
||||
title: string,
|
||||
user: string
|
||||
});
|
@ -1,7 +1,4 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import Col from 'react-bootstrap/lib/Col';
|
||||
import Row from 'react-bootstrap/lib/Row';
|
||||
@ -15,11 +12,14 @@ import GlobalNotificationActions from '../actions/global_notification_actions';
|
||||
import Property from './ascribe_forms/property';
|
||||
import RegisterPieceForm from './ascribe_forms/form_register_piece';
|
||||
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
import withContext from './context/with_context';
|
||||
import { routerShape, whitelabelShape } from './prop_types';
|
||||
|
||||
import { setDocumentTitle } from '../utils/dom_utils';
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
|
||||
|
||||
let RegisterPiece = React.createClass( {
|
||||
const RegisterPiece = React.createClass( {
|
||||
propTypes: {
|
||||
headerMessage: React.PropTypes.string,
|
||||
submitMessage: React.PropTypes.string,
|
||||
@ -29,16 +29,11 @@ let RegisterPiece = React.createClass( {
|
||||
React.PropTypes.string
|
||||
]),
|
||||
|
||||
// Provided from AscribeApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
router: routerShape.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
whitelabel: whitelabelShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
mixins: [History],
|
||||
|
||||
getInitialState(){
|
||||
return PieceListStore.getState();
|
||||
},
|
||||
@ -65,7 +60,7 @@ let RegisterPiece = React.createClass( {
|
||||
// the piece list up to date
|
||||
PieceListActions.fetchPieceList({ page, pageSize, search, orderBy, orderAsc, filterBy });
|
||||
|
||||
this.history.push(`/pieces/${response.piece.id}`);
|
||||
this.props.router.push(`/pieces/${response.piece.id}`);
|
||||
},
|
||||
|
||||
getSpecifyEditions() {
|
||||
@ -107,5 +102,4 @@ let RegisterPiece = React.createClass( {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default RegisterPiece;
|
||||
export default withContext(RegisterPiece, 'router', 'whitelabel');
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
// FIXME: Input is deprecated
|
||||
import Input from 'react-bootstrap/lib/Input';
|
||||
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
|
||||
|
||||
|
@ -1,22 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import Link from 'react-router/es6/Link';
|
||||
|
||||
import SignupForm from './ascribe_forms/form_signup';
|
||||
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
import withContext from './context/with_context';
|
||||
import { whitelabelShape } from './prop_types';
|
||||
|
||||
import { setDocumentTitle } from '../utils/dom_utils';
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
|
||||
|
||||
let SignupContainer = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from AscribeApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
whitelabel: whitelabelShape.isRequired
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
@ -34,8 +31,7 @@ let SignupContainer = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { location,
|
||||
whitelabel: { name: whitelabelName } } = this.props;
|
||||
const { whitelabel: { name: whitelabelName } } = this.props;
|
||||
const { message, submitted } = this.state;
|
||||
|
||||
setDocumentTitle(getLangText('Sign up'));
|
||||
@ -54,8 +50,7 @@ let SignupContainer = React.createClass({
|
||||
<div className="ascribe-login-wrapper">
|
||||
<SignupForm
|
||||
handleSuccess={this.handleSuccess}
|
||||
whitelabelName={whitelabelName}
|
||||
location={location}/>
|
||||
whitelabelName={whitelabelName} />
|
||||
<div className="ascribe-login-text">
|
||||
{getLangText(`Already a ${whitelabelName || 'ascribe'} user`)}? <Link to="/login">{getLangText('Log in')}...</Link><br/>
|
||||
</div>
|
||||
@ -65,5 +60,4 @@ let SignupContainer = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default SignupContainer;
|
||||
export default withContext(SignupContainer, 'whitelabel');
|
||||
|
@ -5,20 +5,17 @@ import React from 'react';
|
||||
import Button from 'react-bootstrap/lib/Button';
|
||||
import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
|
||||
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
import withContext from '../../../../context/with_context';
|
||||
import { whitelabelShape } from '../../../../prop_types';
|
||||
|
||||
import { setDocumentTitle } from '../../../../../utils/dom_utils';
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
|
||||
|
||||
let Vivi23Landing = React.createClass({
|
||||
propTypes: {
|
||||
customThumbnailPlaceholder: React.PropTypes.func,
|
||||
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
whitelabel: whitelabelShape.isRequired
|
||||
},
|
||||
|
||||
componentWillMount() {
|
||||
@ -69,4 +66,4 @@ let Vivi23Landing = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default Vivi23Landing;
|
||||
export default withContext(Vivi23Landing, 'whitelabel');
|
||||
|
@ -7,15 +7,6 @@ import Vivi23AccordionListItemThumbnailPlaceholder from './23vivi_accordion_list
|
||||
import MarketPieceList from '../market/market_piece_list';
|
||||
|
||||
let Vivi23PieceList = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<MarketPieceList
|
||||
|
@ -5,15 +5,17 @@ import React from 'react';
|
||||
import Button from 'react-bootstrap/lib/Button';
|
||||
import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
|
||||
|
||||
import withContext from '../../../../context/with_context';
|
||||
import { whitelabelShape } from '../../../../prop_types';
|
||||
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
import { setDocumentTitle } from '../../../../../utils/dom_utils';
|
||||
|
||||
|
||||
let ArtcityLanding = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object.isRequired
|
||||
// Injected through HOCs
|
||||
whitelabel: whitelabelShape.isRequired
|
||||
},
|
||||
|
||||
componentWillMount() {
|
||||
@ -61,4 +63,4 @@ let ArtcityLanding = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default ArtcityLanding;
|
||||
export default withContext(ArtcityLanding, 'whitelabel');
|
||||
|
@ -7,17 +7,21 @@ import AclButtonList from '../../../../ascribe_buttons/acl_button_list';
|
||||
import DeleteButton from '../../../../ascribe_buttons/delete_button';
|
||||
|
||||
import AclProxy from '../../../../acl_proxy';
|
||||
import withContext from '../../../../context/with_context';
|
||||
import { currentUserShape } from '../../../../prop_types';
|
||||
|
||||
import { mergeOptions } from '../../../../../utils/general_utils';
|
||||
|
||||
|
||||
let WalletActionPanel = React.createClass({
|
||||
propTypes: {
|
||||
piece: React.PropTypes.object.isRequired,
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
handleDeleteSuccess: React.PropTypes.func.isRequired,
|
||||
loadPiece: React.PropTypes.func.isRequired,
|
||||
submitButtonType: React.PropTypes.func.isRequired
|
||||
piece: React.PropTypes.object.isRequired,
|
||||
submitButtonType: React.PropTypes.func.isRequired,
|
||||
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
render() {
|
||||
@ -27,7 +31,6 @@ let WalletActionPanel = React.createClass({
|
||||
return (
|
||||
<ListRequestActions
|
||||
pieceOrEditions={piece}
|
||||
currentUser={currentUser}
|
||||
handleSuccess={loadPiece}
|
||||
notifications={piece.notifications}/>);
|
||||
} else {
|
||||
@ -46,7 +49,6 @@ let WalletActionPanel = React.createClass({
|
||||
<AclButtonList
|
||||
availableAcls={availableAcls}
|
||||
className="text-center ascribe-button-list"
|
||||
currentUser={currentUser}
|
||||
pieceOrEditions={piece}
|
||||
handleSuccess={loadPiece}>
|
||||
<AclProxy
|
||||
@ -69,4 +71,4 @@ let WalletActionPanel = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default WalletActionPanel;
|
||||
export default withContext(WalletActionPanel, 'currentUser');
|
||||
|
@ -13,6 +13,7 @@ import Note from '../../../../ascribe_detail/note';
|
||||
import Piece from '../../../../../components/ascribe_detail/piece';
|
||||
|
||||
import AscribeSpinner from '../../../../ascribe_spinner';
|
||||
import withContext from '../../../../context/with_context';
|
||||
|
||||
import ApiUrls from '../../../../../constants/api_urls';
|
||||
|
||||
@ -22,7 +23,6 @@ import { getLangText } from '../../../../../utils/lang_utils';
|
||||
let WalletPieceContainer = React.createClass({
|
||||
propTypes: {
|
||||
piece: React.PropTypes.object.isRequired,
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
handleDeleteSuccess: React.PropTypes.func.isRequired,
|
||||
loadPiece: React.PropTypes.func.isRequired,
|
||||
submitButtonType: React.PropTypes.func.isRequired,
|
||||
@ -30,13 +30,16 @@ let WalletPieceContainer = React.createClass({
|
||||
children: React.PropTypes.oneOfType([
|
||||
React.PropTypes.object,
|
||||
React.PropTypes.array
|
||||
])
|
||||
]),
|
||||
|
||||
// Injected through HOCs
|
||||
isLoggedIn: React.PropTypes.bool.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
render() {
|
||||
const { children,
|
||||
currentUser,
|
||||
handleDeleteSuccess,
|
||||
isLoggedIn,
|
||||
loadPiece,
|
||||
piece,
|
||||
submitButtonType } = this.props;
|
||||
@ -45,7 +48,6 @@ let WalletPieceContainer = React.createClass({
|
||||
return (
|
||||
<Piece
|
||||
piece={piece}
|
||||
currentUser={currentUser}
|
||||
header={
|
||||
<div className="ascribe-detail-header">
|
||||
<hr style={{marginTop: 0}}/>
|
||||
@ -64,7 +66,6 @@ let WalletPieceContainer = React.createClass({
|
||||
}>
|
||||
<WalletActionPanel
|
||||
piece={piece}
|
||||
currentUser={currentUser}
|
||||
loadPiece={loadPiece}
|
||||
handleDeleteSuccess={handleDeleteSuccess}
|
||||
submitButtonType={submitButtonType}/>
|
||||
@ -76,7 +77,7 @@ let WalletPieceContainer = React.createClass({
|
||||
</CollapsibleParagraph>
|
||||
<CollapsibleParagraph
|
||||
title={getLangText('Notes')}
|
||||
show={!!(currentUser.username || piece.public_note)}>
|
||||
show={!!(isLoggedIn || piece.public_note)}>
|
||||
<Note
|
||||
id={() => {return {'id': piece.id}; }}
|
||||
label={getLangText('Personal note (private)')}
|
||||
@ -84,8 +85,7 @@ let WalletPieceContainer = React.createClass({
|
||||
placeholder={getLangText('Enter your comments ...')}
|
||||
editable={true}
|
||||
successMessage={getLangText('Private note saved')}
|
||||
url={ApiUrls.note_private_piece}
|
||||
currentUser={currentUser}/>
|
||||
url={ApiUrls.note_private_piece} />
|
||||
</CollapsibleParagraph>
|
||||
{children}
|
||||
</Piece>
|
||||
@ -101,4 +101,4 @@ let WalletPieceContainer = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default WalletPieceContainer;
|
||||
export default withContext(WalletPieceContainer, 'isLoggedIn');
|
||||
|
@ -12,15 +12,6 @@ import { setDocumentTitle } from '../../../../../utils/dom_utils';
|
||||
import { mergeOptions } from '../../../../../utils/general_utils';
|
||||
|
||||
let CCRegisterPiece = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from AscribeApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return mergeOptions(
|
||||
LicenseStore.getState(),
|
||||
@ -93,8 +84,7 @@ let CCRegisterPiece = React.createClass({
|
||||
{...this.props}
|
||||
enableLocalHashing={false}
|
||||
headerMessage={getLangText('Register under a Creative Commons license')}
|
||||
submitMessage={getLangText('Submit')}
|
||||
location={this.props.location}>
|
||||
submitMessage={getLangText('Submit')}>
|
||||
{this.getLicenses()}
|
||||
</RegisterPiece>
|
||||
);
|
||||
|
@ -1,7 +1,4 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import EditionListActions from '../../../../../../actions/edition_list_actions';
|
||||
|
||||
@ -23,25 +20,23 @@ import WalletPieceContainer from '../../ascribe_detail/wallet_piece_container';
|
||||
import CollapsibleParagraph from '../../../../../../components/ascribe_collapsible/collapsible_paragraph';
|
||||
|
||||
import AscribeSpinner from '../../../../../ascribe_spinner';
|
||||
import withContext from '../../../../../context/with_context';
|
||||
import { routerShape } from '../../../../../prop_types';
|
||||
|
||||
import { getLangText } from '../../../../../../utils/lang_utils';
|
||||
import { setDocumentTitle } from '../../../../../../utils/dom_utils';
|
||||
import { mergeOptions } from '../../../../../../utils/general_utils';
|
||||
import { getLangText } from '../../../../../../utils/lang_utils';
|
||||
|
||||
|
||||
let CylandPieceContainer = React.createClass({
|
||||
const CylandPieceContainer = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object,
|
||||
// Injected through HOCs
|
||||
router: routerShape.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object,
|
||||
params: React.PropTypes.object
|
||||
},
|
||||
|
||||
mixins: [History],
|
||||
|
||||
getInitialState() {
|
||||
return mergeOptions(
|
||||
PieceStore.getInitialState(),
|
||||
@ -90,22 +85,19 @@ let CylandPieceContainer = React.createClass({
|
||||
const notification = new GlobalNotificationModel(response.notification, 'success');
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
|
||||
this.history.push('/collection');
|
||||
this.props.router.push('/collection');
|
||||
},
|
||||
|
||||
render() {
|
||||
const { piece } = this.state;
|
||||
|
||||
if (piece.id) {
|
||||
const { currentUser } = this.props;
|
||||
|
||||
setDocumentTitle(`${piece.artist_name}, ${piece.title}`);
|
||||
|
||||
return (
|
||||
<WalletPieceContainer
|
||||
{...this.props}
|
||||
piece={this.state.piece}
|
||||
currentUser={currentUser}
|
||||
loadPiece={this.loadPiece}
|
||||
handleDeleteSuccess={this.handleDeleteSuccess}
|
||||
submitButtonType={CylandSubmitButton}>
|
||||
@ -129,4 +121,4 @@ let CylandPieceContainer = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default CylandPieceContainer;
|
||||
export default withContext(CylandPieceContainer, 'router');
|
||||
|
@ -6,20 +6,17 @@ import Button from 'react-bootstrap/lib/Button';
|
||||
|
||||
import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
|
||||
|
||||
import AscribeSpinner from '../../../../ascribe_spinner';
|
||||
import withContext from '../../../../context/with_context';
|
||||
import { whitelabelShape } from '../../../../prop_types';
|
||||
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
import { setDocumentTitle } from '../../../../../utils/dom_utils';
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
|
||||
|
||||
let CylandLanding = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
whitelabel: whitelabelShape.isRequired,
|
||||
},
|
||||
|
||||
render() {
|
||||
@ -67,4 +64,4 @@ let CylandLanding = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default CylandLanding;
|
||||
export default withContext(CylandLanding, 'whitelabel');
|
||||
|
@ -5,24 +5,26 @@ import PieceList from '../../../../piece_list';
|
||||
|
||||
import CylandAccordionListItem from './cyland_accordion_list/cyland_accordion_list_item';
|
||||
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
import withContext from '../../../../context/with_context';
|
||||
import { currentUserShape, whitelabelShape } from '../../../../prop_types';
|
||||
|
||||
import { setDocumentTitle } from '../../../../../utils/dom_utils';
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
|
||||
let CylandPieceList = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired,
|
||||
whitelabel: whitelabelShape.isRequired
|
||||
},
|
||||
|
||||
shouldRedirect(pieceCount) {
|
||||
const { currentUser: { email: userEmail },
|
||||
const {
|
||||
currentUser: { email: userEmail },
|
||||
whitelabel: {
|
||||
user: whitelabelAdminEmail
|
||||
} } = this.props;
|
||||
}
|
||||
} = this.props;
|
||||
|
||||
return userEmail !== whitelabelAdminEmail && !pieceCount;
|
||||
},
|
||||
@ -52,4 +54,4 @@ let CylandPieceList = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default CylandPieceList;
|
||||
export default withContext(CylandPieceList, 'currentUser', 'whitelabel');
|
||||
|
@ -1,7 +1,4 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import Moment from 'moment';
|
||||
|
||||
@ -26,26 +23,26 @@ import RegisterPieceForm from '../../../../ascribe_forms/form_register_piece';
|
||||
|
||||
import SlidesContainer from '../../../../ascribe_slides_container/slides_container';
|
||||
|
||||
import withContext from '../../../../context/with_context';
|
||||
import { currentUserShape, locationShape, routerShape, whitelabelShape } from '../../../../prop_types';
|
||||
|
||||
import ApiUrls from '../../../../../constants/api_urls';
|
||||
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
import { setDocumentTitle } from '../../../../../utils/dom_utils';
|
||||
import { mergeOptions } from '../../../../../utils/general_utils';
|
||||
import { getAclFormMessage } from '../../../../../utils/form_utils';
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
import { mergeOptions } from '../../../../../utils/general_utils';
|
||||
|
||||
|
||||
let CylandRegisterPiece = React.createClass({
|
||||
const CylandRegisterPiece = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired,
|
||||
location: locationShape.isRequired,
|
||||
router: routerShape.isRequired,
|
||||
whitelabel: whitelabelShape.isRequired,
|
||||
},
|
||||
|
||||
mixins: [History],
|
||||
|
||||
getInitialState(){
|
||||
return mergeOptions(
|
||||
PieceListStore.getState(),
|
||||
@ -110,7 +107,7 @@ let CylandRegisterPiece = React.createClass({
|
||||
|
||||
this.refreshPieceList();
|
||||
|
||||
this.history.push(`/pieces/${this.state.piece.id}`);
|
||||
this.props.router.push(`/pieces/${this.state.piece.id}`);
|
||||
},
|
||||
|
||||
nextSlide(queryParams) {
|
||||
@ -129,7 +126,7 @@ let CylandRegisterPiece = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { currentUser, location, whitelabel } = this.props;
|
||||
const { currentUser, whitelabel } = this.props;
|
||||
const { piece, step } = this.state;
|
||||
|
||||
const today = new Moment();
|
||||
@ -164,8 +161,7 @@ let CylandRegisterPiece = React.createClass({
|
||||
glyphiconClassNames={{
|
||||
pending: 'glyphicon glyphicon-chevron-right',
|
||||
completed: 'glyphicon glyphicon-lock'
|
||||
}}
|
||||
location={location}>
|
||||
}}>
|
||||
<div data-slide-title={getLangText('Register work')}>
|
||||
<Row className="no-margin">
|
||||
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
|
||||
@ -220,4 +216,4 @@ let CylandRegisterPiece = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default CylandRegisterPiece;
|
||||
export default withContext(CylandRegisterPiece, 'currentUser', 'location', 'router', 'whitelabel');
|
||||
|
@ -5,18 +5,17 @@ import React from 'react';
|
||||
import Button from 'react-bootstrap/lib/Button';
|
||||
import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
|
||||
|
||||
import WhitelabelActions from '../../../../../actions/whitelabel_actions';
|
||||
import WhitelabelStore from '../../../../../stores/whitelabel_store';
|
||||
import withContext from '../../../../context/with_context';
|
||||
import { whitelabelShape } from '../../../../prop_types';
|
||||
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
import { setDocumentTitle } from '../../../../../utils/dom_utils';
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
|
||||
|
||||
let DemoLanding = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object.isRequired
|
||||
whitelabel: whitelabelShape.isRequired,
|
||||
},
|
||||
|
||||
componentWillMount() {
|
||||
@ -64,4 +63,4 @@ let DemoLanding = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default DemoLanding;
|
||||
export default withContext(DemoLanding, 'whitelabel');
|
||||
|
@ -14,21 +14,24 @@ import IkonotvSubmitButton from '../ikonotv_buttons/ikonotv_submit_button';
|
||||
import AccordionListItemPiece from '../../../../../ascribe_accordion_list/accordion_list_item_piece';
|
||||
|
||||
import AclProxy from '../../../../../acl_proxy';
|
||||
import withContext from '../../../../../context/with_context';
|
||||
import { currentUserShape } from '../../../../../prop_types';
|
||||
|
||||
import { getLangText } from '../../../../../../utils/lang_utils';
|
||||
import { mergeOptions } from '../../../../../../utils/general_utils';
|
||||
|
||||
|
||||
let IkonotvAccordionListItem = React.createClass({
|
||||
propTypes: {
|
||||
content: React.PropTypes.object.isRequired,
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
|
||||
children: React.PropTypes.oneOfType([
|
||||
React.PropTypes.arrayOf(React.PropTypes.element),
|
||||
React.PropTypes.element
|
||||
]),
|
||||
className: React.PropTypes.string
|
||||
className: React.PropTypes.string,
|
||||
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
@ -116,4 +119,4 @@ let IkonotvAccordionListItem = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default IkonotvAccordionListItem;
|
||||
export default withContext(IkonotvAccordionListItem, 'currentUser');
|
||||
|
@ -1,7 +1,4 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
|
||||
import Button from 'react-bootstrap/lib/Button';
|
||||
@ -17,24 +14,23 @@ import OwnershipFetcher from '../../../../../fetchers/ownership_fetcher';
|
||||
import CopyrightAssociationForm from '../../../../ascribe_forms/form_copyright_association';
|
||||
import Property from '../../../../ascribe_forms/property';
|
||||
|
||||
import withContext from '../../../../context/with_context';
|
||||
import { currentUserShape, routerShape, whitelabelShape } from '../../../../prop_types';
|
||||
|
||||
import AppConstants from '../../../../../constants/application_constants';
|
||||
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
import { setDocumentTitle } from '../../../../../utils/dom_utils';
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
|
||||
|
||||
let IkonotvContractNotifications = React.createClass({
|
||||
const IkonotvContractNotifications = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired,
|
||||
router: routerShape.isRequired,
|
||||
whitelabel: whitelabelShape.isRequired
|
||||
},
|
||||
|
||||
mixins: [History],
|
||||
|
||||
getInitialState() {
|
||||
return NotificationStore.getState();
|
||||
},
|
||||
@ -115,7 +111,7 @@ let IkonotvContractNotifications = React.createClass({
|
||||
NotificationActions.flushContractAgreementListNotifications();
|
||||
NotificationActions.fetchContractAgreementListNotifications();
|
||||
|
||||
this.history.push('/collection');
|
||||
this.props.router.push('/collection');
|
||||
},
|
||||
|
||||
handleDeny() {
|
||||
@ -129,13 +125,13 @@ let IkonotvContractNotifications = React.createClass({
|
||||
const notification = new GlobalNotificationModel(getLangText('You have denied the conditions'), 'success', 5000);
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
|
||||
this.history.push('/collection');
|
||||
this.props.router.push('/collection');
|
||||
},
|
||||
|
||||
getCopyrightAssociationForm(){
|
||||
const { currentUser } = this.props;
|
||||
getCopyrightAssociationForm() {
|
||||
const { profile } = this.props.currentUser;
|
||||
|
||||
if (currentUser.profile && !currentUser.profile.copyright_association) {
|
||||
if (profile && !profile.copyright_association) {
|
||||
return (
|
||||
<div className='notification-contract-footer'>
|
||||
<h1>{getLangText('Are you a member of any copyright societies?')}</h1>
|
||||
@ -143,7 +139,7 @@ let IkonotvContractNotifications = React.createClass({
|
||||
<p>
|
||||
{AppConstants.copyrightAssociations.join(', ')}
|
||||
</p>
|
||||
<CopyrightAssociationForm currentUser={currentUser}/>
|
||||
<CopyrightAssociationForm />
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
@ -200,4 +196,4 @@ let IkonotvContractNotifications = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default IkonotvContractNotifications;
|
||||
export default withContext(IkonotvContractNotifications, 'currentUser', 'router', 'whitelabel');
|
||||
|
@ -1,7 +1,4 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import EditionListActions from '../../../../../../actions/edition_list_actions';
|
||||
|
||||
@ -24,25 +21,23 @@ import WalletPieceContainer from '../../ascribe_detail/wallet_piece_container';
|
||||
import CollapsibleParagraph from '../../../../../../components/ascribe_collapsible/collapsible_paragraph';
|
||||
|
||||
import AscribeSpinner from '../../../../../ascribe_spinner';
|
||||
import withContext from '../../../../../context/with_context';
|
||||
import { routerShape } from '../../../../../prop_types';
|
||||
|
||||
import { getLangText } from '../../../../../../utils/lang_utils';
|
||||
import { setDocumentTitle } from '../../../../../../utils/dom_utils';
|
||||
import { mergeOptions } from '../../../../../../utils/general_utils';
|
||||
import { getLangText } from '../../../../../../utils/lang_utils';
|
||||
|
||||
|
||||
let IkonotvPieceContainer = React.createClass({
|
||||
const IkonotvPieceContainer = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object,
|
||||
// Injected through HOCs
|
||||
router: routerShape.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object,
|
||||
params: React.PropTypes.object
|
||||
},
|
||||
|
||||
mixins: [History],
|
||||
|
||||
getInitialState() {
|
||||
return mergeOptions(
|
||||
PieceListStore.getState(),
|
||||
@ -91,11 +86,10 @@ let IkonotvPieceContainer = React.createClass({
|
||||
const notification = new GlobalNotificationModel(response.notification, 'success');
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
|
||||
this.history.push('/collection');
|
||||
this.props.router.push('/collection');
|
||||
},
|
||||
|
||||
render() {
|
||||
const { currentUser } = this.props;
|
||||
const { piece } = this.state;
|
||||
|
||||
let furtherDetails = (
|
||||
@ -129,7 +123,6 @@ let IkonotvPieceContainer = React.createClass({
|
||||
return (
|
||||
<WalletPieceContainer
|
||||
piece={piece}
|
||||
currentUser={currentUser}
|
||||
loadPiece={this.loadPiece}
|
||||
handleDeleteSuccess={this.handleDeleteSuccess}
|
||||
submitButtonType={IkonotvSubmitButton}>
|
||||
@ -146,4 +139,4 @@ let IkonotvPieceContainer = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default IkonotvPieceContainer;
|
||||
export default withContext(IkonotvPieceContainer, 'router');
|
||||
|
@ -6,32 +6,32 @@ import Button from 'react-bootstrap/lib/Button';
|
||||
|
||||
import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
|
||||
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
import withContext from '../../../../context/with_context';
|
||||
import { locationShape } from '../../../../prop_types';
|
||||
|
||||
import { setDocumentTitle } from '../../../../../utils/dom_utils';
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
|
||||
|
||||
let IkonotvLanding = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
isLoggedIn: React.PropTypes.bool.isRequired,
|
||||
location: locationShape.isRequired
|
||||
},
|
||||
|
||||
getEnterButton() {
|
||||
const { currentUser, location } = this.props;
|
||||
const { isLoggedIn, location: { query } } = this.props;
|
||||
let redirect = '/login';
|
||||
|
||||
if (currentUser.email) {
|
||||
if (isLoggedIn) {
|
||||
redirect = '/collection';
|
||||
} else if (location.query.redirect) {
|
||||
redirect = '/' + location.query.redirect;
|
||||
} else if (query.redirect) {
|
||||
redirect = `/${query.redirect}`;
|
||||
}
|
||||
|
||||
return (
|
||||
<LinkContainer to={redirect} query={location.query}>
|
||||
<LinkContainer to={redirect} query={query}>
|
||||
<Button>
|
||||
{getLangText('ENTER TO START')}
|
||||
</Button>
|
||||
@ -101,4 +101,4 @@ let IkonotvLanding = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default IkonotvLanding;
|
||||
export default withContext(IkonotvLanding, 'isLoggedIn', 'location');
|
||||
|
@ -8,18 +8,18 @@ import NotificationStore from '../../../../../stores/notification_store';
|
||||
|
||||
import IkonotvAccordionListItem from './ikonotv_accordion_list/ikonotv_accordion_list_item';
|
||||
|
||||
import withContext from '../../../../context/with_context';
|
||||
import { currentUserShape, whitelabelShape } from '../../../../prop_types';
|
||||
|
||||
import { setDocumentTitle } from '../../../../../utils/dom_utils';
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
|
||||
|
||||
let IkonotvPieceList = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired,
|
||||
whitelabel: whitelabelShape.isRequired
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
@ -39,10 +39,12 @@ let IkonotvPieceList = React.createClass({
|
||||
},
|
||||
|
||||
shouldRedirect(pieceCount) {
|
||||
const { currentUser: { email: userEmail },
|
||||
const {
|
||||
currentUser: { email: userEmail },
|
||||
whitelabel: {
|
||||
user: whitelabelAdminEmail
|
||||
} } = this.props;
|
||||
}
|
||||
} = this.props;
|
||||
const { contractAgreementListNotifications } = this.state;
|
||||
|
||||
return contractAgreementListNotifications &&
|
||||
@ -84,4 +86,4 @@ let IkonotvPieceList = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default IkonotvPieceList;
|
||||
export default withContext(IkonotvPieceList, 'currentUser', 'whitelabel');
|
||||
|
@ -1,8 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import Moment from 'moment';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import Col from 'react-bootstrap/lib/Col';
|
||||
import Row from 'react-bootstrap/lib/Row';
|
||||
@ -24,43 +21,46 @@ import LoanForm from '../../../../ascribe_forms/form_loan';
|
||||
|
||||
import SlidesContainer from '../../../../ascribe_slides_container/slides_container';
|
||||
|
||||
import withContext from '../../../../context/with_context';
|
||||
import { currentUserShape, locationShape, routerShape, whitelabelShape } from '../../../../prop_types';
|
||||
|
||||
import ApiUrls from '../../../../../constants/api_urls';
|
||||
|
||||
import { mergeOptions } from '../../../../../utils/general_utils';
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
|
||||
|
||||
let IkonotvRegisterPiece = React.createClass({
|
||||
const IkonotvRegisterPiece = React.createClass({
|
||||
propTypes: {
|
||||
handleSuccess: React.PropTypes.func,
|
||||
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
location: locationShape.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
router: routerShape.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
whitelabel: whitelabelShape.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
route: React.PropTypes.object.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
mixins: [History],
|
||||
|
||||
getInitialState() {
|
||||
return mergeOptions(
|
||||
PieceListStore.getState(),
|
||||
PieceStore.getInitialState(),
|
||||
{
|
||||
step: 0,
|
||||
pageExitWarning: getLangText("If you leave this form now, your work will not be loaned to Ikono TV.")
|
||||
pageExitWarning: getLangText('If you leave this form now, your work will not be loaned to Ikono TV.')
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
const { location: { query }, route, router } = this.props;
|
||||
|
||||
PieceListStore.listen(this.onChange);
|
||||
PieceStore.listen(this.onChange);
|
||||
|
||||
const queryParams = this.props.location.query;
|
||||
|
||||
// Since every step of this register process is atomic,
|
||||
// we may need to enter the process at step 1 or 2.
|
||||
// If this is the case, we'll need the piece number to complete submission.
|
||||
@ -68,9 +68,12 @@ let IkonotvRegisterPiece = React.createClass({
|
||||
//
|
||||
// We're using 'in' here as we want to know if 'piece_id' is present in the url,
|
||||
// we don't care about the value.
|
||||
if ('piece_id' in queryParams) {
|
||||
PieceActions.fetchPiece(queryParams.piece_id);
|
||||
if ('piece_id' in query) {
|
||||
PieceActions.fetchPiece(query.piece_id);
|
||||
}
|
||||
|
||||
// Warn the user if they try to leave before completing registration
|
||||
router.setRouteLeaveHook(route, () => this.state.pageExitWarning);
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -92,7 +95,7 @@ let IkonotvRegisterPiece = React.createClass({
|
||||
}
|
||||
|
||||
if (!this.canSubmit()) {
|
||||
this.history.push('/collection');
|
||||
this.props.router.push('/collection');
|
||||
} else {
|
||||
this.nextSlide({ piece_id: response.piece.id });
|
||||
}
|
||||
@ -117,7 +120,7 @@ let IkonotvRegisterPiece = React.createClass({
|
||||
|
||||
this.refreshPieceList();
|
||||
|
||||
this.history.push(`/pieces/${this.state.piece.id}`);
|
||||
this.props.router.push(`/pieces/${this.state.piece.id}`);
|
||||
},
|
||||
|
||||
nextSlide(queryParams) {
|
||||
@ -210,7 +213,6 @@ let IkonotvRegisterPiece = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { location } = this.props;
|
||||
const { pageExitWarning, step } = this.state;
|
||||
|
||||
return (
|
||||
@ -221,7 +223,6 @@ let IkonotvRegisterPiece = React.createClass({
|
||||
pending: 'glyphicon glyphicon-chevron-right',
|
||||
completed: 'glyphicon glyphicon-lock'
|
||||
}}
|
||||
location={location}
|
||||
pageExitWarning={pageExitWarning}>
|
||||
<div data-slide-title={getLangText('Register work')}>
|
||||
<Row className="no-margin">
|
||||
@ -245,4 +246,4 @@ let IkonotvRegisterPiece = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default IkonotvRegisterPiece;
|
||||
export default withContext(IkonotvRegisterPiece, 'currentUser', 'location', 'router', 'whitelabel');
|
||||
|
@ -5,18 +5,17 @@ import React from 'react';
|
||||
import Button from 'react-bootstrap/lib/Button';
|
||||
import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
|
||||
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
import withContext from '../../../../context/with_context';
|
||||
import { whitelabelShape } from '../../../../prop_types';
|
||||
|
||||
import { setDocumentTitle } from '../../../../../utils/dom_utils';
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
|
||||
|
||||
let LumenusLanding = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
whitelabel: whitelabelShape.isRequired,
|
||||
},
|
||||
|
||||
componentWillMount() {
|
||||
@ -66,4 +65,4 @@ let LumenusLanding = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default LumenusLanding;
|
||||
export default withContext(LumenusLanding, 'whitelabel');
|
||||
|
@ -14,10 +14,8 @@ import { selectFromObject } from '../../../../../../utils/general_utils';
|
||||
let MarketAclButtonList = React.createClass({
|
||||
propTypes: {
|
||||
availableAcls: React.PropTypes.object.isRequired,
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
handleSuccess: React.PropTypes.func.isRequired,
|
||||
pieceOrEditions: React.PropTypes.array.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
children: React.PropTypes.oneOfType([
|
||||
React.PropTypes.arrayOf(React.PropTypes.element),
|
||||
@ -27,17 +25,16 @@ let MarketAclButtonList = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { availableAcls,
|
||||
const {
|
||||
availableAcls,
|
||||
children,
|
||||
className,
|
||||
currentUser,
|
||||
handleSuccess,
|
||||
pieceOrEditions,
|
||||
whitelabel } = this.props;
|
||||
pieceOrEditions
|
||||
} = this.props;
|
||||
|
||||
const buttonProps = selectFromObject(this.props, [
|
||||
'availableAcls',
|
||||
'currentUser',
|
||||
'handleSuccess',
|
||||
'pieceOrEditions'
|
||||
]);
|
||||
@ -46,10 +43,8 @@ let MarketAclButtonList = React.createClass({
|
||||
<div className={className}>
|
||||
<MarketSubmitButton
|
||||
availableAcls={availableAcls}
|
||||
currentUser={currentUser}
|
||||
editions={pieceOrEditions}
|
||||
handleSuccess={handleSuccess}
|
||||
whitelabel={whitelabel} />
|
||||
handleSuccess={handleSuccess} />
|
||||
<EmailButton {...buttonProps} />
|
||||
<TransferButton {...buttonProps} />
|
||||
<UnconsignButton {...buttonProps} />
|
||||
|
@ -10,13 +10,12 @@ import MarketAdditionalDataForm from '../market_forms/market_additional_data_for
|
||||
import MarketErrorConsignUnavailable from '../market_error_consign_unavailable';
|
||||
|
||||
import AclFormFactory from '../../../../../ascribe_forms/acl_form_factory';
|
||||
import ConsignForm from '../../../../../ascribe_forms/form_consign';
|
||||
|
||||
import ModalWrapper from '../../../../../ascribe_modal/modal_wrapper';
|
||||
|
||||
import AclProxy from '../../../../../acl_proxy';
|
||||
|
||||
import ApiUrls from '../../../../../../constants/api_urls';
|
||||
import withContext from '../../../../../context/with_context';
|
||||
import { currentUserShape, whitelabelShape } from '../../../../../prop_types';
|
||||
|
||||
import { getAclFormMessage, getAclFormDataId } from '../../../../../../utils/form_utils';
|
||||
import { getLangText } from '../../../../../../utils/lang_utils';
|
||||
@ -24,12 +23,14 @@ import { getLangText } from '../../../../../../utils/lang_utils';
|
||||
let MarketSubmitButton = React.createClass({
|
||||
propTypes: {
|
||||
availableAcls: React.PropTypes.object.isRequired,
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
editions: React.PropTypes.array.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
className: React.PropTypes.string,
|
||||
handleSuccess: React.PropTypes.func
|
||||
handleSuccess: React.PropTypes.func,
|
||||
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
whitelabel: whitelabelShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
canEditionBeSubmitted(edition) {
|
||||
@ -81,12 +82,14 @@ let MarketSubmitButton = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { availableAcls,
|
||||
const {
|
||||
availableAcls,
|
||||
currentUser,
|
||||
className,
|
||||
editions,
|
||||
handleSuccess,
|
||||
whitelabel: { name: whitelabelName = 'Market', user: whitelabelAdminEmail } } = this.props;
|
||||
whitelabel: { name: whitelabelName = 'Market', user: whitelabelAdminEmail }
|
||||
} = this.props;
|
||||
|
||||
const { solePieceId, canEdit, canSubmit } = this.getAggregateEditionDetails();
|
||||
const message = getAclFormMessage({
|
||||
@ -184,4 +187,4 @@ let MarketSubmitButton = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default MarketSubmitButton;
|
||||
export default withContext(MarketSubmitButton, 'currentUser', 'whitelabel');
|
||||
|
@ -5,18 +5,17 @@ import React from 'react';
|
||||
import Button from 'react-bootstrap/lib/Button';
|
||||
import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
|
||||
|
||||
import WhitelabelActions from '../../../../../actions/whitelabel_actions';
|
||||
import WhitelabelStore from '../../../../../stores/whitelabel_store';
|
||||
import withContext from '../../../../context/with_context';
|
||||
import { whitelabelShape } from '../../../../prop_types';
|
||||
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
import { setDocumentTitle } from '../../../../../utils/dom_utils';
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
|
||||
|
||||
let MarketLanding = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object.isRequired
|
||||
// Injected through HOCs
|
||||
whitelabel: whitelabelShape.isRequired,
|
||||
},
|
||||
|
||||
componentDidUpdate() {
|
||||
@ -70,4 +69,4 @@ let MarketLanding = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default MarketLanding;
|
||||
export default withContext(MarketLanding, 'whitelabel');
|
||||
|
@ -4,22 +4,20 @@ import React from 'react';
|
||||
|
||||
import MarketAclButtonList from './market_buttons/market_acl_button_list';
|
||||
|
||||
import withContext from '../../../../context/with_context';
|
||||
import PieceList from '../../../../piece_list';
|
||||
import { currentUserShape, whitelabelShape } from '../../../../prop_types';
|
||||
|
||||
import { setDocumentTitle } from '../../../../../utils/dom_utils';
|
||||
import { mergeOptions } from '../../../../../utils/general_utils';
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
|
||||
let MarketPieceList = React.createClass({
|
||||
propTypes: {
|
||||
customThumbnailPlaceholder: React.PropTypes.func,
|
||||
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object.isRequired,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
currentUser: currentUserShape.isRequired, // eslint-disable-line react/sort-prop-types
|
||||
whitelabel: whitelabelShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
componentWillMount() {
|
||||
@ -27,11 +25,13 @@ let MarketPieceList = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { currentUser: { email: userEmail },
|
||||
const {
|
||||
currentUser: { email: userEmail },
|
||||
whitelabel: {
|
||||
name: whitelabelName = 'Market',
|
||||
user: whitelabelAdminEmail
|
||||
} } = this.props;
|
||||
}
|
||||
} = this.props;
|
||||
|
||||
let filterParams = null;
|
||||
let isUserAdmin = null;
|
||||
@ -68,4 +68,4 @@ let MarketPieceList = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default MarketPieceList;
|
||||
export default withContext(MarketPieceList, 'currentUser', 'whitelabel');
|
||||
|
@ -1,7 +1,4 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { History } from 'react-router';
|
||||
|
||||
import Col from 'react-bootstrap/lib/Col';
|
||||
import Row from 'react-bootstrap/lib/Row';
|
||||
@ -19,22 +16,21 @@ import RegisterPieceForm from '../../../../ascribe_forms/form_register_piece';
|
||||
|
||||
import SlidesContainer from '../../../../ascribe_slides_container/slides_container';
|
||||
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
import withContext from '../../../../context/with_context';
|
||||
import { locationShape, routerShape, whitelabelShape } from '../../../../prop_types';
|
||||
|
||||
import { setDocumentTitle } from '../../../../../utils/dom_utils';
|
||||
import { mergeOptions } from '../../../../../utils/general_utils';
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
|
||||
let MarketRegisterPiece = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object.isRequired,
|
||||
|
||||
// Provided from router
|
||||
location: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
router: routerShape.isRequired,
|
||||
location: locationShape.isRequired,
|
||||
whitelabel: whitelabelShape.isRequired
|
||||
},
|
||||
|
||||
mixins: [History],
|
||||
|
||||
getInitialState(){
|
||||
return mergeOptions(
|
||||
PieceListStore.getState(),
|
||||
@ -82,7 +78,7 @@ let MarketRegisterPiece = React.createClass({
|
||||
handleAdditionalDataSuccess() {
|
||||
this.refreshPieceList();
|
||||
|
||||
this.history.push('/collection');
|
||||
this.props.router.push('/collection');
|
||||
},
|
||||
|
||||
nextSlide(queryParams) {
|
||||
@ -101,10 +97,7 @@ let MarketRegisterPiece = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
const { location,
|
||||
whitelabel: {
|
||||
name: whitelabelName = 'Market'
|
||||
} } = this.props
|
||||
const { whitelabel: { name: whitelabelName = 'Market' } } = this.props;
|
||||
const { piece, step } = this.state;
|
||||
|
||||
setDocumentTitle(getLangText('Register a new piece'));
|
||||
@ -116,8 +109,7 @@ let MarketRegisterPiece = React.createClass({
|
||||
glyphiconClassNames={{
|
||||
pending: 'glyphicon glyphicon-chevron-right',
|
||||
completed: 'glyphicon glyphicon-lock'
|
||||
}}
|
||||
location={location}>
|
||||
}}>
|
||||
<div data-slide-title={getLangText('Register work')}>
|
||||
<Row className="no-margin">
|
||||
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
|
||||
@ -160,4 +152,4 @@ let MarketRegisterPiece = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default MarketRegisterPiece;
|
||||
export default withContext(MarketRegisterPiece, 'location', 'router', 'whitelabel');
|
||||
|
@ -5,18 +5,17 @@ import React from 'react';
|
||||
import Button from 'react-bootstrap/lib/Button';
|
||||
import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
|
||||
|
||||
import WhitelabelActions from '../../../../../actions/whitelabel_actions';
|
||||
import WhitelabelStore from '../../../../../stores/whitelabel_store';
|
||||
import withContext from '../../../../context/with_context';
|
||||
import { whitelabelShape } from '../../../../prop_types';
|
||||
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
import { setDocumentTitle } from '../../../../../utils/dom_utils';
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
|
||||
|
||||
let PollineLanding = React.createClass({
|
||||
propTypes: {
|
||||
// Provided from WalletApp
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object.isRequired
|
||||
// Injected through HOCs
|
||||
whitelabel: whitelabelShape.isRequired,
|
||||
},
|
||||
|
||||
componentWillMount() {
|
||||
@ -64,4 +63,4 @@ let PollineLanding = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default PollineLanding;
|
||||
export default withContext(PollineLanding, 'whitelabel');
|
||||
|
@ -1,11 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import AppBase from '../../app_base';
|
||||
import AppRouteWrapper from '../../app_route_wrapper';
|
||||
import withContext from '../../context/with_context';
|
||||
import Header from '../../header';
|
||||
import { routerShape } from '../../prop_types';
|
||||
|
||||
import { getSubdomain } from '../../../utils/general_utils';
|
||||
|
||||
@ -14,31 +13,26 @@ let WalletApp = React.createClass({
|
||||
propTypes: {
|
||||
activeRoute: React.PropTypes.object.isRequired,
|
||||
children: React.PropTypes.element.isRequired,
|
||||
history: React.PropTypes.object.isRequired,
|
||||
routes: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
|
||||
|
||||
// Provided from AppBase
|
||||
currentUser: React.PropTypes.object,
|
||||
whitelabel: React.PropTypes.object
|
||||
// Injected through HOCs
|
||||
router: routerShape.isRequired // eslint-disable-line react/sort-prop-types
|
||||
},
|
||||
|
||||
render() {
|
||||
const { activeRoute, children, currentUser, history, routes, whitelabel } = this.props;
|
||||
const { activeRoute, children, router, routes } = this.props;
|
||||
const subdomain = getSubdomain();
|
||||
const path = activeRoute && activeRoute.path;
|
||||
const Footer = activeRoute && activeRoute.footer;
|
||||
const RouteFooterType = activeRoute && activeRoute.footer;
|
||||
|
||||
let header = null;
|
||||
// if the path of the current activeRoute is not defined, then this is the IndexRoute
|
||||
if ((!path || history.isActive('/login') || history.isActive('/signup') || history.isActive('/contract_notifications'))
|
||||
if ((!path || router.isActive('/login') || router.isActive('/signup') || router.isActive('/contract_notifications'))
|
||||
&& (['cyland', 'ikonotv', 'lumenus', '23vivi', 'polline', 'artcity', 'demo', 'liquidgallery']).includes(subdomain)) {
|
||||
header = (<div className="hero"/>);
|
||||
} else {
|
||||
header = (
|
||||
<Header
|
||||
currentUser={currentUser}
|
||||
routes={routes}
|
||||
whitelabel={whitelabel} />
|
||||
<Header routes={routes} />
|
||||
);
|
||||
}
|
||||
|
||||
@ -47,16 +41,14 @@ let WalletApp = React.createClass({
|
||||
return (
|
||||
<div className={classNames('ascribe-app', 'ascribe-wallet-app', `route--${(path ? path.split('/')[0] : 'landing')}`)}>
|
||||
{header}
|
||||
<AppRouteWrapper
|
||||
currentUser={currentUser}
|
||||
whitelabel={whitelabel}>
|
||||
<div className="container ascribe-body">
|
||||
{/* Routes are injected here */}
|
||||
{children}
|
||||
</AppRouteWrapper>
|
||||
{Footer ? <Footer /> : null}
|
||||
</div>
|
||||
{RouteFooterType ? <RouteFooterType /> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default AppBase(WalletApp);
|
||||
export default AppBase(withContext(WalletApp, 'router'));
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Redirect } from 'react-router';
|
||||
import Redirect from 'react-router/es6/Redirect';
|
||||
|
||||
import getWalletApiUrls from './constants/wallet_api_urls';
|
||||
import getWalletRoutes from './wallet_routes';
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Route, IndexRoute } from 'react-router';
|
||||
import IndexRoute from 'react-router/es6/IndexRoute';
|
||||
import Route from 'react-router/es6/Route';
|
||||
|
||||
import { ProxyHandler, AuthRedirect } from '../../../components/ascribe_routes/proxy_handler';
|
||||
|
||||
|
@ -1,12 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
import useBasename from 'history/lib/useBasename';
|
||||
import useQueries from 'history/lib/useQueries';
|
||||
import useRouterHistory from 'react-router/es6/useRouterHistory';
|
||||
import createBrowserHistory from 'history/lib/createBrowserHistory';
|
||||
|
||||
import AppConstants from './constants/application_constants';
|
||||
|
||||
|
||||
const history = useBasename(useQueries(createBrowserHistory))({
|
||||
const history = useRouterHistory(createBrowserHistory)({
|
||||
basename: AppConstants.baseUrl
|
||||
});
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Route } from 'react-router';
|
||||
import Route from 'react-router/es6/Route';
|
||||
|
||||
import AscribeApp from './components/ascribe_app';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import update from 'react-addons-update';
|
||||
|
||||
import { alt } from '../alt';
|
||||
import EditionsListActions from '../actions/edition_list_actions';
|
||||
@ -30,7 +30,7 @@ class EditionListStore {
|
||||
|
||||
// if edition already exists, just merge
|
||||
if (pieceEditionList[storeEditionIndex]) {
|
||||
pieceEditionList[storeEditionIndex] = React.addons.update(pieceEditionList[storeEditionIndex], { $merge: updatedEdition });
|
||||
pieceEditionList[storeEditionIndex] = update(pieceEditionList[storeEditionIndex], { $merge: updatedEdition });
|
||||
} else {
|
||||
// if does not exist, assign
|
||||
pieceEditionList[storeEditionIndex] = updatedEdition;
|
||||
|
@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import update from 'react-addons-update';
|
||||
import { alt } from '../alt';
|
||||
|
||||
import PieceListActions from '../actions/piece_list_actions';
|
||||
@ -62,7 +62,7 @@ class PieceListStore {
|
||||
pieceList.forEach((piece, i) => {
|
||||
const oldPiece = this.pieceList[i];
|
||||
if (oldPiece) {
|
||||
piece = React.addons.update(piece, {
|
||||
piece = update(piece, {
|
||||
show: { $set: oldPiece.show }
|
||||
});
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ class WhitelabelStore {
|
||||
this.whitelabel = whitelabel;
|
||||
}
|
||||
|
||||
onErrorCurrentUser(err) {
|
||||
onErrorWhitelabel(err) {
|
||||
console.logGlobal(err);
|
||||
this.whitelabelMeta.err = err;
|
||||
}
|
||||
|
7
js/utils/react_utils.js
Normal file
7
js/utils/react_utils.js
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Taken from react-router (https://github.com/reactjs/react-router/blob/master/modules/withRouter.js)
|
||||
* FIXME: should be put into react-component's utils
|
||||
*/
|
||||
export function getDisplayName(WrappedComponent) {
|
||||
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
|
||||
}
|
19
package.json
19
package.json
@ -88,9 +88,8 @@
|
||||
"express": "^4.13.4",
|
||||
"extract-text-webpack-plugin": "^1.0.1",
|
||||
"file-loader": "^0.8.5",
|
||||
"history": "1.17.0",
|
||||
"html-webpack-plugin": "^2.19.0",
|
||||
"invariant": "^2.1.1",
|
||||
"invariant": "^2.2.1",
|
||||
"isomorphic-fetch": "^2.0.2",
|
||||
"moment": "^2.10.6",
|
||||
"node-sass": "^3.7.0",
|
||||
@ -98,13 +97,15 @@
|
||||
"q": "^1.4.1",
|
||||
"query-string": "^3.0.0",
|
||||
"raven-js": "^1.1.19",
|
||||
"react": "0.13.2",
|
||||
"react-bootstrap": "0.25.1",
|
||||
"react-datepicker": "^0.12.0",
|
||||
"react-router": "1.0.3",
|
||||
"react-router-bootstrap": "^0.19.0",
|
||||
"react-star-rating": "~1.3.2",
|
||||
"react-textarea-autosize": "^2.5.2",
|
||||
"react": "^15.1.0",
|
||||
"react-addons-update": "^15.1.0",
|
||||
"react-bootstrap": "^0.29.4",
|
||||
"react-datepicker": "^0.27.0",
|
||||
"react-dom": "^15.1.0",
|
||||
"react-router": "^2.4.1",
|
||||
"react-router-bootstrap": "^0.23.0",
|
||||
"react-star-rating": "^1.4.2",
|
||||
"react-textarea-autosize": "^4.0.2",
|
||||
"react-transform-hmr": "^1.0.4",
|
||||
"remove-trailing-slash": "^0.1.0",
|
||||
"resolve-url-loader": "^1.4.3",
|
||||
|
@ -20,6 +20,10 @@ config.entry.unshift(`webpack-dev-server/client?http://${HOST}:${PORT}/`,
|
||||
'webpack/hot/dev-server');
|
||||
config.plugins.push(new webpack.HotModuleReplacementPlugin());
|
||||
|
||||
// Set absolute url for public path to avoid OTS parsing errors in Chrome
|
||||
// See http://stackoverflow.com/questions/34133808/webpack-ots-parsing-error-loading-fonts
|
||||
config.output.publicPath = `http://${HOST}:${PORT}${config.output.publicPath}`;
|
||||
|
||||
// Configure server
|
||||
const compiler = webpack(config);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user