mirror of
https://github.com/ascribe/onion.git
synced 2024-12-22 17:33:14 +01:00
Merge remote-tracking branch 'remotes/origin/AD-456-ikonotv-branded-page-for-registra' into AD-943-add-custom-additional-fields
Conflicts: js/components/signup_container.js js/components/whitelabel/wallet/components/ikonotv/ikonotv_landing.js
This commit is contained in:
commit
9bfd50e3bc
@ -21,7 +21,7 @@ let AccordionList = React.createClass({
|
||||
);
|
||||
} else if(this.props.count === 0) {
|
||||
return (
|
||||
<div>
|
||||
<div className="ascribe-accordion-list-placeholder">
|
||||
<p className="text-center">{getLangText('We could not find any works related to you...')}</p>
|
||||
<p className="text-center">{getLangText('To register one, click')} <a href="register_piece">{getLangText('here')}</a>!</p>
|
||||
</div>
|
||||
|
@ -137,7 +137,7 @@ let RegisterPieceForm = React.createClass({
|
||||
<input
|
||||
type="number"
|
||||
placeholder="(e.g. 1962)"
|
||||
min={0}
|
||||
min={1}
|
||||
required/>
|
||||
</Property>
|
||||
{this.props.children}
|
||||
|
@ -14,7 +14,20 @@ let PieceListToolbar = React.createClass({
|
||||
propTypes: {
|
||||
className: React.PropTypes.string,
|
||||
searchFor: React.PropTypes.func,
|
||||
filterParams: React.PropTypes.array,
|
||||
filterParams: React.PropTypes.arrayOf(
|
||||
React.PropTypes.shape({
|
||||
label: React.PropTypes.string,
|
||||
items: React.PropTypes.arrayOf(
|
||||
React.PropTypes.oneOfType([
|
||||
React.PropTypes.string,
|
||||
React.PropTypes.shape({
|
||||
key: React.PropTypes.string,
|
||||
label: React.PropTypes.string
|
||||
})
|
||||
])
|
||||
)
|
||||
})
|
||||
),
|
||||
filterBy: React.PropTypes.object,
|
||||
applyFilterBy: React.PropTypes.func,
|
||||
orderParams: React.PropTypes.array,
|
||||
|
@ -3,20 +3,26 @@
|
||||
import React from 'react';
|
||||
|
||||
import DropdownButton from 'react-bootstrap/lib/DropdownButton';
|
||||
import MenuItem from 'react-bootstrap/lib/MenuItem';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils.js';
|
||||
|
||||
|
||||
let PieceListToolbarFilterWidgetFilter = React.createClass({
|
||||
propTypes: {
|
||||
// An array of either strings (which represent acl enums) or objects of the form
|
||||
//
|
||||
// {
|
||||
// key: <acl enum>,
|
||||
// label: <a human readable string>
|
||||
// }
|
||||
//
|
||||
filterParams: React.PropTypes.arrayOf(React.PropTypes.any).isRequired,
|
||||
filterParams: React.PropTypes.arrayOf(
|
||||
React.PropTypes.shape({
|
||||
label: React.PropTypes.string,
|
||||
items: React.PropTypes.arrayOf(
|
||||
React.PropTypes.oneOfType([
|
||||
React.PropTypes.string,
|
||||
React.PropTypes.shape({
|
||||
key: React.PropTypes.string,
|
||||
label: React.PropTypes.string
|
||||
})
|
||||
])
|
||||
)
|
||||
})
|
||||
).isRequired,
|
||||
filterBy: React.PropTypes.object,
|
||||
applyFilterBy: React.PropTypes.func
|
||||
},
|
||||
@ -79,35 +85,53 @@ let PieceListToolbarFilterWidgetFilter = React.createClass({
|
||||
<DropdownButton
|
||||
title={filterIcon}
|
||||
className="ascribe-piece-list-toolbar-filter-widget">
|
||||
<li style={{'textAlign': 'center'}}>
|
||||
<em>{getLangText('Show works I can')}:</em>
|
||||
</li>
|
||||
{this.props.filterParams.map((param, i) => {
|
||||
let label;
|
||||
|
||||
if(typeof param !== 'string') {
|
||||
label = param.label;
|
||||
param = param.key;
|
||||
} else {
|
||||
param = param;
|
||||
label = param.split('_')[1];
|
||||
}
|
||||
|
||||
{/* We iterate over filterParams, to receive the label and then for each
|
||||
label also iterate over its items, to get all filterable options */}
|
||||
{this.props.filterParams.map(({ label, items }, i) => {
|
||||
return (
|
||||
<MenuItem
|
||||
key={i}
|
||||
onClick={this.filterBy(param)}
|
||||
className="filter-widget-item">
|
||||
<div className="checkbox-line">
|
||||
<span>
|
||||
{getLangText(label)}
|
||||
</span>
|
||||
<input
|
||||
readOnly
|
||||
type="checkbox"
|
||||
checked={this.props.filterBy[param]} />
|
||||
</div>
|
||||
</MenuItem>
|
||||
<div>
|
||||
<li
|
||||
style={{'textAlign': 'center'}}
|
||||
key={i}>
|
||||
<em>{label}:</em>
|
||||
</li>
|
||||
{items.map((param, j) => {
|
||||
|
||||
// As can be seen in the PropTypes, a param can either
|
||||
// be a string or an object of the shape:
|
||||
//
|
||||
// {
|
||||
// key: <String>,
|
||||
// label: <String>
|
||||
// }
|
||||
//
|
||||
// This is why we need to distinguish between both here.
|
||||
if(typeof param !== 'string') {
|
||||
label = param.label;
|
||||
param = param.key;
|
||||
} else {
|
||||
param = param;
|
||||
label = param.split('acl_')[1].replace(/_/g, ' ');
|
||||
}
|
||||
|
||||
return (
|
||||
<li
|
||||
key={j}
|
||||
onClick={this.filterBy(param)}
|
||||
className="filter-widget-item">
|
||||
<div className="checkbox-line">
|
||||
<span>
|
||||
{getLangText(label)}
|
||||
</span>
|
||||
<input
|
||||
readOnly
|
||||
type="checkbox"
|
||||
checked={this.props.filterBy[param]} />
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</DropdownButton>
|
||||
|
@ -2,9 +2,6 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import UserStore from '../../stores/user_store';
|
||||
import UserActions from '../../actions/user_actions';
|
||||
|
||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||
|
||||
@ -21,38 +18,26 @@ import AppConstants from '../../constants/application_constants';
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
let AccountSettings = React.createClass({
|
||||
getInitialState() {
|
||||
return UserStore.getState();
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
UserStore.listen(this.onChange);
|
||||
UserActions.fetchCurrentUser();
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
UserStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
propTypes: {
|
||||
currentUser: React.PropTypes.object.required,
|
||||
loadUser: React.PropTypes.func.required
|
||||
},
|
||||
|
||||
handleSuccess(){
|
||||
UserActions.fetchCurrentUser();
|
||||
this.props.loadUser();
|
||||
let notification = new GlobalNotificationModel(getLangText('Settings succesfully updated'), 'success', 5000);
|
||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||
},
|
||||
|
||||
getFormDataProfile(){
|
||||
return {'email': this.state.currentUser.email};
|
||||
return {'email': this.props.currentUser.email};
|
||||
},
|
||||
|
||||
render() {
|
||||
let content = <img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />;
|
||||
let profile = null;
|
||||
|
||||
if (this.state.currentUser.username) {
|
||||
if (this.props.currentUser.username) {
|
||||
content = (
|
||||
<Form
|
||||
url={ApiUrls.users_username}
|
||||
@ -62,7 +47,7 @@ let AccountSettings = React.createClass({
|
||||
label={getLangText('Username')}>
|
||||
<input
|
||||
type="text"
|
||||
defaultValue={this.state.currentUser.username}
|
||||
defaultValue={this.props.currentUser.username}
|
||||
placeholder={getLangText('Enter your username')}
|
||||
required/>
|
||||
</Property>
|
||||
@ -72,7 +57,7 @@ let AccountSettings = React.createClass({
|
||||
editable={false}>
|
||||
<input
|
||||
type="text"
|
||||
defaultValue={this.state.currentUser.email}
|
||||
defaultValue={this.props.currentUser.email}
|
||||
placeholder={getLangText('Enter your username')}
|
||||
required/>
|
||||
</Property>
|
||||
@ -89,7 +74,7 @@ let AccountSettings = React.createClass({
|
||||
className="ascribe-settings-property-collapsible-toggle"
|
||||
style={{paddingBottom: 0}}>
|
||||
<InputCheckbox
|
||||
defaultChecked={this.state.currentUser.profile.hash_locally}>
|
||||
defaultChecked={this.props.currentUser.profile.hash_locally}>
|
||||
<span>
|
||||
{' ' + getLangText('Enable hash option, e.g. slow connections or to keep piece private')}
|
||||
</span>
|
||||
|
@ -14,11 +14,14 @@ import ContractSettingsUpdateButton from './contract_settings_update_button';
|
||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||
|
||||
import AclProxy from '../acl_proxy';
|
||||
|
||||
import { getLangText } from '../../utils/lang_utils';
|
||||
|
||||
|
||||
let ContractSettings = React.createClass({
|
||||
propTypes: {
|
||||
currentUser: React.PropTypes.object,
|
||||
defaultExpanded: React.PropTypes.bool
|
||||
},
|
||||
|
||||
@ -72,87 +75,93 @@ let ContractSettings = React.createClass({
|
||||
<CreateContractForm
|
||||
isPublic={true}
|
||||
fileClassToUpload={{
|
||||
singular: 'new public contract',
|
||||
plural: 'new public contracts'
|
||||
singular: 'new contract',
|
||||
plural: 'new contracts'
|
||||
}}/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<CollapsibleParagraph
|
||||
title={getLangText('Contracts')}
|
||||
show={true}
|
||||
defaultExpanded={true}>
|
||||
<AclProxy
|
||||
aclName="acl_view_contract_settings"
|
||||
aclObject={this.props.currentUser.acl}>
|
||||
<CollapsibleParagraph
|
||||
title={getLangText('Public Contracts')}
|
||||
title={getLangText('Contracts')}
|
||||
show={true}
|
||||
defaultExpanded={true}>
|
||||
{createPublicContractForm}
|
||||
{publicContracts.map((contract, i) => {
|
||||
return (
|
||||
<ActionPanel
|
||||
key={i}
|
||||
title={contract.name}
|
||||
content={contract.name}
|
||||
buttons={
|
||||
<div className="pull-right">
|
||||
<ContractSettingsUpdateButton contract={contract}/>
|
||||
<a
|
||||
className="btn btn-default btn-sm margin-left-2px"
|
||||
href={contract.blob.url_safe}
|
||||
target="_blank">
|
||||
{getLangText('PREVIEW')}
|
||||
</a>
|
||||
<button
|
||||
className="btn btn-default btn-sm margin-left-2px"
|
||||
onClick={this.removeContract(contract)}>
|
||||
{getLangText('REMOVE')}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
leftColumnWidth="40%"
|
||||
rightColumnWidth="60%"/>
|
||||
);
|
||||
})}
|
||||
defaultExpanded={false}>
|
||||
<AclProxy
|
||||
aclName="acl_edit_public_contract"
|
||||
aclObject={this.props.currentUser.acl}>
|
||||
<div>
|
||||
{createPublicContractForm}
|
||||
{publicContracts.map((contract, i) => {
|
||||
return (
|
||||
<ActionPanel
|
||||
key={i}
|
||||
title={contract.name}
|
||||
content={contract.name}
|
||||
buttons={
|
||||
<div className="pull-right">
|
||||
<ContractSettingsUpdateButton contract={contract}/>
|
||||
<a
|
||||
className="btn btn-default btn-sm margin-left-2px"
|
||||
href={contract.blob.url_safe}
|
||||
target="_blank">
|
||||
{getLangText('PREVIEW')}
|
||||
</a>
|
||||
<button
|
||||
className="btn btn-danger btn-sm margin-left-2px"
|
||||
onClick={this.removeContract(contract)}>
|
||||
{getLangText('REMOVE')}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
leftColumnWidth="40%"
|
||||
rightColumnWidth="60%"/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</AclProxy>
|
||||
<AclProxy
|
||||
aclName="acl_edit_private_contract"
|
||||
aclObject={this.props.currentUser.acl}>
|
||||
<div>
|
||||
<CreateContractForm
|
||||
isPublic={false}
|
||||
fileClassToUpload={{
|
||||
singular: getLangText('new contract'),
|
||||
plural: getLangText('new contracts')
|
||||
}}/>
|
||||
{privateContracts.map((contract, i) => {
|
||||
return (
|
||||
<ActionPanel
|
||||
key={i}
|
||||
title={contract.name}
|
||||
content={contract.name}
|
||||
buttons={
|
||||
<div className="pull-right">
|
||||
<ContractSettingsUpdateButton contract={contract} />
|
||||
<a
|
||||
className="btn btn-default btn-sm margin-left-2px"
|
||||
href={contract.blob.url_safe}
|
||||
target="_blank">
|
||||
{getLangText('PREVIEW')}
|
||||
</a>
|
||||
<button
|
||||
className="btn btn-danger btn-sm margin-left-2px"
|
||||
onClick={this.removeContract(contract)}>
|
||||
{getLangText('REMOVE')}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
leftColumnWidth="40%"
|
||||
rightColumnWidth="60%"/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</AclProxy>
|
||||
</CollapsibleParagraph>
|
||||
<CollapsibleParagraph
|
||||
title={getLangText('Private Contracts')}
|
||||
show={true}
|
||||
defaultExpanded={true}>
|
||||
<CreateContractForm
|
||||
isPublic={false}
|
||||
fileClassToUpload={{
|
||||
singular: getLangText('new private contract'),
|
||||
plural: getLangText('new private contracts')
|
||||
}}/>
|
||||
{privateContracts.map((contract, i) => {
|
||||
return (
|
||||
<ActionPanel
|
||||
key={i}
|
||||
title={contract.name}
|
||||
content={contract.name}
|
||||
buttons={
|
||||
<div className="pull-right">
|
||||
<ContractSettingsUpdateButton contract={contract} />
|
||||
<a
|
||||
className="btn btn-default btn-sm margin-left-2px"
|
||||
href={contract.blob.url_safe}
|
||||
target="_blank">
|
||||
{getLangText('PREVIEW')}
|
||||
</a>
|
||||
<button
|
||||
className="btn btn-default btn-sm margin-left-2px"
|
||||
onClick={this.removeContract(contract)}>
|
||||
{getLangText('REMOVE')}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
leftColumnWidth="40%"
|
||||
rightColumnWidth="60%"/>
|
||||
);
|
||||
})}
|
||||
</CollapsibleParagraph>
|
||||
</CollapsibleParagraph>
|
||||
</AclProxy>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -3,6 +3,9 @@
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
|
||||
import UserStore from '../../stores/user_store';
|
||||
import UserActions from '../../actions/user_actions';
|
||||
|
||||
import AccountSettings from './account_settings';
|
||||
import BitcoinWalletSettings from './bitcoin_wallet_settings';
|
||||
import ContractSettings from './contract_settings';
|
||||
@ -18,14 +21,35 @@ let SettingsContainer = React.createClass({
|
||||
|
||||
mixins: [Router.Navigation],
|
||||
|
||||
getInitialState() {
|
||||
return UserStore.getState();
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
UserStore.listen(this.onChange);
|
||||
UserActions.fetchCurrentUser();
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
UserStore.unlisten(this.onChange);
|
||||
},
|
||||
|
||||
loadUser(){
|
||||
UserActions.fetchCurrentUser();
|
||||
},
|
||||
|
||||
onChange(state) {
|
||||
this.setState(state);
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="settings-container">
|
||||
<AccountSettings />
|
||||
<AccountSettings currentUser={this.state.currentUser} loadUser={this.loadUser}/>
|
||||
{this.props.children}
|
||||
<APISettings />
|
||||
<BitcoinWalletSettings />
|
||||
<ContractSettings />
|
||||
<ContractSettings currentUser={this.state.currentUser} loadUser={this.loadUser}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ import AccordionListItemTableEditions from './ascribe_accordion_list/accordion_l
|
||||
|
||||
import Pagination from './ascribe_pagination/pagination';
|
||||
|
||||
import PieceListFilterDisplay from './piece_list_filter_display';
|
||||
|
||||
import GlobalAction from './global_action';
|
||||
import PieceListBulkModal from './ascribe_piece_list_bulk_modal/piece_list_bulk_modal';
|
||||
import PieceListToolbar from './ascribe_piece_list_toolbar/piece_list_toolbar';
|
||||
@ -22,6 +24,8 @@ import PieceListToolbar from './ascribe_piece_list_toolbar/piece_list_toolbar';
|
||||
import AppConstants from '../constants/application_constants';
|
||||
|
||||
import { mergeOptions } from '../utils/general_utils';
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
|
||||
|
||||
let PieceList = React.createClass({
|
||||
propTypes: {
|
||||
@ -31,7 +35,6 @@ let PieceList = React.createClass({
|
||||
filterParams: React.PropTypes.array,
|
||||
orderParams: React.PropTypes.array,
|
||||
orderBy: React.PropTypes.string
|
||||
|
||||
},
|
||||
|
||||
mixins: [Router.Navigation, Router.State],
|
||||
@ -40,13 +43,14 @@ let PieceList = React.createClass({
|
||||
return {
|
||||
accordionListItemType: AccordionListItemWallet,
|
||||
orderParams: ['artist_name', 'title'],
|
||||
filterParams: [
|
||||
'acl_transfer',
|
||||
'acl_consign',
|
||||
{
|
||||
key: 'acl_create_editions',
|
||||
label: 'create editions'
|
||||
}]
|
||||
filterParams: [{
|
||||
label: getLangText('Show works I can'),
|
||||
items: [
|
||||
'acl_transfer',
|
||||
'acl_consign',
|
||||
'acl_create_editions'
|
||||
]
|
||||
}]
|
||||
};
|
||||
},
|
||||
getInitialState() {
|
||||
@ -91,8 +95,8 @@ let PieceList = React.createClass({
|
||||
// the site should go to the top
|
||||
document.body.scrollTop = document.documentElement.scrollTop = 0;
|
||||
PieceListActions.fetchPieceList(page, this.state.pageSize, this.state.search,
|
||||
this.state.orderBy, this.state.orderAsc,
|
||||
this.state.filterBy);
|
||||
this.state.orderBy, this.state.orderAsc,
|
||||
this.state.filterBy);
|
||||
};
|
||||
},
|
||||
|
||||
@ -149,9 +153,6 @@ let PieceList = React.createClass({
|
||||
let loadingElement = (<img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} />);
|
||||
let AccordionListItemType = this.props.accordionListItemType;
|
||||
|
||||
//<GlobalAction requestActions={this.state.requestActions} />
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PieceListToolbar
|
||||
@ -166,6 +167,9 @@ let PieceList = React.createClass({
|
||||
{this.props.customSubmitButton}
|
||||
</PieceListToolbar>
|
||||
<PieceListBulkModal className="ascribe-piece-list-bulk-modal" />
|
||||
<PieceListFilterDisplay
|
||||
filterBy={this.state.filterBy}
|
||||
filterParams={this.props.filterParams}/>
|
||||
<AccordionList
|
||||
className="ascribe-accordion-list"
|
||||
changeOrder={this.accordionChangeOrder}
|
||||
|
118
js/components/piece_list_filter_display.js
Normal file
118
js/components/piece_list_filter_display.js
Normal file
@ -0,0 +1,118 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
|
||||
let PieceListFilterDisplay = React.createClass({
|
||||
propTypes: {
|
||||
filterBy: React.PropTypes.object,
|
||||
filterParams: React.PropTypes.arrayOf(
|
||||
React.PropTypes.shape({
|
||||
label: React.PropTypes.string,
|
||||
items: React.PropTypes.arrayOf(
|
||||
React.PropTypes.oneOfType([
|
||||
React.PropTypes.string,
|
||||
React.PropTypes.shape({
|
||||
key: React.PropTypes.string,
|
||||
label: React.PropTypes.string
|
||||
})
|
||||
])
|
||||
)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
/**
|
||||
* Takes the above described filterParams prop,
|
||||
* assigns it it's true filterBy value that is derived from the filterBy prop
|
||||
* and also - if there wasn't already one defined - generates a label
|
||||
* @return {object}
|
||||
*/
|
||||
transformFilterParamsItemsToBools() {
|
||||
let { filterParams, filterBy } = this.props;
|
||||
|
||||
return filterParams.map((filterParam) => {
|
||||
return {
|
||||
label: filterParam.label,
|
||||
items: filterParam.items.map((item) => {
|
||||
if(typeof item !== 'string' && typeof item.key === 'string' && typeof item.label === 'string') {
|
||||
return {
|
||||
key: item.key,
|
||||
label: item.label,
|
||||
value: filterBy[item.key] || false
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
key: item,
|
||||
label: item.split('acl_')[1].replace(/_/g, ' '),
|
||||
value: filterBy[item] || false
|
||||
};
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Takes the list of filters generated in transformFilterParamsItemsToBools and
|
||||
* transforms them into human readable text.
|
||||
* @param {Object} filtersWithLabel An object of the shape {key: <String>, label: <String>, value: <Bool>}
|
||||
* @return {string} A human readable string
|
||||
*/
|
||||
getFilterText(filtersWithLabel) {
|
||||
let filterTextList = filtersWithLabel
|
||||
// Iterate over all provided filterLabels and generate a list
|
||||
// of human readable strings
|
||||
.map((filterWithLabel) => {
|
||||
let activeFilterWithLabel = filterWithLabel
|
||||
.items
|
||||
// If the filter is active (which it is when its value is true),
|
||||
// we're going to include it's label into a list,
|
||||
// otherwise we'll just return nothing
|
||||
.map((filter) => {
|
||||
if(filter.value) {
|
||||
return filter.label;
|
||||
}
|
||||
})
|
||||
// if nothing is returned, that index is 'undefined'.
|
||||
// As we only want active filter, we filter out all falsy values e.g. undefined
|
||||
.filter((filterName) => !!filterName)
|
||||
// and join the result to a string
|
||||
.join(', ');
|
||||
|
||||
// If this actually didn't generate an empty string,
|
||||
// we take the label and concat it to the result.
|
||||
if(activeFilterWithLabel) {
|
||||
return filterWithLabel.label + ': ' + activeFilterWithLabel;
|
||||
}
|
||||
})
|
||||
// filter out strings that are undefined, as their filter's were not activated
|
||||
.filter((filterText) => !!filterText)
|
||||
// if there are multiple sentences, capitalize the first one and lowercase the others
|
||||
.map((filterText, i) => i === 0 ? filterText.charAt(0).toUpperCase() + filterText.substr(1) : filterText.charAt(0).toLowerCase() + filterText.substr(1))
|
||||
.join(' and ');
|
||||
|
||||
return filterTextList;
|
||||
},
|
||||
|
||||
render() {
|
||||
let { filterBy } = this.props;
|
||||
let filtersWithLabel = this.transformFilterParamsItemsToBools();
|
||||
|
||||
// do not show the FilterDisplay if there are no filters applied
|
||||
if(filterBy && Object.keys(filterBy).length === 0) {
|
||||
return null;
|
||||
} else {
|
||||
return (
|
||||
<div className="row">
|
||||
<div className="ascribe-piece-list-filter-display col-xs-12 col-sm-10 col-md-8 col-lg-8 col-sm-offset-1 col-md-offset-2 col-lg-offset-2">
|
||||
{this.getFilterText(filtersWithLabel)}
|
||||
<hr />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default PieceListFilterDisplay;
|
@ -2,6 +2,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import Router from 'react-router';
|
||||
|
||||
import SignupForm from './ascribe_forms/form_signup';
|
||||
|
||||
import { getLangText } from '../utils/lang_utils';
|
||||
@ -39,7 +40,6 @@ let SignupContainer = React.createClass({
|
||||
<SignupForm handleSuccess={this.handleSuccess} />
|
||||
<div className="ascribe-login-text">
|
||||
{getLangText('Already an ascribe user')}? <Link to="login">{getLangText('Log in')}...</Link><br/>
|
||||
{getLangText('Forgot my password')}? <Link to="password_reset">{getLangText('Rescue me')}...</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -27,7 +27,7 @@ let PrizeApp = React.createClass({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container ascribe-prize-app">
|
||||
<div className={'container ascribe-prize-app client--' + subdomain}>
|
||||
{header}
|
||||
<RouteHandler />
|
||||
<GlobalNotification />
|
||||
|
@ -8,6 +8,8 @@ import UserStore from '../../../../../stores/user_store';
|
||||
|
||||
import CylandAccordionListItem from './ascribe_accordion_list/cyland_accordion_list_item';
|
||||
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
|
||||
|
||||
let CylandPieceList = React.createClass({
|
||||
getInitialState() {
|
||||
@ -33,6 +35,13 @@ let CylandPieceList = React.createClass({
|
||||
<PieceList
|
||||
redirectTo="register_piece"
|
||||
accordionListItemType={CylandAccordionListItem}
|
||||
filterParams={[{
|
||||
label: getLangText('Show works I have'),
|
||||
items: [{
|
||||
key: 'acl_loaned',
|
||||
label: getLangText('loaned to Cyland')
|
||||
}]
|
||||
}]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -41,7 +41,7 @@ let IkonotvLanding = React.createClass({
|
||||
}
|
||||
return (
|
||||
<ButtonLink to={redirect} query={this.getQuery()}>
|
||||
{getLangText('ENTER')}
|
||||
{getLangText('ENTER TO START')}
|
||||
</ButtonLink>
|
||||
);
|
||||
},
|
||||
@ -53,11 +53,13 @@ let IkonotvLanding = React.createClass({
|
||||
<img src="https://s3-us-west-2.amazonaws.com/ascribe0/whitelabel/ikonotv/ikono_tv.png" />
|
||||
<div className="tagline">
|
||||
<h1>PROTECT</h1>
|
||||
<img src="http://placehold.it/600x300" />
|
||||
<div className="poster">
|
||||
<div className="content">
|
||||
</div>
|
||||
</div>
|
||||
<h1>& SHARE</h1>
|
||||
</div>
|
||||
<h2>Welcome to the ikonoTV</h2>
|
||||
<h2>Registration Page</h2>
|
||||
<h2>Welcome to the ikonoTV<br />Registration Page</h2>
|
||||
</header>
|
||||
<article>
|
||||
<section>
|
||||
@ -104,4 +106,4 @@ let IkonotvLanding = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
export default IkonotvLanding;
|
||||
export default IkonotvLanding;
|
||||
|
@ -8,6 +8,9 @@ import UserStore from '../../../../../stores/user_store';
|
||||
|
||||
import IkonotvAccordionListItem from './ascribe_accordion_list/ikonotv_accordion_list_item';
|
||||
|
||||
import { getLangText } from '../../../../../utils/lang_utils';
|
||||
|
||||
|
||||
let IkonotvPieceList = React.createClass({
|
||||
getInitialState() {
|
||||
return UserStore.getState();
|
||||
@ -32,7 +35,13 @@ let IkonotvPieceList = React.createClass({
|
||||
<PieceList
|
||||
redirectTo="register_piece"
|
||||
accordionListItemType={IkonotvAccordionListItem}
|
||||
/>
|
||||
filterParams={[{
|
||||
label: getLangText('Show works I have'),
|
||||
items: [{
|
||||
key: 'acl_loaned',
|
||||
label: getLangText('loaned to IkonoTV')
|
||||
}]
|
||||
}]}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -8,15 +8,19 @@ import Footer from '../../footer';
|
||||
import GlobalNotification from '../../global_notification';
|
||||
|
||||
import getRoutes from './wallet_routes';
|
||||
import classNames from 'classnames';
|
||||
|
||||
|
||||
let RouteHandler = Router.RouteHandler;
|
||||
|
||||
|
||||
let WalletApp = React.createClass({
|
||||
mixins: [Router.State],
|
||||
|
||||
render() {
|
||||
let subdomain = window.location.host.split('.')[0];
|
||||
let ROUTES = getRoutes(null, subdomain);
|
||||
let activeRoutes = this.getRoutes().map(elem => 'route--' + elem.name);
|
||||
|
||||
let header = null;
|
||||
if ((this.isActive('landing') || this.isActive('login') || this.isActive('signup') || this.isActive('contract_notifications'))
|
||||
@ -28,12 +32,14 @@ let WalletApp = React.createClass({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container ascribe-prize-app">
|
||||
{header}
|
||||
<RouteHandler />
|
||||
<GlobalNotification />
|
||||
<div id="modal" className="container"></div>
|
||||
<Footer />
|
||||
<div className={classNames('ascribe-wallet-app', 'client--' + subdomain, activeRoutes)}>
|
||||
<div className='container'>
|
||||
{header}
|
||||
<RouteHandler />
|
||||
<GlobalNotification />
|
||||
<div id="modal" className="container"></div>
|
||||
<Footer />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -5,6 +5,10 @@ $ascribe-accordion-list-item-height: 8em;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.ascribe-accordion-list-placeholder {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.ascribe-accordion-list-item {
|
||||
background-color: white;
|
||||
border: 1px solid black;
|
||||
|
@ -54,8 +54,7 @@
|
||||
}
|
||||
|
||||
.filter-widget-item {
|
||||
|
||||
> a {
|
||||
a {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
@ -64,6 +63,13 @@
|
||||
.checkbox-line {
|
||||
height: 25px;
|
||||
position: relative;
|
||||
color: #333333;
|
||||
|
||||
/* Fuck you react-bootstrap */
|
||||
&:hover {
|
||||
background-color: $dropdown-link-hover-bg;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
span {
|
||||
cursor: pointer;
|
||||
|
@ -487,3 +487,23 @@ hr {
|
||||
.ascribe-progress-bar-xs {
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
|
||||
.ascribe-piece-list-filter-display {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
|
||||
> span {
|
||||
font-size: 1.1em;
|
||||
font-weight: 600;
|
||||
color: #616161;
|
||||
|
||||
padding-left: .3em;
|
||||
}
|
||||
|
||||
> hr {
|
||||
margin-top: .15em;
|
||||
margin-bottom: .1em;
|
||||
border-color: #ccc;
|
||||
}
|
||||
}
|
@ -1,2 +1,3 @@
|
||||
@import 'prize/index';
|
||||
@import 'wallet/ikonotv/ikonotv_landing';
|
||||
@import 'wallet/index';
|
||||
@import 'wallet/ikonotv/ikonotv_landing';
|
||||
|
@ -1,11 +1,117 @@
|
||||
.client--ikonotv {
|
||||
font-family: 'Helvetica Neue', 'Helvetica', sans-serif;
|
||||
}
|
||||
|
||||
.client--ikonotv.route--landing {
|
||||
background-color: #c40050;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
padding: 5em 1em;
|
||||
}
|
||||
|
||||
|
||||
.client--ikonotv.route--login,
|
||||
.client--ikonotv.route--signup {
|
||||
background-color: #c40050;
|
||||
|
||||
.ascribe-btn-login {
|
||||
display: block;
|
||||
margin: 50px auto 0;
|
||||
width: auto;
|
||||
padding: 10px 30px;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.ascribe-btn-login-spinner {
|
||||
background-color: #02b6a3;
|
||||
}
|
||||
|
||||
.ascribe-form-header {
|
||||
background-image: url(https://s3-us-west-2.amazonaws.com/ascribe0/whitelabel/ikonotv/ikono_tv.png);
|
||||
background-color: transparent;
|
||||
background-position: center 0;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 300px;
|
||||
margin-bottom: 30px;
|
||||
height: 150px;
|
||||
position: relative;
|
||||
|
||||
h3 {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
color: white;
|
||||
text-align: center;
|
||||
font-size: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.ascribe-settings-wrapper {
|
||||
background-color: transparent;
|
||||
|
||||
&:hover {
|
||||
border-left: 3px solid transparent;
|
||||
}
|
||||
|
||||
&.is-focused {
|
||||
border-left: 3px solid transparent !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ascribe-settings-property {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.ascribe-settings-property > span {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.ascribe-settings-property > input {
|
||||
padding: 10px;
|
||||
background-color: #fff;
|
||||
margin-top: .1em;
|
||||
|
||||
&:focus {
|
||||
background-color: #ffff00;
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox,
|
||||
.checkbox a {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.ascribe-login-text {
|
||||
color: white;
|
||||
text-align: center;
|
||||
|
||||
a {
|
||||
color: white;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.client--ikonotv .ascribe-form-bordered {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.client--ikonotv .ascribe-login-wrapper {
|
||||
}
|
||||
|
||||
.client--ikonotv .ascribe-footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ikonotv-landing {
|
||||
/* center all text on the page */
|
||||
text-align: center;
|
||||
background-color: #c40050;
|
||||
color: white;
|
||||
|
||||
padding: 5em 5em 5em 5em;
|
||||
|
||||
header {
|
||||
/* center all images on the page */
|
||||
img {
|
||||
@ -16,7 +122,7 @@
|
||||
|
||||
/* Ikonotv logo */
|
||||
img:first-child {
|
||||
width: 200px;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
> .tagline {
|
||||
@ -29,12 +135,30 @@
|
||||
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
font-size: 4em;
|
||||
}
|
||||
}
|
||||
|
||||
> .poster {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
> .content {
|
||||
width: 100%;
|
||||
padding-bottom: 56.25%;
|
||||
height: 0;
|
||||
background-color: #ffff00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> h2 {
|
||||
font-weight: 600;
|
||||
font-size: 2.75em;
|
||||
@media only screen and (max-width: 600px) {
|
||||
font-size: 1.75em;
|
||||
}
|
||||
}
|
||||
|
||||
> h2 + h2 {
|
||||
@ -44,7 +168,8 @@
|
||||
|
||||
article {
|
||||
> section {
|
||||
width: 65%;
|
||||
width: 100%;
|
||||
max-width: 60em;
|
||||
margin: 3em auto 1em auto;
|
||||
|
||||
> h1 {
|
||||
@ -57,6 +182,9 @@
|
||||
text-align: left;
|
||||
font-size: 1.3em;
|
||||
line-height: 1.8;
|
||||
@media only screen and (max-width: 600px) {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -78,4 +206,4 @@
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
5
sass/whitelabel/wallet/index.scss
Normal file
5
sass/whitelabel/wallet/index.scss
Normal file
@ -0,0 +1,5 @@
|
||||
.ascribe-wallet-app {
|
||||
border-radius: 0;
|
||||
padding-top: 70px;
|
||||
min-height: 100vh;
|
||||
}
|
Loading…
Reference in New Issue
Block a user