1
0
mirror of https://github.com/ascribe/onion.git synced 2024-12-22 09:23:13 +01:00

Merge remote-tracking branch 'remotes/origin/master' into AD-44-in-piece-detail-support-public-not

Conflicts:
	js/utils/requests.js
This commit is contained in:
ddejongh 2015-06-16 14:06:35 +02:00
commit 1ecd579718
41 changed files with 220 additions and 182 deletions

View File

@ -2,4 +2,6 @@
gulpfile.js
node_modules
js/**/__tests__
js/**/__tests__
server.js

View File

@ -105,7 +105,7 @@ gulp.task('sass:build', function () {
});
gulp.task('sass:watch', function () {
gulp.watch('./sass/**/*.scss', ['sass']);
gulp.watch('./sass/**/*.scss', ['sass:build']);
});
gulp.task('copy', function () {

View File

@ -7,6 +7,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="//brick.a.ssl.fastly.net/Source+Sans+Pro:400,600,700,900">
<link rel="stylesheet" href="<%= BASE_URL %>static/css/main.css">
<link rel="stylesheet" href="<%= BASE_URL %>static/css/maps/main.css.map">
<script>
window.BASE_URL = '<%= BASE_URL %>';
window.API_ENDPOINT = '<%= API_ENDPOINT %>';

View File

@ -9,7 +9,9 @@ class EditionListActions {
this.generateActions(
'updateEditionList',
'selectEdition',
'clearAllEditionSelections'
'clearAllEditionSelections',
'closeAllEditionLists',
'toggleEditionList'
);
}
@ -19,19 +21,24 @@ class EditionListActions {
orderAsc = true;
}
EditionListFetcher
.fetch(pieceId, orderBy, orderAsc)
.then((res) => {
this.actions.updateEditionList({
'editionListOfPiece': res.editions,
pieceId,
orderBy,
orderAsc
return new Promise((resolve, reject) => {
EditionListFetcher
.fetch(pieceId, orderBy, orderAsc)
.then((res) => {
this.actions.updateEditionList({
'editionListOfPiece': res.editions,
pieceId,
orderBy,
orderAsc
});
resolve(res);
})
.catch((err) => {
reject(err);
console.log(err);
});
})
.catch((err) => {
console.log(err);
});
});
}
}

View File

@ -8,9 +8,7 @@ import PieceListFetcher from '../fetchers/piece_list_fetcher';
class PieceListActions {
constructor() {
this.generateActions(
'updatePieceList',
'showEditionList',
'closeAllEditionLists'
'updatePieceList'
);
}

View File

@ -5,17 +5,19 @@ import Router from 'react-router';
import promise from 'es6-promise';
promise.polyfill();
import fetch from 'isomorphic-fetch';
//require('isomorphic-fetch');
import ApiUrls from './constants/api_urls';
import routes from './routes';
import fetch from './utils/fetch';
import requests from './utils/requests';
let headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
};
fetch.defaults({
requests.defaults({
urlMap: ApiUrls,
http: {
headers: headers,

View File

@ -2,11 +2,11 @@
import React from 'react';
let AccordionList = React.createClass({
propTypes: {
className: React.PropTypes.string,
children: React.PropTypes.arrayOf(React.PropTypes.element).isRequired
children: React.PropTypes.arrayOf(React.PropTypes.element).isRequired,
loadingElement: React.PropTypes.element
},
render() {
@ -18,7 +18,9 @@ let AccordionList = React.createClass({
);
} else {
return (
<p>Loading</p>
<div className={this.props.className + ' ascribe-accordion-list-loading'}>
{this.props.loadingElement}
</div>
);
}
}

View File

@ -1,12 +1,9 @@
'use strict';
import React from 'react';
import Router from 'react-router';
import { getLangText } from '../../utils/lang_utils';
let Link = Router.Link;
let AccordionListItem = React.createClass({
propTypes: {
className: React.PropTypes.string,

View File

@ -13,7 +13,6 @@ let AccordionListItemTable = React.createClass({
parentId: React.PropTypes.number,
itemList: React.PropTypes.array,
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(ColumnModel)),
numOfTableItems: React.PropTypes.number,
show: React.PropTypes.bool,
changeOrder: React.PropTypes.func,
orderBy: React.PropTypes.string,

View File

@ -1,7 +1,6 @@
'use strict';
import React from 'react';
import Router from 'react-router';
import EditionListStore from '../../stores/edition_list_store';
import EditionListActions from '../../actions/edition_list_actions';
@ -19,15 +18,11 @@ import TableItemAclFiltered from '../ascribe_table/table_item_acl_filtered';
import { getLangText } from '../../utils/lang_utils';
let Link = Router.Link;
let AccordionListItemTableEditions = React.createClass({
propTypes: {
className: React.PropTypes.string,
parentId: React.PropTypes.number,
numOfEditions: React.PropTypes.number,
show: React.PropTypes.bool
parentId: React.PropTypes.number
},
getInitialState() {
@ -64,8 +59,13 @@ let AccordionListItemTableEditions = React.createClass({
},
toggleTable() {
PieceListActions.showEditionList(this.props.parentId);
EditionListActions.fetchEditionList(this.props.parentId);
let isEditionListOpen = this.state.isEditionListOpenForPieceId[this.props.parentId] ? this.state.isEditionListOpenForPieceId[this.props.parentId].show : false;
if(isEditionListOpen) {
EditionListActions.toggleEditionList(this.props.parentId);
} else {
EditionListActions.toggleEditionList(this.props.parentId);
EditionListActions.fetchEditionList(this.props.parentId);
}
},
changeEditionListOrder(orderBy, orderAsc) {
@ -77,6 +77,7 @@ let AccordionListItemTableEditions = React.createClass({
let allEditionsCount = 0;
let orderBy;
let orderAsc;
let show;
// here we need to check if all editions of a specific
// piece are already defined. Otherwise .length will throw an error and we'll not
@ -88,7 +89,11 @@ let AccordionListItemTableEditions = React.createClass({
orderAsc = this.state.editionList[this.props.parentId].orderAsc;
}
let transition = new TransitionModel('edition', 'editionId', 'bitcoin_id', PieceListActions.closeAllEditionLists);
if(this.props.parentId in this.state.isEditionListOpenForPieceId) {
show = this.state.isEditionListOpenForPieceId[this.props.parentId].show;
}
let transition = new TransitionModel('edition', 'editionId', 'bitcoin_id');
let columnList = [
new ColumnModel(
@ -153,16 +158,14 @@ let AccordionListItemTableEditions = React.createClass({
parentId={this.props.parentId}
itemList={this.state.editionList[this.props.parentId]}
columnList={columnList}
numOfTableItems={this.props.numOfEditions}
show={this.props.show}
show={show}
orderBy={orderBy}
orderAsc={orderAsc}
changeOrder={this.changeEditionListOrder}>
<AccordionListItemTableToggle
className="ascribe-accordion-list-table-toggle"
onClick={this.toggleTable}
show={this.props.show}
numOfTableItems={this.props.numOfEditions} />
show={show} />
</AccordionListItemTable>
</div>

View File

@ -6,8 +6,7 @@ let AccordionListItemTableToggle = React.createClass({
propTypes: {
className: React.PropTypes.string,
onClick: React.PropTypes.func,
show: React.PropTypes.bool,
numOfTableItems: React.PropTypes.number
show: React.PropTypes.bool
},
render() {
@ -15,7 +14,7 @@ let AccordionListItemTableToggle = React.createClass({
<span
className={this.props.className}
onClick={this.props.onClick}>
{this.props.show ? 'Hide all ' + this.props.numOfTableItems + ' Editions' : 'Show all ' + this.props.numOfTableItems + ' Editions'}
{this.props.show ? 'Hide all Editions' : 'Show all Editions'}
</span>
);
}

View File

@ -2,6 +2,8 @@
import React from 'react';
import AppConstants from '../../constants/application_constants';
let ButtonSubmitOrClose = React.createClass({
propTypes: {
submitted: React.PropTypes.bool.isRequired,
@ -13,7 +15,7 @@ let ButtonSubmitOrClose = React.createClass({
if (this.props.submitted){
return (
<div className="modal-footer">
<img src="https://s3-us-west-2.amazonaws.com/ascribe0/media/thumbnails/ascribe_animated_medium.gif" />
<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />
</div>
);
}

View File

@ -23,12 +23,13 @@ let DeleteButton = React.createClass({
mixins: [Router.Navigation],
showNotification(response){
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);
@ -45,7 +46,7 @@ let DeleteButton = React.createClass({
}
else if (availableAcls.indexOf('del_from_collection') > -1){
content = <EditionRemoveFromCollectionForm editions={ this.props.editions }/>;
btnDelete = <Button bsStyle="danger" bsSize="small">REMOVE FROM LIST</Button>;
btnDelete = <Button bsStyle="danger" bsSize="small">REMOVE FROM COLLECTION</Button>;
}
else{
return null;

View File

@ -2,7 +2,7 @@
import React from 'react';
import fetch from '../../utils/fetch';
import requests from '../../utils/requests';
import ApiUrls from '../../constants/api_urls';
import FormMixin from '../../mixins/form_mixin';
@ -11,7 +11,7 @@ let EditionDeleteForm = React.createClass({
mixins: [FormMixin],
url() {
return fetch.prepareUrl(ApiUrls.edition_delete, {edition_id: this.getBitcoinIds().join()});
return requests.prepareUrl(ApiUrls.edition_delete, {edition_id: this.getBitcoinIds().join()});
},
httpVerb(){
return 'delete';
@ -32,4 +32,4 @@ let EditionDeleteForm = React.createClass({
});
export default EditionDeleteForm;
export default EditionDeleteForm;

View File

@ -52,7 +52,7 @@ let LoanForm = React.createClass({
loaneeHasContract: true
});
}
else{
else {
this.resetLoanContract();
}
})
@ -63,10 +63,11 @@ let LoanForm = React.createClass({
},
resetLoanContract(){
this.setState({contract_key: null,
contract_url: null,
loaneeHasContract: false
});
this.setState({
contract_key: null,
contract_url: null,
loaneeHasContract: false
});
},
renderForm() {

View File

@ -2,7 +2,7 @@
import React from 'react';
import fetch from '../../utils/fetch';
import requests from '../../utils/requests';
import apiUrls from '../../constants/api_urls';
import FormMixin from '../../mixins/form_mixin';
@ -14,7 +14,7 @@ let PieceExtraDataForm = React.createClass({
mixins: [FormMixin],
url() {
return fetch.prepareUrl(apiUrls.piece_extradata, {piece_id: this.props.editions[0].bitcoin_id});
return requests.prepareUrl(apiUrls.piece_extradata, {piece_id: this.props.editions[0].bitcoin_id});
},
getFormData() {
@ -48,4 +48,4 @@ let PieceExtraDataForm = React.createClass({
}
});
export default PieceExtraDataForm;
export default PieceExtraDataForm;

View File

@ -2,7 +2,7 @@
import React from 'react';
import fetch from '../../utils/fetch';
import requests from '../../utils/requests';
import apiUrls from '../../constants/api_urls';
import FormMixin from '../../mixins/form_mixin';
@ -11,7 +11,7 @@ let EditionRemoveFromCollectionForm = React.createClass({
mixins: [FormMixin],
url() {
return fetch.prepareUrl(apiUrls.edition_remove_from_collection, {edition_id: this.getBitcoinIds().join()});
return requests.prepareUrl(apiUrls.edition_remove_from_collection, {edition_id: this.getBitcoinIds().join()});
},
httpVerb(){
return 'delete';
@ -32,4 +32,4 @@ let EditionRemoveFromCollectionForm = React.createClass({
});
export default EditionRemoveFromCollectionForm;
export default EditionRemoveFromCollectionForm;

View File

@ -7,6 +7,8 @@ import Alert from 'react-bootstrap/lib/Alert';
import apiUrls from '../../constants/api_urls';
import FormMixin from '../../mixins/form_mixin';
import AppConstants from '../../constants/application_constants';
let RequestActionForm = React.createClass({
mixins: [FormMixin],
@ -62,7 +64,7 @@ let RequestActionForm = React.createClass({
if (this.state.submitted){
buttons = (
<span>
<img src="https://s3-us-west-2.amazonaws.com/ascribe0/media/thumbnails/ascribe_animated_small.gif" />
<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />
</span>
);
}

View File

@ -9,7 +9,6 @@ let Pagination = React.createClass({
goToPage: React.PropTypes.func.isRequired,
currentPage: React.PropTypes.number.isRequired,
totalPages: React.PropTypes.number.isRequired
//itemListCount: React.PropTypes.number.isRequired
},
render() {

View File

@ -65,6 +65,7 @@ let PieceListBulkModal = React.createClass({
clearAllSelections() {
EditionListActions.clearAllEditionSelections();
EditionListActions.closeAllEditionLists();
},
handleSuccess() {

View File

@ -2,37 +2,19 @@
import React from 'react';
import PieceListStore from '../../stores/piece_list_store';
import PieceListActions from '../../actions/piece_list_actions';
import Input from 'react-bootstrap/lib/Input';
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
let PieceListToolbar = React.createClass({
propTypes: {
className: React.PropTypes.string
},
getInitialState() {
return PieceListStore.getState();
},
componentDidMount() {
PieceListStore.listen(this.onChange);
},
componentWillUnmount() {
PieceListStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
className: React.PropTypes.string,
searchFor: React.PropTypes.func
},
searchFor() {
let searchTerm = this.refs.search.getInputDOMNode().value;
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, searchTerm, this.state.orderBy, this.state.orderAsc);
this.props.searchFor(searchTerm);
},
render() {

View File

@ -20,7 +20,6 @@ let Table = React.createClass({
},
renderChildren() {
var that = this;
return ReactAddons.Children.map(this.props.children, (child, i) => {
return ReactAddons.addons.cloneWithProps(child, {
columnList: this.props.columnList,

View File

@ -17,7 +17,9 @@ let TableItemCheckbox = React.createClass({
render() {
return (
<input type="checkbox" onChange={this.selectItem} checked={this.props.selected}/>
<span>
<input type="checkbox" onChange={this.selectItem} checked={this.props.selected}/>
</span>
);
}
});

View File

@ -4,7 +4,6 @@ import React from 'react';
import Router from 'react-router';
import { ColumnModel } from './models/table_models';
import TableColumnMixin from '../../mixins/table_column_mixin';
let Link = Router.Link;
@ -15,7 +14,7 @@ let TableItemWrapper = React.createClass({
columnWidth: React.PropTypes.number.isRequired
},
mixins: [TableColumnMixin, Router.Navigation],
mixins: [Router.Navigation],
render() {
return (
@ -25,8 +24,6 @@ let TableItemWrapper = React.createClass({
let TypeElement = column.displayType;
let typeElementProps = column.transformFn(this.props.columnContent);
let columnClass = this.calcColumnClasses(this.props.columnList, i, this.props.columnWidth);
if(!column.transition) {
return (
<td

View File

@ -73,7 +73,7 @@ let Header = React.createClass({
return (
<Navbar>
<Nav>
<Link className="navbar-brand" to="pieces">
<Link className="navbar-brand" to="pieces" path="/?page=1">
<span>ascribe </span>
<span className="glyph-ascribe-spool-chunked ascribe-color"></span>
</Link>

View File

@ -1,6 +1,7 @@
'use strict';
import React from 'react';
import Router from 'react-router';
import PieceListStore from '../stores/piece_list_store';
import PieceListActions from '../actions/piece_list_actions';
@ -14,12 +15,16 @@ import Pagination from './ascribe_pagination/pagination';
import PieceListBulkModal from './ascribe_piece_list_bulk_modal/piece_list_bulk_modal';
import PieceListToolbar from './ascribe_piece_list_toolbar/piece_list_toolbar';
import AppConstants from '../constants/application_constants';
let PieceList = React.createClass({
propTypes: {
query: React.PropTypes.object
},
mixins: [Router.Navigation, Router.State],
getInitialState() {
return PieceListStore.getState();
},
@ -30,7 +35,6 @@ let PieceList = React.createClass({
if (this.state.pieceList.length === 0){
PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search, this.state.orderBy, this.state.orderAsc);
}
},
componentWillUnmount() {
@ -47,6 +51,11 @@ let PieceList = React.createClass({
this.state.orderAsc);
},
searchFor(searchTerm) {
PieceListActions.fetchPieceList(1, this.state.pageSize, searchTerm, this.state.orderBy, this.state.orderAsc);
this.transitionTo(this.getPathname(), {page: 1});
},
accordionChangeOrder(orderBy, orderAsc) {
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize,
this.state.search, orderBy, orderAsc);
@ -55,10 +64,13 @@ let PieceList = React.createClass({
render() {
let currentPage = parseInt(this.props.query.page, 10) || 1;
let totalPages = Math.ceil(this.state.pieceListCount / this.state.pageSize);
let loadingElement = (<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />);
return (
<div>
<PieceListToolbar className="ascribe-piece-list-toolbar" />
<PieceListToolbar
className="ascribe-piece-list-toolbar"
searchFor={this.searchFor} />
<PieceListBulkModal className="ascribe-piece-list-bulk-modal" />
<AccordionList
className="ascribe-accordion-list"
@ -68,7 +80,8 @@ let PieceList = React.createClass({
orderAsc={this.state.orderAsc}
search={this.state.search}
page={this.state.page}
pageSize={this.state.pageSize}>
pageSize={this.state.pageSize}
loadingElement={loadingElement}>
{this.state.pieceList.map((item, i) => {
return (
<AccordionListItem
@ -77,9 +90,7 @@ let PieceList = React.createClass({
key={i}>
<AccordionListItemTableEditions
className="ascribe-accordion-list-item-table col-xs-12 col-sm-8 col-md-6 col-lg-6 col-sm-offset-2 col-md-offset-3 col-lg-offset-3"
parentId={item.id}
show={item.show}
numOfEditions={item.num_editions}/>
parentId={item.id} />
</AccordionListItem>
);
})}

View File

@ -3,31 +3,31 @@
import AppConstants from './application_constants';
let apiUrls = {
'piece': AppConstants.apiEndpoint + 'pieces/${piece_id}',
'pieces_list': AppConstants.apiEndpoint + 'pieces/',
'piece_extradata': AppConstants.apiEndpoint + 'pieces/${piece_id}/extradata/',
'edition': AppConstants.apiEndpoint + 'editions/${bitcoin_id}/',
'editions_list': AppConstants.apiEndpoint + 'pieces/${piece_id}/editions/',
'edition_delete': AppConstants.apiEndpoint + 'editions/${edition_id}/',
'edition_remove_from_collection': AppConstants.apiEndpoint + 'ownership/shares/${edition_id}/',
'ownership_shares_mail': AppConstants.apiEndpoint + 'ownership/shares/mail/',
'ownership_transfers': AppConstants.apiEndpoint + 'ownership/transfers/',
'editions_list': AppConstants.apiEndpoint + 'pieces/${piece_id}/editions/',
'note_notes': AppConstants.apiEndpoint + 'note/notes/',
'ownership_consigns': AppConstants.apiEndpoint + 'ownership/consigns/',
'ownership_consigns_confirm': AppConstants.apiEndpoint + 'ownership/consigns/confirm/',
'ownership_consigns_deny': AppConstants.apiEndpoint + 'ownership/consigns/deny/',
'ownership_unconsigns': AppConstants.apiEndpoint + 'ownership/unconsigns/',
'ownership_unconsigns_request': AppConstants.apiEndpoint + 'ownership/unconsigns/request/',
'ownership_unconsigns_deny': AppConstants.apiEndpoint + 'ownership/unconsigns/deny/',
'ownership_loans': AppConstants.apiEndpoint + 'ownership/loans/',
'ownership_loans_confirm': AppConstants.apiEndpoint + 'ownership/loans/confirm/',
'ownership_loans_deny': AppConstants.apiEndpoint + 'ownership/loans/deny/',
'note_notes': AppConstants.apiEndpoint + 'note/notes/',
'ownership_shares_mail': AppConstants.apiEndpoint + 'ownership/shares/mail/',
'ownership_transfers': AppConstants.apiEndpoint + 'ownership/transfers/',
'ownership_unconsigns': AppConstants.apiEndpoint + 'ownership/unconsigns/',
'ownership_unconsigns_deny': AppConstants.apiEndpoint + 'ownership/unconsigns/deny/',
'ownership_unconsigns_request': AppConstants.apiEndpoint + 'ownership/unconsigns/request/',
'piece': AppConstants.apiEndpoint + 'pieces/${piece_id}',
'piece_extradata': AppConstants.apiEndpoint + 'pieces/${piece_id}/extradata/',
'pieces_list': AppConstants.apiEndpoint + 'pieces/',
'user': AppConstants.apiEndpoint + 'users/',
'users_login': AppConstants.apiEndpoint + 'users/login/',
'users_logout': AppConstants.apiEndpoint + 'users/logout/',
'users_signup': AppConstants.apiEndpoint + 'users/',
'users_password_reset': AppConstants.apiEndpoint + 'users/reset_password/',
'users_password_reset_request': AppConstants.apiEndpoint + 'users/request_reset_password/',
'users_password_reset': AppConstants.apiEndpoint + 'users/reset_password/'
'users_signup': AppConstants.apiEndpoint + 'users/'
};
export default apiUrls;

View File

@ -8,9 +8,8 @@ let constants = {
//'baseUrl': window.BASE_URL,
'apiEndpoint': window.API_ENDPOINT,
'baseUrl': window.BASE_URL,
//'debugCredentialBase64': 'ZGltaUBtYWlsaW5hdG9yLmNvbTowMDAwMDAwMDAw', // dimi@mailinator:0000000000
'aclList': ['edit', 'consign', 'consign_request', 'unconsign', 'unconsign_request', 'transfer',
'loan', 'loan_request', 'share', 'download', 'view', 'delete', 'del_from_collection', 'add_to_collection']
'loan', 'loan_request', 'share', 'download', 'view', 'delete', 'del_from_collection', 'add_to_collection']
};
export default constants;

View File

@ -1,6 +1,6 @@
'use strict';
import fetch from '../utils/fetch';
import requests from '../utils/requests';
let EditionFetcher = {
/**
@ -8,7 +8,7 @@ let EditionFetcher = {
* If no arg is supplied, load the current user
*/
fetchOne(editionId) {
return fetch.get('edition', {'bitcoin_id': editionId});
return requests.get('edition', {'bitcoin_id': editionId});
}
};

View File

@ -1,6 +1,6 @@
'use strict';
import fetch from '../utils/fetch';
import requests from '../utils/requests';
import { generateOrderingQueryParams } from '../utils/fetch_api_utils';
@ -11,7 +11,7 @@ let EditionListFetcher = {
*/
fetch(pieceId, orderBy, orderAsc) {
let ordering = generateOrderingQueryParams(orderBy, orderAsc);
return fetch.get('editions_list', { 'piece_id': pieceId, ordering });
return requests.get('editions_list', { 'piece_id': pieceId, ordering });
}
};

View File

@ -1,6 +1,6 @@
'use strict';
import fetch from '../utils/fetch';
import requests from '../utils/requests';
let PieceFetcher = {
@ -9,7 +9,7 @@ let PieceFetcher = {
* If no arg is supplied, load the current user
*/
fetchOne() {
return fetch.get('piece');
return requests.get('piece');
}
};

View File

@ -1,7 +1,7 @@
'use strict';
import { generateOrderingQueryParams } from '../utils/fetch_api_utils';
import fetch from '../utils/fetch';
import requests from '../utils/requests';
let PieceListFetcher = {
@ -11,7 +11,7 @@ let PieceListFetcher = {
*/
fetch(page, pageSize, search, orderBy, orderAsc) {
let ordering = generateOrderingQueryParams(orderBy, orderAsc);
return fetch.get('pieces_list', { page, pageSize, search, ordering });
return requests.get('pieces_list', { page, pageSize, search, ordering });
}
};

View File

@ -1,6 +1,6 @@
'use strict';
import fetch from '../utils/fetch';
import requests from '../utils/requests';
let UserFetcher = {
@ -9,7 +9,7 @@ let UserFetcher = {
* If no arg is supplied, load the current user
*/
fetchOne() {
return fetch.get('user');
return requests.get('user');
}
};

View File

@ -1,6 +1,6 @@
'use strict';
import fetch from '../utils/fetch';
import requests from '../utils/requests';
import React from 'react';
import AlertDismissable from '../components/ascribe_forms/alert';
@ -29,14 +29,14 @@ export const FormMixin = {
},
post(e){
fetch
requests
.post(this.url(e), { body: this.getFormData() })
.then(this.handleSuccess)
.catch(this.handleError);
},
delete(e){
fetch
requests
.delete(this.url(e))
.then(this.handleSuccess)
.catch(this.handleError);

View File

@ -8,6 +8,7 @@ import EditionsListActions from '../actions/edition_list_actions';
class EditionListStore {
constructor() {
this.editionList = {};
this.isEditionListOpenForPieceId = {};
this.bindActions(EditionsListActions);
}
@ -16,15 +17,16 @@ class EditionListStore {
this.editionList[pieceId].forEach((edition, i) => {
// This uses the index of the new editionList for determining the edition.
// If the list of editions can be sorted in the future, this needs to be changed!
if (editionListOfPiece[i]){
if (editionListOfPiece[i]) {
editionListOfPiece[i] = React.addons.update(edition, {$merge: editionListOfPiece[i]});
}
});
}
this.editionList[pieceId] = editionListOfPiece;
/**
* orderBy and orderAsc are specific to a single list of editons
* orderBy and orderAsc are specific to a single list of editions
* therefore they need to be saved in relation to their parent-piece.
*
* Default values for both are set in the editon_list-actions.
@ -36,7 +38,7 @@ class EditionListStore {
onSelectEdition({pieceId, editionId, toValue}) {
this.editionList[pieceId].forEach((edition) => {
// http://stackoverflow.com/a/519157/1263876
// Taken from: http://stackoverflow.com/a/519157/1263876
if(typeof toValue !== 'undefined' && edition.id === editionId) {
edition.selected = toValue;
} else if(edition.id === editionId) {
@ -57,12 +59,20 @@ class EditionListStore {
.forEach((edition) => {
try {
delete edition.selected;
} catch(err) {
//just ignore
}
} catch(err) {/* ignore and keep going */}
});
});
}
onToggleEditionList(pieceId) {
this.isEditionListOpenForPieceId[pieceId] = {
show: this.isEditionListOpenForPieceId[pieceId] ? !this.isEditionListOpenForPieceId[pieceId].show : true
};
}
onCloseAllEditionLists() {
this.isEditionListOpenForPieceId = {};
}
}
export default alt.createStore(EditionListStore, 'EditionListStore');

View File

@ -1,5 +1,6 @@
'use strict';
import React from 'react';
import alt from '../alt';
import PieceListActions from '../actions/piece_list_actions';
@ -27,7 +28,7 @@ class PieceListStore {
this.bindActions(PieceListActions);
}
onShowEditionList(pieceId) {
/*onShowEditionList(pieceId) {
this.pieceList
.forEach((piece) => {
if(piece.id === pieceId) {
@ -38,14 +39,14 @@ class PieceListStore {
}
}
});
}
}*/
onCloseAllEditionLists() {
/*onCloseAllEditionLists() {
this.pieceList
.forEach((piece) => {
piece.show = false;
});
}
}*/
onUpdatePieceList({ page, pageSize, search, pieceList, orderBy, orderAsc, pieceListCount }) {
this.page = page;
@ -72,6 +73,16 @@ class PieceListStore {
* We did not implement this, as we're going to add pagination to pieceList at some
* point anyway. Then, this problem is automatically resolved.
*/
pieceList.forEach((piece, i) => {
let oldPiece = this.pieceList[i];
if(oldPiece) {
piece = React.addons.update(piece, {
show: { $set: oldPiece.show }
});
}
});
this.pieceList = pieceList;
}
}

View File

@ -1,7 +1,5 @@
'use strict';
import { default as _fetch } from 'isomorphic-fetch';
import { argsToQueryParams, getCookie } from '../utils/fetch_api_utils';
@ -10,7 +8,7 @@ class ServerError extends Error {}
class APIError extends Error {}
class Fetch {
class Requests {
_merge(defaults, options) {
let merged = {};
for (let key in defaults) {
@ -80,7 +78,7 @@ class Fetch {
let merged = this._merge(this.httpOptions, options);
this.httpOptions.headers['X-CSRFToken'] = getCookie('csrftoken');
merged.method = verb;
return _fetch(url, merged)
return fetch(url, merged)
.then(this.unpackResponse)
.then(JSON.parse)
.catch(this.handleFatalError.bind(this))
@ -107,7 +105,6 @@ class Fetch {
if (paramsCopy && paramsCopy.body) {
body = JSON.stringify(paramsCopy.body);
}
return this.request('post', newUrl, { body });
}
@ -119,6 +116,6 @@ class Fetch {
}
let fetch = new Fetch();
let requests = new Requests();
export default fetch;
export default requests;

View File

@ -39,6 +39,16 @@ $ascribe-accordion-list-font: 'Source Sans Pro';
}
}
.ascribe-accordion-list-loading {
padding-top: 30%;
padding-bottom: 30%;
}
.ascribe-accordion-list-loading img {
display: block;
margin: auto;
}
.ascribe-accordion-list-item-table {
text-align: center;
margin-bottom: 3em;

44
sass/ascribe_table.scss Normal file
View File

@ -0,0 +1,44 @@
.ascribe-table {
margin-bottom:0;
}
/*This is aligning the first checkbox in pieclist detail with all the other ones*/
.table > thead:first-child > tr:first-child > th {
padding-left:0;
}
.ascribe-table-header-column > span {
display: table-cell;
vertical-align: middle;
font-family: 'Source Sans Pro';
font-weight: 600;
color: #424242;
}
.ascribe-table-item-column {
display: table;
font-family: 'Source Sans Pro';
font-size: .8em;
height:3em;
}
.ascribe-table-item-column > * {
display: table-cell;
vertical-align: middle;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.ascribe-table-item-column > span > input {
margin-top:14px;
}
.ascribe-table-item-selected {
background-color: rgba(2, 182, 163, 0.5);
}
.ascribe-table-item-selectable {
cursor: default;
}

View File

@ -9,6 +9,7 @@ $BASE_URL: '<%= BASE_URL %>';
@import '../node_modules/react-datepicker/dist/react-datepicker';
@import './ascribe-fonts/style';
@import './ascribe-fonts/ascribe-fonts';
@import 'ascribe_table';
@import 'ascribe_accordion_list';
@import 'ascribe_piece_list_bulk_modal';
@import 'ascribe_piece_list_toolbar';
@ -49,45 +50,6 @@ $BASE_URL: '<%= BASE_URL %>';
float: none;
}
.ascribe-table {
margin-bottom:0;
}
.ascribe-table-header-column > span {
display: table-cell;
vertical-align: middle;
font-family: 'Source Sans Pro';
font-weight: 600;
color: #424242;
}
.ascribe-table-header-column > span > .glyphicon {
font-size: .5em;
}
.ascribe-table-item-column {
display: table;
font-family: 'Source Sans Pro';
font-size: .8em;
height:3em;
}
.ascribe-table-item-column > * {
display: table-cell;
vertical-align: middle;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.ascribe-table-item-selected {
background-color: rgba(2, 182, 163, 0.5);
}
.ascribe-table-item-selectable {
cursor: default;
}
.no-margin {
margin-right: 0;
margin-left: 0;
@ -100,7 +62,6 @@ $BASE_URL: '<%= BASE_URL %>';
margin-left: 0 !important;
font-family: sans-serif !important;
border-radius: 0 !important;
}
.btn-ascribe, .btn-ascribe-inv:active, .btn-ascribe-inv:hover {
@ -130,7 +91,6 @@ $BASE_URL: '<%= BASE_URL %>';
margin-left: 0 !important;
font-family: sans-serif !important;
border-radius: 0 !important;
}
.btn-ascribe-green, .btn-ascribe-green-inv:active, .btn-ascribe-green-inv:hover {
@ -149,7 +109,6 @@ $BASE_URL: '<%= BASE_URL %>';
margin-top: 2em;
}
.ascribe-detail-title {
font-size: 2em;
margin-bottom: -0.2em;

View File

@ -9,6 +9,7 @@ var app = express();
app.use(compression());
app.use(baseUrl + 'static/js', express.static(__dirname + '/build/js'));
app.use(baseUrl + 'static/img', express.static(__dirname + '/build/img'));
app.use(baseUrl + 'static/css', express.static(__dirname + '/build/css'));
app.use(baseUrl + 'static/fonts', express.static(__dirname + '/build/fonts'));
app.use(baseUrl + 'static/thirdparty/', express.static(__dirname + '/node_modules'));