1
0
mirror of https://github.com/ascribe/onion.git synced 2025-02-14 21:10:27 +01:00

Merge branch 'AD-456-ikonotv-branded-page-for-registra' of bitbucket.org:ascribe/onion into AD-456-ikonotv-branded-page-for-registra

This commit is contained in:
Tim Daubenschütz 2015-09-04 15:55:07 +02:00
commit 85efa4b416
27 changed files with 526 additions and 59 deletions

24
.gitignore~ Normal file
View File

@ -0,0 +1,24 @@
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
*.sublime-project
.idea
spool-project.sublime-project
*.sublime-workspace
*.sublime-workspace
webapp-dependencies.txt
pids
logs
results
README.md~
node_modules/*
build
.DS_Store

View File

@ -43,6 +43,7 @@ class ContractActions {
/* No email was entered - Ignore and keep going*/ /* No email was entered - Ignore and keep going*/
} }
} }
} }
export default alt.createActions(ContractActions); export default alt.createActions(ContractActions);

View File

@ -3,7 +3,6 @@
import alt from '../alt'; import alt from '../alt';
import OwnershipFetcher from '../fetchers/ownership_fetcher'; import OwnershipFetcher from '../fetchers/ownership_fetcher';
class ContractListActions { class ContractListActions {
constructor() { constructor() {
this.generateActions( this.generateActions(
@ -15,13 +14,23 @@ class ContractListActions {
fetchContractList() { fetchContractList() {
OwnershipFetcher.fetchContractList() OwnershipFetcher.fetchContractList()
.then((contracts) => { .then((contracts) => {
this.actions.updateContractList(contracts); this.actions.updateContractList(contracts.results);
}) })
.catch((err) => { .catch((err) => {
console.logGlobal(err); console.logGlobal(err);
this.actions.updateContractList([]); this.actions.updateContractList([]);
}); });
} }
makeContractPublic(contract){
OwnershipFetcher.makeContractPublic(contract)
.then((res) =>{
return res;
})
.catch((err)=>{
console.logGlobal(err);
});
}
} }
export default alt.createActions(ContractListActions); export default alt.createActions(ContractListActions);

View File

@ -57,7 +57,7 @@ class PieceListActions {
PieceListFetcher PieceListFetcher
.fetchRequestActions() .fetchRequestActions()
.then((res) => { .then((res) => {
this.actions.updatePieceListRequestActions(res.piece_ids); this.actions.updatePieceListRequestActions(res);
}) })
.catch((err) => console.logGlobal(err)); .catch((err) => console.logGlobal(err));
} }

View File

@ -61,12 +61,13 @@ let AccordionListItemWallet = React.createClass({
}, },
getGlyphicon(){ getGlyphicon(){
if (this.props.content.requestAction && this.props.content.requestAction.length > 0) { if ((this.props.content.request_action && this.props.content.request_action.length > 0) ||
(this.props.content.request_action_editions)){
return ( return (
<OverlayTrigger <OverlayTrigger
delay={500} delay={500}
placement="left" placement="left"
overlay={<Tooltip>{getLangText('You have actions pending in one of your editions')}</Tooltip>}> overlay={<Tooltip>{getLangText('You have actions pending')}</Tooltip>}>
<Glyphicon glyph='bell' color="green"/> <Glyphicon glyph='bell' color="green"/>
</OverlayTrigger>); </OverlayTrigger>);
} }

View File

@ -305,7 +305,6 @@ let EditionSummary = React.createClass({
<hr/> <hr/>
</div> </div>
); );
} }
}); });

View File

