Merged in AD-419-decouple-piece-registration-from- (pull request #8)
Ad 419 decouple piece registration from
@ -184,8 +184,8 @@ function bundle(watch) {
|
|||||||
.on('error', notify.onError('Error: <%= error.message %>'))
|
.on('error', notify.onError('Error: <%= error.message %>'))
|
||||||
.pipe(gulpif(!argv.production, sourcemaps.write())) // writes .map file
|
.pipe(gulpif(!argv.production, sourcemaps.write())) // writes .map file
|
||||||
.on('error', notify.onError('Error: <%= error.message %>'))
|
.on('error', notify.onError('Error: <%= error.message %>'))
|
||||||
//.pipe(gulpif(argv.production, uglify()))
|
.pipe(gulpif(argv.production, uglify()))
|
||||||
//.on('error', notify.onError('Error: <%= error.message %>'))
|
.on('error', notify.onError('Error: <%= error.message %>'))
|
||||||
.pipe(gulp.dest('./build/js'))
|
.pipe(gulp.dest('./build/js'))
|
||||||
.on('error', notify.onError('Error: <%= error.message %>'))
|
.on('error', notify.onError('Error: <%= error.message %>'))
|
||||||
.pipe(browserSync.stream())
|
.pipe(browserSync.stream())
|
||||||
|
BIN
img/hq-favicons/android-chrome-144x144.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
img/hq-favicons/android-chrome-36x36.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
img/hq-favicons/android-chrome-48x48.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
img/hq-favicons/android-chrome-72x72.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
img/hq-favicons/android-chrome-96x96.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
img/hq-favicons/apple-touch-icon-114x114.png
Normal file
After Width: | Height: | Size: 8.9 KiB |
BIN
img/hq-favicons/apple-touch-icon-120x120.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
img/hq-favicons/apple-touch-icon-144x144.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
img/hq-favicons/apple-touch-icon-152x152.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
img/hq-favicons/apple-touch-icon-57x57.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
img/hq-favicons/apple-touch-icon-60x60.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
img/hq-favicons/apple-touch-icon-72x72.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
img/hq-favicons/apple-touch-icon-76x76.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
img/hq-favicons/apple-touch-icon-precomposed.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
img/hq-favicons/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 12 KiB |
12
img/hq-favicons/browserconfig.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<browserconfig>
|
||||||
|
<msapplication>
|
||||||
|
<tile>
|
||||||
|
<square70x70logo src="images/hq-favicons/mstile-70x70.png"/>
|
||||||
|
<square150x150logo src="images/hq-favicons/mstile-150x150.png"/>
|
||||||
|
<square310x310logo src="images/hq-favicons/mstile-310x310.png"/>
|
||||||
|
<wide310x150logo src="images/hq-favicons/mstile-310x150.png"/>
|
||||||
|
<TileColor>#00aba9</TileColor>
|
||||||
|
</tile>
|
||||||
|
</msapplication>
|
||||||
|
</browserconfig>
|
BIN
img/hq-favicons/favicon-16x16.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
img/hq-favicons/favicon-32x32.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
img/hq-favicons/favicon-96x96.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
img/hq-favicons/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
35
img/hq-favicons/manifest.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "Ascribe",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "images\/hq-favicons\/android-chrome-36x36.png",
|
||||||
|
"sizes": "36x36",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "0.75"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "images\/hq-favicons\/android-chrome-48x48.png",
|
||||||
|
"sizes": "48x48",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "1.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "images\/hq-favicons\/android-chrome-72x72.png",
|
||||||
|
"sizes": "72x72",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "1.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "images\/hq-favicons\/android-chrome-96x96.png",
|
||||||
|
"sizes": "96x96",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "2.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "images\/hq-favicons\/android-chrome-144x144.png",
|
||||||
|
"sizes": "144x144",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "3.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
BIN
img/hq-favicons/mstile-144x144.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
img/hq-favicons/mstile-150x150.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
img/hq-favicons/mstile-310x150.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
img/hq-favicons/mstile-310x310.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
img/hq-favicons/mstile-70x70.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
18
index.html
@ -2,6 +2,24 @@
|
|||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
<link rel="apple-touch-icon" sizes="57x57" href="<%= BASE_URL %>static/img/hq-favicons/apple-touch-icon-57x57.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="60x60" href="<%= BASE_URL %>static/img/hq-favicons/apple-touch-icon-60x60.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="72x72" href="<%= BASE_URL %>static/img/hq-favicons/apple-touch-icon-72x72.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="76x76" href="<%= BASE_URL %>static/img/hq-favicons/apple-touch-icon-76x76.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="114x114" href="<%= BASE_URL %>static/img/hq-favicons/apple-touch-icon-114x114.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="120x120" href="<%= BASE_URL %>static/img/hq-favicons/apple-touch-icon-120x120.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="144x144" href="<%= BASE_URL %>static/img/hq-favicons/apple-touch-icon-144x144.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="152x152" href="<%= BASE_URL %>static/img/hq-favicons/apple-touch-icon-152x152.png">
|
||||||
|
<link rel="icon" type="image/png" href="<%= BASE_URL %>static/img/hq-favicons/favicon-32x32.png" sizes="32x32">
|
||||||
|
<link rel="icon" type="image/png" href="<%= BASE_URL %>static/img/hq-favicons/favicon-96x96.png" sizes="96x96">
|
||||||
|
<link rel="icon" type="image/png" href="<%= BASE_URL %>static/img/hq-favicons/favicon-16x16.png" sizes="16x16">
|
||||||
|
<link rel="manifest" href="<%= BASE_URL %>static/img/hq-favicons/manifest.json">
|
||||||
|
<link rel="shortcut icon" href="<%= BASE_URL %>static/img/hq-favicons/favicon.ico">
|
||||||
|
<meta name="msapplication-TileColor" content="#00aba9">
|
||||||
|
<meta name="msapplication-TileImage" content="<%= BASE_URL %>static/img/hq-favicons/mstile-144x144.png">
|
||||||
|
<meta name="msapplication-config" content="<%= BASE_URL %>static/img/hq-favicons/browserconfig.xml">
|
||||||
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
<title>ascribe</title>
|
<title>ascribe</title>
|
||||||
|
@ -8,6 +8,7 @@ class EditionListActions {
|
|||||||
constructor() {
|
constructor() {
|
||||||
this.generateActions(
|
this.generateActions(
|
||||||
'updateEditionList',
|
'updateEditionList',
|
||||||
|
'refreshEditionList',
|
||||||
'selectEdition',
|
'selectEdition',
|
||||||
'clearAllEditionSelections',
|
'clearAllEditionSelections',
|
||||||
'closeAllEditionLists',
|
'closeAllEditionLists',
|
||||||
@ -16,7 +17,7 @@ class EditionListActions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetchEditionList(pieceId, page, pageSize, orderBy, orderAsc) {
|
fetchEditionList(pieceId, page, pageSize, orderBy, orderAsc) {
|
||||||
if(!orderBy && typeof orderAsc == 'undefined') {
|
if(!orderBy && typeof orderAsc === 'undefined') {
|
||||||
orderBy = 'edition_number';
|
orderBy = 'edition_number';
|
||||||
orderAsc = true;
|
orderAsc = true;
|
||||||
}
|
}
|
||||||
|
38
js/components/acl_proxy.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component can easily be used to present another component conditionally
|
||||||
|
* - dependent on their acl.
|
||||||
|
*
|
||||||
|
* In order to do that, just wrap AclProxy around the component, add aclObject and
|
||||||
|
* the acl name you're looking for.
|
||||||
|
*/
|
||||||
|
let AclProxy = React.createClass({
|
||||||
|
propTypes: {
|
||||||
|
children: React.PropTypes.oneOfType([
|
||||||
|
React.PropTypes.arrayOf(React.PropTypes.element),
|
||||||
|
React.PropTypes.element
|
||||||
|
]).isRequired,
|
||||||
|
aclObject: React.PropTypes.object.isRequired,
|
||||||
|
aclName: React.PropTypes.string.isRequired
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if(this.props.aclObject[this.props.aclName]) {
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{this.props.children}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if(typeof this.props.aclObject[this.props.aclName] === 'undefined') {
|
||||||
|
console.warn('The aclName you\'re filtering for was not present (undefined) in the aclObject.');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default AclProxy;
|
@ -13,6 +13,9 @@ import CreateEditionsForm from '../ascribe_forms/create_editions_form';
|
|||||||
import PieceListActions from '../../actions/piece_list_actions';
|
import PieceListActions from '../../actions/piece_list_actions';
|
||||||
import EditionListActions from '../../actions/edition_list_actions';
|
import EditionListActions from '../../actions/edition_list_actions';
|
||||||
|
|
||||||
|
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||||
|
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||||
|
|
||||||
import { getLangText } from '../../utils/lang_utils';
|
import { getLangText } from '../../utils/lang_utils';
|
||||||
|
|
||||||
let Link = Router.Link;
|
let Link = Router.Link;
|
||||||
@ -63,6 +66,9 @@ let AccordionListItem = React.createClass({
|
|||||||
});
|
});
|
||||||
|
|
||||||
EditionListActions.toggleEditionList(pieceId);
|
EditionListActions.toggleEditionList(pieceId);
|
||||||
|
|
||||||
|
let notification = new GlobalNotificationModel('Editions successfully created', 'success', 10000);
|
||||||
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
},
|
},
|
||||||
|
|
||||||
getCreateEditionsDialog() {
|
getCreateEditionsDialog() {
|
||||||
|
@ -162,11 +162,9 @@ let AccordionListItemTableEditions = React.createClass({
|
|||||||
new ColumnModel(
|
new ColumnModel(
|
||||||
(item) => {
|
(item) => {
|
||||||
let content = item.acl;
|
let content = item.acl;
|
||||||
if (item.request_action) {
|
|
||||||
content = [item.request_action + ' request'];
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
'content': content
|
'content': content,
|
||||||
|
'requestAction': item.request_action
|
||||||
}; },
|
}; },
|
||||||
'acl',
|
'acl',
|
||||||
getLangText('Actions'),
|
getLangText('Actions'),
|
||||||
|
@ -38,7 +38,12 @@ let AclButton = React.createClass({
|
|||||||
return {
|
return {
|
||||||
title: getLangText('Consign artwork'),
|
title: getLangText('Consign artwork'),
|
||||||
tooltip: getLangText('Have someone else sell the artwork'),
|
tooltip: getLangText('Have someone else sell the artwork'),
|
||||||
form: <ConsignForm currentUser={ this.props.currentUser } editions={ this.props.pieceOrEditions }/>,
|
form: (
|
||||||
|
<ConsignForm
|
||||||
|
message={this.getConsignMessage()}
|
||||||
|
id={this.getFormDataId()}
|
||||||
|
url={apiUrls.ownership_consigns}/>
|
||||||
|
),
|
||||||
handleSuccess: this.showNotification
|
handleSuccess: this.showNotification
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -46,14 +51,24 @@ let AclButton = React.createClass({
|
|||||||
return {
|
return {
|
||||||
title: getLangText('Unconsign artwork'),
|
title: getLangText('Unconsign artwork'),
|
||||||
tooltip: getLangText('Have the owner manage his sales again'),
|
tooltip: getLangText('Have the owner manage his sales again'),
|
||||||
form: <UnConsignForm currentUser={ this.props.currentUser } editions={ this.props.pieceOrEditions }/>,
|
form: (
|
||||||
|
<UnConsignForm
|
||||||
|
message={this.getUnConsignMessage()}
|
||||||
|
id={this.getFormDataId()}
|
||||||
|
url={apiUrls.ownership_unconsigns}/>
|
||||||
|
),
|
||||||
handleSuccess: this.showNotification
|
handleSuccess: this.showNotification
|
||||||
};
|
};
|
||||||
}else if (this.props.action === 'acl_transfer') {
|
}else if (this.props.action === 'acl_transfer') {
|
||||||
return {
|
return {
|
||||||
title: getLangText('Transfer artwork'),
|
title: getLangText('Transfer artwork'),
|
||||||
tooltip: getLangText('Transfer the ownership of the artwork'),
|
tooltip: getLangText('Transfer the ownership of the artwork'),
|
||||||
form: <TransferForm currentUser={ this.props.currentUser } editions={ this.props.pieceOrEditions }/>,
|
form: (
|
||||||
|
<TransferForm
|
||||||
|
message={this.getTransferMessage()}
|
||||||
|
id={this.getFormDataId()}
|
||||||
|
url={apiUrls.ownership_transfers}/>
|
||||||
|
),
|
||||||
handleSuccess: this.showNotification
|
handleSuccess: this.showNotification
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -112,11 +127,52 @@ let AclButton = React.createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// plz move to transfer form
|
||||||
|
getTransferMessage(){
|
||||||
|
return (
|
||||||
|
`${getLangText('Hi')},
|
||||||
|
|
||||||
|
${getLangText('I transfer ownership of')}:
|
||||||
|
${this.getTitlesString()} ${getLangText('to you')}.
|
||||||
|
|
||||||
|
${getLangText('Truly yours')},
|
||||||
|
${this.props.currentUser.username}
|
||||||
|
`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
// plz move to consign form
|
||||||
|
getConsignMessage(){
|
||||||
|
return (
|
||||||
|
`${getLangText('Hi')},
|
||||||
|
|
||||||
|
${getLangText('I consign')}:
|
||||||
|
${this.getTitlesString()} ${getLangText('to you')}.
|
||||||
|
|
||||||
|
${getLangText('Truly yours')},
|
||||||
|
${this.props.currentUser.username}
|
||||||
|
`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
// plz move to consign form
|
||||||
|
getUnConsignMessage(){
|
||||||
|
return (
|
||||||
|
`${getLangText('Hi')},
|
||||||
|
|
||||||
|
${getLangText('I un-consign')}:
|
||||||
|
${this.getTitlesString()} ${getLangText('from you')}.
|
||||||
|
|
||||||
|
${getLangText('Truly yours')},
|
||||||
|
${this.props.currentUser.username}
|
||||||
|
`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
// plz move to share form
|
// plz move to share form
|
||||||
getShareMessage(){
|
getShareMessage(){
|
||||||
return (
|
return (
|
||||||
`
|
`${getLangText('Hi')},
|
||||||
${getLangText('Hi')},
|
|
||||||
|
|
||||||
${getLangText('I am sharing')}:
|
${getLangText('I am sharing')}:
|
||||||
${this.getTitlesString()} ${getLangText('with you')}.
|
${this.getTitlesString()} ${getLangText('with you')}.
|
||||||
|
@ -6,7 +6,6 @@ import UserActions from '../../actions/user_actions';
|
|||||||
import UserStore from '../../stores/user_store';
|
import UserStore from '../../stores/user_store';
|
||||||
|
|
||||||
import AclButton from '../ascribe_buttons/acl_button';
|
import AclButton from '../ascribe_buttons/acl_button';
|
||||||
import DeleteButton from '../ascribe_buttons/delete_button';
|
|
||||||
|
|
||||||
let AclButtonList = React.createClass({
|
let AclButtonList = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
@ -73,8 +72,6 @@ let AclButtonList = React.createClass({
|
|||||||
pieceOrEditions={this.props.editions}
|
pieceOrEditions={this.props.editions}
|
||||||
currentUser={this.state.currentUser}
|
currentUser={this.state.currentUser}
|
||||||
handleSuccess={this.props.handleSuccess} />
|
handleSuccess={this.props.handleSuccess} />
|
||||||
<DeleteButton
|
|
||||||
editions={this.props.editions}/>
|
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -6,59 +6,71 @@ import Router from 'react-router';
|
|||||||
import Button from 'react-bootstrap/lib/Button';
|
import Button from 'react-bootstrap/lib/Button';
|
||||||
|
|
||||||
import EditionDeleteForm from '../ascribe_forms/form_delete_edition';
|
import EditionDeleteForm from '../ascribe_forms/form_delete_edition';
|
||||||
import EditionRemoveFromCollectionForm from '../ascribe_forms/form_remove_editions_from_collection';
|
import PieceDeleteForm from '../ascribe_forms/form_delete_piece';
|
||||||
import ModalWrapper from '../ascribe_modal/modal_wrapper';
|
|
||||||
|
|
||||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
import EditionRemoveFromCollectionForm from '../ascribe_forms/form_remove_editions_from_collection';
|
||||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
import PieceRemoveFromCollectionForm from '../ascribe_forms/form_remove_piece_from_collection';
|
||||||
|
|
||||||
|
import ModalWrapper from '../ascribe_modal/modal_wrapper';
|
||||||
|
|
||||||
import { getAvailableAcls } from '../../utils/acl_utils';
|
import { getAvailableAcls } from '../../utils/acl_utils';
|
||||||
import { getLangText } from '../../utils/lang_utils.js';
|
import { getLangText } from '../../utils/lang_utils.js';
|
||||||
|
|
||||||
import EditionListActions from '../../actions/edition_list_actions';
|
|
||||||
|
|
||||||
let DeleteButton = React.createClass({
|
let DeleteButton = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
editions: React.PropTypes.array.isRequired
|
editions: React.PropTypes.array,
|
||||||
|
piece: React.PropTypes.object,
|
||||||
|
handleSuccess: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
mixins: [Router.Navigation],
|
mixins: [Router.Navigation],
|
||||||
|
|
||||||
showNotification(response) {
|
|
||||||
this.props.editions
|
|
||||||
.forEach((edition) => {
|
|
||||||
EditionListActions.fetchEditionList(edition.parent);
|
|
||||||
});
|
|
||||||
EditionListActions.clearAllEditionSelections();
|
|
||||||
EditionListActions.closeAllEditionLists();
|
|
||||||
this.transitionTo('pieces');
|
|
||||||
let notification = new GlobalNotificationModel(response.notification, 'success');
|
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function () {
|
render: function () {
|
||||||
let availableAcls = getAvailableAcls(this.props.editions);
|
let availableAcls;
|
||||||
let btnDelete = null;
|
let btnDelete;
|
||||||
let content = null;
|
let content;
|
||||||
|
let title;
|
||||||
|
|
||||||
if (availableAcls.acl_delete) {
|
if(this.props.piece && !this.props.editions) {
|
||||||
content = <EditionDeleteForm editions={ this.props.editions }/>;
|
availableAcls = getAvailableAcls([this.props.piece]);
|
||||||
btnDelete = <Button bsStyle="danger" className="btn-delete" bsSize="small">{getLangText('DELETE')}</Button>;
|
} else {
|
||||||
|
availableAcls = getAvailableAcls(this.props.editions);
|
||||||
}
|
}
|
||||||
else if (availableAcls.acl_unshare || (this.props.editions.constructor !== Array && this.props.editions.acl.acl_unshare)){
|
|
||||||
content = <EditionRemoveFromCollectionForm editions={ this.props.editions }/>;
|
if(availableAcls.acl_delete) {
|
||||||
|
|
||||||
|
if(this.props.piece && !this.props.editions) {
|
||||||
|
content = <PieceDeleteForm pieceId={this.props.piece.id}/>;
|
||||||
|
title = getLangText('Remove Piece');
|
||||||
|
} else {
|
||||||
|
content = <EditionDeleteForm editions={this.props.editions}/>;
|
||||||
|
title = getLangText('Remove Edition');
|
||||||
|
}
|
||||||
|
|
||||||
|
btnDelete = <Button bsStyle="danger" className="btn-delete" bsSize="small">{getLangText('DELETE')}</Button>;
|
||||||
|
|
||||||
|
} else if(availableAcls.acl_unshare){
|
||||||
|
|
||||||
|
if(this.props.editions && this.props.editions.constructor !== Array && this.props.editions.acl.acl_unshare) {
|
||||||
|
content = <EditionRemoveFromCollectionForm editions={this.props.editions}/>;
|
||||||
|
title = getLangText('Remove Edition from Collection');
|
||||||
|
} else {
|
||||||
|
content = <PieceRemoveFromCollectionForm pieceId={this.props.piece.id}/>;
|
||||||
|
title = getLangText('Remove Piece from Collection');
|
||||||
|
}
|
||||||
|
|
||||||
btnDelete = <Button bsStyle="danger" className="btn-delete" bsSize="small">{getLangText('REMOVE FROM COLLECTION')}</Button>;
|
btnDelete = <Button bsStyle="danger" className="btn-delete" bsSize="small">{getLangText('REMOVE FROM COLLECTION')}</Button>;
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<ModalWrapper
|
<ModalWrapper
|
||||||
button={ btnDelete }
|
button={btnDelete}
|
||||||
handleSuccess={ this.showNotification }
|
handleSuccess={this.props.handleSuccess}
|
||||||
title={getLangText('Remove Edition')}
|
title={title}>
|
||||||
tooltip={getLangText('Click to remove edition')}>
|
{content}
|
||||||
{ content }
|
|
||||||
</ModalWrapper>
|
</ModalWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
47
js/components/ascribe_buttons/unconsign_request_button.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Button from 'react-bootstrap/lib/Button';
|
||||||
|
|
||||||
|
import ModalWrapper from '../ascribe_modal/modal_wrapper';
|
||||||
|
import UnConsignRequestForm from './../ascribe_forms/form_unconsign_request';
|
||||||
|
|
||||||
|
import { getLangText } from '../../utils/lang_utils.js';
|
||||||
|
import apiUrls from '../../constants/api_urls';
|
||||||
|
|
||||||
|
|
||||||
|
let UnConsignRequestButton = React.createClass({
|
||||||
|
propTypes: {
|
||||||
|
currentUser: React.PropTypes.object.isRequired,
|
||||||
|
edition: React.PropTypes.object.isRequired,
|
||||||
|
handleSuccess: React.PropTypes.func.isRequired
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function () {
|
||||||
|
return (
|
||||||
|
<ModalWrapper
|
||||||
|
button={
|
||||||
|
<Button bsStyle="danger" className="btn-delete pull-center" bsSize="small" type="submit">
|
||||||
|
REQUEST UNCONSIGN
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
handleSuccess={this.props.handleSuccess}
|
||||||
|
title='Request to Un-Consign'
|
||||||
|
tooltip='Ask the consignee to return the ownership of the work back to you'>
|
||||||
|
<UnConsignRequestForm
|
||||||
|
url={apiUrls.ownership_unconsigns_request}
|
||||||
|
id={{'bitcoin_id': this.props.edition.bitcoin_id}}
|
||||||
|
message={`${getLangText('Hi')},
|
||||||
|
|
||||||
|
${getLangText('I request you to un-consign')} \" ${this.props.edition.title} \".
|
||||||
|
|
||||||
|
${getLangText('Truly yours')},
|
||||||
|
${this.props.currentUser.username}`}/>
|
||||||
|
</ModalWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default UnConsignRequestButton;
|
||||||
|
|
@ -6,11 +6,16 @@ import Router from 'react-router';
|
|||||||
import Row from 'react-bootstrap/lib/Row';
|
import Row from 'react-bootstrap/lib/Row';
|
||||||
import Col from 'react-bootstrap/lib/Col';
|
import Col from 'react-bootstrap/lib/Col';
|
||||||
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
|
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
|
||||||
|
import Button from 'react-bootstrap/lib/Button';
|
||||||
|
|
||||||
import UserActions from '../../actions/user_actions';
|
import UserActions from '../../actions/user_actions';
|
||||||
import UserStore from '../../stores/user_store';
|
import UserStore from '../../stores/user_store';
|
||||||
import CoaActions from '../../actions/coa_actions';
|
import CoaActions from '../../actions/coa_actions';
|
||||||
import CoaStore from '../../stores/coa_store';
|
import CoaStore from '../../stores/coa_store';
|
||||||
|
import PieceListActions from '../../actions/piece_list_actions';
|
||||||
|
import PieceListStore from '../../stores/piece_list_store';
|
||||||
|
import EditionListActions from '../../actions/edition_list_actions';
|
||||||
|
|
||||||
|
|
||||||
import MediaContainer from './media_container';
|
import MediaContainer from './media_container';
|
||||||
|
|
||||||
@ -23,12 +28,11 @@ import InputTextAreaToggable from './../ascribe_forms/input_textarea_toggable';
|
|||||||
|
|
||||||
import EditionFurtherDetails from './further_details';
|
import EditionFurtherDetails from './further_details';
|
||||||
|
|
||||||
//import PieceExtraDataForm from './../ascribe_forms/form_piece_extradata';
|
|
||||||
import RequestActionForm from './../ascribe_forms/form_request_action';
|
import RequestActionForm from './../ascribe_forms/form_request_action';
|
||||||
import EditionActions from '../../actions/edition_actions';
|
import EditionActions from '../../actions/edition_actions';
|
||||||
import AclButtonList from './../ascribe_buttons/acl_button_list';
|
import AclButtonList from './../ascribe_buttons/acl_button_list';
|
||||||
|
import UnConsignRequestButton from './../ascribe_buttons/unconsign_request_button';
|
||||||
//import ReactS3FineUploader from './../ascribe_uploader/react_s3_fine_uploader';
|
import DeleteButton from '../ascribe_buttons/delete_button';
|
||||||
|
|
||||||
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';
|
||||||
@ -37,6 +41,7 @@ import apiUrls from '../../constants/api_urls';
|
|||||||
import AppConstants from '../../constants/application_constants';
|
import AppConstants from '../../constants/application_constants';
|
||||||
|
|
||||||
import { getLangText } from '../../utils/lang_utils';
|
import { getLangText } from '../../utils/lang_utils';
|
||||||
|
import { mergeOptions } from '../../utils/general_utils';
|
||||||
|
|
||||||
let Link = Router.Link;
|
let Link = Router.Link;
|
||||||
/**
|
/**
|
||||||
@ -48,23 +53,44 @@ let Edition = React.createClass({
|
|||||||
loadEdition: React.PropTypes.func
|
loadEdition: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
|
mixins: [Router.Navigation],
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return UserStore.getState();
|
return mergeOptions(
|
||||||
|
UserStore.getState(),
|
||||||
|
PieceListStore.getState()
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
UserStore.listen(this.onChange);
|
UserStore.listen(this.onChange);
|
||||||
|
PieceListStore.listen(this.onChange);
|
||||||
UserActions.fetchCurrentUser();
|
UserActions.fetchCurrentUser();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
UserStore.unlisten(this.onChange);
|
UserStore.unlisten(this.onChange);
|
||||||
|
PieceListStore.unlisten(this.onChange);
|
||||||
},
|
},
|
||||||
|
|
||||||
onChange(state) {
|
onChange(state) {
|
||||||
this.setState(state);
|
this.setState(state);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleDeleteSuccess(response) {
|
||||||
|
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search, this.state.orderBy, this.state.orderAsc);
|
||||||
|
|
||||||
|
// we don't need to refresh the edition list for a piece here, since its reloaded from
|
||||||
|
// scatch once you click on show-editions anyway
|
||||||
|
EditionListActions.closeAllEditionLists();
|
||||||
|
EditionListActions.clearAllEditionSelections();
|
||||||
|
|
||||||
|
let notification = new GlobalNotificationModel(response.notification, 'success');
|
||||||
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
|
|
||||||
|
this.transitionTo('pieces');
|
||||||
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Row>
|
<Row>
|
||||||
@ -80,12 +106,14 @@ let Edition = React.createClass({
|
|||||||
<hr/>
|
<hr/>
|
||||||
</div>
|
</div>
|
||||||
<EditionSummary
|
<EditionSummary
|
||||||
|
handleSuccess={this.props.loadEdition}
|
||||||
currentUser={this.state.currentUser}
|
currentUser={this.state.currentUser}
|
||||||
edition={this.props.edition} />
|
edition={this.props.edition}
|
||||||
|
handleDeleteSuccess={this.handleDeleteSuccess}/>
|
||||||
|
|
||||||
<CollapsibleParagraph
|
<CollapsibleParagraph
|
||||||
title={getLangText('Certificate of Authenticity')}
|
title={getLangText('Certificate of Authenticity')}
|
||||||
show={this.props.edition.acl.acl_coa}>
|
show={this.props.edition.acl.acl_coa === true}>
|
||||||
<CoaDetails
|
<CoaDetails
|
||||||
edition={this.props.edition}/>
|
edition={this.props.edition}/>
|
||||||
</CollapsibleParagraph>
|
</CollapsibleParagraph>
|
||||||
@ -151,19 +179,21 @@ let Edition = React.createClass({
|
|||||||
|
|
||||||
let EditionSummary = React.createClass({
|
let EditionSummary = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
edition: React.PropTypes.object
|
edition: React.PropTypes.object,
|
||||||
|
handleSuccess: React.PropTypes.func,
|
||||||
|
currentUser: React.PropTypes.object,
|
||||||
|
handleDeleteSuccess: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
getTransferWithdrawData(){
|
getTransferWithdrawData(){
|
||||||
return {'bitcoin_id': this.props.edition.bitcoin_id};
|
return {'bitcoin_id': this.props.edition.bitcoin_id};
|
||||||
},
|
},
|
||||||
handleSuccess(){
|
|
||||||
EditionActions.fetchOne(this.props.edition.id);
|
|
||||||
},
|
|
||||||
showNotification(response){
|
showNotification(response){
|
||||||
this.handleSuccess();
|
this.props.handleSuccess();
|
||||||
let notification = new GlobalNotificationModel(response.notification, 'success');
|
if (response){
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
let notification = new GlobalNotificationModel(response.notification, 'success');
|
||||||
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
getStatus(){
|
getStatus(){
|
||||||
let status = null;
|
let status = null;
|
||||||
@ -172,32 +202,47 @@ let EditionSummary = React.createClass({
|
|||||||
status = <EditionDetailProperty label="STATUS" value={ statusStr }/>;
|
status = <EditionDetailProperty label="STATUS" value={ statusStr }/>;
|
||||||
if (this.props.edition.pending_new_owner && this.props.edition.acl.acl_withdraw_transfer){
|
if (this.props.edition.pending_new_owner && this.props.edition.acl.acl_withdraw_transfer){
|
||||||
status = (
|
status = (
|
||||||
<Form
|
<EditionDetailProperty label="STATUS" value={ statusStr } />
|
||||||
url={apiUrls.ownership_transfers_withdraw}
|
|
||||||
getFormData={this.getTransferWithdrawData}
|
|
||||||
handleSuccess={this.showNotification}>
|
|
||||||
<EditionDetailProperty label="STATUS" value={ statusStr }>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="pull-right btn btn-default btn-sm">
|
|
||||||
WITHDRAW
|
|
||||||
</button>
|
|
||||||
</EditionDetailProperty>
|
|
||||||
</Form>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
},
|
},
|
||||||
|
|
||||||
getActions(){
|
getActions(){
|
||||||
let actions = null;
|
let actions = null;
|
||||||
if (this.props.edition.request_action && this.props.edition.request_action.length > 0){
|
if (this.props.edition.request_action && this.props.edition.request_action.length > 0){
|
||||||
actions = (
|
actions = (
|
||||||
<RequestActionForm
|
<RequestActionForm
|
||||||
|
currentUser={this.props.currentUser}
|
||||||
editions={ [this.props.edition] }
|
editions={ [this.props.edition] }
|
||||||
handleSuccess={this.showNotification}/>);
|
handleSuccess={this.showNotification}/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
let withdrawButton = null;
|
||||||
|
if (this.props.edition.status.length > 0 && this.props.edition.pending_new_owner && this.props.edition.acl.acl_withdraw_transfer) {
|
||||||
|
withdrawButton = (
|
||||||
|
<Form
|
||||||
|
url={apiUrls.ownership_transfers_withdraw}
|
||||||
|
getFormData={this.getTransferWithdrawData}
|
||||||
|
handleSuccess={this.showNotification}
|
||||||
|
className='inline'>
|
||||||
|
<Button bsStyle="danger" className="btn-delete pull-center" bsSize="small" type="submit">
|
||||||
|
WITHDRAW TRANSFER
|
||||||
|
</Button>
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let unconsignRequestButton = null;
|
||||||
|
if (this.props.edition.acl.acl_request_unconsign) {
|
||||||
|
unconsignRequestButton = (
|
||||||
|
<UnConsignRequestButton
|
||||||
|
currentUser={this.props.currentUser}
|
||||||
|
edition={this.props.edition}
|
||||||
|
handleSuccess={this.props.handleSuccess} />
|
||||||
|
);
|
||||||
|
}
|
||||||
actions = (
|
actions = (
|
||||||
<Row>
|
<Row>
|
||||||
<Col md={12}>
|
<Col md={12}>
|
||||||
@ -205,7 +250,13 @@ let EditionSummary = React.createClass({
|
|||||||
className="text-center ascribe-button-list"
|
className="text-center ascribe-button-list"
|
||||||
availableAcls={this.props.edition.acl}
|
availableAcls={this.props.edition.acl}
|
||||||
editions={[this.props.edition]}
|
editions={[this.props.edition]}
|
||||||
handleSuccess={this.handleSuccess} />
|
handleSuccess={this.props.handleSuccess}>
|
||||||
|
{withdrawButton}
|
||||||
|
<DeleteButton
|
||||||
|
handleSuccess={this.props.handleDeleteSuccess}
|
||||||
|
editions={[this.props.edition]}/>
|
||||||
|
{unconsignRequestButton}
|
||||||
|
</AclButtonList>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>);
|
</Row>);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ import MediaPlayer from './../ascribe_media/media_player';
|
|||||||
|
|
||||||
import CollapsibleButton from './../ascribe_collapsible/collapsible_button';
|
import CollapsibleButton from './../ascribe_collapsible/collapsible_button';
|
||||||
|
|
||||||
|
import AclProxy from '../acl_proxy';
|
||||||
|
|
||||||
|
|
||||||
let MediaContainer = React.createClass({
|
let MediaContainer = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
@ -49,9 +51,13 @@ let MediaContainer = React.createClass({
|
|||||||
url={this.props.content.digital_work.url}
|
url={this.props.content.digital_work.url}
|
||||||
extraData={extraData} />
|
extraData={extraData} />
|
||||||
<p className="text-center">
|
<p className="text-center">
|
||||||
<Button bsSize="xsmall" className="ascribe-margin-1px" href={this.props.content.digital_work.url} target="_blank">
|
<AclProxy
|
||||||
Download <Glyphicon glyph="cloud-download"/>
|
aclObject={this.props.content.acl}
|
||||||
</Button>
|
aclName="acl_download">
|
||||||
|
<Button bsSize="xsmall" className="ascribe-margin-1px" href={this.props.content.digital_work.url} target="_blank">
|
||||||
|
Download <Glyphicon glyph="cloud-download"/>
|
||||||
|
</Button>
|
||||||
|
</AclProxy>
|
||||||
{embed}
|
{embed}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Router from 'react-router';
|
||||||
|
|
||||||
import Row from 'react-bootstrap/lib/Row';
|
import Row from 'react-bootstrap/lib/Row';
|
||||||
import Col from 'react-bootstrap/lib/Col';
|
import Col from 'react-bootstrap/lib/Col';
|
||||||
@ -14,6 +15,11 @@ import FurtherDetails from './further_details';
|
|||||||
import UserActions from '../../actions/user_actions';
|
import UserActions from '../../actions/user_actions';
|
||||||
import UserStore from '../../stores/user_store';
|
import UserStore from '../../stores/user_store';
|
||||||
|
|
||||||
|
import PieceListActions from '../../actions/piece_list_actions';
|
||||||
|
import PieceListStore from '../../stores/piece_list_store';
|
||||||
|
|
||||||
|
import EditionListActions from '../../actions/edition_list_actions';
|
||||||
|
|
||||||
import PieceActions from '../../actions/piece_actions';
|
import PieceActions from '../../actions/piece_actions';
|
||||||
|
|
||||||
import MediaContainer from './media_container';
|
import MediaContainer from './media_container';
|
||||||
@ -23,6 +29,10 @@ import EditionDetailProperty from './detail_property';
|
|||||||
import AclButtonList from './../ascribe_buttons/acl_button_list';
|
import AclButtonList from './../ascribe_buttons/acl_button_list';
|
||||||
import CreateEditionsForm from '../ascribe_forms/create_editions_form';
|
import CreateEditionsForm from '../ascribe_forms/create_editions_form';
|
||||||
import CreateEditionsButton from '../ascribe_buttons/create_editions_button';
|
import CreateEditionsButton from '../ascribe_buttons/create_editions_button';
|
||||||
|
import DeleteButton from '../ascribe_buttons/delete_button';
|
||||||
|
|
||||||
|
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||||
|
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||||
|
|
||||||
import { getLangText } from '../../utils/lang_utils';
|
import { getLangText } from '../../utils/lang_utils';
|
||||||
import { mergeOptions } from '../../utils/general_utils';
|
import { mergeOptions } from '../../utils/general_utils';
|
||||||
@ -36,9 +46,12 @@ let Piece = React.createClass({
|
|||||||
loadPiece: React.PropTypes.func
|
loadPiece: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
|
mixins: [Router.Navigation],
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return mergeOptions(
|
return mergeOptions(
|
||||||
UserStore.getState(),
|
UserStore.getState(),
|
||||||
|
PieceListStore.getState(),
|
||||||
{
|
{
|
||||||
showCreateEditionsDialog: false
|
showCreateEditionsDialog: false
|
||||||
}
|
}
|
||||||
@ -47,11 +60,13 @@ let Piece = React.createClass({
|
|||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
UserStore.listen(this.onChange);
|
UserStore.listen(this.onChange);
|
||||||
|
PieceListStore.listen(this.onChange);
|
||||||
UserActions.fetchCurrentUser();
|
UserActions.fetchCurrentUser();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
UserStore.unlisten(this.onChange);
|
UserStore.unlisten(this.onChange);
|
||||||
|
PieceListStore.unlisten(this.onChange);
|
||||||
},
|
},
|
||||||
|
|
||||||
onChange(state) {
|
onChange(state) {
|
||||||
@ -69,6 +84,20 @@ let Piece = React.createClass({
|
|||||||
this.toggleCreateEditionsDialog();
|
this.toggleCreateEditionsDialog();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleDeleteSuccess(response) {
|
||||||
|
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search, this.state.orderBy, this.state.orderAsc);
|
||||||
|
|
||||||
|
// since we're deleting a piece, we just need to close
|
||||||
|
// all editions dialogs and not reload them
|
||||||
|
EditionListActions.closeAllEditionLists();
|
||||||
|
EditionListActions.clearAllEditionSelections();
|
||||||
|
|
||||||
|
let notification = new GlobalNotificationModel(response.notification, 'success');
|
||||||
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
|
|
||||||
|
this.transitionTo('pieces');
|
||||||
|
},
|
||||||
|
|
||||||
getCreateEditionsDialog() {
|
getCreateEditionsDialog() {
|
||||||
if(this.props.piece.num_editions < 1 && this.state.showCreateEditionsDialog) {
|
if(this.props.piece.num_editions < 1 && this.state.showCreateEditionsDialog) {
|
||||||
return (
|
return (
|
||||||
@ -89,6 +118,9 @@ let Piece = React.createClass({
|
|||||||
key: 'num_editions',
|
key: 'num_editions',
|
||||||
value: numEditions
|
value: numEditions
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let notification = new GlobalNotificationModel('Editions successfully created', 'success', 10000);
|
||||||
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -121,6 +153,9 @@ let Piece = React.createClass({
|
|||||||
piece={this.props.piece}
|
piece={this.props.piece}
|
||||||
toggleCreateEditionsDialog={this.toggleCreateEditionsDialog}
|
toggleCreateEditionsDialog={this.toggleCreateEditionsDialog}
|
||||||
onPollingSuccess={this.handlePollingSuccess}/>
|
onPollingSuccess={this.handlePollingSuccess}/>
|
||||||
|
<DeleteButton
|
||||||
|
handleSuccess={this.handleDeleteSuccess}
|
||||||
|
piece={this.props.piece}/>
|
||||||
</AclButtonList>
|
</AclButtonList>
|
||||||
|
|
||||||
{this.getCreateEditionsDialog()}
|
{this.getCreateEditionsDialog()}
|
||||||
|
@ -2,68 +2,83 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import ApiUrls from '../../constants/api_urls';
|
import Button from 'react-bootstrap/lib/Button';
|
||||||
import FormMixin from '../../mixins/form_mixin';
|
|
||||||
import InputText from './input_text';
|
import Form from './form';
|
||||||
import InputTextArea from './input_textarea';
|
import Property from './property';
|
||||||
import ButtonSubmitOrClose from '../ascribe_buttons/button_submit_close';
|
import InputTextAreaToggable from './input_textarea_toggable';
|
||||||
import { getLangText } from '../../utils/lang_utils.js'
|
|
||||||
|
|
||||||
|
import AppConstants from '../../constants/application_constants';
|
||||||
|
import { getLangText } from '../../utils/lang_utils.js';
|
||||||
|
|
||||||
|
|
||||||
let ConsignForm = React.createClass({
|
let ConsignForm = React.createClass({
|
||||||
mixins: [FormMixin],
|
propTypes: {
|
||||||
|
url: React.PropTypes.string,
|
||||||
|
id: React.PropTypes.object,
|
||||||
url() {
|
message: React.PropTypes.string,
|
||||||
return ApiUrls.ownership_consigns;
|
onRequestHide: React.PropTypes.func,
|
||||||
},
|
handleSuccess: React.PropTypes.func
|
||||||
|
|
||||||
getFormData() {
|
|
||||||
return {
|
|
||||||
bitcoin_id: this.getBitcoinIds().join(),
|
|
||||||
consignee: this.refs.consignee.state.value,
|
|
||||||
consign_message: this.refs.consign_message.state.value,
|
|
||||||
password: this.refs.password.state.value
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
|
|
||||||
renderForm() {
|
getFormData(){
|
||||||
let title = this.getTitlesString().join('');
|
return this.props.id;
|
||||||
let username = this.props.currentUser.username;
|
},
|
||||||
let message =
|
|
||||||
`${getLangText('Hi')},
|
|
||||||
|
|
||||||
${getLangText('I consign')} :
|
render() {
|
||||||
${title}${getLangText('to you')}.
|
|
||||||
|
|
||||||
${getLangText('Truly yours')},
|
|
||||||
${username}`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form id="consign_modal_content" role="form" onSubmit={this.submit}>
|
<Form
|
||||||
<input className="invisible" type="email" name="fake_consignee"/>
|
ref='form'
|
||||||
<input className="invisible" type="password" name="fake_password"/>
|
url={this.props.url}
|
||||||
<InputText
|
getFormData={this.getFormData}
|
||||||
ref="consignee"
|
handleSuccess={this.props.handleSuccess}
|
||||||
placeHolder={getLangText('Consignee email')}
|
buttons={
|
||||||
required="required"
|
<div className="modal-footer">
|
||||||
type="email"
|
<p className="pull-right">
|
||||||
submitted={this.state.submitted}/>
|
<Button
|
||||||
<InputTextArea
|
className="btn btn-default btn-sm ascribe-margin-1px"
|
||||||
ref="consign_message"
|
type="submit">{getLangText('CONSIGN')}</Button>
|
||||||
defaultValue={message}
|
<Button
|
||||||
required=""
|
className="btn btn-danger btn-delete btn-sm ascribe-margin-1px"
|
||||||
/>
|
style={{marginLeft: '0'}}
|
||||||
<InputText
|
onClick={this.props.onRequestHide}>{getLangText('CLOSE')}</Button>
|
||||||
ref="password"
|
</p>
|
||||||
placeHolder={getLangText('Password')}
|
</div>}
|
||||||
required="required"
|
spinner={
|
||||||
type="password"
|
<div className="modal-footer">
|
||||||
submitted={this.state.submitted}/>
|
<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_small.gif'} />
|
||||||
<ButtonSubmitOrClose
|
</div>}>
|
||||||
text={getLangText('CONSIGN')}
|
<Property
|
||||||
onClose={this.props.onRequestHide}
|
name='consignee'
|
||||||
submitted={this.state.submitted} />
|
label={getLangText('Email')}>
|
||||||
</form>
|
<input
|
||||||
|
type="email"
|
||||||
|
placeholder={getLangText('Email of the consignee')}
|
||||||
|
required/>
|
||||||
|
</Property>
|
||||||
|
<Property
|
||||||
|
name='consign_message'
|
||||||
|
label={getLangText('Personal Message')}
|
||||||
|
editable={true}>
|
||||||
|
<InputTextAreaToggable
|
||||||
|
rows={1}
|
||||||
|
editable={true}
|
||||||
|
defaultValue={this.props.message}
|
||||||
|
placeholder={getLangText('Enter a message...')}
|
||||||
|
required="required"/>
|
||||||
|
</Property>
|
||||||
|
<Property
|
||||||
|
name='password'
|
||||||
|
label={getLangText('Password')}>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
placeholder={getLangText('Enter your password')}
|
||||||
|
required/>
|
||||||
|
</Property>
|
||||||
|
<hr />
|
||||||
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
41
js/components/ascribe_forms/form_delete_piece.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import requests from '../../utils/requests';
|
||||||
|
import ApiUrls from '../../constants/api_urls';
|
||||||
|
import FormMixin from '../../mixins/form_mixin';
|
||||||
|
import { getLangText } from '../../utils/lang_utils';
|
||||||
|
|
||||||
|
let PieceDeleteForm = React.createClass({
|
||||||
|
propTypes: {
|
||||||
|
pieceId: React.PropTypes.number
|
||||||
|
},
|
||||||
|
|
||||||
|
mixins: [FormMixin],
|
||||||
|
|
||||||
|
url() {
|
||||||
|
return requests.prepareUrl(ApiUrls.piece, {piece_id: this.props.pieceId});
|
||||||
|
},
|
||||||
|
|
||||||
|
httpVerb() {
|
||||||
|
return 'delete';
|
||||||
|
},
|
||||||
|
|
||||||
|
renderForm () {
|
||||||
|
return (
|
||||||
|
<div className="modal-body">
|
||||||
|
<p>{getLangText('Are you sure you would like to permanently delete this piece')}?</p>
|
||||||
|
<p>{getLangText('This is an irrevocable action%s', '.')}</p>
|
||||||
|
<div className="modal-footer">
|
||||||
|
<button type="submit" className="btn btn-danger btn-delete btn-sm ascribe-margin-1px" onClick={this.submit}>{getLangText('YES, DELETE')}</button>
|
||||||
|
<button className="btn btn-default btn-sm ascribe-margin-1px" style={{marginLeft: '0'}}
|
||||||
|
onClick={this.props.onRequestHide}>{getLangText('CLOSE')}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
export default PieceDeleteForm;
|
@ -12,13 +12,9 @@ let EditionRemoveFromCollectionForm = React.createClass({
|
|||||||
mixins: [FormMixin],
|
mixins: [FormMixin],
|
||||||
|
|
||||||
url() {
|
url() {
|
||||||
if (this.props.editions.constructor === Array) {
|
return requests.prepareUrl(apiUrls.edition_remove_from_collection, {edition_id: this.getBitcoinIds().join()});
|
||||||
return requests.prepareUrl(apiUrls.edition_remove_from_collection, {edition_id: this.getBitcoinIds().join()});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return requests.prepareUrl(apiUrls.piece_remove_from_collection, {piece_id: this.editions.piece_id});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
httpVerb(){
|
httpVerb(){
|
||||||
return 'delete';
|
return 'delete';
|
||||||
},
|
},
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { getLangText } from '../../utils/lang_utils.js';
|
||||||
|
import requests from '../../utils/requests';
|
||||||
|
import apiUrls from '../../constants/api_urls';
|
||||||
|
import FormMixin from '../../mixins/form_mixin';
|
||||||
|
|
||||||
|
let PieceRemoveFromCollectionForm = React.createClass({
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
pieceId: React.PropTypes.number
|
||||||
|
},
|
||||||
|
|
||||||
|
mixins: [FormMixin],
|
||||||
|
|
||||||
|
url() {
|
||||||
|
return requests.prepareUrl(apiUrls.piece_remove_from_collection, {piece_id: this.props.pieceId});
|
||||||
|
},
|
||||||
|
|
||||||
|
httpVerb(){
|
||||||
|
return 'delete';
|
||||||
|
},
|
||||||
|
|
||||||
|
renderForm () {
|
||||||
|
return (
|
||||||
|
<div className="modal-body">
|
||||||
|
<p>{getLangText('Are you sure you would like to remove this piece from your collection')}?</p>
|
||||||
|
<p>{getLangText('This is an irrevocable action%s', '.')}</p>
|
||||||
|
<div className="modal-footer">
|
||||||
|
<button type="submit" className="btn btn-danger btn-delete btn-sm ascribe-margin-1px" onClick={this.submit}>{getLangText('YES, REMOVE')}</button>
|
||||||
|
<button className="btn btn-default btn-sm ascribe-margin-1px" style={{marginLeft: '0'}}
|
||||||
|
onClick={this.props.onRequestHide}>{getLangText('CLOSE')}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
export default PieceRemoveFromCollectionForm;
|
@ -7,8 +7,10 @@ import Alert from 'react-bootstrap/lib/Alert';
|
|||||||
import apiUrls from '../../constants/api_urls';
|
import apiUrls from '../../constants/api_urls';
|
||||||
import FormMixin from '../../mixins/form_mixin';
|
import FormMixin from '../../mixins/form_mixin';
|
||||||
|
|
||||||
|
import AclButton from './../ascribe_buttons/acl_button';
|
||||||
|
|
||||||
import AppConstants from '../../constants/application_constants';
|
import AppConstants from '../../constants/application_constants';
|
||||||
import { getLangText } from '../../utils/lang_utils.js'
|
import { getLangText } from '../../utils/lang_utils.js';
|
||||||
|
|
||||||
let RequestActionForm = React.createClass({
|
let RequestActionForm = React.createClass({
|
||||||
mixins: [FormMixin],
|
mixins: [FormMixin],
|
||||||
@ -52,15 +54,31 @@ let RequestActionForm = React.createClass({
|
|||||||
|
|
||||||
renderForm() {
|
renderForm() {
|
||||||
let edition = this.props.editions[0];
|
let edition = this.props.editions[0];
|
||||||
|
let buttonAccept = (
|
||||||
|
<div id="request_accept"
|
||||||
|
onClick={this.handleRequest}
|
||||||
|
className='btn btn-default btn-sm ascribe-margin-1px'>{getLangText('ACCEPT')}
|
||||||
|
</div>);
|
||||||
|
if (edition.request_action === 'unconsign'){
|
||||||
|
console.log(this.props)
|
||||||
|
buttonAccept = (
|
||||||
|
<AclButton
|
||||||
|
availableAcls={{'acl_unconsign': true}}
|
||||||
|
action="acl_unconsign"
|
||||||
|
pieceOrEditions={this.props.editions}
|
||||||
|
currentUser={this.props.currentUser}
|
||||||
|
handleSuccess={this.props.handleSuccess} />
|
||||||
|
);
|
||||||
|
}
|
||||||
let buttons = (
|
let buttons = (
|
||||||
|
<span>
|
||||||
<span>
|
<span>
|
||||||
<span>
|
{buttonAccept}
|
||||||
<div id="request_accept" onClick={this.handleRequest} className='btn btn-default btn-sm ascribe-margin-1px'>{getLangText('ACCEPT')}</div>
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
<div id="request_deny" onClick={this.handleRequest} className='btn btn-danger btn-delete btn-sm ascribe-margin-1px'>{getLangText('REJECT')}</div>
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
|
<span>
|
||||||
|
<div id="request_deny" onClick={this.handleRequest} className='btn btn-danger btn-delete btn-sm ascribe-margin-1px'>{getLangText('REJECT')}</div>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
);
|
);
|
||||||
if (this.state.submitted){
|
if (this.state.submitted){
|
||||||
buttons = (
|
buttons = (
|
||||||
@ -72,7 +90,7 @@ let RequestActionForm = React.createClass({
|
|||||||
return (
|
return (
|
||||||
<Alert bsStyle='warning'>
|
<Alert bsStyle='warning'>
|
||||||
<div style={{textAlign: 'center'}}>
|
<div style={{textAlign: 'center'}}>
|
||||||
<div>{ edition.owner } {getFormData('requests you')} { edition.request_action } {getLangText('this edition%s', '.')} </div>
|
<div>{ edition.owner } {getLangText('requests you')} { edition.request_action } {getLangText('this edition%s', '.')} </div>
|
||||||
{buttons}
|
{buttons}
|
||||||
</div>
|
</div>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
@ -2,71 +2,91 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import ApiUrls from '../../constants/api_urls';
|
import Button from 'react-bootstrap/lib/Button';
|
||||||
import FormMixin from '../../mixins/form_mixin';
|
import Alert from 'react-bootstrap/lib/Alert';
|
||||||
import InputText from './input_text';
|
|
||||||
import InputTextArea from './input_textarea';
|
import Form from './form';
|
||||||
import ButtonSubmitOrClose from '../ascribe_buttons/button_submit_close';
|
import Property from './property';
|
||||||
import { getLangText } from '../../utils/lang_utils.js'
|
import InputTextAreaToggable from './input_textarea_toggable';
|
||||||
|
|
||||||
|
|
||||||
|
import AppConstants from '../../constants/application_constants';
|
||||||
|
import { getLangText } from '../../utils/lang_utils.js';
|
||||||
|
|
||||||
|
|
||||||
let TransferForm = React.createClass({
|
let TransferForm = React.createClass({
|
||||||
mixins: [FormMixin],
|
propTypes: {
|
||||||
|
url: React.PropTypes.string,
|
||||||
url() {
|
id: React.PropTypes.object,
|
||||||
return ApiUrls.ownership_transfers;
|
message: React.PropTypes.string,
|
||||||
},
|
editions: React.PropTypes.array,
|
||||||
|
currentUser: React.PropTypes.object,
|
||||||
getFormData() {
|
onRequestHide: React.PropTypes.func,
|
||||||
return {
|
handleSuccess: React.PropTypes.func
|
||||||
bitcoin_id: this.getBitcoinIds().join(),
|
|
||||||
transferee: this.refs.transferee.state.value,
|
|
||||||
transfer_message: this.refs.transfer_message.state.value,
|
|
||||||
password: this.refs.password.state.value
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
|
|
||||||
renderForm() {
|
getFormData(){
|
||||||
let title = this.getTitlesString().join('');
|
return this.props.id;
|
||||||
let username = this.props.currentUser.username;
|
},
|
||||||
let message =
|
|
||||||
`${getLangText('Hi')},
|
|
||||||
|
|
||||||
${getLangText('I transfer ownership of')} :
|
render() {
|
||||||
${title}${getLangText('to you')}.
|
|
||||||
|
|
||||||
${getLangText('Truly yours')},
|
|
||||||
${username}`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form id="transfer_modal_content" role="form" onSubmit={this.submit}>
|
<Form
|
||||||
<input className="invisible" type="email" name="fake_transferee"/>
|
ref='form'
|
||||||
<input className="invisible" type="password" name="fake_password"/>
|
url={this.props.url}
|
||||||
<InputText
|
getFormData={this.getFormData}
|
||||||
ref="transferee"
|
handleSuccess={this.props.handleSuccess}
|
||||||
placeHolder={getLangText('Transferee email')}
|
buttons={
|
||||||
required="required"
|
<div className="modal-footer">
|
||||||
type="email"
|
<p className="pull-right">
|
||||||
submitted={this.state.submitted}/>
|
<Button
|
||||||
<InputTextArea
|
className="btn btn-default btn-sm ascribe-margin-1px"
|
||||||
ref="transfer_message"
|
type="submit">{getLangText('TRANSFER')}</Button>
|
||||||
defaultValue={message}
|
<Button
|
||||||
required=""
|
className="btn btn-danger btn-delete btn-sm ascribe-margin-1px"
|
||||||
/>
|
style={{marginLeft: '0'}}
|
||||||
<InputText
|
onClick={this.props.onRequestHide}>{getLangText('CLOSE')}</Button>
|
||||||
ref="password"
|
</p>
|
||||||
placeHolder={getLangText('Password')}
|
</div>}
|
||||||
required="required"
|
spinner={
|
||||||
type="password"
|
<div className="modal-footer">
|
||||||
submitted={this.state.submitted}/>
|
<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_small.gif'} />
|
||||||
<div>
|
</div>}>
|
||||||
Make sure that display instructions and technology details are correct.
|
<Property
|
||||||
|
name='transferee'
|
||||||
|
label={getLangText('Email')}>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
placeholder={getLangText('Email of the transferee')}
|
||||||
|
required/>
|
||||||
|
</Property>
|
||||||
|
<Property
|
||||||
|
name='transfer_message'
|
||||||
|
label={getLangText('Personal Message')}
|
||||||
|
editable={true}>
|
||||||
|
<InputTextAreaToggable
|
||||||
|
rows={1}
|
||||||
|
editable={true}
|
||||||
|
defaultValue={this.props.message}
|
||||||
|
placeholder={getLangText('Enter a message...')}
|
||||||
|
required="required"/>
|
||||||
|
</Property>
|
||||||
|
<Property
|
||||||
|
name='password'
|
||||||
|
label={getLangText('Password')}>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
placeholder={getLangText('Enter your password')}
|
||||||
|
required/>
|
||||||
|
</Property>
|
||||||
|
<hr />
|
||||||
|
<br />
|
||||||
|
<Alert bsStyle='warning'>
|
||||||
|
Make sure that display instructions and technology details are correct.<br/>
|
||||||
They cannot be edited after the transfer.
|
They cannot be edited after the transfer.
|
||||||
</div>
|
</Alert>
|
||||||
<ButtonSubmitOrClose
|
</Form>
|
||||||
text={getLangText('TRANSFER')}
|
|
||||||
onClose={this.props.onRequestHide}
|
|
||||||
submitted={this.state.submitted} />
|
|
||||||
</form>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2,59 +2,75 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import ApiUrls from '../../constants/api_urls';
|
import Button from 'react-bootstrap/lib/Button';
|
||||||
import FormMixin from '../../mixins/form_mixin';
|
|
||||||
import InputText from './input_text';
|
import Form from './form';
|
||||||
import InputTextArea from './input_textarea';
|
import Property from './property';
|
||||||
import ButtonSubmitOrClose from '../ascribe_buttons/button_submit_close';
|
import InputTextAreaToggable from './input_textarea_toggable';
|
||||||
import { getLangText } from '../../utils/lang_utils.js'
|
|
||||||
|
import AppConstants from '../../constants/application_constants';
|
||||||
|
import { getLangText } from '../../utils/lang_utils.js';
|
||||||
|
|
||||||
|
|
||||||
let UnConsignForm = React.createClass({
|
let UnConsignForm = React.createClass({
|
||||||
mixins: [FormMixin],
|
propTypes: {
|
||||||
|
url: React.PropTypes.string,
|
||||||
url() {
|
id: React.PropTypes.object,
|
||||||
return ApiUrls.ownership_unconsigns;
|
message: React.PropTypes.string,
|
||||||
|
editions: React.PropTypes.array,
|
||||||
|
onRequestHide: React.PropTypes.func,
|
||||||
|
handleSuccess: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
getFormData() {
|
getFormData(){
|
||||||
return {
|
return this.props.id;
|
||||||
bitcoin_id: this.getBitcoinIds().join(),
|
|
||||||
unconsign_message: this.refs.unconsign_message.state.value,
|
|
||||||
password: this.refs.password.state.value
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
|
|
||||||
renderForm() {
|
render() {
|
||||||
let title = this.getTitlesString().join('');
|
|
||||||
let username = this.props.currentUser.username;
|
|
||||||
let message =
|
|
||||||
`${getLangText('Hi')},
|
|
||||||
|
|
||||||
${getLangText('I un-consign')}:
|
|
||||||
${title}${getLangText('from you')}.
|
|
||||||
|
|
||||||
${getLangText('Truly yours')},
|
|
||||||
${username}`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form id="unconsign_modal_content" role="form" onSubmit={this.submit}>
|
<Form
|
||||||
<input className="invisible" type="email" name="fake_unconsignee"/>
|
ref='form'
|
||||||
<input className="invisible" type="password" name="fake_password"/>
|
url={this.props.url}
|
||||||
<InputTextArea
|
getFormData={this.getFormData}
|
||||||
ref="unconsign_message"
|
handleSuccess={this.props.handleSuccess}
|
||||||
defaultValue={message}
|
buttons={
|
||||||
required="" />
|
<div className="modal-footer">
|
||||||
<InputText
|
<p className="pull-right">
|
||||||
ref="password"
|
<Button
|
||||||
placeHolder={getLangText('Password')}
|
className="btn btn-default btn-sm ascribe-margin-1px"
|
||||||
required="required"
|
type="submit">{getLangText('UNCONSIGN')}</Button>
|
||||||
type="password"
|
<Button
|
||||||
submitted={this.state.submitted} />
|
className="btn btn-danger btn-delete btn-sm ascribe-margin-1px"
|
||||||
<ButtonSubmitOrClose
|
style={{marginLeft: '0'}}
|
||||||
text={getLangText('UNCONSIGN')}
|
onClick={this.props.onRequestHide}>{getLangText('CLOSE')}</Button>
|
||||||
onClose={this.props.onRequestHide}
|
</p>
|
||||||
submitted={this.state.submitted} />
|
</div>}
|
||||||
</form>
|
spinner={
|
||||||
|
<div className="modal-footer">
|
||||||
|
<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_small.gif'} />
|
||||||
|
</div>}>
|
||||||
|
<Property
|
||||||
|
name='unconsign_message'
|
||||||
|
label={getLangText('Personal Message')}
|
||||||
|
editable={true}>
|
||||||
|
<InputTextAreaToggable
|
||||||
|
rows={1}
|
||||||
|
editable={true}
|
||||||
|
defaultValue={this.props.message}
|
||||||
|
placeholder={getLangText('Enter a message...')}
|
||||||
|
required="required"/>
|
||||||
|
</Property>
|
||||||
|
<Property
|
||||||
|
name='password'
|
||||||
|
label={getLangText('Password')}>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
placeholder={getLangText('Enter your password')}
|
||||||
|
required/>
|
||||||
|
</Property>
|
||||||
|
<hr />
|
||||||
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2,48 +2,68 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import ApiUrls from '../../constants/api_urls';
|
import Button from 'react-bootstrap/lib/Button';
|
||||||
import FormMixin from '../../mixins/form_mixin';
|
import Alert from 'react-bootstrap/lib/Alert';
|
||||||
import InputTextArea from './input_textarea';
|
|
||||||
import ButtonSubmitOrClose from '../ascribe_buttons/button_submit_close';
|
import Form from './form';
|
||||||
import { getLangText } from '../../utils/lang_utils.js'
|
import Property from './property';
|
||||||
|
import InputTextAreaToggable from './input_textarea_toggable';
|
||||||
|
|
||||||
|
|
||||||
|
import AppConstants from '../../constants/application_constants';
|
||||||
|
import { getLangText } from '../../utils/lang_utils.js';
|
||||||
|
|
||||||
|
|
||||||
let UnConsignRequestForm = React.createClass({
|
let UnConsignRequestForm = React.createClass({
|
||||||
mixins: [FormMixin],
|
propTypes: {
|
||||||
|
url: React.PropTypes.string,
|
||||||
url() {
|
id: React.PropTypes.object,
|
||||||
return ApiUrls.ownership_unconsigns_request;
|
message: React.PropTypes.string,
|
||||||
|
onRequestHide: React.PropTypes.func,
|
||||||
|
handleSuccess: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
getFormData() {
|
getFormData(){
|
||||||
return {
|
return this.props.id;
|
||||||
bitcoin_id: this.props.edition.bitcoin_id,
|
|
||||||
unconsign_request_message: this.refs.unconsign_request_message.state.value
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
|
|
||||||
renderForm() {
|
render() {
|
||||||
let title = this.props.edition.title;
|
|
||||||
let username = this.props.currentUser.username;
|
|
||||||
let message =
|
|
||||||
`${getLangText('Hi')},
|
|
||||||
|
|
||||||
${getLangText('I request you to un-consign')} \" ${title} \".
|
|
||||||
|
|
||||||
${getLangText('Truly yours')},
|
|
||||||
${username}`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form id="unconsign_request_modal_content" role="form" onSubmit={this.submit}>
|
<Form
|
||||||
<InputTextArea
|
ref='form'
|
||||||
ref="unconsign_request_message"
|
url={this.props.url}
|
||||||
defaultValue={message}
|
getFormData={this.getFormData}
|
||||||
required="" />
|
handleSuccess={this.props.handleSuccess}
|
||||||
<ButtonSubmitOrClose
|
buttons={
|
||||||
text={getLangText('UNCONSIGN REQUEST')}
|
<div className="modal-footer">
|
||||||
onClose={this.props.onRequestHide}
|
<p className="pull-right">
|
||||||
submitted={this.state.submitted} />
|
<Button
|
||||||
</form>
|
className="btn btn-default btn-sm ascribe-margin-1px"
|
||||||
|
type="submit">{getLangText('REQUEST UNCONSIGN')}</Button>
|
||||||
|
<Button
|
||||||
|
className="btn btn-danger btn-delete btn-sm ascribe-margin-1px"
|
||||||
|
style={{marginLeft: '0'}}
|
||||||
|
onClick={this.props.onRequestHide}>{getLangText('CLOSE')}</Button>
|
||||||
|
</p>
|
||||||
|
</div>}
|
||||||
|
spinner={
|
||||||
|
<div className="modal-footer">
|
||||||
|
<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_small.gif'} />
|
||||||
|
</div>}>
|
||||||
|
<Property
|
||||||
|
name='unconsign_request_message'
|
||||||
|
label={getLangText('Personal Message')}
|
||||||
|
editable={true}>
|
||||||
|
<InputTextAreaToggable
|
||||||
|
rows={1}
|
||||||
|
editable={true}
|
||||||
|
defaultValue={this.props.message}
|
||||||
|
placeholder={getLangText('Enter a message...')}
|
||||||
|
required="required"/>
|
||||||
|
</Property>
|
||||||
|
<hr />
|
||||||
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -32,6 +32,7 @@ let InputTextAreaToggable = React.createClass({
|
|||||||
className={className}
|
className={className}
|
||||||
value={this.state.value}
|
value={this.state.value}
|
||||||
rows={this.props.rows}
|
rows={this.props.rows}
|
||||||
|
maxRows={10}
|
||||||
required={this.props.required}
|
required={this.props.required}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
onBlur={this.props.onBlur}
|
onBlur={this.props.onBlur}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import ReactAddons from 'react/addons';
|
||||||
|
|
||||||
import CollapsibleMixin from 'react-bootstrap/lib/CollapsibleMixin';
|
import CollapsibleMixin from 'react-bootstrap/lib/CollapsibleMixin';
|
||||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||||
@ -39,15 +40,17 @@ let PropertyCollapsile = React.createClass({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleChange(event) {
|
||||||
|
this.setState({value: event.target.value});
|
||||||
|
},
|
||||||
|
|
||||||
renderChildren() {
|
renderChildren() {
|
||||||
if(this.state.show) {
|
if(this.state.show) {
|
||||||
return (<div
|
return ReactAddons.Children.map(this.props.children, (child) => {
|
||||||
className={classNames(this.getCollapsibleClassSet()) + ' ascribe-settings-property'}
|
return ReactAddons.addons.cloneWithProps(child, {
|
||||||
ref="panel">
|
onChange: this.handleChange
|
||||||
{this.props.children}
|
});
|
||||||
</div>);
|
});
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -75,13 +78,18 @@ let PropertyCollapsile = React.createClass({
|
|||||||
onClick={this.handleFocus}
|
onClick={this.handleFocus}
|
||||||
onFocus={this.handleFocus}>
|
onFocus={this.handleFocus}>
|
||||||
<input
|
<input
|
||||||
|
onChange={this.handleChange}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
ref="checkboxCollapsible"/>
|
ref="checkboxCollapsible"/>
|
||||||
{/* PLEASE LEAVE THE SPACE BETWEEN LABEL and this.props.label */}
|
{/* PLEASE LEAVE THE SPACE BETWEEN LABEL and this.props.label */}
|
||||||
<span className="checkbox"> {this.props.checkboxLabel}</span>
|
<span className="checkbox"> {this.props.checkboxLabel}</span>
|
||||||
</div>
|
</div>
|
||||||
</OverlayTrigger>
|
</OverlayTrigger>
|
||||||
{this.renderChildren()}
|
<div
|
||||||
|
className={classNames(this.getCollapsibleClassSet()) + ' ascribe-settings-property'}
|
||||||
|
ref="panel">
|
||||||
|
{this.renderChildren()}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -17,24 +17,41 @@ let ModalWrapper = React.createClass({
|
|||||||
handleSuccess: React.PropTypes.func.isRequired,
|
handleSuccess: React.PropTypes.func.isRequired,
|
||||||
button: React.PropTypes.object.isRequired,
|
button: React.PropTypes.object.isRequired,
|
||||||
children: React.PropTypes.object,
|
children: React.PropTypes.object,
|
||||||
tooltip: React.PropTypes.string.isRequired
|
tooltip: React.PropTypes.string
|
||||||
|
},
|
||||||
|
|
||||||
|
getModalTrigger() {
|
||||||
|
return (
|
||||||
|
<ModalTrigger modal={
|
||||||
|
<ModalBody
|
||||||
|
title={this.props.title}
|
||||||
|
handleSuccess={this.props.handleSuccess}>
|
||||||
|
{this.props.children}
|
||||||
|
</ModalBody>
|
||||||
|
}>
|
||||||
|
{this.props.button}
|
||||||
|
</ModalTrigger>
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
if(this.props.tooltip) {
|
||||||
<OverlayTrigger delay={500} placement="left"
|
return (
|
||||||
overlay={<Tooltip>{this.props.tooltip}</Tooltip>}>
|
<OverlayTrigger
|
||||||
<ModalTrigger modal={
|
delay={500}
|
||||||
<ModalBody
|
placement="left"
|
||||||
title={this.props.title}
|
overlay={<Tooltip>{this.props.tooltip}</Tooltip>}>
|
||||||
handleSuccess={this.props.handleSuccess}>
|
{this.getModalTrigger()}
|
||||||
{this.props.children}
|
</OverlayTrigger>
|
||||||
</ModalBody>
|
);
|
||||||
}>
|
} else {
|
||||||
{this.props.button}
|
return (
|
||||||
</ModalTrigger>
|
<span>
|
||||||
</OverlayTrigger>
|
{/* This needs to be some kind of inline-block */}
|
||||||
);
|
{this.getModalTrigger()}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -10,9 +10,12 @@ import EditionListActions from '../../actions/edition_list_actions';
|
|||||||
import UserStore from '../../stores/user_store';
|
import UserStore from '../../stores/user_store';
|
||||||
import UserActions from '../../actions/user_actions';
|
import UserActions from '../../actions/user_actions';
|
||||||
|
|
||||||
|
import PieceListStore from '../../stores/piece_list_store';
|
||||||
|
import PieceListActions from '../../actions/piece_list_actions';
|
||||||
|
|
||||||
import PieceListBulkModalSelectedEditionsWidget from './piece_list_bulk_modal_selected_editions_widget';
|
import PieceListBulkModalSelectedEditionsWidget from './piece_list_bulk_modal_selected_editions_widget';
|
||||||
import AclButtonList from '../ascribe_buttons/acl_button_list';
|
import AclButtonList from '../ascribe_buttons/acl_button_list';
|
||||||
|
import DeleteButton from '../ascribe_buttons/delete_button';
|
||||||
|
|
||||||
import { getAvailableAcls } from '../../utils/acl_utils';
|
import { getAvailableAcls } from '../../utils/acl_utils';
|
||||||
import { getLangText } from '../../utils/lang_utils.js';
|
import { getLangText } from '../../utils/lang_utils.js';
|
||||||
@ -23,7 +26,11 @@ let PieceListBulkModal = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return mergeOptions(EditionListStore.getState(), UserStore.getState());
|
return mergeOptions(
|
||||||
|
EditionListStore.getState(),
|
||||||
|
UserStore.getState(),
|
||||||
|
PieceListStore.getState()
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
onChange(state) {
|
onChange(state) {
|
||||||
@ -69,20 +76,18 @@ let PieceListBulkModal = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleSuccess() {
|
handleSuccess() {
|
||||||
|
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search, this.state.orderBy, this.state.orderAsc);
|
||||||
|
|
||||||
this.fetchSelectedPieceEditionList()
|
this.fetchSelectedPieceEditionList()
|
||||||
.forEach((pieceId) => {
|
.forEach((pieceId) => {
|
||||||
let editionsForPiece = this.state.editionList[pieceId];
|
EditionListActions.refreshEditionList(pieceId);
|
||||||
for(let i = 1; i <= editionsForPiece.page; i++) {
|
|
||||||
EditionListActions.fetchEditionList(pieceId, i, editionsForPiece.pageSize, editionsForPiece.orderBy, editionsForPiece.orderAsc);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
EditionListActions.clearAllEditionSelections();
|
EditionListActions.clearAllEditionSelections();
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let selectedEditions = this.fetchSelectedEditionList();
|
let selectedEditions = this.fetchSelectedEditionList();
|
||||||
let availableAcls = getAvailableAcls(selectedEditions);
|
let availableAcls = getAvailableAcls(selectedEditions, (aclName) => aclName !== 'acl_view');
|
||||||
|
|
||||||
if(Object.keys(availableAcls).length > 0) {
|
if(Object.keys(availableAcls).length > 0) {
|
||||||
return (
|
return (
|
||||||
@ -106,7 +111,11 @@ let PieceListBulkModal = React.createClass({
|
|||||||
availableAcls={availableAcls}
|
availableAcls={availableAcls}
|
||||||
editions={selectedEditions}
|
editions={selectedEditions}
|
||||||
handleSuccess={this.handleSuccess}
|
handleSuccess={this.handleSuccess}
|
||||||
className="text-center ascribe-button-list collapse-group"/>
|
className="text-center ascribe-button-list collapse-group">
|
||||||
|
<DeleteButton
|
||||||
|
handleSuccess={this.handleSuccess}
|
||||||
|
editions={selectedEditions}/>
|
||||||
|
</AclButtonList>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,11 +5,19 @@ import React from 'react';
|
|||||||
|
|
||||||
let TableItemAclFiltered = React.createClass({
|
let TableItemAclFiltered = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
content: React.PropTypes.object.isRequired
|
content: React.PropTypes.object,
|
||||||
|
requestAction: React.PropTypes.string
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
var availableAcls = ['acl_consign', 'acl_loan', 'acl_transfer', 'acl_view', 'acl_share', 'acl_unshare'];
|
var availableAcls = ['acl_consign', 'acl_loan', 'acl_transfer', 'acl_view', 'acl_share', 'acl_unshare', 'acl_delete'];
|
||||||
|
if (this.props.requestAction){
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{this.props.requestAction + ' request pending'}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let filteredAcls = Object.keys(this.props.content).filter((key) => {
|
let filteredAcls = Object.keys(this.props.content).filter((key) => {
|
||||||
return availableAcls.indexOf(key) > -1 && this.props.content[key];
|
return availableAcls.indexOf(key) > -1 && this.props.content[key];
|
||||||
|
@ -2,11 +2,6 @@
|
|||||||
|
|
||||||
import React from 'react/addons';
|
import React from 'react/addons';
|
||||||
|
|
||||||
import promise from 'es6-promise';
|
|
||||||
promise.polyfill();
|
|
||||||
|
|
||||||
import fetch from 'isomorphic-fetch';
|
|
||||||
|
|
||||||
import { getCookie } from '../../utils/fetch_api_utils';
|
import { getCookie } from '../../utils/fetch_api_utils';
|
||||||
import { getLangText } from '../../utils/lang_utils';
|
import { getLangText } from '../../utils/lang_utils';
|
||||||
|
|
||||||
@ -96,7 +91,8 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
setIsUploadReady: React.PropTypes.func,
|
setIsUploadReady: React.PropTypes.func,
|
||||||
isReadyForFormSubmission: React.PropTypes.func,
|
isReadyForFormSubmission: React.PropTypes.func,
|
||||||
areAssetsDownloadable: React.PropTypes.bool,
|
areAssetsDownloadable: React.PropTypes.bool,
|
||||||
areAssetsEditable: React.PropTypes.bool
|
areAssetsEditable: React.PropTypes.bool,
|
||||||
|
defaultErrorMessage: React.PropTypes.string
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps() {
|
getDefaultProps() {
|
||||||
@ -141,7 +137,8 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
},
|
},
|
||||||
multiple: false
|
multiple: false,
|
||||||
|
defaultErrorMessage: 'Unexpected error. Please contact us if this happens repeatedly.'
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -188,56 +185,87 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
multiple: this.props.multiple,
|
multiple: this.props.multiple,
|
||||||
retry: this.props.retry,
|
retry: this.props.retry,
|
||||||
callbacks: {
|
callbacks: {
|
||||||
onSubmit: this.onSubmit,
|
|
||||||
onComplete: this.onComplete,
|
onComplete: this.onComplete,
|
||||||
onCancel: this.onCancel,
|
onCancel: this.onCancel,
|
||||||
onDelete: this.onDelete,
|
|
||||||
onProgress: this.onProgress,
|
onProgress: this.onProgress,
|
||||||
onRetry: this.onRetry,
|
|
||||||
onAutoRetry: this.onAutoRetry,
|
|
||||||
onManualRetry: this.onManualRetry,
|
|
||||||
onDeleteComplete: this.onDeleteComplete,
|
onDeleteComplete: this.onDeleteComplete,
|
||||||
onSessionRequestComplete: this.onSessionRequestComplete
|
onSessionRequestComplete: this.onSessionRequestComplete,
|
||||||
|
onError: this.onError
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
requestKey(fileId) {
|
requestKey(fileId) {
|
||||||
|
let defer = new fineUploader.Promise();
|
||||||
let filename = this.state.uploader.getName(fileId);
|
let filename = this.state.uploader.getName(fileId);
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
fetch(this.props.keyRoutine.url, {
|
window.fetch(this.props.keyRoutine.url, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'X-CSRFToken': getCookie('csrftoken')
|
'X-CSRFToken': getCookie('csrftoken')
|
||||||
},
|
},
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
'filename': filename,
|
'filename': filename,
|
||||||
'file_class': this.props.keyRoutine.fileClass,
|
'file_class': this.props.keyRoutine.fileClass,
|
||||||
'piece_id': this.props.keyRoutine.pieceId
|
'piece_id': this.props.keyRoutine.pieceId
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.then((res) => {
|
})
|
||||||
return res.json();
|
.then((res) => {
|
||||||
})
|
return res.json();
|
||||||
.then((res) =>{
|
})
|
||||||
resolve(res.key);
|
.then((res) =>{
|
||||||
})
|
defer.success(res.key);
|
||||||
.catch((err) => {
|
})
|
||||||
console.error(err);
|
.catch((err) => {
|
||||||
reject(err);
|
defer.failure(err);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return defer;
|
||||||
|
},
|
||||||
|
|
||||||
|
createBlob(file) {
|
||||||
|
let defer = new fineUploader.Promise();
|
||||||
|
window.fetch(this.props.createBlobRoutine.url, {
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRFToken': getCookie('csrftoken')
|
||||||
|
},
|
||||||
|
credentials: 'include',
|
||||||
|
body: JSON.stringify({
|
||||||
|
'filename': file.name,
|
||||||
|
'key': file.key,
|
||||||
|
'piece_id': this.props.createBlobRoutine.pieceId
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
.then((res) =>{
|
||||||
|
if(res.otherdata) {
|
||||||
|
file.s3Url = res.otherdata.url_safe;
|
||||||
|
file.s3UrlSafe = res.otherdata.url_safe;
|
||||||
|
} else if(res.digitalwork) {
|
||||||
|
file.s3Url = res.digitalwork.url_safe;
|
||||||
|
file.s3UrlSafe = res.digitalwork.url_safe;
|
||||||
|
} else {
|
||||||
|
throw new Error('Could not find a url to download.');
|
||||||
|
}
|
||||||
|
defer.success(res.key);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
defer.failure(err);
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
return defer;
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FineUploader specific callback function handlers */
|
/* FineUploader specific callback function handlers */
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
console.log('submit');
|
|
||||||
},
|
|
||||||
|
|
||||||
onComplete(id) {
|
onComplete(id) {
|
||||||
let files = this.state.filesToUpload;
|
let files = this.state.filesToUpload;
|
||||||
files[id].status = 'upload successful';
|
files[id].status = 'upload successful';
|
||||||
@ -272,57 +300,9 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
createBlob(file) {
|
onError() {
|
||||||
let defer = new fineUploader.Promise();
|
let notification = new GlobalNotificationModel(this.props.defaultErrorMessage, 'danger', 5000);
|
||||||
fetch(this.props.createBlobRoutine.url, {
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'X-CSRFToken': getCookie('csrftoken')
|
|
||||||
},
|
|
||||||
credentials: 'include',
|
|
||||||
body: JSON.stringify({
|
|
||||||
'filename': file.name,
|
|
||||||
'key': file.key,
|
|
||||||
'piece_id': this.props.createBlobRoutine.pieceId
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.then((res) => {
|
|
||||||
return res.json();
|
|
||||||
})
|
|
||||||
.then((res) =>{
|
|
||||||
if(res.otherdata) {
|
|
||||||
file.s3Url = res.otherdata.url_safe;
|
|
||||||
file.s3UrlSafe = res.otherdata.url_safe;
|
|
||||||
} else if(res.digitalwork) {
|
|
||||||
file.s3Url = res.digitalwork.url_safe;
|
|
||||||
file.s3UrlSafe = res.digitalwork.url_safe;
|
|
||||||
} else {
|
|
||||||
throw new Error('Could not find a url to download.');
|
|
||||||
}
|
|
||||||
defer.success(res.key);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
return defer;
|
|
||||||
},
|
|
||||||
|
|
||||||
onRetry() {
|
|
||||||
console.log('retry');
|
|
||||||
},
|
|
||||||
|
|
||||||
onAutoRetry() {
|
|
||||||
console.log('autoretry');
|
|
||||||
},
|
|
||||||
|
|
||||||
onManualRetry() {
|
|
||||||
console.log('manualretry');
|
|
||||||
},
|
|
||||||
|
|
||||||
onDelete() {
|
|
||||||
console.log('delete');
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onCancel(id) {
|
onCancel(id) {
|
||||||
|
@ -139,6 +139,7 @@ let RegisterPiece = React.createClass( {
|
|||||||
if (this.props.canSpecifyEditions) {
|
if (this.props.canSpecifyEditions) {
|
||||||
return (
|
return (
|
||||||
<PropertyCollapsible
|
<PropertyCollapsible
|
||||||
|
name="num_editions"
|
||||||
checkboxLabel={getLangText('Specify editions')}>
|
checkboxLabel={getLangText('Specify editions')}>
|
||||||
<span>{getLangText('Editions')}</span>
|
<span>{getLangText('Editions')}</span>
|
||||||
<input
|
<input
|
||||||
|
@ -56,6 +56,31 @@ class EditionListStore {
|
|||||||
this.editionList[pieceId].count = count;
|
this.editionList[pieceId].count = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We often just have to refresh the edition list for a certain pieceId,
|
||||||
|
* this method provides exactly that functionality without any side effects
|
||||||
|
*/
|
||||||
|
onRefreshEditionList(pieceId) {
|
||||||
|
const prevEditionListLength = this.editionList[pieceId].length;
|
||||||
|
const prevEditionListPage = this.editionList[pieceId].page;
|
||||||
|
const prevEditionListPageSize = this.editionList[pieceId].pageSize;
|
||||||
|
|
||||||
|
// to clear an array, david walsh recommends to just set it's length to zero
|
||||||
|
// http://davidwalsh.name/empty-array
|
||||||
|
this.editionList[pieceId].length = 0;
|
||||||
|
|
||||||
|
// refetch editions with adjusted page size
|
||||||
|
EditionsListActions.fetchEditionList(pieceId, 1, prevEditionListLength, this.editionList[pieceId].orderBy, this.editionList[pieceId].orderAsc)
|
||||||
|
.then(() => {
|
||||||
|
// reset back to the normal pageSize and page
|
||||||
|
this.editionList[pieceId].page = prevEditionListPage;
|
||||||
|
this.editionList[pieceId].pageSize = prevEditionListPageSize;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
onSelectEdition({pieceId, editionId, toValue}) {
|
onSelectEdition({pieceId, editionId, toValue}) {
|
||||||
this.editionList[pieceId].forEach((edition) => {
|
this.editionList[pieceId].forEach((edition) => {
|
||||||
|
|
||||||
|
@ -6,9 +6,9 @@ function intersectAcls(a, b) {
|
|||||||
return a.filter((val) => b.indexOf(val) > -1);
|
return a.filter((val) => b.indexOf(val) > -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAvailableAcls(editions) {
|
export function getAvailableAcls(editions, filterFn) {
|
||||||
let availableAcls = [];
|
let availableAcls = [];
|
||||||
if (editions.constructor !== Array){
|
if (!editions || editions.constructor !== Array){
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
// if you copy a javascript array of objects using slice, then
|
// if you copy a javascript array of objects using slice, then
|
||||||
@ -26,6 +26,13 @@ export function getAvailableAcls(editions) {
|
|||||||
|
|
||||||
edition.acl = sanitize(edition.acl, (val) => !val);
|
edition.acl = sanitize(edition.acl, (val) => !val);
|
||||||
edition.acl = Object.keys(edition.acl);
|
edition.acl = Object.keys(edition.acl);
|
||||||
|
|
||||||
|
// additionally, the user can specify a filter function for
|
||||||
|
// an acl array
|
||||||
|
if(typeof filterFn === 'function') {
|
||||||
|
edition.acl = edition.acl.filter(filterFn);
|
||||||
|
}
|
||||||
|
|
||||||
return edition;
|
return edition;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -54,6 +54,11 @@ class Requests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getUrl(url) {
|
getUrl(url) {
|
||||||
|
// Handle case, that the url string is not defined at all
|
||||||
|
if (!url) {
|
||||||
|
throw new Error('Url was not defined and could therefore not be mapped.');
|
||||||
|
}
|
||||||
|
|
||||||
let name = url;
|
let name = url;
|
||||||
if (!url.match(/^http/)) {
|
if (!url.match(/^http/)) {
|
||||||
url = this.urlMap[url];
|
url = this.urlMap[url];
|
||||||
@ -66,9 +71,16 @@ class Requests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prepareUrl(url, params, attachParamsToQuery) {
|
prepareUrl(url, params, attachParamsToQuery) {
|
||||||
let newUrl = this.getUrl(url);
|
let newUrl;
|
||||||
let re = /\${(\w+)}/g;
|
let re = /\${(\w+)}/g;
|
||||||
|
|
||||||
|
// catch errors and throw them to react
|
||||||
|
try {
|
||||||
|
newUrl = this.getUrl(url);
|
||||||
|
} catch(err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
newUrl = newUrl.replace(re, (match, key) => {
|
newUrl = newUrl.replace(re, (match, key) => {
|
||||||
let val = params[key];
|
let val = params[key];
|
||||||
if (!val) {
|
if (!val) {
|
||||||
|
@ -58,6 +58,10 @@ hr {
|
|||||||
.no-padding{
|
.no-padding{
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
.inline{
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
.navbar-default {
|
.navbar-default {
|
||||||
border: none;
|
border: none;
|
||||||
border-left:0;
|
border-left:0;
|
||||||
|