mirror of
https://github.com/ascribe/onion.git
synced 2024-12-23 01:39:36 +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:
commit
85efa4b416
24
.gitignore~
Normal file
24
.gitignore~
Normal 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
|
@ -43,6 +43,7 @@ class ContractActions {
|
||||
/* No email was entered - Ignore and keep going*/
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default alt.createActions(ContractActions);
|
||||
|
@ -3,7 +3,6 @@
|
||||
import alt from '../alt';
|
||||
import OwnershipFetcher from '../fetchers/ownership_fetcher';
|
||||
|
||||
|
||||
class ContractListActions {
|
||||
constructor() {
|
||||
this.generateActions(
|
||||
@ -15,13 +14,23 @@ class ContractListActions {
|
||||
fetchContractList() {
|
||||
OwnershipFetcher.fetchContractList()
|
||||
.then((contracts) => {
|
||||
this.actions.updateContractList(contracts);
|
||||
this.actions.updateContractList(contracts.results);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.logGlobal(err);
|
||||
this.actions.updateContractList([]);
|
||||
});
|
||||
}
|
||||
|
||||
makeContractPublic(contract){
|
||||
OwnershipFetcher.makeContractPublic(contract)
|
||||
.then((res) =>{
|
||||
return res;
|
||||
})
|
||||
.catch((err)=>{
|
||||
console.logGlobal(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default alt.createActions(ContractListActions);
|
||||
|
@ -57,7 +57,7 @@ class PieceListActions {
|
||||
PieceListFetcher
|
||||
.fetchRequestActions()
|
||||
.then((res) => {
|
||||
this.actions.updatePieceListRequestActions(res.piece_ids);
|
||||
this.actions.updatePieceListRequestActions(res);
|
||||
})
|
||||
.catch((err) => console.logGlobal(err));
|
||||
}
|
||||
|
@ -61,12 +61,13 @@ let AccordionListItemWallet = React.createClass({
|
||||
},
|
||||
|
||||
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 (
|
||||
<OverlayTrigger
|
||||
delay={500}
|
||||
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"/>
|
||||
</OverlayTrigger>);
|
||||
}
|
||||
|
@ -305,7 +305,6 @@ let EditionSummary = React.createClass({
|
||||
<hr/>
|
||||
</div>
|
||||
);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -9,6 +9,8 @@ import Edition from './edition';
|
||||
|
||||
import AppConstants from '../../constants/application_constants';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This is the component that implements resource/data specific functionality
|
||||
*/
|
||||
@ -34,6 +36,15 @@ let EditionContainer = React.createClass({
|
||||
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() {
|
||||
// Every time we're leaving the edition detail page,
|
||||
// just reset the edition that is saved in the edition store
|
||||
@ -50,6 +61,7 @@ let EditionContainer = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
console.log(this.state);
|
||||
if('title' in this.state.edition) {
|
||||
return (
|
||||
<Edition
|
||||
|
@ -19,7 +19,7 @@ import { getLangText } from '../../utils/lang_utils';
|
||||
import { mergeOptions } from '../../utils/general_utils';
|
||||
|
||||
|
||||
let ContractForm = React.createClass({
|
||||
let ContractAgreementForm = React.createClass({
|
||||
propTypes: {
|
||||
handleSuccess: React.PropTypes.func
|
||||
},
|
||||
@ -55,8 +55,13 @@ let ContractForm = React.createClass({
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
},
|
||||
|
||||
getFormData(){
|
||||
return {'appendix': {'default': this.refs.form.refs.appendix.state.value}};
|
||||
},
|
||||
|
||||
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 (
|
||||
<Property
|
||||
name='contract'
|
||||
@ -65,13 +70,13 @@ let ContractForm = React.createClass({
|
||||
footer={
|
||||
<a
|
||||
className="pull-right"
|
||||
href={this.state.contractList[this.state.selectedContract].s3UrlSafe}
|
||||
href={contractList[this.state.selectedContract].blob}
|
||||
target="_blank">
|
||||
{getLangText('Learn more')}
|
||||
</a>
|
||||
}>
|
||||
<select name="contract">
|
||||
{this.state.contractList.map((contract, i) => {
|
||||
{contractList.map((contract, i) => {
|
||||
return (
|
||||
<option
|
||||
name={i}
|
||||
@ -92,7 +97,8 @@ let ContractForm = React.createClass({
|
||||
<Form
|
||||
className="ascribe-form-bordered ascribe-form-wrapper"
|
||||
ref='form'
|
||||
url={ApiUrls.blob_contracts}
|
||||
url={ApiUrls.ownership_contract_agreements}
|
||||
getFormData={this.getFormData}
|
||||
handleSuccess={this.props.handleSuccess}
|
||||
buttons={<button
|
||||
type="submit"
|
||||
@ -108,15 +114,7 @@ let ContractForm = React.createClass({
|
||||
<h3>{getLangText('Contract form')}</h3>
|
||||
</div>
|
||||
<Property
|
||||
name='artist_name'
|
||||
label={getLangText('Artist Name')}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder={getLangText('(e.g. Andy Warhol)')}
|
||||
required/>
|
||||
</Property>
|
||||
<Property
|
||||
name='artist_email'
|
||||
name='signee'
|
||||
label={getLangText('Artist Email')}>
|
||||
<input
|
||||
type="email"
|
||||
@ -138,4 +136,4 @@ let ContractForm = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default ContractForm;
|
||||
export default ContractAgreementForm;
|
@ -6,6 +6,9 @@ import Form from '../ascribe_forms/form';
|
||||
import Property from '../ascribe_forms/property';
|
||||
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 AppConstants from '../../constants/application_constants';
|
||||
@ -19,14 +22,20 @@ let CreateContractForm = React.createClass({
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
digitalWorkKey: null,
|
||||
contractKey: null,
|
||||
isUploadReady: false
|
||||
};
|
||||
},
|
||||
|
||||
getFormData(){
|
||||
return {
|
||||
blob: this.state.contractKey
|
||||
};
|
||||
},
|
||||
|
||||
submitKey(key) {
|
||||
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() {
|
||||
return (
|
||||
<Form
|
||||
url={ApiUrls.ownership_contract}
|
||||
url={ApiUrls.ownership_contract_list}
|
||||
getFormData={this.getFormData}
|
||||
handleSuccess={this.handleCreateSuccess}
|
||||
buttons={
|
||||
<button
|
||||
type="submit"
|
||||
@ -88,7 +105,7 @@ let CreateContractForm = React.createClass({
|
||||
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}/>
|
||||
</Property>
|
||||
<Property
|
||||
name='contract_ name'
|
||||
name='name'
|
||||
label={getLangText('Contract name')}>
|
||||
<input
|
||||
type="text"
|
||||
|
@ -6,6 +6,8 @@ import AclButton from './../ascribe_buttons/acl_button';
|
||||
import ActionPanel from '../ascribe_panel/action_panel';
|
||||
import Form from './form';
|
||||
|
||||
import PieceListActions from '../../actions/piece_list_actions';
|
||||
|
||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||
|
||||
@ -71,12 +73,18 @@ let RequestActionForm = React.createClass({
|
||||
let notification = new GlobalNotificationModel(message, 'success');
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
|
||||
if(this.props.handleSuccess) {
|
||||
this.props.handleSuccess();
|
||||
}
|
||||
this.handleSuccess();
|
||||
|
||||
};
|
||||
},
|
||||
|
||||
handleSuccess() {
|
||||
PieceListActions.fetchPieceRequestActions();
|
||||
if(this.props.handleSuccess) {
|
||||
this.props.handleSuccess();
|
||||
}
|
||||
},
|
||||
|
||||
getContent() {
|
||||
let pieceOrEditionStr = this.isPiece() ? getLangText('this work%s', '.') : getLangText('this edition%s', '.');
|
||||
let message = this.props.requestUser + ' ' + getLangText('requests you') + ' ' + this.props.requestAction + ' ' + pieceOrEditionStr;
|
||||
@ -99,7 +107,7 @@ let RequestActionForm = React.createClass({
|
||||
buttonAcceptClassName='inline pull-right btn-sm ascribe-margin-1px'
|
||||
pieceOrEditions={this.props.pieceOrEditions}
|
||||
currentUser={this.props.currentUser}
|
||||
handleSuccess={this.props.handleSuccess} />
|
||||
handleSuccess={this.handleSuccess} />
|
||||
);
|
||||
} else if(this.props.requestAction === 'loan_request') {
|
||||
return (
|
||||
@ -110,7 +118,7 @@ let RequestActionForm = React.createClass({
|
||||
buttonAcceptClassName='inline pull-right btn-sm ascribe-margin-1px'
|
||||
pieceOrEditions={this.props.pieceOrEditions}
|
||||
currentUser={this.props.currentUser}
|
||||
handleSuccess={this.props.handleSuccess} />
|
||||
handleSuccess={this.handleSuccess} />
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
|
@ -14,7 +14,6 @@ let ActionPanel = React.createClass({
|
||||
onClick: React.PropTypes.func,
|
||||
ignoreFocus: React.PropTypes.bool
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
isFocused: false
|
||||
|
@ -5,22 +5,99 @@ import React from 'react';
|
||||
import CollapsibleParagraph from '../ascribe_collapsible/collapsible_paragraph';
|
||||
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({
|
||||
propTypes: {
|
||||
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() {
|
||||
let publicContracts = this.getPublicContracts();
|
||||
let privateContracts = this.getPrivateContracts();
|
||||
console.log(this.state.contractList);
|
||||
return (
|
||||
<CollapsibleParagraph
|
||||
title={getLangText('Contract Settings')}
|
||||
show={true}
|
||||
defaultExpanded={true}>
|
||||
defaultExpanded={false}>
|
||||
{/* this should be this.props.defaultExpanded */}
|
||||
<CreateContractForm />
|
||||
<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 />
|
||||
</CollapsibleParagraph>
|
||||
</CollapsibleParagraph>
|
||||
);
|
||||
}
|
||||
|
43
js/components/global_action.js
Normal file
43
js/components/global_action.js
Normal 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;
|
@ -3,12 +3,6 @@
|
||||
import React from 'react';
|
||||
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 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 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 NavRoutesLinks from './nav_routes_links';
|
||||
@ -41,7 +44,10 @@ let Header = React.createClass({
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return mergeOptions(WhitelabelStore.getState(), UserStore.getState());
|
||||
return mergeOptions(
|
||||
WhitelabelStore.getState(),
|
||||
UserStore.getState()
|
||||
);
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
@ -96,11 +102,13 @@ let Header = React.createClass({
|
||||
let navRoutesLinks;
|
||||
if (this.state.currentUser.username){
|
||||
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>
|
||||
<MenuItem divider />
|
||||
<MenuItemLink eventKey="3" to="logout">{getLangText('Log out')}</MenuItemLink>
|
||||
</DropdownButton>
|
||||
</DropdownButton>
|
||||
);
|
||||
navRoutesLinks = <NavRoutesLinks routes={this.props.routes} navbar right/>;
|
||||
}
|
||||
@ -126,6 +134,7 @@ let Header = React.createClass({
|
||||
{account}
|
||||
{signup}
|
||||
</Nav>
|
||||
<HeaderNotifications />
|
||||
{navRoutesLinks}
|
||||
</CollapsibleNav>
|
||||
</Navbar>
|
||||
|
144
js/components/header_notification.js
Normal file
144
js/components/header_notification.js
Normal 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;
|
@ -15,6 +15,7 @@ import AccordionListItemTableEditions from './ascribe_accordion_list/accordion_l
|
||||
|
||||
import Pagination from './ascribe_pagination/pagination';
|
||||
|
||||
import GlobalAction from './global_action';
|
||||
import PieceListBulkModal from './ascribe_piece_list_bulk_modal/piece_list_bulk_modal';
|
||||
import PieceListToolbar from './ascribe_piece_list_toolbar/piece_list_toolbar';
|
||||
|
||||
@ -148,6 +149,10 @@ let PieceList = React.createClass({
|
||||
render() {
|
||||
let loadingElement = (<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />);
|
||||
let AccordionListItemType = this.props.accordionListItemType;
|
||||
|
||||
//<GlobalAction requestActions={this.state.requestActions} />
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PieceListToolbar
|
||||
|
@ -86,7 +86,6 @@ let PieceContainer = React.createClass({
|
||||
|
||||
loadPiece() {
|
||||
PieceActions.fetchOne(this.props.params.pieceId);
|
||||
this.setState(this.state);
|
||||
},
|
||||
|
||||
render() {
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import ContractForm from '../../../../../components/ascribe_forms/form_contract';
|
||||
import ContractAgreementForm from '../../../../ascribe_forms/form_contract_agreement';
|
||||
|
||||
|
||||
let IkonotvRequestLoan = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<ContractForm />
|
||||
<ContractAgreementForm />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -27,6 +27,7 @@ let ApiUrls = {
|
||||
'note_private_piece': AppConstants.apiEndpoint + 'note/private/pieces/',
|
||||
'note_public_edition': AppConstants.apiEndpoint + 'note/public/editions/',
|
||||
'note_public_piece': AppConstants.apiEndpoint + 'note/public/pieces/',
|
||||
'ownership_contract_agreements': AppConstants.apiEndpoint + 'ownership/contract_agreements/',
|
||||
'ownership_consigns': AppConstants.apiEndpoint + 'ownership/consigns/',
|
||||
'ownership_consigns_confirm': AppConstants.apiEndpoint + 'ownership/consigns/confirm/',
|
||||
'ownership_consigns_deny': AppConstants.apiEndpoint + 'ownership/consigns/deny/',
|
||||
@ -46,7 +47,8 @@ let ApiUrls = {
|
||||
'ownership_unconsigns': AppConstants.apiEndpoint + 'ownership/unconsigns/',
|
||||
'ownership_unconsigns_deny': AppConstants.apiEndpoint + 'ownership/unconsigns/deny/',
|
||||
'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_extradata': AppConstants.apiEndpoint + 'pieces/${piece_id}/extradata/',
|
||||
'piece_first_edition_id': AppConstants.apiEndpoint + 'pieces/${piece_id}/edition_index/',
|
||||
|
@ -16,11 +16,16 @@ let OwnershipFetcher = {
|
||||
* Fetch the contracts of the logged-in user from the API.
|
||||
*/
|
||||
fetchContractList(){
|
||||
return requests.get(ApiUrls.ownership_contract);
|
||||
return requests.get(ApiUrls.ownership_contract_list);
|
||||
},
|
||||
|
||||
fetchLoanPieceRequestList(){
|
||||
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 });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -28,6 +28,7 @@ class PieceListStore {
|
||||
this.orderBy = 'artist_name';
|
||||
this.orderAsc = true;
|
||||
this.filterBy = {};
|
||||
this.requestActions = {};
|
||||
this.bindActions(PieceListActions);
|
||||
}
|
||||
|
||||
@ -71,10 +72,8 @@ class PieceListStore {
|
||||
this.pieceList = pieceList;
|
||||
}
|
||||
|
||||
onUpdatePieceListRequestActions(requestActions) {
|
||||
this.pieceList.forEach((piece) => {
|
||||
piece.requestAction = requestActions.indexOf(piece.id) > -1;
|
||||
});
|
||||
onUpdatePieceListRequestActions(res) {
|
||||
this.requestActions = res.actions;
|
||||
}
|
||||
|
||||
onUpdatePropertyForPiece({pieceId, key, value}) {
|
||||
|
@ -52,6 +52,19 @@ export function sumNumList(l) {
|
||||
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
|
||||
Behaves like C's format string function
|
||||
|
@ -6,6 +6,7 @@ import { argsToQueryParams, getCookie } from '../utils/fetch_api_utils';
|
||||
|
||||
import AppConstants from '../constants/application_constants';
|
||||
|
||||
import {excludePropFromObject} from '../utils/general_utils';
|
||||
|
||||
class Requests {
|
||||
_merge(defaults, options) {
|
||||
@ -137,15 +138,25 @@ class Requests {
|
||||
return this.request('delete', newUrl);
|
||||
}
|
||||
|
||||
post(url, params) {
|
||||
let paramsCopy = this._merge(params);
|
||||
let newUrl = this.prepareUrl(url, paramsCopy);
|
||||
_putOrPost(url,paramsAndBody,method){
|
||||
let paramsCopy = this._merge(paramsAndBody);
|
||||
let params = excludePropFromObject(paramsAndBody,['body']);
|
||||
let newUrl = this.prepareUrl(url, params);
|
||||
let body = null;
|
||||
|
||||
if (paramsCopy && paramsCopy.body) {
|
||||
console.log(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) {
|
||||
|
@ -166,7 +166,7 @@ $ascribe-accordion-list-item-height: 8em;
|
||||
.request-action-badge {
|
||||
color: $ascribe-color-green;
|
||||
font-size: 1.2em;
|
||||
padding: .3em;
|
||||
padding: .8em;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
|
25
sass/ascribe_global_action.scss
Normal file
25
sass/ascribe_global_action.scss
Normal 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;
|
||||
}
|
65
sass/ascribe_notification_list.scss
Normal file
65
sass/ascribe_notification_list.scss
Normal 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;
|
||||
}
|
@ -22,7 +22,9 @@ $BASE_URL: '<%= BASE_URL %>';
|
||||
@import 'ascribe_media_player';
|
||||
@import 'ascribe_uploader';
|
||||
@import 'ascribe_footer';
|
||||
@import 'ascribe_global_action';
|
||||
@import 'ascribe_global_notification';
|
||||
@import 'ascribe_notification_list';
|
||||
@import 'ascribe_piece_register';
|
||||
@import 'offset_right';
|
||||
@import 'ascribe_settings';
|
||||
|
Loading…
Reference in New Issue
Block a user