@ -9,6 +9,8 @@ import Edition from './edition';
import AppConstants from '../../constants/application_constants'; import AppConstants from '../../constants/application_constants';
/** /**
* This is the component that implements resource/data specific functionality * This is the component that implements resource/data specific functionality
*/ */
@ -34,6 +36,15 @@ let EditionContainer = React.createClass({
EditionActions.fetchOne(this.props.params.editionId); EditionActions.fetchOne(this.props.params.editionId);
}, },
// This is done to update the container when the user clicks on the prev or next
// button to update the URL parameter (and therefore to switch pieces)
componentWillReceiveProps(nextProps) {
if(this.props.params.editionId !== nextProps.params.editionId) {
EditionActions.updateEdition({});
EditionActions.fetchOne(nextProps.params.editionId);
}
},
componentWillUnmount() { componentWillUnmount() {
// Every time we're leaving the edition detail page, // Every time we're leaving the edition detail page,
// just reset the edition that is saved in the edition store // just reset the edition that is saved in the edition store
@ -50,6 +61,7 @@ let EditionContainer = React.createClass({
}, },
render() { render() {
console.log(this.state);
if('title' in this.state.edition) { if('title' in this.state.edition) {
return ( return (
<Edition <Edition

View File

@ -19,7 +19,7 @@ import { getLangText } from '../../utils/lang_utils';
import { mergeOptions } from '../../utils/general_utils'; import { mergeOptions } from '../../utils/general_utils';
let ContractForm = React.createClass({ let ContractAgreementForm = React.createClass({
propTypes: { propTypes: {
handleSuccess: React.PropTypes.func handleSuccess: React.PropTypes.func
}, },
@ -55,8 +55,13 @@ let ContractForm = React.createClass({
GlobalNotificationActions.appendGlobalNotification(notification); GlobalNotificationActions.appendGlobalNotification(notification);
}, },
getFormData(){
return {'appendix': {'default': this.refs.form.refs.appendix.state.value}};
},
getContracts() { getContracts() {
if (this.state.contractList && this.state.contractList.length > 0) { if (this.state.contractList && this.state.contractList.count > 0) {
let contractList = this.state.contractList.results;
return ( return (
<Property <Property
name='contract' name='contract'
@ -65,13 +70,13 @@ let ContractForm = React.createClass({
footer={ footer={
<a <a
className="pull-right" className="pull-right"
href={this.state.contractList[this.state.selectedContract].s3UrlSafe} href={contractList[this.state.selectedContract].blob}
target="_blank"> target="_blank">
{getLangText('Learn more')} {getLangText('Learn more')}
</a> </a>
}> }>
<select name="contract"> <select name="contract">
{this.state.contractList.map((contract, i) => { {contractList.map((contract, i) => {
return ( return (
<option <option
name={i} name={i}
@ -92,7 +97,8 @@ let ContractForm = React.createClass({
<Form <Form
className="ascribe-form-bordered ascribe-form-wrapper" className="ascribe-form-bordered ascribe-form-wrapper"
ref='form' ref='form'
url={ApiUrls.blob_contracts} url={ApiUrls.ownership_contract_agreements}
getFormData={this.getFormData}
handleSuccess={this.props.handleSuccess} handleSuccess={this.props.handleSuccess}
buttons={<button buttons={<button
type="submit" type="submit"
@ -108,15 +114,7 @@ let ContractForm = React.createClass({
<h3>{getLangText('Contract form')}</h3> <h3>{getLangText('Contract form')}</h3>
</div> </div>
<Property <Property
name='artist_name' name='signee'
label={getLangText('Artist Name')}>
<input
type="text"
placeholder={getLangText('(e.g. Andy Warhol)')}
required/>
</Property>
<Property
name='artist_email'
label={getLangText('Artist Email')}> label={getLangText('Artist Email')}>
<input <input
type="email" type="email"
@ -138,4 +136,4 @@ let ContractForm = React.createClass({
} }
}); });
export default ContractForm; export default ContractAgreementForm;

View File

@ -6,6 +6,9 @@ import Form from '../ascribe_forms/form';
import Property from '../ascribe_forms/property'; import Property from '../ascribe_forms/property';
import InputCheckbox from '../ascribe_forms/input_checkbox'; import InputCheckbox from '../ascribe_forms/input_checkbox';
import GlobalNotificationModel from '../../models/global_notification_model';
import GlobalNotificationActions from '../../actions/global_notification_actions';
import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader'; import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader';
import AppConstants from '../../constants/application_constants'; import AppConstants from '../../constants/application_constants';
@ -19,14 +22,20 @@ let CreateContractForm = React.createClass({
getInitialState() { getInitialState() {
return { return {
digitalWorkKey: null, contractKey: null,
isUploadReady: false isUploadReady: false
}; };
}, },
getFormData(){
return {
blob: this.state.contractKey
};
},
submitKey(key) { submitKey(key) {
this.setState({ this.setState({
digitalWorkKey: key contractKey: key
}); });
}, },
@ -36,10 +45,18 @@ let CreateContractForm = React.createClass({
}); });
}, },
handleCreateSuccess(response) {
let notification = new GlobalNotificationModel(getLangText('Contract %s successfully created', response.name), 'success', 5000);
GlobalNotificationActions.appendGlobalNotification(notification);
},
render() { render() {
return ( return (
<Form <Form
url={ApiUrls.ownership_contract} url={ApiUrls.ownership_contract_list}
getFormData={this.getFormData}
handleSuccess={this.handleCreateSuccess}
buttons={ buttons={
<button <button
type="submit" type="submit"
@ -88,7 +105,7 @@ let CreateContractForm = React.createClass({
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}/> isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}/>
</Property> </Property>
<Property <Property
name='contract_ name' name='name'
label={getLangText('Contract name')}> label={getLangText('Contract name')}>
<input <input
type="text" type="text"

View File

@ -6,6 +6,8 @@ import AclButton from './../ascribe_buttons/acl_button';
import ActionPanel from '../ascribe_panel/action_panel'; import ActionPanel from '../ascribe_panel/action_panel';
import Form from './form'; import Form from './form';
import PieceListActions from '../../actions/piece_list_actions';
import GlobalNotificationModel from '../../models/global_notification_model'; import GlobalNotificationModel from '../../models/global_notification_model';
import GlobalNotificationActions from '../../actions/global_notification_actions'; import GlobalNotificationActions from '../../actions/global_notification_actions';
@ -71,10 +73,16 @@ let RequestActionForm = React.createClass({
let notification = new GlobalNotificationModel(message, 'success'); let notification = new GlobalNotificationModel(message, 'success');
GlobalNotificationActions.appendGlobalNotification(notification); GlobalNotificationActions.appendGlobalNotification(notification);
this.handleSuccess();
};
},
handleSuccess() {
PieceListActions.fetchPieceRequestActions();
if(this.props.handleSuccess) { if(this.props.handleSuccess) {
this.props.handleSuccess(); this.props.handleSuccess();
} }
};
}, },
getContent() { getContent() {
@ -99,7 +107,7 @@ let RequestActionForm = React.createClass({
buttonAcceptClassName='inline pull-right btn-sm ascribe-margin-1px' buttonAcceptClassName='inline pull-right btn-sm ascribe-margin-1px'
pieceOrEditions={this.props.pieceOrEditions} pieceOrEditions={this.props.pieceOrEditions}
currentUser={this.props.currentUser} currentUser={this.props.currentUser}
handleSuccess={this.props.handleSuccess} /> handleSuccess={this.handleSuccess} />
); );
} else if(this.props.requestAction === 'loan_request') { } else if(this.props.requestAction === 'loan_request') {
return ( return (
@ -110,7 +118,7 @@ let RequestActionForm = React.createClass({
buttonAcceptClassName='inline pull-right btn-sm ascribe-margin-1px' buttonAcceptClassName='inline pull-right btn-sm ascribe-margin-1px'
pieceOrEditions={this.props.pieceOrEditions} pieceOrEditions={this.props.pieceOrEditions}
currentUser={this.props.currentUser} currentUser={this.props.currentUser}
handleSuccess={this.props.handleSuccess} /> handleSuccess={this.handleSuccess} />
); );
} else { } else {
return ( return (

View File

@ -14,7 +14,6 @@ let ActionPanel = React.createClass({
onClick: React.PropTypes.func, onClick: React.PropTypes.func,
ignoreFocus: React.PropTypes.bool ignoreFocus: React.PropTypes.bool
}, },
getInitialState() { getInitialState() {
return { return {
isFocused: false isFocused: false

View File

@ -5,23 +5,100 @@ import React from 'react';
import CollapsibleParagraph from '../ascribe_collapsible/collapsible_paragraph'; import CollapsibleParagraph from '../ascribe_collapsible/collapsible_paragraph';
import CreateContractForm from '../ascribe_forms/form_create_contract'; import CreateContractForm from '../ascribe_forms/form_create_contract';
import { getLangText } from '../../utils/lang_utils'; import ContractListStore from '../../stores/contract_list_store';
import ContractListActions from '../../actions/contract_list_actions';
import ActionPanel from '../ascribe_panel/action_panel';
import { getLangText } from '../../utils/lang_utils';
let ContractSettings = React.createClass({ let ContractSettings = React.createClass({
propTypes: { propTypes: {
defaultExpanded: React.PropTypes.bool defaultExpanded: React.PropTypes.bool
}, },
getInitialState(){
return ContractListStore.getState();
},
componentDidMount() {
ContractListStore.listen(this.onChange);
ContractListActions.fetchContractList();
},
componentWillUnmount() {
ContractListStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
makeContractPublic(contract){
console.log(contract);
ContractListActions.makeContractPublic(contract)
.then(( ) => ContractListActions.fetchContractList())
.catch((error)=>{console.log("Error ", error)})
},
getPublicContracts(){
return this.state.contractList.filter((contract) => contract.public);
},
getPrivateContracts(){
return this.state.contractList.filter((contract) => !contract.public);
},
getblobEndName(contract){
return contract.blob.match(/.*\/(.*)/)[1];
},
render() { render() {
let publicContracts = this.getPublicContracts();
let privateContracts = this.getPrivateContracts();
console.log(this.state.contractList);
return ( return (
<CollapsibleParagraph <CollapsibleParagraph
title={getLangText('Contract Settings')} title={getLangText('Contract Settings')}
show={true} show={true}
defaultExpanded={true}> defaultExpanded={false}>
{/* this should be this.props.defaultExpanded */} {/* this should be this.props.defaultExpanded */}
<CollapsibleParagraph
title={getLangText('List Contracts')}
show={true}
defaultExpanded={false}>
{<div>
<p>Public Contracts</p>
{(publicContracts.length > 0) ?
publicContracts.map(
(contract) => {
return(
<ActionPanel title = {contract.name}
content = {this.getblobEndName(contract)}
buttons = {<span>
<button className="btn btn-default btn-sm margin-left-2px">UPDATE</button>
<button className="btn btn-default btn-sm margin-left-2px">REMOVE</button>
</span>}
/>)
}
) : null }
</div>}
{<div>
<p>Private Contracts</p>
{(privateContracts.length>0) ?
privateContracts.map(
(contract) => {
return(
<ActionPanel title = {contract.name}
content = {this.getblobEndName(contract)}
buttons = {<span> <button className="btn btn-default btn-sm margin-left-2px">UPDATE</button>
<button className="btn btn-default btn-sm margin-left-2px" >REMOVE</button>
<button className="btn btn-default btn-sm margin-left-2px"
onClick={this.makeContractPublic.bind(this, contract)}>MAKE PUBLIC</button> </span>}
/>)
}
) : null}
</div>}
</CollapsibleParagraph>
<CollapsibleParagraph
title={getLangText('Create Contract')}
show={true}
defaultExpanded={false}>
<CreateContractForm /> <CreateContractForm />
</CollapsibleParagraph> </CollapsibleParagraph>
</CollapsibleParagraph>
); );
} }
}); });

View File

@ -0,0 +1,43 @@
'use strict';
import React from 'react';
let GlobalAction = React.createClass({
propTypes: {
requestActions: React.PropTypes.object
},
render() {
let pieceActions = null;
if (this.props.requestActions && this.props.requestActions.pieces){
pieceActions = this.props.requestActions.pieces.map((item) => {
return (
<div className="ascribe-global-action">
{item}
</div>);
});
}
let editionActions = null;
if (this.props.requestActions && this.props.requestActions.editions){
editionActions = Object.keys(this.props.requestActions.editions).map((pieceId) => {
return this.props.requestActions.editions[pieceId].map((item) => {
return (
<div className="ascribe-global-action">
{item}
</div>);
});
});
}
if (pieceActions || editionActions) {
return (
<div className="ascribe-global-action-wrapper">
{pieceActions}
{editionActions}
</div>);
}
return null;
}
});
export default GlobalAction;

View File

@ -3,12 +3,6 @@
import React from 'react'; import React from 'react';
import Router from 'react-router'; import Router from 'react-router';
import UserActions from '../actions/user_actions';
import UserStore from '../stores/user_store';
import WhitelabelActions from '../actions/whitelabel_actions';
import WhitelabelStore from '../stores/whitelabel_store';
import EventActions from '../actions/event_actions';
import Nav from 'react-bootstrap/lib/Nav'; import Nav from 'react-bootstrap/lib/Nav';
import Navbar from 'react-bootstrap/lib/Navbar'; import Navbar from 'react-bootstrap/lib/Navbar';
@ -18,6 +12,15 @@ import MenuItem from 'react-bootstrap/lib/MenuItem';
import MenuItemLink from 'react-router-bootstrap/lib/MenuItemLink'; import MenuItemLink from 'react-router-bootstrap/lib/MenuItemLink';
import NavItemLink from 'react-router-bootstrap/lib/NavItemLink'; import NavItemLink from 'react-router-bootstrap/lib/NavItemLink';
import UserActions from '../actions/user_actions';
import UserStore from '../stores/user_store';
import WhitelabelActions from '../actions/whitelabel_actions';
import WhitelabelStore from '../stores/whitelabel_store';
import EventActions from '../actions/event_actions';
import HeaderNotifications from './header_notification';
import HeaderNotificationDebug from './header_notification_debug'; import HeaderNotificationDebug from './header_notification_debug';
import NavRoutesLinks from './nav_routes_links'; import NavRoutesLinks from './nav_routes_links';
@ -41,7 +44,10 @@ let Header = React.createClass({
}, },
getInitialState() { getInitialState() {
return mergeOptions(WhitelabelStore.getState(), UserStore.getState()); return mergeOptions(
WhitelabelStore.getState(),
UserStore.getState()
);
}, },
componentDidMount() { componentDidMount() {
@ -96,7 +102,9 @@ let Header = React.createClass({
let navRoutesLinks; let navRoutesLinks;
if (this.state.currentUser.username){ if (this.state.currentUser.username){
account = ( account = (
<DropdownButton eventKey="1" title={this.state.currentUser.username}> <DropdownButton
eventKey="1"
title={this.state.currentUser.username}>
<MenuItemLink eventKey="2" to="settings">{getLangText('Account Settings')}</MenuItemLink> <MenuItemLink eventKey="2" to="settings">{getLangText('Account Settings')}</MenuItemLink>
<MenuItem divider /> <MenuItem divider />
<MenuItemLink eventKey="3" to="logout">{getLangText('Log out')}</MenuItemLink> <MenuItemLink eventKey="3" to="logout">{getLangText('Log out')}</MenuItemLink>
@ -126,6 +134,7 @@ let Header = React.createClass({
{account} {account}
{signup} {signup}
</Nav> </Nav>
<HeaderNotifications />
{navRoutesLinks} {navRoutesLinks}
</CollapsibleNav> </CollapsibleNav>
</Navbar> </Navbar>

View File

@ -0,0 +1,144 @@
'use strict';
import React from 'react';
import Router from 'react-router';
import DropdownButton from 'react-bootstrap/lib/DropdownButton';
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
import MenuItem from 'react-bootstrap/lib/MenuItem';
import Nav from 'react-bootstrap/lib/Nav';
import PieceListStore from '../stores/piece_list_store';
import { mergeOptions } from '../utils/general_utils';
import { getLangText } from '../utils/lang_utils';
let Link = Router.Link;
let HeaderNotifications = React.createClass({
getInitialState() {
return mergeOptions(
PieceListStore.getState()
);
},
componentDidMount() {
PieceListStore.listen(this.onChange);
},
componentWillUnmount() {
PieceListStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
onSelected(event) {
/*
This is a hack to make the dropdown close after clicking on an item
The function just need to be defined
from https://github.com/react-bootstrap/react-bootstrap/issues/368:
@jvillasante - Have you tried to use onSelect with the DropdownButton?
I don't have a working example that is exactly like yours,
but I just noticed that the Dropdown closes when I've attached an event handler to OnSelect:
<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.
*/
},
render() {
if (this.state.requestActions && this.state.requestActions.length > 0) {
return (
<Nav navbar right>
<DropdownButton
eventKey="1"
title={
<span>
<Glyphicon glyph='envelope' color="green"/>
<span className="notification-amount">({this.state.requestActions.length})</span>
</span>
}
className="notification-menu"
onSelect={this.onSelected}>
{this.state.requestActions.map((pieceOrEdition, i) => {
return (
<MenuItem eventKey={i + 2}>
<NotificationListItem
ref={i}
pieceOrEdition={pieceOrEdition}/>
</MenuItem>);
}
)}
</DropdownButton>
</Nav>
);
}
return null;
}
});
let NotificationListItem = React.createClass({
propTypes: {
pieceOrEdition: React.PropTypes.object
},
getLinkData() {
if(this.props.pieceOrEdition && this.props.pieceOrEdition.parent) {
return {
to: 'edition',
params: {
editionId: this.props.pieceOrEdition.bitcoin_id
}
};
} else {
return {
to: 'piece',
params: {
pieceId: this.props.pieceOrEdition.id
}
};
}
},
render() {
if (this.props.pieceOrEdition) {
return (
<Link {...this.getLinkData()}>
<div className="row notification-wrapper">
<div className="col-xs-4 clear-paddings">
<div className="thumbnail-wrapper">
<img src={this.props.pieceOrEdition.thumbnail.url_safe}/>
</div>
</div>
<div className="col-xs-8 notification-list-item-header">
<h1>{this.props.pieceOrEdition.title}</h1>
<div className="sub-header">by {this.props.pieceOrEdition.artist_name}</div>
<div className="notification-action">
{
this.props.pieceOrEdition.request_action.map((requestAction) => {
return 'Pending ' + requestAction.action + ' request';
})
}
</div>
</div>
</div>
</Link>);
}
return null;
}
});
export default HeaderNotifications;

View File

@ -15,6 +15,7 @@ import AccordionListItemTableEditions from './ascribe_accordion_list/accordion_l
import Pagination from './ascribe_pagination/pagination'; import Pagination from './ascribe_pagination/pagination';
import GlobalAction from './global_action';
import PieceListBulkModal from './ascribe_piece_list_bulk_modal/piece_list_bulk_modal'; import PieceListBulkModal from './ascribe_piece_list_bulk_modal/piece_list_bulk_modal';
import PieceListToolbar from './ascribe_piece_list_toolbar/piece_list_toolbar'; import PieceListToolbar from './ascribe_piece_list_toolbar/piece_list_toolbar';
@ -148,6 +149,10 @@ let PieceList = React.createClass({
render() { render() {
let loadingElement = (<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />); let loadingElement = (<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />);
let AccordionListItemType = this.props.accordionListItemType; let AccordionListItemType = this.props.accordionListItemType;
//<GlobalAction requestActions={this.state.requestActions} />
return ( return (
<div> <div>
<PieceListToolbar <PieceListToolbar

View File

@ -86,7 +86,6 @@ let PieceContainer = React.createClass({
loadPiece() { loadPiece() {
PieceActions.fetchOne(this.props.params.pieceId); PieceActions.fetchOne(this.props.params.pieceId);
this.setState(this.state);
}, },
render() { render() {

View File

@ -2,13 +2,13 @@
import React from 'react'; import React from 'react';
import ContractForm from '../../../../../components/ascribe_forms/form_contract'; import ContractAgreementForm from '../../../../ascribe_forms/form_contract_agreement';
let IkonotvRequestLoan = React.createClass({ let IkonotvRequestLoan = React.createClass({
render() { render() {
return ( return (
<ContractForm /> <ContractAgreementForm />
); );
} }
}); });

View File

@ -27,6 +27,7 @@ let ApiUrls = {
'note_private_piece': AppConstants.apiEndpoint + 'note/private/pieces/', 'note_private_piece': AppConstants.apiEndpoint + 'note/private/pieces/',
'note_public_edition': AppConstants.apiEndpoint + 'note/public/editions/', 'note_public_edition': AppConstants.apiEndpoint + 'note/public/editions/',
'note_public_piece': AppConstants.apiEndpoint + 'note/public/pieces/', 'note_public_piece': AppConstants.apiEndpoint + 'note/public/pieces/',
'ownership_contract_agreements': AppConstants.apiEndpoint + 'ownership/contract_agreements/',
'ownership_consigns': AppConstants.apiEndpoint + 'ownership/consigns/', 'ownership_consigns': AppConstants.apiEndpoint + 'ownership/consigns/',
'ownership_consigns_confirm': AppConstants.apiEndpoint + 'ownership/consigns/confirm/', 'ownership_consigns_confirm': AppConstants.apiEndpoint + 'ownership/consigns/confirm/',
'ownership_consigns_deny': AppConstants.apiEndpoint + 'ownership/consigns/deny/', 'ownership_consigns_deny': AppConstants.apiEndpoint + 'ownership/consigns/deny/',
@ -46,7 +47,8 @@ let ApiUrls = {
'ownership_unconsigns': AppConstants.apiEndpoint + 'ownership/unconsigns/', 'ownership_unconsigns': AppConstants.apiEndpoint + 'ownership/unconsigns/',
'ownership_unconsigns_deny': AppConstants.apiEndpoint + 'ownership/unconsigns/deny/', 'ownership_unconsigns_deny': AppConstants.apiEndpoint + 'ownership/unconsigns/deny/',
'ownership_unconsigns_request': AppConstants.apiEndpoint + 'ownership/unconsigns/request/', 'ownership_unconsigns_request': AppConstants.apiEndpoint + 'ownership/unconsigns/request/',
'ownership_contract': AppConstants.apiEndpoint + 'ownership/contracts/', 'ownership_contract':AppConstants.apiEndpoint + 'ownership/contracts/${contract_id}',
"ownership_contract_list": AppConstants.apiEndpoint + 'ownership/contracts/',
'piece': AppConstants.apiEndpoint + 'pieces/${piece_id}/', 'piece': AppConstants.apiEndpoint + 'pieces/${piece_id}/',
'piece_extradata': AppConstants.apiEndpoint + 'pieces/${piece_id}/extradata/', 'piece_extradata': AppConstants.apiEndpoint + 'pieces/${piece_id}/extradata/',
'piece_first_edition_id': AppConstants.apiEndpoint + 'pieces/${piece_id}/edition_index/', 'piece_first_edition_id': AppConstants.apiEndpoint + 'pieces/${piece_id}/edition_index/',

View File

@ -16,11 +16,16 @@ let OwnershipFetcher = {
* Fetch the contracts of the logged-in user from the API. * Fetch the contracts of the logged-in user from the API.
*/ */
fetchContractList(){ fetchContractList(){
return requests.get(ApiUrls.ownership_contract); return requests.get(ApiUrls.ownership_contract_list);
}, },
fetchLoanPieceRequestList(){ fetchLoanPieceRequestList(){
return requests.get(ApiUrls.ownership_loans_pieces_request); return requests.get(ApiUrls.ownership_loans_pieces_request);
},
makeContractPublic(contractObj){
console.log(contractObj);
return requests.put('ownership_contract_list',{ body: contractObj, contract_id:contractObj.id });
} }
}; };

View File

@ -28,6 +28,7 @@ class PieceListStore {
this.orderBy = 'artist_name'; this.orderBy = 'artist_name';
this.orderAsc = true; this.orderAsc = true;
this.filterBy = {}; this.filterBy = {};
this.requestActions = {};
this.bindActions(PieceListActions); this.bindActions(PieceListActions);
} }
@ -71,10 +72,8 @@ class PieceListStore {
this.pieceList = pieceList; this.pieceList = pieceList;
} }
onUpdatePieceListRequestActions(requestActions) { onUpdatePieceListRequestActions(res) {
this.pieceList.forEach((piece) => { this.requestActions = res.actions;
piece.requestAction = requestActions.indexOf(piece.id) > -1;
});
} }
onUpdatePropertyForPiece({pieceId, key, value}) { onUpdatePropertyForPiece({pieceId, key, value}) {

View File

@ -52,6 +52,19 @@ export function sumNumList(l) {
return sum; return sum;
} }
export function excludePropFromObject(obj, propList){
let clonedObj = mergeOptions({},obj);
for (let item in propList){
console.log(item);
if (clonedObj[propList[item]]){
console.log('deleting... ');
delete clonedObj[propList[item]];
}
}
console.log(clonedObj);
return clonedObj;
}
/* /*
Taken from http://stackoverflow.com/a/4795914/1263876 Taken from http://stackoverflow.com/a/4795914/1263876
Behaves like C's format string function Behaves like C's format string function

View File

@ -6,6 +6,7 @@ import { argsToQueryParams, getCookie } from '../utils/fetch_api_utils';
import AppConstants from '../constants/application_constants'; import AppConstants from '../constants/application_constants';
import {excludePropFromObject} from '../utils/general_utils';
class Requests { class Requests {
_merge(defaults, options) { _merge(defaults, options) {
@ -137,15 +138,25 @@ class Requests {
return this.request('delete', newUrl); return this.request('delete', newUrl);
} }
post(url, params) { _putOrPost(url,paramsAndBody,method){
let paramsCopy = this._merge(params); let paramsCopy = this._merge(paramsAndBody);
let newUrl = this.prepareUrl(url, paramsCopy); let params = excludePropFromObject(paramsAndBody,['body']);
let newUrl = this.prepareUrl(url, params);
let body = null; let body = null;
if (paramsCopy && paramsCopy.body) { if (paramsCopy && paramsCopy.body) {
console.log(paramsCopy.body);
body = JSON.stringify(paramsCopy.body); body = JSON.stringify(paramsCopy.body);
} }
return this.request('post', newUrl, { body }); return this.request(method, newUrl, { body });
}
post(url, params) {
return this._putOrPost(url,params,'post')
}
put(url, params){
console.log(params);
return this._putOrPost(url,params,'put')
} }
defaults(options) { defaults(options) {

View File

@ -166,7 +166,7 @@ $ascribe-accordion-list-item-height: 8em;
.request-action-badge { .request-action-badge {
color: $ascribe-color-green; color: $ascribe-color-green;
font-size: 1.2em; font-size: 1.2em;
padding: .3em; padding: .8em;
position: absolute; position: absolute;
right: 0; right: 0;
top: 0; top: 0;

View File

@ -0,0 +1,25 @@
$break-small: 764px;
$break-medium: 991px;
$break-medium: 1200px;
.ascribe-global-action-wrapper {
position: fixed;
width: 100%;
max-width: 500px;
height:3.5em;
left:0;
right: 0;
top:0;
z-index: 2000;
display:table;
margin: 1px auto;
}
.ascribe-global-action {
text-align: center;
padding: 1em;
color: black;
border: 1px solid #cccccc;
background-color: white;
margin-top: 1px;
}

View File

@ -0,0 +1,65 @@
$break-small: 764px;
$break-medium: 991px;
$break-medium: 1200px;
.notification-wrapper {
width: 350px;
height:8em;
padding: 0.3em;
border-bottom: 1px solid #cccccc;
margin: -3px -20px;
// ToDo: Include media queries for thumbnail
.thumbnail-wrapper {
width: 7.4em;
height: 7.4em;
padding:0;
cursor: pointer;
text-align: center;
img {
max-width: 100%;
max-height: 100%;
}
&::before {
content: ' ';
display: inline-block;
vertical-align: middle; /* vertical alignment of the inline element */
height: 100%;
}
}
h1 {
margin-top: 0.3em;
margin-bottom: 0.15em;
font-size: 1.8em;
}
.sub-header{
margin-bottom: 1em;
}
.notification-action{
color: $ascribe-color-green;
}
}
.notification-menu {
.dropdown-menu {
padding: 0 !important;
li a {
padding-top: 0;
}
}
}
.notification-amount {
padding: 0.3em;
font-size: 1.2em;
}
.ascribe-global-action {
text-align: center;
padding: 1em;
color: black;
border: 1px solid #cccccc;
background-color: white;
margin-top: 1px;
}

View File

@ -22,7 +22,9 @@ $BASE_URL: '<%= BASE_URL %>';
@import 'ascribe_media_player'; @import 'ascribe_media_player';
@import 'ascribe_uploader'; @import 'ascribe_uploader';
@import 'ascribe_footer'; @import 'ascribe_footer';
@import 'ascribe_global_action';
@import 'ascribe_global_notification'; @import 'ascribe_global_notification';
@import 'ascribe_notification_list';
@import 'ascribe_piece_register'; @import 'ascribe_piece_register';
@import 'offset_right'; @import 'offset_right';
@import 'ascribe_settings'; @import 'ascribe_settings';