mirror of
https://github.com/ascribe/onion.git
synced 2025-01-03 10:25:08 +01:00
Merge remote-tracking branch 'origin/AD-368-harmonize-functionality-of-ascrib' into AD-527-transition-to-login-form-if-user-
Conflicts: js/components/register_piece.js
This commit is contained in:
commit
1f6d20fb15
@ -8,23 +8,34 @@ import PieceListFetcher from '../fetchers/piece_list_fetcher';
|
|||||||
class PieceListActions {
|
class PieceListActions {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.generateActions(
|
this.generateActions(
|
||||||
'updatePieceList'
|
'updatePieceList',
|
||||||
|
'updatePieceListRequestActions'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchPieceList(page, pageSize, search, orderBy, orderAsc) {
|
fetchPieceList(page, pageSize, search, orderBy, orderAsc) {
|
||||||
PieceListFetcher
|
return new Promise((resolve, reject) => {
|
||||||
.fetch(page, pageSize, search, orderBy, orderAsc)
|
PieceListFetcher
|
||||||
.then((res) => {
|
.fetch(page, pageSize, search, orderBy, orderAsc)
|
||||||
this.actions.updatePieceList({
|
.then((res) => {
|
||||||
page,
|
this.actions.updatePieceList({
|
||||||
pageSize,
|
page,
|
||||||
search,
|
pageSize,
|
||||||
orderBy,
|
search,
|
||||||
orderAsc,
|
orderBy,
|
||||||
'pieceList': res.pieces,
|
orderAsc,
|
||||||
'pieceListCount': res.count
|
'pieceList': res.pieces,
|
||||||
|
'pieceListCount': res.count
|
||||||
|
});
|
||||||
|
resolve();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fetchPieceRequestActions() {
|
||||||
|
PieceListFetcher
|
||||||
|
.fetchRequestActions()
|
||||||
|
.then((res) => {
|
||||||
|
this.actions.updatePieceListRequestActions(res.piece_ids);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,30 +1,64 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Router from 'react-router';
|
||||||
|
|
||||||
|
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
|
||||||
|
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||||
|
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||||
|
|
||||||
|
import requests from '../../utils/requests';
|
||||||
|
|
||||||
import { getLangText } from '../../utils/lang_utils';
|
import { getLangText } from '../../utils/lang_utils';
|
||||||
|
|
||||||
let AccordionListItem = React.createClass({
|
let AccordionListItem = React.createClass({
|
||||||
|
mixins: [Router.Navigation],
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
className: React.PropTypes.string,
|
className: React.PropTypes.string,
|
||||||
content: React.PropTypes.object,
|
content: React.PropTypes.object,
|
||||||
children: React.PropTypes.object
|
children: React.PropTypes.object
|
||||||
},
|
},
|
||||||
|
handleClick(event){
|
||||||
|
requests.get('piece_first_edition_id', {'piece_id': this.props.content.id})
|
||||||
|
.then((res) => this.transitionTo('edition', {editionId: res.bitcoin_id}));
|
||||||
|
|
||||||
|
console.log(event.target);
|
||||||
|
},
|
||||||
|
getGlyphicon(){
|
||||||
|
if (this.props.content.requestAction){
|
||||||
|
return (
|
||||||
|
<OverlayTrigger delay={500} placement="left"
|
||||||
|
overlay={<Tooltip>You have actions pending in one of your editions</Tooltip>}>
|
||||||
|
<Glyphicon glyph='bell' />
|
||||||
|
</OverlayTrigger>);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className={this.props.className}>
|
<div className={this.props.className}>
|
||||||
<div className="wrapper">
|
<div className="wrapper">
|
||||||
<div className="col-xs-5 col-sm-5 col-md-4 col-lg-4 thumbnail-wrapper">
|
<div className="col-xs-4 col-sm-3 col-md-2 col-lg-2 clear-paddings">
|
||||||
<img src={this.props.content.thumbnail} />
|
<div className="thumbnail-wrapper" onClick={this.handleClick}>
|
||||||
|
<img src={this.props.content.thumbnail} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-xs-7 col-sm-7 col-md-7 col-lg-7 col-md-offset-1 col-lg-offset-1">
|
<div className="col-xs-8 col-sm-9 col-md-9 col-lg-9 col-md-offset-1 col-lg-offset-1 accordion-list-item-header">
|
||||||
<h1>{this.props.content.title}</h1>
|
<h1 onClick={this.handleClick}>{this.props.content.title}</h1>
|
||||||
<h3>{getLangText('by %s', this.props.content.artist_name)}</h3>
|
<h3>{getLangText('by %s', this.props.content.artist_name)}</h3>
|
||||||
<h3>{this.props.content.date_created.split('-')[0]}</h3>
|
<div>
|
||||||
|
<span>{this.props.content.date_created.split('-')[0]}</span>
|
||||||
|
<a href={this.props.content.license_type.url} target="_blank" className="pull-right">
|
||||||
|
{this.props.content.license_type.code} license
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span style={{'clear': 'both'}}></span>
|
<span style={{'clear': 'both'}}></span>
|
||||||
|
<div className="request-action-batch">
|
||||||
|
{this.getGlyphicon()}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
|
@ -139,8 +139,12 @@ let AccordionListItemTableEditions = React.createClass({
|
|||||||
),
|
),
|
||||||
new ColumnModel(
|
new ColumnModel(
|
||||||
(item) => {
|
(item) => {
|
||||||
|
let content = item.acl;
|
||||||
|
if (item.request_action){
|
||||||
|
content = [item.request_action + ' request'];
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
'content': item.acl
|
'content': content
|
||||||
}; },
|
}; },
|
||||||
'acl',
|
'acl',
|
||||||
getLangText('Actions'),
|
getLangText('Actions'),
|
||||||
|
@ -42,11 +42,11 @@ let DeleteButton = React.createClass({
|
|||||||
|
|
||||||
if (availableAcls.indexOf('delete') > -1) {
|
if (availableAcls.indexOf('delete') > -1) {
|
||||||
content = <EditionDeleteForm editions={ this.props.editions }/>;
|
content = <EditionDeleteForm editions={ this.props.editions }/>;
|
||||||
btnDelete = <Button bsStyle="danger" bsSize="small">DELETE</Button>;
|
btnDelete = <Button bsStyle="danger" className="btn-delete" bsSize="small">DELETE</Button>;
|
||||||
}
|
}
|
||||||
else if (availableAcls.indexOf('del_from_collection') > -1){
|
else if (availableAcls.indexOf('del_from_collection') > -1){
|
||||||
content = <EditionRemoveFromCollectionForm editions={ this.props.editions }/>;
|
content = <EditionRemoveFromCollectionForm editions={ this.props.editions }/>;
|
||||||
btnDelete = <Button bsStyle="danger" bsSize="small">REMOVE FROM COLLECTION</Button>;
|
btnDelete = <Button bsStyle="danger" className="btn-delete" bsSize="small">REMOVE FROM COLLECTION</Button>;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
return null;
|
return null;
|
||||||
|
@ -54,10 +54,10 @@ let RequestActionForm = React.createClass({
|
|||||||
let buttons = (
|
let buttons = (
|
||||||
<span>
|
<span>
|
||||||
<span>
|
<span>
|
||||||
<div id="request_accept" onClick={this.handleRequest} className='btn btn-default btn-sm'>ACCEPT</div>
|
<div id="request_accept" onClick={this.handleRequest} className='btn btn-default btn-sm ascribe-margin-1px'>ACCEPT</div>
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<div id="request_deny" onClick={this.handleRequest} className='btn btn-default btn-sm'>REJECT</div>
|
<div id="request_deny" onClick={this.handleRequest} className='btn btn-danger btn-delete btn-sm ascribe-margin-1px'>REJECT</div>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
@ -21,7 +21,7 @@ let PieceListToolbar = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let searchIcon = <Glyphicon glyph='search' />;
|
let searchIcon = <Glyphicon glyph='search' className="filter-glyph"/>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={this.props.className}>
|
<div className={this.props.className}>
|
||||||
|
@ -8,7 +8,7 @@ import MenuItem from 'react-bootstrap/lib/MenuItem';
|
|||||||
|
|
||||||
let PieceListToolbarFilterWidgetFilter = React.createClass({
|
let PieceListToolbarFilterWidgetFilter = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
let filterIcon = <Glyphicon glyph='filter' />;
|
let filterIcon = <Glyphicon glyph='filter' className="filter-glyph"/>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownButton title={filterIcon}>
|
<DropdownButton title={filterIcon}>
|
||||||
|
@ -9,7 +9,7 @@ let TableItemAclFiltered = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
var availableAcls = ['consign', 'loan', 'transfer', 'view'];
|
var availableAcls = ['consign', 'loan', 'transfer', 'view', 'consign request', 'unconsign request', 'loan request'];
|
||||||
|
|
||||||
let filteredAcls = this.props.content.filter((v) => {
|
let filteredAcls = this.props.content.filter((v) => {
|
||||||
return availableAcls.indexOf(v) > -1;
|
return availableAcls.indexOf(v) > -1;
|
||||||
|
@ -80,6 +80,7 @@ let Header = React.createClass({
|
|||||||
render() {
|
render() {
|
||||||
let account = null;
|
let account = null;
|
||||||
let signup = null;
|
let signup = null;
|
||||||
|
let collection = null;
|
||||||
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}>
|
||||||
@ -91,6 +92,7 @@ let Header = React.createClass({
|
|||||||
<MenuItem eventKey="4" onClick={this.handleLogout}>{getLangText('Log out')}</MenuItem>
|
<MenuItem eventKey="4" onClick={this.handleLogout}>{getLangText('Log out')}</MenuItem>
|
||||||
</DropdownButton>
|
</DropdownButton>
|
||||||
);
|
);
|
||||||
|
collection = <NavItemLink to="pieces">COLLECTION</NavItemLink>;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
account = <NavItemLink to="login">LOGIN</NavItemLink>;
|
account = <NavItemLink to="login">LOGIN</NavItemLink>;
|
||||||
@ -101,11 +103,14 @@ let Header = React.createClass({
|
|||||||
<div>
|
<div>
|
||||||
<Navbar
|
<Navbar
|
||||||
brand={
|
brand={
|
||||||
<Link className="navbar-brand" to="pieces" path="/?page=1">
|
<Link className="navbar-brand" to="pieces">
|
||||||
{this.getLogo()}
|
{this.getLogo()}
|
||||||
</Link>}
|
</Link>}
|
||||||
toggleNavKey={0}>
|
toggleNavKey={0}>
|
||||||
<CollapsibleNav eventKey={0}>
|
<CollapsibleNav eventKey={0}>
|
||||||
|
<Nav navbar left>
|
||||||
|
{collection}
|
||||||
|
</Nav>
|
||||||
<Nav navbar right>
|
<Nav navbar right>
|
||||||
{account}
|
{account}
|
||||||
{signup}
|
{signup}
|
||||||
|
@ -33,7 +33,8 @@ let PieceList = React.createClass({
|
|||||||
let page = this.props.query.page || 1;
|
let page = this.props.query.page || 1;
|
||||||
PieceListStore.listen(this.onChange);
|
PieceListStore.listen(this.onChange);
|
||||||
if (this.state.pieceList.length === 0){
|
if (this.state.pieceList.length === 0){
|
||||||
PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search, this.state.orderBy, this.state.orderAsc);
|
PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search, this.state.orderBy, this.state.orderAsc)
|
||||||
|
.then(PieceListActions.fetchPieceRequestActions());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -58,15 +58,15 @@ let RegisterPiece = React.createClass( {
|
|||||||
this.setState(state);
|
this.setState(state);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleSuccess(){
|
handleSuccess(response){
|
||||||
let notification = new GlobalNotificationModel('Piece registration successful', 'success', 10000);
|
let notification = new GlobalNotificationModel(response.notification, 'success', 10000);
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
|
|
||||||
// once the user was able to register a piece successfully, we need to make sure to keep
|
// once the user was able to register a piece successfully, we need to make sure to keep
|
||||||
// the piece list up to date
|
// the piece list up to date
|
||||||
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.searchTerm, this.state.orderBy, this.state.orderAsc);
|
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.searchTerm, this.state.orderBy, this.state.orderAsc);
|
||||||
|
|
||||||
this.transitionTo('pieces');
|
this.transitionTo('edition', {editionId: response.edition.bitcoin_id});
|
||||||
},
|
},
|
||||||
|
|
||||||
getFormData(){
|
getFormData(){
|
||||||
@ -111,7 +111,7 @@ let RegisterPiece = React.createClass( {
|
|||||||
onChange={this.onLicenseChange}
|
onChange={this.onLicenseChange}
|
||||||
footer={
|
footer={
|
||||||
<a className="pull-right" href={this.state.licenses[this.state.selectedLicense].url} target="_blank">
|
<a className="pull-right" href={this.state.licenses[this.state.selectedLicense].url} target="_blank">
|
||||||
Learn more about this license
|
Learn more
|
||||||
</a>}>
|
</a>}>
|
||||||
<select name="license">
|
<select name="license">
|
||||||
{this.state.licenses.map((license, i) => {
|
{this.state.licenses.map((license, i) => {
|
||||||
|
@ -227,7 +227,7 @@ let APISettings = React.createClass({
|
|||||||
name={app.name}
|
name={app.name}
|
||||||
label={app.name}>
|
label={app.name}>
|
||||||
<div className="row-same-height">
|
<div className="row-same-height">
|
||||||
<div className="col-xs-6 col-xs-height col-middle">
|
<div className="no-padding col-xs-6 col-xs-height col-middle">
|
||||||
{'Bearer ' + app.bearer_token.token}
|
{'Bearer ' + app.bearer_token.token}
|
||||||
</div>
|
</div>
|
||||||
<div className="col-xs-6 col-xs-height">
|
<div className="col-xs-6 col-xs-height">
|
||||||
|
@ -31,7 +31,9 @@ let apiUrls = {
|
|||||||
'ownership_unconsigns_request': AppConstants.apiEndpoint + 'ownership/unconsigns/request/',
|
'ownership_unconsigns_request': AppConstants.apiEndpoint + 'ownership/unconsigns/request/',
|
||||||
'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/',
|
||||||
'pieces_list': AppConstants.apiEndpoint + 'pieces/',
|
'pieces_list': AppConstants.apiEndpoint + 'pieces/',
|
||||||
|
'pieces_list_request_actions': AppConstants.apiEndpoint + 'pieces/request_actions/',
|
||||||
'user': AppConstants.apiEndpoint + 'users/',
|
'user': AppConstants.apiEndpoint + 'users/',
|
||||||
'users_login': AppConstants.apiEndpoint + 'users/login/',
|
'users_login': AppConstants.apiEndpoint + 'users/login/',
|
||||||
'users_logout': AppConstants.apiEndpoint + 'users/logout/',
|
'users_logout': AppConstants.apiEndpoint + 'users/logout/',
|
||||||
|
@ -12,6 +12,10 @@ let PieceListFetcher = {
|
|||||||
fetch(page, pageSize, search, orderBy, orderAsc) {
|
fetch(page, pageSize, search, orderBy, orderAsc) {
|
||||||
let ordering = generateOrderingQueryParams(orderBy, orderAsc);
|
let ordering = generateOrderingQueryParams(orderBy, orderAsc);
|
||||||
return requests.get('pieces_list', { page, pageSize, search, ordering });
|
return requests.get('pieces_list', { page, pageSize, search, ordering });
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchRequestActions() {
|
||||||
|
return requests.get('pieces_list_request_actions');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,6 +85,11 @@ class PieceListStore {
|
|||||||
|
|
||||||
this.pieceList = pieceList;
|
this.pieceList = pieceList;
|
||||||
}
|
}
|
||||||
|
onUpdatePieceListRequestActions(requestActions) {
|
||||||
|
this.pieceList.forEach((piece) => {
|
||||||
|
piece.requestAction = requestActions.indexOf(piece.id) > -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default alt.createStore(PieceListStore, 'PieceListStore');
|
export default alt.createStore(PieceListStore, 'PieceListStore');
|
||||||
|
@ -24,6 +24,7 @@ $ascribe-accordion-list-font: 'Source Sans Pro';
|
|||||||
width: 110px;
|
width: 110px;
|
||||||
height: 110px;
|
height: 110px;
|
||||||
padding:0;
|
padding:0;
|
||||||
|
cursor: pointer;
|
||||||
img {
|
img {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
@ -38,10 +39,14 @@ $ascribe-accordion-list-font: 'Source Sans Pro';
|
|||||||
h1 {
|
h1 {
|
||||||
margin-top: .3em;
|
margin-top: .3em;
|
||||||
font-size: 2.25em;
|
font-size: 2.25em;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
h3 {
|
h3 {
|
||||||
font-size: 1.1em;
|
font-size: 1.1em;
|
||||||
margin: .7em 0 0 0;
|
margin: .2em 0 0 0;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #666;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,4 +89,13 @@ span.ascribe-accordion-list-table-toggle {
|
|||||||
font-size:.85em;
|
font-size:.85em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.request-action-batch {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
right: 0px;
|
||||||
|
color: #666;
|
||||||
|
font-size: 1.2em;
|
||||||
|
padding: 0.3em;
|
||||||
}
|
}
|
@ -29,6 +29,10 @@ body {
|
|||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -92,12 +96,21 @@ body {
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
float: none;
|
float: none;
|
||||||
}
|
}
|
||||||
|
.filter-glyph{
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
.no-margin {
|
.no-margin {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
.btn-delete{
|
||||||
|
background-color: rgba(0,0,0,0);
|
||||||
|
color: #888;
|
||||||
|
border: 1px solid rgba(0,0,0,0);
|
||||||
|
&:hover{
|
||||||
|
border: 1px solid $ascribe-brand-danger;
|
||||||
|
}
|
||||||
|
}
|
||||||
.btn-ascribe, .btn-ascribe-inv {
|
.btn-ascribe, .btn-ascribe-inv {
|
||||||
border: 1px solid #444;
|
border: 1px solid #444;
|
||||||
line-height: 2em;
|
line-height: 2em;
|
||||||
@ -243,7 +256,7 @@ body {
|
|||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ascribe-button-list button {
|
.ascribe-button-list button, .ascribe-margin-1px {
|
||||||
margin-right: 1px;
|
margin-right: 1px;
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ $input-bg: #fff !default;
|
|||||||
$input-bg-disabled: $gray-lighter !default;
|
$input-bg-disabled: $gray-lighter !default;
|
||||||
|
|
||||||
//** Text color for `<input>`s
|
//** Text color for `<input>`s
|
||||||
$input-color: white !default;
|
$input-color: $gray !default;
|
||||||
//** `<input>` border color
|
//** `<input>` border color
|
||||||
$input-border: #ccc !default;
|
$input-border: #ccc !default;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user