mirror of
https://github.com/ascribe/onion.git
synced 2024-12-22 17:33:14 +01:00
Merge remote-tracking branch 'remotes/origin/AD-551-work-on-burn-down-list' into AD-419-decouple-piece-registration-from-
Conflicts: js/components/ascribe_detail/edition.js
This commit is contained in:
commit
bf0a36f2a3
@ -4,12 +4,12 @@ import alt from '../alt';
|
||||
|
||||
import PieceListFetcher from '../fetchers/piece_list_fetcher';
|
||||
|
||||
|
||||
class PieceListActions {
|
||||
constructor() {
|
||||
this.generateActions(
|
||||
'updatePieceList',
|
||||
'updatePieceListRequestActions'
|
||||
'updatePieceListRequestActions',
|
||||
'addFirstEditionToPiece'
|
||||
);
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@ class PieceListActions {
|
||||
.catch((err) => reject(err));
|
||||
});
|
||||
}
|
||||
|
||||
fetchPieceRequestActions() {
|
||||
PieceListFetcher
|
||||
.fetchRequestActions()
|
||||
@ -40,6 +41,16 @@ class PieceListActions {
|
||||
});
|
||||
}
|
||||
|
||||
fetchFirstEditionForPiece(pieceId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
PieceListFetcher.fetchFirstEditionForPiece(pieceId)
|
||||
.then((firstEdition) => {
|
||||
this.actions.addFirstEditionToPiece({pieceId, firstEdition});
|
||||
resolve();
|
||||
})
|
||||
.catch((err) => reject(err));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default alt.createActions(PieceListActions);
|
||||
|
@ -3,28 +3,36 @@
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
|
||||
import PieceListStore from '../../stores/piece_list_store';
|
||||
import PieceListActions from '../../actions/piece_list_actions';
|
||||
|
||||
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
|
||||
import requests from '../../utils/requests';
|
||||
import AccordionListItemEditionWidget from './accordion_list_item_edition_widget';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
let AccordionListItem = React.createClass({
|
||||
mixins: [Router.Navigation],
|
||||
|
||||
propTypes: {
|
||||
className: React.PropTypes.string,
|
||||
content: React.PropTypes.object,
|
||||
children: React.PropTypes.object
|
||||
},
|
||||
handleClick(event){
|
||||
requests.get('piece_first_edition_id', {'piece_id': this.props.content.id})
|
||||
.then((res) => this.transitionTo('edition', {editionId: res.bitcoin_id}));
|
||||
|
||||
console.log(event.target);
|
||||
mixins: [Router.Navigation],
|
||||
|
||||
componentDidMount() {
|
||||
if(this.props.content.num_editions !== 0) {
|
||||
PieceListActions.fetchFirstEditionForPiece(this.props.content.id);
|
||||
}
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
},
|
||||
|
||||
getGlyphicon(){
|
||||
if (this.props.content.requestAction){
|
||||
return (
|
||||
@ -35,6 +43,7 @@ let AccordionListItem = React.createClass({
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="row">
|
||||
@ -53,9 +62,12 @@ let AccordionListItem = React.createClass({
|
||||
<h3>{getLangText('by %s', this.props.content.artist_name)}</h3>
|
||||
<div>
|
||||
<span>{this.props.content.date_created.split('-')[0]}</span>
|
||||
<a href={this.props.content.license_type.url} target="_blank" className="pull-right">
|
||||
<AccordionListItemEditionWidget
|
||||
piece={this.props.content} />
|
||||
{/* <a href={this.props.content.license_type.url} target="_blank" className="pull-right">
|
||||
{getLangText('%s license', this.props.content.license_type.code)}
|
||||
</a>
|
||||
</a> */}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<span style={{'clear': 'both'}}></span>
|
||||
|
@ -0,0 +1,93 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import EditionListActions from '../../actions/edition_list_actions';
|
||||
import EditionListStore from '../../stores/edition_list_store';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
import { mergeOptions } from '../../utils/general_utils';
|
||||
|
||||
let AccordionListItemEditionWidget = React.createClass({
|
||||
propTypes: {
|
||||
piece: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return EditionListStore.getState();
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
EditionListStore.listen(this.onChange);
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
EditionListStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
},
|
||||
|
||||
/**
|
||||
* Calls the store to either show or hide the editionListTable
|
||||
*/
|
||||
toggleTable() {
|
||||
let pieceId = this.props.piece.id;
|
||||
let isEditionListOpen = this.state.isEditionListOpenForPieceId[pieceId] ? this.state.isEditionListOpenForPieceId[pieceId].show : false;
|
||||
|
||||
if(isEditionListOpen) {
|
||||
EditionListActions.toggleEditionList(pieceId);
|
||||
} else {
|
||||
EditionListActions.toggleEditionList(pieceId);
|
||||
EditionListActions.fetchEditionList(pieceId);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Depending on the state of isEditionListOpenForPieceId we either want to display
|
||||
* a glyphicon arrow pointing upwards or downwards
|
||||
*/
|
||||
getGlyphicon() {
|
||||
let pieceId = this.props.piece.id;
|
||||
let isEditionListOpen = this.state.isEditionListOpenForPieceId[pieceId] ? this.state.isEditionListOpenForPieceId[pieceId].show : false;
|
||||
|
||||
if(isEditionListOpen) {
|
||||
return (
|
||||
<span className="glyphicon glyphicon-menu-up" aria-hidden="true" style={{top: 2}}></span>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<span className="glyphicon glyphicon-menu-down" aria-hidden="true" style={{top: 2}}></span>
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
let piece = this.props.piece;
|
||||
let numEditions = piece.num_editions;
|
||||
|
||||
if(numEditions === 1) {
|
||||
let firstEditionId = piece && piece.firstEdition ? ', ' + piece.firstEdition.bitcoin_id : '';
|
||||
let editionMapping = piece && piece.firstEdition ? piece.firstEdition.edition_number + '/' + piece.num_editions : '';
|
||||
|
||||
return (
|
||||
<span
|
||||
onClick={this.toggleTable}
|
||||
className="ascribe-accordion-list-item-edition-widget pull-right">
|
||||
{this.getGlyphicon()} {editionMapping + ' ' + getLangText('Edition') + firstEditionId}
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<span
|
||||
onClick={this.toggleTable}
|
||||
className="ascribe-accordion-list-item-edition-widget pull-right">
|
||||
{this.getGlyphicon()} {numEditions + ' ' + getLangText('Editions')}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default AccordionListItemEditionWidget;
|
@ -3,7 +3,7 @@
|
||||
import React from 'react';
|
||||
|
||||
import Table from '../ascribe_table/table';
|
||||
import TableItem from '../ascribe_table/table_item';
|
||||
import TableItemSelectable from '../ascribe_table/table_item_selectable';
|
||||
|
||||
import { ColumnModel } from '../ascribe_table/models/table_models';
|
||||
|
||||
@ -16,7 +16,8 @@ let AccordionListItemTable = React.createClass({
|
||||
show: React.PropTypes.bool,
|
||||
changeOrder: React.PropTypes.func,
|
||||
orderBy: React.PropTypes.string,
|
||||
orderAsc: React.PropTypes.bool
|
||||
orderAsc: React.PropTypes.bool,
|
||||
selectItem: React.PropTypes.func
|
||||
},
|
||||
|
||||
render() {
|
||||
@ -32,9 +33,11 @@ let AccordionListItemTable = React.createClass({
|
||||
orderAsc={this.props.orderAsc}>
|
||||
{this.props.itemList.map((item, i) => {
|
||||
return (
|
||||
<TableItem
|
||||
<TableItemSelectable
|
||||
className="ascribe-table-item-selectable"
|
||||
key={i} />
|
||||
key={i}
|
||||
selectItem={this.props.selectItem}
|
||||
parentId={this.props.parentId}/>
|
||||
);
|
||||
})}
|
||||
</Table>
|
||||
|
@ -69,16 +69,6 @@ let AccordionListItemTableEditions = React.createClass({
|
||||
return selectedEditions;
|
||||
},
|
||||
|
||||
toggleTable() {
|
||||
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);
|
||||
}
|
||||
},
|
||||
|
||||
loadFurtherEditions() {
|
||||
// trigger loading animation
|
||||
this.setState({
|
||||
@ -187,14 +177,14 @@ let AccordionListItemTableEditions = React.createClass({
|
||||
)
|
||||
];
|
||||
|
||||
let loadingSpinner = <span className="glyph-ascribe-spool-chunked ascribe-color spin"/> ;
|
||||
let loadingSpinner = <span className="glyph-ascribe-spool-chunked ascribe-color spin"/>;
|
||||
|
||||
return (
|
||||
<div className={this.props.className}>
|
||||
<AccordionListItemTableToggle
|
||||
{/* <AccordionListItemTableToggle
|
||||
className="ascribe-accordion-list-table-toggle"
|
||||
onClick={this.toggleTable}
|
||||
message={show && typeof editionsForPiece !== 'undefined' ? <span><span className="glyphicon glyphicon-menu-up" aria-hidden="true" style={{top: 2}}></span> {getLangText('Hide editions')}</span> : <span><span className="glyphicon glyphicon-menu-down" aria-hidden="true" style={{top: 2}}></span> {getLangText('Show editions')} {show && typeof editionsForPiece === 'undefined' ? loadingSpinner : null}</span>} />
|
||||
message={show && typeof editionsForPiece !== 'undefined' ? <span><span className="glyphicon glyphicon-menu-up" aria-hidden="true" style={{top: 2}}></span> {getLangText('Hide editions')}</span> : <span><span className="glyphicon glyphicon-menu-down" aria-hidden="true" style={{top: 2}}></span> {getLangText('Show editions')} {show && typeof editionsForPiece === 'undefined' ? loadingSpinner : null}</span>} /> */}
|
||||
<AccordionListItemTable
|
||||
parentId={this.props.parentId}
|
||||
itemList={editionsForPiece}
|
||||
@ -202,7 +192,8 @@ let AccordionListItemTableEditions = React.createClass({
|
||||
show={show}
|
||||
orderBy={orderBy}
|
||||
orderAsc={orderAsc}
|
||||
changeOrder={this.changeEditionListOrder} />
|
||||
changeOrder={this.changeEditionListOrder}
|
||||
selectItem={this.selectItem}/>
|
||||
<AccordionListItemTableToggle
|
||||
className="ascribe-accordion-list-table-toggle"
|
||||
onClick={this.loadFurtherEditions}
|
||||
|
@ -6,8 +6,6 @@ import CollapsibleMixin from 'react-bootstrap/lib/CollapsibleMixin';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils.js'
|
||||
|
||||
|
||||
const CollapsibleParagraph = React.createClass({
|
||||
|
||||
@ -43,13 +41,14 @@ const CollapsibleParagraph = React.createClass({
|
||||
|
||||
render() {
|
||||
let styles = this.getCollapsibleClassSet();
|
||||
let text = this.isExpanded() ? '[' + getLangText('hide') + ']' : '[' + getLangText('show') + ']';
|
||||
let text = this.isExpanded() ? '-' : '+';
|
||||
|
||||
if(this.props.show) {
|
||||
return (
|
||||
<div className="ascribe-detail-header">
|
||||
<div className="ascribe-edition-collapsible-wrapper">
|
||||
<div onClick={this.handleToggle}>
|
||||
<span>{this.props.title}</span><span className="pull-right">{text}</span>
|
||||
<span>{text} {this.props.title}</span>
|
||||
</div>
|
||||
<div ref='panel' className={classNames(styles) + ' ascribe-edition-collapible-content'}>
|
||||
{this.props.children}
|
||||
|
@ -39,6 +39,7 @@ import apiUrls from '../../constants/api_urls';
|
||||
import AppConstants from '../../constants/application_constants';
|
||||
|
||||
import { getCookie } from '../../utils/fetch_api_utils';
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
let Link = Router.Link;
|
||||
/**
|
||||
|
@ -17,10 +17,10 @@ let EditionContainer = React.createClass({
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
let isEncoding = state.edition.digital_work.isEncoding;
|
||||
if (isEncoding !== undefined && isEncoding !== 100) {
|
||||
let isEncoding = state.edition.digital_work ? state.edition.digital_work.isEncoding : null;
|
||||
if (typeof isEncoding === 'number' && isEncoding !== 100 && !this.state.timerId) {
|
||||
let timerId = window.setInterval(() => EditionActions.fetchOne(this.props.params.editionId), 10000);
|
||||
this.setState({timerId: timerId})
|
||||
this.setState({timerId: timerId});
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -18,7 +18,8 @@ let Form = React.createClass({
|
||||
children: React.PropTypes.oneOfType([
|
||||
React.PropTypes.object,
|
||||
React.PropTypes.array
|
||||
])
|
||||
]),
|
||||
className: React.PropTypes.string
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
@ -141,10 +142,16 @@ let Form = React.createClass({
|
||||
});
|
||||
},
|
||||
render() {
|
||||
let className = 'ascribe-form';
|
||||
|
||||
if(this.props.className) {
|
||||
className += ' ' + this.props.className;
|
||||
}
|
||||
|
||||
return (
|
||||
<form
|
||||
role="form"
|
||||
className="ascribe-form"
|
||||
className={className}
|
||||
onSubmit={this.submit}
|
||||
autoComplete="on">
|
||||
{this.getErrors()}
|
||||
|
@ -9,7 +9,7 @@ import ButtonSubmitOrClose from '../ascribe_buttons/button_submit_close';
|
||||
|
||||
import SignupModal from '../ascribe_modal/modal_signup';
|
||||
import PasswordResetRequestModal from '../ascribe_modal/modal_password_request_reset';
|
||||
import { getLangText } from '../../utils/lang_utils.js'
|
||||
import { getLangText } from '../../utils/lang_utils.js';
|
||||
|
||||
let LoginForm = React.createClass({
|
||||
mixins: [FormMixin],
|
||||
|
19
js/components/ascribe_forms/form_property_header.js
Normal file
19
js/components/ascribe_forms/form_property_header.js
Normal file
@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
let FormPropertyHeader = React.createClass({
|
||||
propTypes: {
|
||||
children: React.PropTypes.arrayOf(React.PropTypes.element)
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="ascribe-form-header">
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default FormPropertyHeader;
|
90
js/components/ascribe_forms/property_collapsible.js
Normal file
90
js/components/ascribe_forms/property_collapsible.js
Normal file
@ -0,0 +1,90 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import CollapsibleMixin from 'react-bootstrap/lib/CollapsibleMixin';
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
|
||||
let PropertyCollapsile = React.createClass({
|
||||
propTypes: {
|
||||
children: React.PropTypes.arrayOf(React.PropTypes.element),
|
||||
checkboxLabel: React.PropTypes.string,
|
||||
tooltip: React.PropTypes.string
|
||||
},
|
||||
|
||||
mixins: [CollapsibleMixin],
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
show: false
|
||||
};
|
||||
},
|
||||
|
||||
getCollapsibleDOMNode(){
|
||||
return React.findDOMNode(this.refs.panel);
|
||||
},
|
||||
|
||||
getCollapsibleDimensionValue(){
|
||||
return React.findDOMNode(this.refs.panel).scrollHeight;
|
||||
},
|
||||
|
||||
handleFocus() {
|
||||
this.refs.checkboxCollapsible.getDOMNode().checked = !this.refs.checkboxCollapsible.getDOMNode().checked;
|
||||
this.setState({
|
||||
show: this.refs.checkboxCollapsible.getDOMNode().checked
|
||||
});
|
||||
},
|
||||
|
||||
renderChildren() {
|
||||
if(this.state.show) {
|
||||
return (<div
|
||||
className={classNames(this.getCollapsibleClassSet()) + ' ascribe-settings-property'}
|
||||
ref="panel">
|
||||
{this.props.children}
|
||||
</div>);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
let tooltip = <span/>;
|
||||
if (this.props.tooltip){
|
||||
tooltip = (
|
||||
<Tooltip>
|
||||
{this.props.tooltip}
|
||||
</Tooltip>);
|
||||
}
|
||||
|
||||
let style = this.state.show ? {} : {paddingBottom: 0};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={'ascribe-settings-wrapper'}
|
||||
style={style}>
|
||||
<OverlayTrigger
|
||||
delay={500}
|
||||
placement="top"
|
||||
overlay={tooltip}>
|
||||
<div
|
||||
className="ascribe-settings-property-collapsible-toggle"
|
||||
onClick={this.handleFocus}
|
||||
onFocus={this.handleFocus}>
|
||||
<input
|
||||
type="checkbox"
|
||||
ref="checkboxCollapsible"/>
|
||||
{/* PLEASE LEAVE THE SPACE BETWEEN LABEL and this.props.label */}
|
||||
<span className="checkbox"> {this.props.checkboxLabel}</span>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
{this.renderChildren()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default PropertyCollapsile;
|
@ -133,25 +133,6 @@ let Video = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
let EncodingStatus = React.createClass({
|
||||
propTypes: {
|
||||
encodingStatus: React.PropTypes.number.isRequired
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<video ref="video" className="video-js vjs-default-skin" poster={this.props.preview}
|
||||
controls preload="none" width="auto" height="auto">
|
||||
{this.props.extraData.map((data, i) =>
|
||||
<source key={i} type={'video/' + data.type} src={data.url} />
|
||||
)}
|
||||
</video>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
let resourceMap = {
|
||||
'image': Image,
|
||||
'video': Video,
|
||||
@ -169,7 +150,7 @@ let MediaPlayer = React.createClass({
|
||||
},
|
||||
|
||||
render() {
|
||||
if (this.props.encodingStatus !== undefined && this.props.encodingStatus !== 100) {
|
||||
if (this.props.mimetype === 'video' && this.props.encodingStatus !== undefined && this.props.encodingStatus !== 100) {
|
||||
return (
|
||||
<div className="ascribe-detail-header ascribe-media-player">
|
||||
<p><em>Please be patient, the video is been encoded</em></p>
|
||||
|
@ -12,12 +12,14 @@ let TableItem = React.createClass({
|
||||
propTypes: {
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(ColumnModel)),
|
||||
columnContent: React.PropTypes.object,
|
||||
className: React.PropTypes.string
|
||||
className: React.PropTypes.string,
|
||||
onClick: React.PropTypes.func
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<TableItemWrapper
|
||||
onClick={this.props.onClick}
|
||||
columnList={this.props.columnList}
|
||||
columnContent={this.props.columnContent}
|
||||
columnWidth={12} />
|
||||
|
@ -7,18 +7,13 @@ let TableItemCheckbox = React.createClass({
|
||||
propTypes: {
|
||||
editionId: React.PropTypes.number,
|
||||
pieceId: React.PropTypes.number,
|
||||
selectItem: React.PropTypes.func,
|
||||
selected: React.PropTypes.bool
|
||||
},
|
||||
|
||||
selectItem() {
|
||||
this.props.selectItem(this.props.pieceId, this.props.editionId);
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<span>
|
||||
<input type="checkbox" onChange={this.selectItem} checked={this.props.selected}/>
|
||||
<input type="checkbox" checked={this.props.selected} readOnly/>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ let TableItemSelectable = React.createClass({
|
||||
},
|
||||
|
||||
selectItem() {
|
||||
this.props.selectItem(this.props.parentId, this.props.columnContent.edition_number);
|
||||
this.props.selectItem(this.props.parentId, this.props.columnContent.id);
|
||||
},
|
||||
|
||||
render() {
|
||||
|
@ -11,14 +11,15 @@ let TableItemWrapper = React.createClass({
|
||||
propTypes: {
|
||||
columnList: React.PropTypes.arrayOf(React.PropTypes.instanceOf(ColumnModel)),
|
||||
columnContent: React.PropTypes.object,
|
||||
columnWidth: React.PropTypes.number.isRequired
|
||||
columnWidth: React.PropTypes.number.isRequired,
|
||||
onClick: React.PropTypes.func
|
||||
},
|
||||
|
||||
mixins: [Router.Navigation],
|
||||
|
||||
render() {
|
||||
return (
|
||||
<tr>
|
||||
<tr onClick={this.props.onClick}>
|
||||
{this.props.columnList.map((column, i) => {
|
||||
|
||||
let TypeElement = column.displayType;
|
||||
|
@ -7,66 +7,116 @@ import GlobalNotificationStore from '../stores/global_notification_store';
|
||||
import Row from 'react-bootstrap/lib/Row';
|
||||
import Col from 'react-bootstrap/lib/Col';
|
||||
|
||||
import { mergeOptions } from '../utils/general_utils';
|
||||
|
||||
let GlobalNotification = React.createClass({
|
||||
|
||||
getInitialState() {
|
||||
return mergeOptions(
|
||||
{
|
||||
containerWidth: 0
|
||||
},
|
||||
this.extractFirstElem(GlobalNotificationStore.getState().notificationQue)
|
||||
);
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
GlobalNotificationStore.listen(this.onChange);
|
||||
|
||||
// init container width
|
||||
this.handleContainerResize();
|
||||
|
||||
// we're using an event listener on window here,
|
||||
// as it was not possible to listen to the resize events of a dom node
|
||||
window.addEventListener('resize', this.handleContainerResize);
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
GlobalNotificationStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
getInititalState() {
|
||||
return this.extractFirstElem(GlobalNotificationStore.getState().notificationQue);
|
||||
window.removeEventListener('resize', this.handleContainerResize);
|
||||
},
|
||||
|
||||
extractFirstElem(l) {
|
||||
return l.length > 0 ? l[0] : null;
|
||||
if(l.length > 0) {
|
||||
return {
|
||||
show: true,
|
||||
message: l[0]
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
show: false,
|
||||
message: ''
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
let notification = this.extractFirstElem(state.notificationQue);
|
||||
|
||||
if(notification) {
|
||||
if(notification.show) {
|
||||
this.setState(notification);
|
||||
} else {
|
||||
this.replaceState(null);
|
||||
this.setState({
|
||||
show: false
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
handleContainerResize() {
|
||||
this.setState({
|
||||
containerWidth: this.refs.notificationWrapper.getDOMNode().offsetWidth
|
||||
});
|
||||
},
|
||||
|
||||
render() {
|
||||
let notificationClass = 'ascribe-global-notification ';
|
||||
let message = this.state && this.state.message ? this.state.message : null;
|
||||
let notificationClass = 'ascribe-global-notification';
|
||||
let textClass;
|
||||
|
||||
if(message) {
|
||||
let colors = {
|
||||
warning: '#f0ad4e',
|
||||
success: '#5cb85c',
|
||||
info: 'rgba(2, 182, 163, 1)',
|
||||
danger: '#d9534f'
|
||||
};
|
||||
if(this.state.containerWidth > 768) {
|
||||
notificationClass = 'ascribe-global-notification-bubble';
|
||||
|
||||
let text = (<div style={{color: colors[this.state.type]}}>{message ? message : null}</div>);
|
||||
if(this.state.show) {
|
||||
notificationClass += ' ascribe-global-notification-bubble-on';
|
||||
} else {
|
||||
notificationClass += ' ascribe-global-notification-bubble-off';
|
||||
}
|
||||
|
||||
return (
|
||||
} else {
|
||||
notificationClass = 'ascribe-global-notification';
|
||||
|
||||
if(this.state.show) {
|
||||
notificationClass += ' ascribe-global-notification-on';
|
||||
} else {
|
||||
notificationClass += ' ascribe-global-notification-off';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(this.state.message) {
|
||||
switch(this.state.message.type) {
|
||||
case 'success':
|
||||
textClass = 'ascribe-global-notification-success';
|
||||
break;
|
||||
case 'danger':
|
||||
textClass = 'ascribe-global-notification-danger';
|
||||
break;
|
||||
default:
|
||||
console.warn('Could not find a matching type in global_notification.js');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div ref="notificationWrapper">
|
||||
<Row>
|
||||
<Col>
|
||||
<div className={notificationClass + 'ascribe-global-notification-on'}>
|
||||
{text}
|
||||
<div className={notificationClass}>
|
||||
<div className={textClass}>{this.state.message.message}</div>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Row>
|
||||
<Col>
|
||||
<div className={notificationClass + 'ascribe-global-notification-off'} />
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -19,11 +19,12 @@ import MenuItem from 'react-bootstrap/lib/MenuItem';
|
||||
import MenuItemLink from 'react-router-bootstrap/lib/MenuItemLink';
|
||||
import NavItemLink from 'react-router-bootstrap/lib/NavItemLink';
|
||||
|
||||
import HeaderNotificationDebug from './header_notification_debug';
|
||||
|
||||
|
||||
import { mergeOptions } from '../utils/general_utils';
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
|
||||
let Link = Router.Link;
|
||||
|
||||
let Header = React.createClass({
|
||||
mixins: [Router.Navigation],
|
||||
@ -43,11 +44,13 @@ let Header = React.createClass({
|
||||
UserStore.unlisten(this.onChange);
|
||||
WhitelabelStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
handleLogout(){
|
||||
UserActions.logoutCurrentUser();
|
||||
Alt.flush();
|
||||
this.transitionTo('login');
|
||||
},
|
||||
|
||||
getLogo(){
|
||||
let logo = (
|
||||
<span>
|
||||
@ -102,15 +105,14 @@ let Header = React.createClass({
|
||||
<div>
|
||||
<Navbar
|
||||
brand={
|
||||
<Link className="navbar-brand" to="pieces">
|
||||
{this.getLogo()}
|
||||
</Link>}
|
||||
this.getLogo()
|
||||
}
|
||||
toggleNavKey={0}
|
||||
fixedTop={true}>
|
||||
<CollapsibleNav eventKey={0}>
|
||||
<Nav navbar left>
|
||||
</Nav>
|
||||
<Nav navbar left />
|
||||
<Nav navbar right>
|
||||
<HeaderNotificationDebug show={false}/>
|
||||
{addNewWork}
|
||||
{collection}
|
||||
{account}
|
||||
|
51
js/components/header_notification_debug.js
Normal file
51
js/components/header_notification_debug.js
Normal file
@ -0,0 +1,51 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import GlobalNotificationModel from '../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../actions/global_notification_actions';
|
||||
|
||||
import MenuItem from 'react-bootstrap/lib/MenuItem';
|
||||
|
||||
/*
|
||||
This components purpose is to be inserted into the page's navigation in order
|
||||
debug the globalnotificationsaction easily
|
||||
|
||||
*/
|
||||
let HeaderNotificationDebug = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
show: React.PropTypes.bool
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
index: 0
|
||||
};
|
||||
},
|
||||
|
||||
triggerNotification() {
|
||||
if(this.state.index === 1) {
|
||||
this.setState({index: 0});
|
||||
} else {
|
||||
this.setState({index: this.state.index + 1});
|
||||
}
|
||||
|
||||
let actions = ['success', 'danger'];
|
||||
|
||||
let notification = new GlobalNotificationModel('this is a test, please ignore', actions[this.state.index]);
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
},
|
||||
|
||||
render() {
|
||||
if(this.props.show) {
|
||||
return (
|
||||
<MenuItem onClick={this.triggerNotification}>Notification</MenuItem>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default HeaderNotificationDebug;
|
@ -5,39 +5,39 @@ import React from 'react';
|
||||
import Button from 'react-bootstrap/lib/Button';
|
||||
import Modal from 'react-bootstrap/lib/Modal';
|
||||
import OverlayMixin from 'react-bootstrap/lib/OverlayMixin';
|
||||
import { getLangText } from '../utils/lang_utils.js'
|
||||
import { getLangText } from '../utils/lang_utils.js';
|
||||
|
||||
let LoginModalHandler = React.createClass({
|
||||
mixins: [OverlayMixin],
|
||||
mixins: [OverlayMixin],
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
isModalOpen: true
|
||||
};
|
||||
},
|
||||
getInitialState() {
|
||||
return {
|
||||
isModalOpen: true
|
||||
};
|
||||
},
|
||||
|
||||
handleToggle() {
|
||||
this.setState({
|
||||
isModalOpen: !this.state.isModalOpen
|
||||
});
|
||||
},
|
||||
handleToggle() {
|
||||
this.setState({
|
||||
isModalOpen: !this.state.isModalOpen
|
||||
});
|
||||
},
|
||||
|
||||
render() {
|
||||
if (!this.state.isModalOpen || !(this.props.query.login === '')) {
|
||||
return <span/>;
|
||||
render() {
|
||||
if(!this.state.isModalOpen || !(this.props.query.login === '')) {
|
||||
return <span/>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal title='Modal heading' onRequestHide={this.handleToggle}>
|
||||
<div className='modal-body'>
|
||||
This modal is controlled by our custom trigger component.
|
||||
</div>
|
||||
<div className='modal-footer'>
|
||||
<Button onClick={this.handleToggle}>{getLangText('Close')}</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal title='Modal heading' onRequestHide={this.handleToggle}>
|
||||
<div className='modal-body'>
|
||||
This modal is controlled by our custom trigger component.
|
||||
</div>
|
||||
<div className='modal-footer'>
|
||||
<Button onClick={this.handleToggle}>{getLangText('Close')}</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default LoginModalHandler;
|
@ -47,6 +47,7 @@ let PieceList = React.createClass({
|
||||
},
|
||||
|
||||
paginationGoToPage(page) {
|
||||
document.body.scrollTop = document.documentElement.scrollTop = 0;
|
||||
return () => PieceListActions.fetchPieceList(page, this.state.pageSize,
|
||||
this.state.search, this.state.orderBy,
|
||||
this.state.orderAsc);
|
||||
@ -84,21 +85,14 @@ let PieceList = React.createClass({
|
||||
pageSize={this.state.pageSize}
|
||||
loadingElement={loadingElement}>
|
||||
{this.state.pieceList.map((piece, i) => {
|
||||
|
||||
let editionsTableForPiece;
|
||||
|
||||
if(piece.num_editions !== 1) {
|
||||
editionsTableForPiece = <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={piece.id} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<AccordionListItem
|
||||
className="col-xs-12 col-sm-10 col-md-8 col-lg-8 col-sm-offset-1 col-md-offset-2 col-lg-offset-2 ascribe-accordion-list-item"
|
||||
content={piece}
|
||||
key={i}>
|
||||
{editionsTableForPiece}
|
||||
<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={piece.id} />
|
||||
</AccordionListItem>
|
||||
);
|
||||
})}
|
||||
|
@ -23,6 +23,8 @@ import GlobalNotificationActions from '../actions/global_notification_actions';
|
||||
|
||||
import Form from './ascribe_forms/form';
|
||||
import Property from './ascribe_forms/property';
|
||||
import PropertyCollapsible from './ascribe_forms/property_collapsible';
|
||||
import FormPropertyHeader from './ascribe_forms/form_property_header';
|
||||
|
||||
import LoginContainer from './login_container';
|
||||
import SlidesContainer from './ascribe_slides_container/slides_container';
|
||||
@ -172,8 +174,8 @@ let RegisterPiece = React.createClass( {
|
||||
onFocus={this.changeSlide}>
|
||||
<Row className="no-margin">
|
||||
<Col xs={12} sm={10} md={8} smOffset={1} mdOffset={2}>
|
||||
<h3 style={{'marginTop': 0, 'marginLeft': '1em'}}>{getLangText('Register your work')}</h3>
|
||||
<Form
|
||||
className="ascribe-form-bordered"
|
||||
ref='form'
|
||||
url={apiUrls.pieces_list}
|
||||
getFormData={this.getFormData}
|
||||
@ -189,6 +191,9 @@ let RegisterPiece = React.createClass( {
|
||||
<img src="https://s3-us-west-2.amazonaws.com/ascribe0/media/thumbnails/ascribe_animated_medium.gif" />
|
||||
</button>
|
||||
}>
|
||||
<FormPropertyHeader>
|
||||
<h3>{getLangText('Register your work')}</h3>
|
||||
</FormPropertyHeader>
|
||||
<Property
|
||||
ignoreFocus={true}>
|
||||
<FileUploader
|
||||
@ -222,8 +227,15 @@ let RegisterPiece = React.createClass( {
|
||||
min={0}
|
||||
required/>
|
||||
</Property>
|
||||
<PropertyCollapsible
|
||||
checkboxLabel={getLangText('Specify editions')}>
|
||||
<span>{getLangText('Editions')}</span>
|
||||
<input
|
||||
type="number"
|
||||
placeholder="(e.g. 32)"
|
||||
min={0}/>
|
||||
</PropertyCollapsible>
|
||||
{this.getLicenses()}
|
||||
<hr />
|
||||
</Form>
|
||||
</Col>
|
||||
</Row>
|
||||
|
@ -131,6 +131,10 @@ let AccountSettings = React.createClass({
|
||||
|
||||
let BitcoinWalletSettings = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
defaultExpanded: React.PropTypes.bool
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return WalletSettingsStore.getState();
|
||||
},
|
||||
@ -172,7 +176,7 @@ let BitcoinWalletSettings = React.createClass({
|
||||
<CollapsibleParagraph
|
||||
title={getLangText('Crypto Wallet')}
|
||||
show={true}
|
||||
defaultExpanded={true}>
|
||||
defaultExpanded={this.props.defaultExpanded}>
|
||||
{content}
|
||||
</CollapsibleParagraph>
|
||||
);
|
||||
@ -180,6 +184,9 @@ let BitcoinWalletSettings = React.createClass({
|
||||
});
|
||||
|
||||
let LoanContractSettings = React.createClass({
|
||||
propTypes: {
|
||||
defaultExpanded: React.PropTypes.bool
|
||||
},
|
||||
|
||||
render() {
|
||||
|
||||
@ -187,7 +194,7 @@ let LoanContractSettings = React.createClass({
|
||||
<CollapsibleParagraph
|
||||
title="Loan Contract Settings"
|
||||
show={true}
|
||||
defaultExpanded={true}>
|
||||
defaultExpanded={this.props.defaultExpanded}>
|
||||
<FileUploader />
|
||||
</CollapsibleParagraph>
|
||||
);
|
||||
@ -249,6 +256,10 @@ let FileUploader = React.createClass({
|
||||
});
|
||||
|
||||
let APISettings = React.createClass({
|
||||
propTypes: {
|
||||
defaultExpanded: React.PropTypes.bool
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return ApplicationStore.getState();
|
||||
},
|
||||
@ -312,7 +323,7 @@ let APISettings = React.createClass({
|
||||
<CollapsibleParagraph
|
||||
title={getLangText('API Integration')}
|
||||
show={true}
|
||||
defaultExpanded={true}>
|
||||
defaultExpanded={this.props.defaultExpanded}>
|
||||
<Form
|
||||
url={apiUrls.applications}
|
||||
handleSuccess={this.handleCreateSuccess}>
|
||||
|
@ -65,7 +65,7 @@ const languages = {
|
||||
'Account': 'Account',
|
||||
'Copyright license%s': 'Copyright license%s',
|
||||
'Files to upload': 'Files to upload',
|
||||
'Lock down title': 'Lock down title',
|
||||
'Register your work': 'Register your work',
|
||||
'Artist Name': 'Artist Name',
|
||||
'The name of the creator': 'The name of the creator',
|
||||
'Number of editions': 'Number of editions',
|
||||
@ -85,8 +85,8 @@ const languages = {
|
||||
'terms of service': 'terms of service',
|
||||
'privacy': 'privacy',
|
||||
'Search%s': 'Search%s',
|
||||
'Hide all Editions' : 'Hide all Editions',
|
||||
'Hide editions' : 'Hide editions',
|
||||
'Hide all Editions': 'Hide all Editions',
|
||||
'Hide editions': 'Hide editions',
|
||||
'Show all Editions': 'Show all Editions',
|
||||
'Show editions': 'Show editions',
|
||||
'Edition': 'Edition',
|
||||
@ -203,6 +203,9 @@ const languages = {
|
||||
'NEW WORK': 'NEW WORK',
|
||||
'Have someone else sell the artwork': 'Have someone else sell the artwork',
|
||||
'Loan History': 'Loan History',
|
||||
'Title': 'Title',
|
||||
'Specify editions': 'Specify editions',
|
||||
'Editions': 'Editions',
|
||||
},
|
||||
'de': {
|
||||
'ID': 'ID',
|
||||
@ -268,7 +271,7 @@ const languages = {
|
||||
'Account': 'Account',
|
||||
'Copyright license%s': 'Copyright license%s',
|
||||
'Files to upload': 'Files to upload',
|
||||
'Lock down title': 'Lock down title',
|
||||
'Register your work': 'Register your work',
|
||||
'Artist Name': 'Artist Name',
|
||||
'The name of the creator': 'The name of the creator',
|
||||
'Number of editions': 'Number of editions',
|
||||
@ -288,8 +291,8 @@ const languages = {
|
||||
'terms of service': 'terms of service',
|
||||
'privacy': 'privacy',
|
||||
'Search%s': 'Search%s',
|
||||
'Hide all Editions' : 'Hide all Editions',
|
||||
'Hide editions' : 'Hide editions',
|
||||
'Hide all Editions': 'Hide all Editions',
|
||||
'Hide editions': 'Hide editions',
|
||||
'Show all Editions': 'Show all Editions',
|
||||
'Show editions': 'Show editions',
|
||||
'Edition': 'Edition',
|
||||
@ -406,6 +409,9 @@ const languages = {
|
||||
'NEW WORK': 'NEW WORK',
|
||||
'Have someone else sell the artwork': 'Have someone else sell the artwork',
|
||||
'Loan History': 'Loan History',
|
||||
'Title': 'Titel',
|
||||
'Specify editions': 'Specify editions',
|
||||
'Editions': 'Editions',
|
||||
},
|
||||
'fr': {
|
||||
'ID': 'ID',
|
||||
@ -471,7 +477,7 @@ const languages = {
|
||||
'Account': 'Compte',
|
||||
'Copyright license%s': 'License de droit d\'auteur%s',
|
||||
'Files to upload': 'Fichiers à télécharger',
|
||||
'Lock down title': 'Verrouillez le titre',
|
||||
'Register your work': 'Verrouillez le titre',
|
||||
'Artist Name': 'Nom de l\'artiste',
|
||||
'The name of the creator': 'Le nom du créateur',
|
||||
'Number of editions': 'Nombre d\'éditions',
|
||||
@ -489,10 +495,10 @@ const languages = {
|
||||
'api': 'api',
|
||||
'impressum': 'impressum',
|
||||
'terms of service': 'conditions d\'utilisation',
|
||||
'privacy': 'confidentialité',
|
||||
'privacy': 'confidentialité',
|
||||
'Search%s': 'Rechercher%s',
|
||||
'Hide all Editions' : 'Cacher toutes les Éditions',
|
||||
'Hide editions' : 'Cacher les éditions',
|
||||
'Hide all Editions': 'Cacher toutes les Éditions',
|
||||
'Hide editions': 'Cacher les éditions',
|
||||
'Show all Editions': 'Montrer toutes les Éditions',
|
||||
'Show editions': 'Montrer les éditions',
|
||||
'Edition': 'Édition',
|
||||
@ -565,7 +571,7 @@ const languages = {
|
||||
'Loan start date': 'Date du commencement du prêt',
|
||||
'Loan end date': 'Date de la fin de prêt',
|
||||
'LOAN': 'PRÊT',
|
||||
'I transfer ownership of': 'Je transfère la propriété de' ,
|
||||
'I transfer ownership of': 'Je transfère la propriété de',
|
||||
'Transferee email': 'Courriel du cessionnaire',
|
||||
'TRANSFER': 'TRANSFÉRER',
|
||||
'Forgot your password': 'Oubliez votre mot de passe',
|
||||
@ -609,6 +615,9 @@ const languages = {
|
||||
'NEW WORK': 'NOUVEL OEUVRE',
|
||||
'Have someone else sell the artwork': 'Demandez à quelqu\'un de vendre l\'oeuvre',
|
||||
'Loan History': 'Historique de Prêts',
|
||||
'Title': 'Title',
|
||||
'Specify editions': 'Specify editions',
|
||||
'Editions': 'Editions',
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -16,6 +16,10 @@ let PieceListFetcher = {
|
||||
|
||||
fetchRequestActions() {
|
||||
return requests.get('pieces_list_request_actions');
|
||||
},
|
||||
|
||||
fetchFirstEditionForPiece(pieceId) {
|
||||
return requests.get('piece_first_edition_id', {'piece_id': pieceId});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -27,26 +27,6 @@ class PieceListStore {
|
||||
this.orderAsc = true;
|
||||
this.bindActions(PieceListActions);
|
||||
}
|
||||
|
||||
/*onShowEditionList(pieceId) {
|
||||
this.pieceList
|
||||
.forEach((piece) => {
|
||||
if(piece.id === pieceId) {
|
||||
if(piece.show) {
|
||||
piece.show = false;
|
||||
} else {
|
||||
piece.show = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}*/
|
||||
|
||||
/*onCloseAllEditionLists() {
|
||||
this.pieceList
|
||||
.forEach((piece) => {
|
||||
piece.show = false;
|
||||
});
|
||||
}*/
|
||||
|
||||
onUpdatePieceList({ page, pageSize, search, pieceList, orderBy, orderAsc, pieceListCount }) {
|
||||
this.page = page;
|
||||
@ -85,11 +65,25 @@ class PieceListStore {
|
||||
|
||||
this.pieceList = pieceList;
|
||||
}
|
||||
|
||||
onUpdatePieceListRequestActions(requestActions) {
|
||||
this.pieceList.forEach((piece) => {
|
||||
piece.requestAction = requestActions.indexOf(piece.id) > -1;
|
||||
});
|
||||
}
|
||||
|
||||
onAddFirstEditionToPiece({pieceId, firstEdition}) {
|
||||
let filteredPieceList = this.pieceList.filter((piece) => piece.id === pieceId);
|
||||
|
||||
if(filteredPieceList.length === 1) {
|
||||
|
||||
let piece = filteredPieceList[0];
|
||||
piece.firstEdition = firstEdition.edition;
|
||||
|
||||
} else {
|
||||
throw new Error('Could not find a matching piece in piece list since its either not there or piecelist contains duplicates.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default alt.createStore(PieceListStore, 'PieceListStore');
|
||||
|
@ -70,11 +70,17 @@ export function formatText() {
|
||||
function _doesObjectListHaveDuplicates(l) {
|
||||
let mergedList = [];
|
||||
|
||||
l = l.map((obj) => Object.keys(obj));
|
||||
l = l.map((obj) => {
|
||||
if(!obj) {
|
||||
throw new Error('The object you are trying to merge is null instead of an empty object');
|
||||
}
|
||||
|
||||
return Object.keys(obj);
|
||||
});
|
||||
|
||||
// Taken from: http://stackoverflow.com/a/10865042
|
||||
// How to flatten an array of arrays in javascript.
|
||||
// If two objects contain the same key, then these two keys
|
||||
// If two objects contain the same key, then these two keys
|
||||
// will actually be represented in the merged array
|
||||
mergedList = mergedList.concat.apply(mergedList, l);
|
||||
|
||||
@ -102,6 +108,7 @@ export function mergeOptions(...l) {
|
||||
for(let i = 1; i < l.length; i++) {
|
||||
newObj = _mergeOptions(newObj, _mergeOptions(l[i - 1], l[i]));
|
||||
}
|
||||
|
||||
return newObj;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
position: fixed;
|
||||
|
||||
background-color: #212121;
|
||||
color: white;
|
||||
width: 100%;
|
||||
height:3.5em;
|
||||
left:0;
|
||||
@ -18,12 +19,48 @@
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.ascribe-global-notification > div {
|
||||
.ascribe-global-notification > div, .ascribe-global-notification-bubble > div {
|
||||
display:table-cell;
|
||||
vertical-align: middle;
|
||||
color: $ascribe-color-full;
|
||||
font-size: 1.25em;
|
||||
font-family: 'Source Sans Pro';
|
||||
text-align: right;
|
||||
padding-right: 3em;
|
||||
}
|
||||
|
||||
.ascribe-global-notification-bubble > div {
|
||||
padding: .75em 1.5em .75em 1.5em;
|
||||
}
|
||||
|
||||
.ascribe-global-notification-bubble {
|
||||
position: fixed;
|
||||
bottom: 3em;
|
||||
right: -50em;
|
||||
|
||||
display:table;
|
||||
|
||||
height: 3.5em;
|
||||
|
||||
background-color: #212121;
|
||||
border-radius: 2px;
|
||||
|
||||
color: white;
|
||||
|
||||
transition: 1s right ease;
|
||||
}
|
||||
|
||||
.ascribe-global-notification-bubble-off {
|
||||
right: -50em;
|
||||
}
|
||||
|
||||
.ascribe-global-notification-bubble-on {
|
||||
right: 3.5em;
|
||||
}
|
||||
|
||||
.ascribe-global-notification-danger {
|
||||
background-color: #d9534f;
|
||||
}
|
||||
|
||||
.ascribe-global-notification-success {
|
||||
background-color: rgba(2, 182, 163, 1);
|
||||
}
|
@ -82,7 +82,7 @@ $ascribe-accordion-list-font: 'Source Sans Pro';
|
||||
thead:first-child {
|
||||
tr:first-child {
|
||||
border: none! important;
|
||||
th{
|
||||
th {
|
||||
padding-left: 10px;
|
||||
border: none! important;
|
||||
}
|
||||
@ -139,4 +139,12 @@ span.ascribe-accordion-list-table-toggle {
|
||||
color: #666;
|
||||
font-size: 1.2em;
|
||||
padding: 0.3em;
|
||||
}
|
||||
|
||||
.ascribe-accordion-list-item-edition-widget {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $ascribe-color-full;
|
||||
}
|
||||
}
|
@ -11,13 +11,12 @@
|
||||
.ascribe-edition-collapsible-wrapper > div:first-child {
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
background-color: #EEE;
|
||||
background-color: #F5F5F5;
|
||||
padding: 10px;
|
||||
border: 1px solid #CCC;
|
||||
|
||||
margin-top: 20px;
|
||||
}
|
||||
.ascribe-edition-collapsible-wrapper > div > span {
|
||||
font-size:1.3em;
|
||||
font-size: 1.2em;
|
||||
margin-right: .5em;
|
||||
}
|
||||
.ascribe-edition-collapsible-wrapper > div > span:nth-child(2) {
|
||||
@ -26,8 +25,6 @@
|
||||
|
||||
.ascribe-edition-collapible-content {
|
||||
width:100%;
|
||||
margin-top: 1em;
|
||||
|
||||
}
|
||||
|
||||
.coa-file-wrapper{
|
||||
@ -44,4 +41,8 @@
|
||||
vertical-align: middle;
|
||||
border: 1px solid #CCC;
|
||||
background-color: #F8F8F8;
|
||||
}
|
||||
|
||||
.ascribe-button-list {
|
||||
margin-top: 1em;
|
||||
}
|
16
sass/ascribe_form.scss
Normal file
16
sass/ascribe_form.scss
Normal file
@ -0,0 +1,16 @@
|
||||
.ascribe-form-bordered {
|
||||
border: 1px solid #F5F5F5;
|
||||
}
|
||||
|
||||
.ascribe-form-header {
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.ascribe-form-header > h3 {
|
||||
padding: .75em 0 .75em 1em;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
color: #616161;
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
text-align: center;
|
||||
padding-bottom: 1em;
|
||||
|
||||
background-color: rgba(0,0,0,0);
|
||||
background-color: white;
|
||||
|
||||
border-left: 3px solid rgba(0,0,0,0);
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
.is-focused {
|
||||
background-color: rgba(2, 182, 163, 0.05);
|
||||
border-left: 3px solid rgba(2, 182, 163, 1)!important;
|
||||
border-left: 3px solid rgba(2, 182, 163, 1) !important;
|
||||
}
|
||||
|
||||
.is-error {
|
||||
@ -128,8 +128,67 @@
|
||||
}
|
||||
}
|
||||
|
||||
.ascribe-property-footer{
|
||||
.ascribe-property-footer {
|
||||
font-size: 0.8em;
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ascribe-settings-property-collapsible-toggle {
|
||||
text-align: left;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
border-top: 1px solid rgba(0,0,0,.05);
|
||||
|
||||
padding: .5em 1.5em .5em 1.5em;
|
||||
|
||||
cursor:pointer;
|
||||
|
||||
/* Taken from: http://www.htmllion.com/css3-checkbox.html */
|
||||
.checkbox {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-weight: normal;
|
||||
font-size: .9em;
|
||||
color: rgba(0, 0, 0, .5);
|
||||
vertical-align:middle;
|
||||
|
||||
span {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
left: 5px;
|
||||
|
||||
&:hover {
|
||||
color: rgba(2, 182, 163, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input[type=checkbox] {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.checkbox:before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
vertical-align:middle;
|
||||
background-color: white;
|
||||
color: #f3f3f3;
|
||||
text-align: center;
|
||||
|
||||
border-radius: 1px;
|
||||
border: 1px solid rgba(0, 0, 0, .5);
|
||||
}
|
||||
|
||||
input[type=checkbox]:checked + .checkbox:before {
|
||||
line-height: .8;
|
||||
|
||||
content: "\2713";
|
||||
font-size: 20px;
|
||||
color: rgba(2, 182, 163, 1);
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
.ascribe-table {
|
||||
margin-bottom:0;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
/*This is aligning the first checkbox in pieclist detail with all the other ones*/
|
||||
@ -8,6 +9,10 @@
|
||||
}
|
||||
|
||||
|
||||
.table > thead > tr > th {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.ascribe-table-header-column > span {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
@ -32,7 +37,7 @@
|
||||
}
|
||||
|
||||
.ascribe-table-item-column > span > input {
|
||||
margin-top:16px;
|
||||
margin-top:18px;
|
||||
}
|
||||
|
||||
.ascribe-table-item-selected {
|
||||
|
@ -4,7 +4,7 @@
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
height: auto;
|
||||
background-color: #FAFAFA;
|
||||
background-color: #FEFEFE;
|
||||
overflow: auto;
|
||||
margin-top: 1em;
|
||||
|
||||
|
@ -26,6 +26,7 @@ $BASE_URL: '<%= BASE_URL %>';
|
||||
@import 'offset_right';
|
||||
@import 'ascribe_settings';
|
||||
@import 'ascribe_slides_container';
|
||||
@import 'ascribe_form';
|
||||
|
||||
body {
|
||||
background-color: #FDFDFD;
|
||||
@ -37,6 +38,10 @@ html {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
@ -187,10 +192,6 @@ html {
|
||||
background-color: rgba(2, 182, 163, 0.5);
|
||||
}
|
||||
|
||||
.ascribe-detail-header {
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
.ascribe-detail-title {
|
||||
font-size: 2em;
|
||||
margin-bottom: -0.2em;
|
||||
|
Loading…
Reference in New Issue
Block a user