mirror of
https://github.com/ascribe/onion.git
synced 2025-02-14 21:10:27 +01:00
Merge pull request #95 from ascribe/add-default-should-redirect
Collection should redirect to Register Work when a user does not have pieces yet
This commit is contained in:
commit
d8f2423344
@ -18,6 +18,8 @@ import AclProxy from './acl_proxy';
|
|||||||
|
|
||||||
import EventActions from '../actions/event_actions';
|
import EventActions from '../actions/event_actions';
|
||||||
|
|
||||||
|
import PieceListStore from '../stores/piece_list_store';
|
||||||
|
|
||||||
import UserActions from '../actions/user_actions';
|
import UserActions from '../actions/user_actions';
|
||||||
import UserStore from '../stores/user_store';
|
import UserStore from '../stores/user_store';
|
||||||
|
|
||||||
@ -43,12 +45,17 @@ let Header = React.createClass({
|
|||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return mergeOptions(
|
return mergeOptions(
|
||||||
|
PieceListStore.getState(),
|
||||||
WhitelabelStore.getState(),
|
WhitelabelStore.getState(),
|
||||||
UserStore.getState()
|
UserStore.getState()
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
// 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);
|
||||||
|
|
||||||
UserStore.listen(this.onChange);
|
UserStore.listen(this.onChange);
|
||||||
UserActions.fetchCurrentUser.defer();
|
UserActions.fetchCurrentUser.defer();
|
||||||
|
|
||||||
@ -75,11 +82,16 @@ let Header = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
PieceListStore.unlisten(this.onChange);
|
||||||
UserStore.unlisten(this.onChange);
|
UserStore.unlisten(this.onChange);
|
||||||
WhitelabelStore.unlisten(this.onChange);
|
WhitelabelStore.unlisten(this.onChange);
|
||||||
//history.unlisten(this.onRouteChange);
|
//history.unlisten(this.onRouteChange);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onChange(state) {
|
||||||
|
this.setState(state);
|
||||||
|
},
|
||||||
|
|
||||||
getLogo() {
|
getLogo() {
|
||||||
let { whitelabel } = this.state;
|
let { whitelabel } = this.state;
|
||||||
|
|
||||||
@ -93,16 +105,16 @@ let Header = React.createClass({
|
|||||||
<img className="img-brand" src={whitelabel.logo} alt="Whitelabel brand"/>
|
<img className="img-brand" src={whitelabel.logo} alt="Whitelabel brand"/>
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
<Link className="icon-ascribe-logo" to="/collection"/>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
<Link className="icon-ascribe-logo" to="/collection"/>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getPoweredBy(){
|
getPoweredBy() {
|
||||||
return (
|
return (
|
||||||
<AclProxy
|
<AclProxy
|
||||||
aclObject={this.state.whitelabel}
|
aclObject={this.state.whitelabel}
|
||||||
@ -117,10 +129,6 @@ let Header = React.createClass({
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
onChange(state) {
|
|
||||||
this.setState(state);
|
|
||||||
},
|
|
||||||
|
|
||||||
onMenuItemClick() {
|
onMenuItemClick() {
|
||||||
/*
|
/*
|
||||||
This is a hack to make the dropdown close after clicking on an item
|
This is a hack to make the dropdown close after clicking on an item
|
||||||
@ -156,15 +164,17 @@ let Header = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { currentUser, unfilteredPieceListCount } = this.state;
|
||||||
let account;
|
let account;
|
||||||
let signup;
|
let signup;
|
||||||
let navRoutesLinks;
|
let navRoutesLinks;
|
||||||
if (this.state.currentUser.username){
|
|
||||||
|
if (currentUser.username) {
|
||||||
account = (
|
account = (
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
ref='dropdownbutton'
|
ref='dropdownbutton'
|
||||||
eventKey="1"
|
eventKey="1"
|
||||||
title={this.state.currentUser.username}>
|
title={currentUser.username}>
|
||||||
<LinkContainer
|
<LinkContainer
|
||||||
to="/settings"
|
to="/settings"
|
||||||
onClick={this.onMenuItemClick}>
|
onClick={this.onMenuItemClick}>
|
||||||
@ -174,7 +184,7 @@ let Header = React.createClass({
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</LinkContainer>
|
</LinkContainer>
|
||||||
<AclProxy
|
<AclProxy
|
||||||
aclObject={this.state.currentUser.acl}
|
aclObject={currentUser.acl}
|
||||||
aclName="acl_view_settings_contract">
|
aclName="acl_view_settings_contract">
|
||||||
<LinkContainer
|
<LinkContainer
|
||||||
to="/contract_settings"
|
to="/contract_settings"
|
||||||
@ -195,9 +205,21 @@ let Header = React.createClass({
|
|||||||
</LinkContainer>
|
</LinkContainer>
|
||||||
</DropdownButton>
|
</DropdownButton>
|
||||||
);
|
);
|
||||||
navRoutesLinks = <NavRoutesLinks routes={this.props.routes} userAcl={this.state.currentUser.acl} navbar right/>;
|
|
||||||
}
|
// Let's assume that if the piece list hasn't loaded yet (ie. when unfilteredPieceListCount === -1)
|
||||||
else {
|
// then the user has pieces
|
||||||
|
// FIXME: this doesn't work that well as the user may not load their piece list
|
||||||
|
// until much later, so we would show the 'Collection' header as available until
|
||||||
|
// they actually click on it and get redirected to piece registration.
|
||||||
|
navRoutesLinks = (
|
||||||
|
<NavRoutesLinks
|
||||||
|
navbar
|
||||||
|
right
|
||||||
|
hasPieces={!!unfilteredPieceListCount}
|
||||||
|
routes={this.props.routes}
|
||||||
|
userAcl={currentUser.acl} />
|
||||||
|
);
|
||||||
|
} else {
|
||||||
account = (
|
account = (
|
||||||
<LinkContainer
|
<LinkContainer
|
||||||
to="/login">
|
to="/login">
|
||||||
|
@ -11,14 +11,33 @@ import AclProxy from './acl_proxy';
|
|||||||
import { sanitizeList } from '../utils/general_utils';
|
import { sanitizeList } from '../utils/general_utils';
|
||||||
|
|
||||||
|
|
||||||
|
const DISABLE_ENUM = ['hasPieces', 'noPieces'];
|
||||||
|
|
||||||
let NavRoutesLinks = React.createClass({
|
let NavRoutesLinks = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
hasPieces: React.PropTypes.bool,
|
||||||
routes: React.PropTypes.arrayOf(React.PropTypes.object),
|
routes: React.PropTypes.arrayOf(React.PropTypes.object),
|
||||||
userAcl: React.PropTypes.object
|
userAcl: React.PropTypes.object
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isRouteDisabled(disableOn) {
|
||||||
|
const { hasPieces } = this.props;
|
||||||
|
|
||||||
|
if (disableOn) {
|
||||||
|
if (!DISABLE_ENUM.includes(disableOn)) {
|
||||||
|
throw new Error(`"disableOn" must be one of: [${DISABLE_ENUM.join(', ')}] got "${disableOn}" instead`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disableOn === 'hasPieces') {
|
||||||
|
return hasPieces;
|
||||||
|
} else if (disableOn === 'noPieces') {
|
||||||
|
return !hasPieces;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method generales a bunch of react-bootstrap specific links
|
* This method generates a bunch of react-bootstrap specific links
|
||||||
* from the routes we defined in one of the specific routes.js file
|
* from the routes we defined in one of the specific routes.js file
|
||||||
*
|
*
|
||||||
* We can define a headerTitle as well as a aclName and according to that the
|
* We can define a headerTitle as well as a aclName and according to that the
|
||||||
@ -29,48 +48,50 @@ let NavRoutesLinks = React.createClass({
|
|||||||
* @return {Array} Array of ReactElements that can be displayed to the user
|
* @return {Array} Array of ReactElements that can be displayed to the user
|
||||||
*/
|
*/
|
||||||
extractLinksFromRoutes(node, userAcl, i) {
|
extractLinksFromRoutes(node, userAcl, i) {
|
||||||
if(!node) {
|
if (!node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let links = node.childRoutes.map((child, j) => {
|
const links = node.childRoutes.map((child, j) => {
|
||||||
let childrenFn = null;
|
const { aclName, disableOn, headerTitle, path, childRoutes } = child;
|
||||||
let { aclName, headerTitle, path, childRoutes } = child;
|
|
||||||
|
|
||||||
// If the node has children that could be rendered, then we want
|
|
||||||
// to execute this function again with the child as the root
|
|
||||||
//
|
|
||||||
// Otherwise we'll just pass childrenFn as false
|
|
||||||
if(child.childRoutes && child.childRoutes.length > 0) {
|
|
||||||
childrenFn = this.extractLinksFromRoutes(child, userAcl, i++);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We validate if the user has set the title correctly,
|
// We validate if the user has set the title correctly,
|
||||||
// otherwise we're not going to render his route
|
// otherwise we're not going to render his route
|
||||||
if(headerTitle && typeof headerTitle === 'string') {
|
if (headerTitle && typeof headerTitle === 'string') {
|
||||||
|
let nestedChildren = null;
|
||||||
|
|
||||||
|
// If the node has children that could be rendered, then we want
|
||||||
|
// to execute this function again with the child as the root
|
||||||
|
//
|
||||||
|
// Otherwise we'll just pass nestedChildren as false
|
||||||
|
if (child.childRoutes && child.childRoutes.length) {
|
||||||
|
nestedChildren = this.extractLinksFromRoutes(child, userAcl, i++);
|
||||||
|
}
|
||||||
|
|
||||||
|
const navLinkProps = {
|
||||||
|
headerTitle,
|
||||||
|
children: nestedChildren,
|
||||||
|
depth: i,
|
||||||
|
disabled: this.isRouteDisabled(disableOn),
|
||||||
|
routePath: `/${path}`
|
||||||
|
};
|
||||||
|
|
||||||
// if there is an aclName present on the route definition,
|
// if there is an aclName present on the route definition,
|
||||||
// we evaluate it against the user's acl
|
// we evaluate it against the user's acl
|
||||||
if(aclName && typeof aclName !== 'undefined') {
|
if (aclName && typeof aclName !== 'undefined') {
|
||||||
return (
|
return (
|
||||||
<AclProxy
|
<AclProxy
|
||||||
key={j}
|
key={j}
|
||||||
aclName={aclName}
|
aclName={aclName}
|
||||||
aclObject={this.props.userAcl}>
|
aclObject={this.props.userAcl}>
|
||||||
<NavRoutesLinksLink
|
<NavRoutesLinksLink {...navLinkProps} />
|
||||||
headerTitle={headerTitle}
|
|
||||||
routePath={'/' + path}
|
|
||||||
depth={i}
|
|
||||||
children={childrenFn}/>
|
|
||||||
</AclProxy>
|
</AclProxy>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<NavRoutesLinksLink
|
<NavRoutesLinksLink
|
||||||
key={j}
|
key={j}
|
||||||
headerTitle={headerTitle}
|
{...navLinkProps} />
|
||||||
routePath={'/' + path}
|
|
||||||
depth={i}
|
|
||||||
children={childrenFn}/>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -84,7 +105,7 @@ let NavRoutesLinks = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {routes, userAcl} = this.props;
|
const {routes, userAcl} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Nav {...this.props}>
|
<Nav {...this.props}>
|
||||||
@ -94,4 +115,4 @@ let NavRoutesLinks = React.createClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default NavRoutesLinks;
|
export default NavRoutesLinks;
|
||||||
|
@ -11,40 +11,45 @@ import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
|
|||||||
|
|
||||||
let NavRoutesLinksLink = React.createClass({
|
let NavRoutesLinksLink = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
headerTitle: React.PropTypes.string,
|
|
||||||
routePath: React.PropTypes.string,
|
|
||||||
|
|
||||||
children: React.PropTypes.oneOfType([
|
children: React.PropTypes.oneOfType([
|
||||||
React.PropTypes.arrayOf(React.PropTypes.element),
|
React.PropTypes.arrayOf(React.PropTypes.element),
|
||||||
React.PropTypes.element
|
React.PropTypes.element
|
||||||
]),
|
]),
|
||||||
|
disabled: React.PropTypes.bool,
|
||||||
depth: React.PropTypes.number
|
depth: React.PropTypes.number,
|
||||||
|
headerTitle: React.PropTypes.string,
|
||||||
|
routePath: React.PropTypes.string
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let { children, headerTitle, depth, routePath } = this.props;
|
const { children, headerTitle, depth, disabled, routePath } = this.props;
|
||||||
|
|
||||||
// if the route has children, we're returning a DropdownButton that will get filled
|
// if the route has children, we're returning a DropdownButton that will get filled
|
||||||
// with MenuItems
|
// with MenuItems
|
||||||
if(children) {
|
if (children) {
|
||||||
return (
|
return (
|
||||||
<DropdownButton title={headerTitle}>
|
<DropdownButton
|
||||||
|
disabled={disabled}
|
||||||
|
title={headerTitle}>
|
||||||
{children}
|
{children}
|
||||||
</DropdownButton>
|
</DropdownButton>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if(depth === 1) {
|
if (depth === 1) {
|
||||||
// if the node's child is actually a node of level one (a child of a node), we're
|
// if the node's child is actually a node of level one (a child of a node), we're
|
||||||
// returning a DropdownButton matching MenuItem
|
// returning a DropdownButton matching MenuItem
|
||||||
return (
|
return (
|
||||||
<LinkContainer to={routePath}>
|
<LinkContainer
|
||||||
|
disabled={disabled}
|
||||||
|
to={routePath}>
|
||||||
<MenuItem>{headerTitle}</MenuItem>
|
<MenuItem>{headerTitle}</MenuItem>
|
||||||
</LinkContainer>
|
</LinkContainer>
|
||||||
);
|
);
|
||||||
} else if(depth === 0) {
|
} else if (depth === 0) {
|
||||||
return (
|
return (
|
||||||
<LinkContainer to={routePath}>
|
<LinkContainer
|
||||||
|
disabled={disabled}
|
||||||
|
to={routePath}>
|
||||||
<NavItem>{headerTitle}</NavItem>
|
<NavItem>{headerTitle}</NavItem>
|
||||||
</LinkContainer>
|
</LinkContainer>
|
||||||
);
|
);
|
||||||
@ -55,4 +60,4 @@ let NavRoutesLinksLink = React.createClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default NavRoutesLinksLink;
|
export default NavRoutesLinksLink;
|
||||||
|
@ -53,7 +53,6 @@ let PieceList = React.createClass({
|
|||||||
accordionListItemType: AccordionListItemWallet,
|
accordionListItemType: AccordionListItemWallet,
|
||||||
bulkModalButtonListType: AclButtonList,
|
bulkModalButtonListType: AclButtonList,
|
||||||
canLoadPieceList: true,
|
canLoadPieceList: true,
|
||||||
orderParams: ['artist_name', 'title'],
|
|
||||||
filterParams: [{
|
filterParams: [{
|
||||||
label: getLangText('Show works I can'),
|
label: getLangText('Show works I can'),
|
||||||
items: [
|
items: [
|
||||||
@ -61,7 +60,10 @@ let PieceList = React.createClass({
|
|||||||
'acl_consign',
|
'acl_consign',
|
||||||
'acl_create_editions'
|
'acl_create_editions'
|
||||||
]
|
]
|
||||||
}]
|
}],
|
||||||
|
orderParams: ['artist_name', 'title'],
|
||||||
|
redirectTo: '/register_piece',
|
||||||
|
shouldRedirect: () => true
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -75,7 +75,6 @@ let PrizePieceList = React.createClass({
|
|||||||
<div>
|
<div>
|
||||||
<PieceList
|
<PieceList
|
||||||
ref="list"
|
ref="list"
|
||||||
redirectTo="/register_piece"
|
|
||||||
accordionListItemType={AccordionListItemPrize}
|
accordionListItemType={AccordionListItemPrize}
|
||||||
orderParams={orderParams}
|
orderParams={orderParams}
|
||||||
orderBy={this.state.currentUser.is_jury ? 'rating' : null}
|
orderBy={this.state.currentUser.is_jury ? 'rating' : null}
|
||||||
|
@ -75,7 +75,8 @@ let ROUTES = {
|
|||||||
<Route
|
<Route
|
||||||
path='collection'
|
path='collection'
|
||||||
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(CylandPieceList)}
|
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(CylandPieceList)}
|
||||||
headerTitle='COLLECTION' />
|
headerTitle='COLLECTION'
|
||||||
|
disableOn='noPieces' />
|
||||||
<Route path='editions/:editionId' component={EditionContainer} />
|
<Route path='editions/:editionId' component={EditionContainer} />
|
||||||
<Route path='verify' component={CoaVerifyContainer} />
|
<Route path='verify' component={CoaVerifyContainer} />
|
||||||
<Route path='pieces/:pieceId' component={CylandPieceContainer} />
|
<Route path='pieces/:pieceId' component={CylandPieceContainer} />
|
||||||
@ -109,7 +110,8 @@ let ROUTES = {
|
|||||||
<Route
|
<Route
|
||||||
path='collection'
|
path='collection'
|
||||||
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(PieceList)}
|
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(PieceList)}
|
||||||
headerTitle='COLLECTION' />
|
headerTitle='COLLECTION'
|
||||||
|
disableOn='noPieces' />
|
||||||
<Route path='pieces/:pieceId' component={PieceContainer} />
|
<Route path='pieces/:pieceId' component={PieceContainer} />
|
||||||
<Route path='editions/:editionId' component={EditionContainer} />
|
<Route path='editions/:editionId' component={EditionContainer} />
|
||||||
<Route path='verify' component={CoaVerifyContainer} />
|
<Route path='verify' component={CoaVerifyContainer} />
|
||||||
@ -150,7 +152,8 @@ let ROUTES = {
|
|||||||
<Route
|
<Route
|
||||||
path='collection'
|
path='collection'
|
||||||
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(IkonotvPieceList)}
|
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(IkonotvPieceList)}
|
||||||
headerTitle='COLLECTION' />
|
headerTitle='COLLECTION'
|
||||||
|
disableOn='noPieces' />
|
||||||
<Route
|
<Route
|
||||||
path='contract_notifications'
|
path='contract_notifications'
|
||||||
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(IkonotvContractNotifications)} />
|
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(IkonotvContractNotifications)} />
|
||||||
@ -189,7 +192,8 @@ let ROUTES = {
|
|||||||
<Route
|
<Route
|
||||||
path='collection'
|
path='collection'
|
||||||
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(MarketPieceList)}
|
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(MarketPieceList)}
|
||||||
headerTitle='COLLECTION' />
|
headerTitle='COLLECTION'
|
||||||
|
disableOn='noPieces' />
|
||||||
<Route path='pieces/:pieceId' component={MarketPieceContainer} />
|
<Route path='pieces/:pieceId' component={MarketPieceContainer} />
|
||||||
<Route path='editions/:editionId' component={MarketEditionContainer} />
|
<Route path='editions/:editionId' component={MarketEditionContainer} />
|
||||||
<Route path='verify' component={CoaVerifyContainer} />
|
<Route path='verify' component={CoaVerifyContainer} />
|
||||||
@ -225,7 +229,8 @@ let ROUTES = {
|
|||||||
<Route
|
<Route
|
||||||
path='collection'
|
path='collection'
|
||||||
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(Vivi23PieceList)}
|
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(Vivi23PieceList)}
|
||||||
headerTitle='COLLECTION' />
|
headerTitle='COLLECTION'
|
||||||
|
disableOn='noPieces' />
|
||||||
<Route path='pieces/:pieceId' component={MarketPieceContainer} />
|
<Route path='pieces/:pieceId' component={MarketPieceContainer} />
|
||||||
<Route path='editions/:editionId' component={MarketEditionContainer} />
|
<Route path='editions/:editionId' component={MarketEditionContainer} />
|
||||||
<Route path='verify' component={CoaVerifyContainer} />
|
<Route path='verify' component={CoaVerifyContainer} />
|
||||||
|
@ -40,7 +40,8 @@ const COMMON_ROUTES = (
|
|||||||
<Route
|
<Route
|
||||||
path='collection'
|
path='collection'
|
||||||
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(PieceList)}
|
component={ProxyHandler(AuthRedirect({to: '/login', when: 'loggedOut'}))(PieceList)}
|
||||||
headerTitle='COLLECTION'/>
|
headerTitle='COLLECTION'
|
||||||
|
disableOn='noPieces' />
|
||||||
<Route
|
<Route
|
||||||
path='signup'
|
path='signup'
|
||||||
component={ProxyHandler(AuthRedirect({to: '/collection', when: 'loggedIn'}))(SignupContainer)} />
|
component={ProxyHandler(AuthRedirect({to: '/collection', when: 'loggedIn'}))(SignupContainer)} />
|
||||||
|
Loading…
Reference in New Issue
Block a user