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

Merge branch 'AD-456-ikonotv-branded-page-for-registra' of bitbucket.org:ascribe/onion into AD-456-ikonotv-branded-page-for-registra

This commit is contained in:
Tim Daubenschütz 2015-09-04 15:55:07 +02:00
commit 85efa4b416
27 changed files with 526 additions and 59 deletions

24
.gitignore~ Normal file
View File

@ -0,0 +1,24 @@
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
*.sublime-project
.idea
spool-project.sublime-project
*.sublime-workspace
*.sublime-workspace
webapp-dependencies.txt
pids
logs
results
README.md~
node_modules/*
build
.DS_Store

View File

@ -43,6 +43,7 @@ class ContractActions {
/* No email was entered - Ignore and keep going*/
}
}
}
export default alt.createActions(ContractActions);

View File

@ -3,7 +3,6 @@
import alt from '../alt';
import OwnershipFetcher from '../fetchers/ownership_fetcher';
class ContractListActions {
constructor() {
this.generateActions(
@ -15,13 +14,23 @@ class ContractListActions {
fetchContractList() {
OwnershipFetcher.fetchContractList()
.then((contracts) => {
this.actions.updateContractList(contracts);
this.actions.updateContractList(contracts.results);
})
.catch((err) => {
console.logGlobal(err);
this.actions.updateContractList([]);
});
}
makeContractPublic(contract){
OwnershipFetcher.makeContractPublic(contract)
.then((res) =>{
return res;
})
.catch((err)=>{
console.logGlobal(err);
});
}
}
export default alt.createActions(ContractListActions);

View File

@ -57,7 +57,7 @@ class PieceListActions {
PieceListFetcher
.fetchRequestActions()
.then((res) => {
this.actions.updatePieceListRequestActions(res.piece_ids);
this.actions.updatePieceListRequestActions(res);
})
.catch((err) => console.logGlobal(err));
}

View File

@ -61,12 +61,13 @@ let AccordionListItemWallet = React.createClass({
},
getGlyphicon(){
if (this.props.content.requestAction && this.props.content.requestAction.length > 0) {
if ((this.props.content.request_action && this.props.content.request_action.length > 0) ||
(this.props.content.request_action_editions)){
return (
<OverlayTrigger
delay={500}
placement="left"
overlay={<Tooltip>{getLangText('You have actions pending in one of your editions')}</Tooltip>}>
overlay={<Tooltip>{getLangText('You have actions pending')}</Tooltip>}>
<Glyphicon glyph='bell' color="green"/>
</OverlayTrigger>);
}

View File

@ -305,7 +305,6 @@ let EditionSummary = React.createClass({
<hr/>
</div>
);
}
});

View File

@ -9,6 +9,8 @@ import Edition from './edition';
import AppConstants from '../../constants/application_constants';
/**
* This is the component that implements resource/data specific functionality
*/
@ -34,6 +36,15 @@ let EditionContainer = React.createClass({
EditionActions.fetchOne(this.props.params.editionId);
},
// This is done to update the container when the user clicks on the prev or next
// button to update the URL parameter (and therefore to switch pieces)
componentWillReceiveProps(nextProps) {
if(this.props.params.editionId !== nextProps.params.editionId) {
EditionActions.updateEdition({});
EditionActions.fetchOne(nextProps.params.editionId);
}
},
componentWillUnmount() {
// Every time we're leaving the edition detail page,
// just reset the edition that is saved in the edition store
@ -50,6 +61,7 @@ let EditionContainer = React.createClass({
},
render() {
console.log(this.state);
if('title' in this.state.edition) {
return (
<Edition

View File

@ -19,7 +19,7 @@ import { getLangText } from '../../utils/lang_utils';
import { mergeOptions } from '../../utils/general_utils';
let ContractForm = React.createClass({
let ContractAgreementForm = React.createClass({
propTypes: {
handleSuccess: React.PropTypes.func
},
@ -55,8 +55,13 @@ let ContractForm = React.createClass({
GlobalNotificationActions.appendGlobalNotification(notification);
},
getFormData(){
return {'appendix': {'default': this.refs.form.refs.appendix.state.value}};
},
getContracts() {
if (this.state.contractList && this.state.contractList.length > 0) {
if (this.state.contractList && this.state.contractList.count > 0) {
let contractList = this.state.contractList.results;
return (
<Property
name='contract'
@ -65,13 +70,13 @@ let ContractForm = React.createClass({
footer={
<a
className="pull-right"
href={this.state.contractList[this.state.selectedContract].s3UrlSafe}
href={contractList[this.state.selectedContract].blob}
target="_blank">
{getLangText('Learn more')}
</a>
}>
<select name="contract">
{this.state.contractList.map((contract, i) => {
{contractList.map((contract, i) => {
return (
<option
name={i}
@ -92,7 +97,8 @@ let ContractForm = React.createClass({
<Form
className="ascribe-form-bordered ascribe-form-wrapper"
ref='form'
url={ApiUrls.blob_contracts}
url={ApiUrls.ownership_contract_agreements}
getFormData={this.getFormData}
handleSuccess={this.props.handleSuccess}
buttons={<button
type="submit"
@ -108,15 +114,7 @@ let ContractForm = React.createClass({
<h3>{getLangText('Contract form')}</h3>
</div>
<Property
name='artist_name'
label={getLangText('Artist Name')}>
<input
type="text"
placeholder={getLangText('(e.g. Andy Warhol)')}
required/>
</Property>
<Property
name='artist_email'
name='signee'
label={getLangText('Artist Email')}>
<input
type="email"
@ -138,4 +136,4 @@ let ContractForm = React.createClass({
}
});
export default ContractForm;
export default ContractAgreementForm;

View File

@ -6,6 +6,9 @@ import Form from '../ascribe_forms/form';
import Property from '../ascribe_forms/property';
import InputCheckbox from '../ascribe_forms/input_checkbox';
import GlobalNotificationModel from '../../models/global_notification_model';
import GlobalNotificationActions from '../../actions/global_notification_actions';
import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader';
import AppConstants from '../../constants/application_constants';
@ -19,14 +22,20 @@ let CreateContractForm = React.createClass({
getInitialState() {
return {
digitalWorkKey: null,
contractKey: null,
isUploadReady: false
};
},
getFormData(){
return {
blob: this.state.contractKey
};
},
submitKey(key) {
this.setState({
digitalWorkKey: key
contractKey: key
});
},
@ -36,10 +45,18 @@ let CreateContractForm = React.createClass({
});
},
handleCreateSuccess(response) {
let notification = new GlobalNotificationModel(getLangText('Contract %s successfully created', response.name), 'success', 5000);
GlobalNotificationActions.appendGlobalNotification(notification);
},
render() {
return (
<Form
url={ApiUrls.ownership_contract}
url={ApiUrls.ownership_contract_list}
getFormData={this.getFormData}
handleSuccess={this.handleCreateSuccess}
buttons={
<button
type="submit"
@ -88,7 +105,7 @@ let CreateContractForm = React.createClass({
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}/>
</Property>
<Property
name='contract_ name'
name='name'
label={getLangText('Contract name')}>
<input
type="text"

View File

@ -6,6 +6,8 @@ import AclButton from './../ascribe_buttons/acl_button';
import ActionPanel from '../ascribe_panel/action_panel';
import Form from './form';
import PieceListActions from '../../actions/piece_list_actions';
import GlobalNotificationModel from '../../models/global_notification_model';
import GlobalNotificationActions from '../../actions/global_notification_actions';
@ -71,10 +73,16 @@ let RequestActionForm = React.createClass({
let notification = new GlobalNotificationModel(message, 'success');
GlobalNotificationActions.appendGlobalNotification(notification);
this.handleSuccess();
};
},
handleSuccess() {
PieceListActions.fetchPieceRequestActions();
if(this.props.handleSuccess) {
this.props.handleSuccess();
}
};
},
getContent() {
@ -99,7 +107,7 @@ let RequestActionForm = React.createClass({
buttonAcceptClassName='inline pull-right btn-sm ascribe-margin-1px'
pieceOrEditions={this.props.pieceOrEditions}
currentUser={this.props.currentUser}
handleSuccess={this.props.handleSuccess} />
handleSuccess={this.handleSuccess} />
);
} else if(this.props.requestAction === 'loan_request') {
return (
@ -110,7 +118,7 @@ let RequestActionForm = React.createClass({
buttonAcceptClassName='inline pull-right btn-sm ascribe-margin-1px'
pieceOrEditions={this.props.pieceOrEditions}
currentUser={this.props.currentUser}
handleSuccess={this.props.handleSuccess} />
handleSuccess={this.handleSuccess} />
);
} else {
return (

View File

@ -14,7 +14,6 @@ let ActionPanel = React.createClass({
onClick: React.PropTypes.func,
ignoreFocus: React.PropTypes.bool
},
getInitialState() {
return {
isFocused: false

View File

@ -5,23 +5,100 @@ import React from 'react';
import CollapsibleParagraph from '../ascribe_collapsible/collapsible_paragraph';
import CreateContractForm from '../ascribe_forms/form_create_contract';
import { getLangText } from '../../utils/lang_utils';
import ContractListStore from '../../stores/contract_list_store';
import ContractListActions from '../../actions/contract_list_actions';
import ActionPanel from '../ascribe_panel/action_panel';
import { getLangText } from '../../utils/lang_utils';
let ContractSettings = React.createClass({
propTypes: {
defaultExpanded: React.PropTypes.bool
},
getInitialState(){
return ContractListStore.getState();
},
componentDidMount() {
ContractListStore.listen(this.onChange);
ContractListActions.fetchContractList();
},
componentWillUnmount() {
ContractListStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
makeContractPublic(contract){
console.log(contract);
ContractListActions.makeContractPublic(contract)
.then(( ) => ContractListActions.fetchContractList())
.catch((error)=>{console.log("Error ", error)})
},
getPublicContracts(){
return this.state.contractList.filter((contract) => contract.public);
},
getPrivateContracts(){
return this.state.contractList.filter((contract) => !contract.public);
},
getblobEndName(contract){
return contract.blob.match(/.*\/(.*)/)[1];
},
render() {
let publicContracts = this.getPublicContracts();
let privateContracts = this.getPrivateContracts();
console.log(this.state.contractList);
return (
<CollapsibleParagraph
title={getLangText('Contract Settings')}
show={true}
defaultExpanded={true}>
defaultExpanded={false}>
{/* this should be this.props.defaultExpanded */}
<CollapsibleParagraph
title={getLangText('List Contracts')}
show={true}
defaultExpanded={false}>
{<div>
<p>Public Contracts</p>
{(publicContracts.length > 0) ?
publicContracts.map(
(contract) => {
return(
<ActionPanel title = {contract.name}
content = {this.getblobEndName(contract)}
buttons = {<span>
<button className="btn btn-default btn-sm margin-left-2px">UPDATE</button>
<button className="btn btn-default btn-sm margin-left-2px">REMOVE</button>
</span>}
/>)
}
) : null }
</div>}
{<div>
<p>Private Contracts</p>
{(privateContracts.length>0) ?
privateContracts.map(
(contract) => {
return(
<ActionPanel title = {contract.name}
content = {this.getblobEndName(contract)}
buttons = {<span> <button className="btn btn-default btn-sm margin-left-2px">UPDATE</button>
<button className="btn btn-default btn-sm margin-left-2px" >REMOVE</button>
<button className="btn btn-default btn-sm margin-left-2px"
onClick={this.makeContractPublic.bind(this, contract)}>MAKE PUBLIC</button> </span>}
/>)
}
) : null}
</div>}
</CollapsibleParagraph>
<CollapsibleParagraph
title={getLangText('Create Contract')}
show={true}
defaultExpanded={false}>
<CreateContractForm />
</CollapsibleParagraph>
</CollapsibleParagraph>
);
}
});

View File

@ -0,0 +1,43 @@
'use strict';
import React from 'react';
let GlobalAction = React.createClass({
propTypes: {
requestActions: React.PropTypes.object
},
render() {
let pieceActions = null;
if (this.props.requestActions && this.props.requestActions.pieces){
pieceActions = this.props.requestActions.pieces.map((item) => {
return (
<div className="ascribe-global-action">
{item}
</div>);
});
}
let editionActions = null;
if (this.props.requestActions && this.props.requestActions.editions){
editionActions = Object.keys(this.props.requestActions.editions).map((pieceId) => {
return this.props.requestActions.editions[pieceId].map((item) => {
return (
<div className="ascribe-global-action">
{item}
</div>);
});
});
}
if (pieceActions || editionActions) {
return (
<div className="ascribe-global-action-wrapper">
{pieceActions}
{editionActions}
</div>);
}
return null;
}
});
export default GlobalAction;

View File

@ -3,12 +3,6 @@
import React from 'react';
import Router from 'react-router';
import UserActions from '../actions/user_actions';
import UserStore from '../stores/user_store';
import WhitelabelActions from '../actions/whitelabel_actions';
import WhitelabelStore from '../stores/whitelabel_store';
import EventActions from '../actions/event_actions';
import Nav from 'react-bootstrap/lib/Nav';
import Navbar from 'react-bootstrap/lib/Navbar';
@ -18,6 +12,15 @@ import MenuItem from 'react-bootstrap/lib/MenuItem';
import MenuItemLink from 'react-router-bootstrap/lib/MenuItemLink';
import NavItemLink from 'react-router-bootstrap/lib/NavItemLink';
import UserActions from '../actions/user_actions';
import UserStore from '../stores/user_store';
import WhitelabelActions from '../actions/whitelabel_actions';
import WhitelabelStore from '../stores/whitelabel_store';
import EventActions from '../actions/event_actions';
import HeaderNotifications from './header_notification';
import HeaderNotificationDebug from './header_notification_debug';
import NavRoutesLinks from './nav_routes_links';
@ -41,7 +44,10 @@ let Header = React.createClass({
},
getInitialState() {
return mergeOptions(WhitelabelStore.getState(), UserStore.getState());
return mergeOptions(
WhitelabelStore.getState(),
UserStore.getState()
);
},
componentDidMount() {
@ -96,7 +102,9 @@ let Header = React.createClass({
let navRoutesLinks;
if (this.state.currentUser.username){
account = (
<DropdownButton eventKey="1" title={this.state.currentUser.username}>
<DropdownButton
eventKey="1"
title={this.state.currentUser.username}>
<MenuItemLink eventKey="2" to="settings">{getLangText('Account Settings')}</MenuItemLink>
<MenuItem divider />
<MenuItemLink eventKey="3" to="logout">{getLangText('Log out')}</MenuItemLink>
@ -126,6 +134,7 @@ let Header = React.createClass({
{account}
{signup}
</Nav>
<HeaderNotifications />
{navRoutesLinks}
</CollapsibleNav>
</Navbar>

View File

@ -0,0 +1,144 @@
'use strict';
import React from 'react';
import Router from 'react-router';
import DropdownButton from 'react-bootstrap/lib/DropdownButton';
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
import MenuItem from 'react-bootstrap/lib/MenuItem';
import Nav from 'react-bootstrap/lib/Nav';
import PieceListStore from '../stores/piece_list_store';
import { mergeOptions } from '../utils/general_utils';
import { getLangText } from '../utils/lang_utils';
let Link = Router.Link;
let HeaderNotifications = React.createClass({
getInitialState() {
return mergeOptions(
PieceListStore.getState()
);
},
componentDidMount() {
PieceListStore.listen(this.onChange);
},
componentWillUnmount() {
PieceListStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
onSelected(event) {
/*
This is a hack to make the dropdown close after clicking on an item
The function just need to be defined
from https://github.com/react-bootstrap/react-bootstrap/issues/368:
@jvillasante - Have you tried to use onSelect with the DropdownButton?
I don't have a working example that is exactly like yours,
but I just noticed that the Dropdown closes when I've attached an event handler to OnSelect:
<DropdownButton eventKey={3} title="Admin" onSelect={ this.OnSelected } >
onSelected: function(e) {
// doesn't need to have functionality (necessarily) ... just wired up
}
Internally, a call to DropdownButton.setDropDownState(false) is made which will hide the dropdown menu.
So, you should be able to call that directly on the DropdownButton instance as well if needed.
*/
},
render() {
if (this.state.requestActions && this.state.requestActions.length > 0) {
return (
<Nav navbar right>
<DropdownButton
eventKey="1"
title={
<span>
<Glyphicon glyph='envelope' color="green"/>
<span className="notification-amount">({this.state.requestActions.length})</span>
</span>
}
className="notification-menu"
onSelect={this.onSelected}>
{this.state.requestActions.map((pieceOrEdition, i) => {
return (
<MenuItem eventKey={i + 2}>
<NotificationListItem
ref={i}
pieceOrEdition={pieceOrEdition}/>
</MenuItem>);
}
)}
</DropdownButton>
</Nav>
);
}
return null;
}
});
let NotificationListItem = React.createClass({
propTypes: {
pieceOrEdition: React.PropTypes.object
},
getLinkData() {
if(this.props.pieceOrEdition && this.props.pieceOrEdition.parent) {
return {
to: 'edition',
params: {
editionId: this.props.pieceOrEdition.bitcoin_id
}
};
} else {
return {
to: 'piece',
params: {
pieceId: this.props.pieceOrEdition.id
}
};
}
},
render() {
if (this.props.pieceOrEdition) {
return (
<Link {...this.getLinkData()}>
<div className="row notification-wrapper">
<div className="col-xs-4 clear-paddings">
<div className="thumbnail-wrapper">
<img src={this.props.pieceOrEdition.thumbnail.url_safe}/>
</div>
</div>
<div className="col-xs-8 notification-list-item-header">
<h1>{this.props.pieceOrEdition.title}</h1>
<div className="sub-header">by {this.props.pieceOrEdition.artist_name}</div>
<div className="notification-action">
{
this.props.pieceOrEdition.request_action.map((requestAction) => {
return 'Pending ' + requestAction.action + ' request';
})
}
</div>
</div>
</div>
</Link>);
}
return null;
}
});
export default HeaderNotifications;

View File

@ -15,6 +15,7 @@ import AccordionListItemTableEditions from './ascribe_accordion_list/accordion_l
import Pagination from './ascribe_pagination/pagination';
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';
@ -148,6 +149,10 @@ let PieceList = React.createClass({
render() {
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

View File

@ -86,7 +86,6 @@ let PieceContainer = React.createClass({
loadPiece() {
PieceActions.fetchOne(this.props.params.pieceId);
this.setState(this.state);
},
render() {

View File

@ -2,13 +2,13 @@
import React from 'react';
import ContractForm from '../../../../../components/ascribe_forms/form_contract';
import ContractAgreementForm from '../../../../ascribe_forms/form_contract_agreement';
let IkonotvRequestLoan = React.createClass({
render() {
return (
<ContractForm />
<ContractAgreementForm />
);
}
});

View File

@ -27,6 +27,7 @@ let ApiUrls = {
'note_private_piece': AppConstants.apiEndpoint + 'note/private/pieces/',
'note_public_edition': AppConstants.apiEndpoint + 'note/public/editions/',
'note_public_piece': AppConstants.apiEndpoint + 'note/public/pieces/',
'ownership_contract_agreements': AppConstants.apiEndpoint + 'ownership/contract_agreements/',
'ownership_consigns': AppConstants.apiEndpoint + 'ownership/consigns/',
'ownership_consigns_confirm': AppConstants.apiEndpoint + 'ownership/consigns/confirm/',
'ownership_consigns_deny': AppConstants.apiEndpoint + 'ownership/consigns/deny/',
@ -46,7 +47,8 @@ let ApiUrls = {
'ownership_unconsigns': AppConstants.apiEndpoint + 'ownership/unconsigns/',
'ownership_unconsigns_deny': AppConstants.apiEndpoint + 'ownership/unconsigns/deny/',
'ownership_unconsigns_request': AppConstants.apiEndpoint + 'ownership/unconsigns/request/',
'ownership_contract': AppConstants.apiEndpoint + 'ownership/contracts/',
'ownership_contract':AppConstants.apiEndpoint + 'ownership/contracts/${contract_id}',
"ownership_contract_list": AppConstants.apiEndpoint + 'ownership/contracts/',
'piece': AppConstants.apiEndpoint + 'pieces/${piece_id}/',
'piece_extradata': AppConstants.apiEndpoint + 'pieces/${piece_id}/extradata/',
'piece_first_edition_id': AppConstants.apiEndpoint + 'pieces/${piece_id}/edition_index/',

View File

@ -16,11 +16,16 @@ let OwnershipFetcher = {
* Fetch the contracts of the logged-in user from the API.
*/
fetchContractList(){
return requests.get(ApiUrls.ownership_contract);
return requests.get(ApiUrls.ownership_contract_list);
},
fetchLoanPieceRequestList(){
return requests.get(ApiUrls.ownership_loans_pieces_request);
},
makeContractPublic(contractObj){
console.log(contractObj);
return requests.put('ownership_contract_list',{ body: contractObj, contract_id:contractObj.id });
}
};

View File

@ -28,6 +28,7 @@ class PieceListStore {
this.orderBy = 'artist_name';
this.orderAsc = true;
this.filterBy = {};
this.requestActions = {};
this.bindActions(PieceListActions);
}
@ -71,10 +72,8 @@ class PieceListStore {
this.pieceList = pieceList;
}
onUpdatePieceListRequestActions(requestActions) {
this.pieceList.forEach((piece) => {
piece.requestAction = requestActions.indexOf(piece.id) > -1;
});
onUpdatePieceListRequestActions(res) {
this.requestActions = res.actions;
}
onUpdatePropertyForPiece({pieceId, key, value}) {

View File

@ -52,6 +52,19 @@ export function sumNumList(l) {
return sum;
}
export function excludePropFromObject(obj, propList){
let clonedObj = mergeOptions({},obj);
for (let item in propList){
console.log(item);
if (clonedObj[propList[item]]){
console.log('deleting... ');
delete clonedObj[propList[item]];
}
}
console.log(clonedObj);
return clonedObj;
}
/*
Taken from http://stackoverflow.com/a/4795914/1263876
Behaves like C's format string function

View File

@ -6,6 +6,7 @@ import { argsToQueryParams, getCookie } from '../utils/fetch_api_utils';
import AppConstants from '../constants/application_constants';
import {excludePropFromObject} from '../utils/general_utils';
class Requests {
_merge(defaults, options) {
@ -137,15 +138,25 @@ class Requests {
return this.request('delete', newUrl);
}
post(url, params) {
let paramsCopy = this._merge(params);
let newUrl = this.prepareUrl(url, paramsCopy);
_putOrPost(url,paramsAndBody,method){
let paramsCopy = this._merge(paramsAndBody);
let params = excludePropFromObject(paramsAndBody,['body']);
let newUrl = this.prepareUrl(url, params);
let body = null;
if (paramsCopy && paramsCopy.body) {
console.log(paramsCopy.body);
body = JSON.stringify(paramsCopy.body);
}
return this.request('post', newUrl, { body });
return this.request(method, newUrl, { body });
}
post(url, params) {
return this._putOrPost(url,params,'post')
}
put(url, params){
console.log(params);
return this._putOrPost(url,params,'put')
}
defaults(options) {

View File

@ -166,7 +166,7 @@ $ascribe-accordion-list-item-height: 8em;
.request-action-badge {
color: $ascribe-color-green;
font-size: 1.2em;
padding: .3em;
padding: .8em;
position: absolute;
right: 0;
top: 0;

View File

@ -0,0 +1,25 @@
$break-small: 764px;
$break-medium: 991px;
$break-medium: 1200px;
.ascribe-global-action-wrapper {
position: fixed;
width: 100%;
max-width: 500px;
height:3.5em;
left:0;
right: 0;
top:0;
z-index: 2000;
display:table;
margin: 1px auto;
}
.ascribe-global-action {
text-align: center;
padding: 1em;
color: black;
border: 1px solid #cccccc;
background-color: white;
margin-top: 1px;
}

View File

@ -0,0 +1,65 @@
$break-small: 764px;
$break-medium: 991px;
$break-medium: 1200px;
.notification-wrapper {
width: 350px;
height:8em;
padding: 0.3em;
border-bottom: 1px solid #cccccc;
margin: -3px -20px;
// ToDo: Include media queries for thumbnail
.thumbnail-wrapper {
width: 7.4em;
height: 7.4em;
padding:0;
cursor: pointer;
text-align: center;
img {
max-width: 100%;
max-height: 100%;
}
&::before {
content: ' ';
display: inline-block;
vertical-align: middle; /* vertical alignment of the inline element */
height: 100%;
}
}
h1 {
margin-top: 0.3em;
margin-bottom: 0.15em;
font-size: 1.8em;
}
.sub-header{
margin-bottom: 1em;
}
.notification-action{
color: $ascribe-color-green;
}
}
.notification-menu {
.dropdown-menu {
padding: 0 !important;
li a {
padding-top: 0;
}
}
}
.notification-amount {
padding: 0.3em;
font-size: 1.2em;
}
.ascribe-global-action {
text-align: center;
padding: 1em;
color: black;
border: 1px solid #cccccc;
background-color: white;
margin-top: 1px;
}

View File

@ -22,7 +22,9 @@ $BASE_URL: '<%= BASE_URL %>';
@import 'ascribe_media_player';
@import 'ascribe_uploader';
@import 'ascribe_footer';
@import 'ascribe_global_action';
@import 'ascribe_global_notification';
@import 'ascribe_notification_list';
@import 'ascribe_piece_register';
@import 'offset_right';
@import 'ascribe_settings';