App Navigation and Wallet pages groundwork #936
|
@ -18,6 +18,7 @@ module.name_mapper='^types\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/types\1'
|
|||
module.name_mapper='^component\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/component\1'
|
||||
module.name_mapper='^page\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/page\1'
|
||||
module.name_mapper='^lbry\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/lbry\1'
|
||||
module.name_mapper='^rewards\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/rewards\1'
|
||||
module.name_mapper='^modal\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/modal\1'
|
||||
|
||||
[strict]
|
||||
|
|
3
.gitignore
vendored
|
@ -5,5 +5,4 @@
|
|||
*.pyc
|
||||
/static/daemon/lbrynet*
|
||||
/static/locales
|
||||
|
||||
|
||||
npm-debug.log*
|
||||
|
|
3
flow-typed/react-feather.js
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
declare module 'react-feather' {
|
||||
declare module.exports: any;
|
||||
}
|
|
@ -52,6 +52,7 @@
|
|||
"rc-progress": "^2.0.6",
|
||||
"react": "^16.2.0",
|
||||
"react-dom": "^16.2.0",
|
||||
"react-feather": "^1.0.8",
|
||||
"react-markdown": "^2.5.0",
|
||||
"react-modal": "^3.1.7",
|
||||
"react-paginate": "^5.0.0",
|
||||
|
|
|
@ -1,52 +1,56 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
// @flow
|
||||
import * as React from 'react';
|
||||
import { clipboard } from 'electron';
|
||||
import Link from 'component/link';
|
||||
import classnames from 'classnames';
|
||||
import { FormField } from 'component/common/form';
|
||||
import Button from 'component/link';
|
||||
|
||||
export default class Address extends React.PureComponent {
|
||||
static propTypes = {
|
||||
address: PropTypes.string,
|
||||
};
|
||||
type Props = {
|
||||
address: string,
|
||||
doShowSnackBar: ({ message: string }) => void,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
export default class Address extends React.PureComponent<Props> {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
|
||||
this._inputElem = null;
|
||||
this.input = null;
|
||||
}
|
||||
|
||||
input: ?HTMLInputElement;
|
||||
|
||||
render() {
|
||||
const { address, showCopyButton, doShowSnackBar } = this.props;
|
||||
const { address, doShowSnackBar } = this.props;
|
||||
|
||||
return (
|
||||
<div className="form-field form-field--address">
|
||||
<input
|
||||
className={classnames('input-copyable', {
|
||||
'input-copyable--with-copy-btn': showCopyButton,
|
||||
})}
|
||||
type="text"
|
||||
ref={input => {
|
||||
this._inputElem = input;
|
||||
}}
|
||||
onFocus={() => {
|
||||
this._inputElem.select();
|
||||
}}
|
||||
readOnly="readonly"
|
||||
value={address || ''}
|
||||
/>
|
||||
{showCopyButton && (
|
||||
<span className="header__item">
|
||||
<Link
|
||||
button="alt button--flat"
|
||||
icon="clipboard"
|
||||
<FormField
|
||||
name="address"
|
||||
render={() => (
|
||||
<React.Fragment>
|
||||
<input
|
||||
id="address"
|
||||
className="input-copyable"
|
||||
readOnly
|
||||
value={address || ''}
|
||||
ref={input => {
|
||||
this.input = input;
|
||||
}}
|
||||
onFocus={() => {
|
||||
if (this.input) {
|
||||
this.input.select();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
alt
|
||||
icon="Clipboard"
|
||||
onClick={() => {
|
||||
clipboard.writeText(address);
|
||||
doShowSnackBar({ message: __('Address copied') });
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</div>
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
selectPageTitle,
|
||||
|
@ -10,7 +9,7 @@ import { doAlertError } from 'redux/actions/app';
|
|||
import { doRecordScroll } from 'redux/actions/navigation';
|
||||
import App from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
const select = state => ({
|
||||
pageTitle: selectPageTitle(state),
|
||||
user: selectUser(state),
|
||||
currentStackIndex: selectHistoryIndex(state),
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import Router from 'component/router/index';
|
||||
import Header from 'component/header';
|
||||
import Theme from 'component/theme';
|
||||
import ModalRouter from 'modal/modalRouter';
|
||||
import ReactModal from 'react-modal';
|
||||
import throttle from 'util/throttle';
|
||||
import SideBar from 'component/sideBar';
|
||||
import Header from 'component/header';
|
||||
|
||||
type Props = {
|
||||
alertError: (string | {}) => void,
|
||||
|
@ -33,7 +34,7 @@ class App extends React.PureComponent<Props> {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
const mainContent = document.getElementById('main-content');
|
||||
const mainContent = document.getElementById('content');
|
||||
this.mainContent = mainContent;
|
||||
|
||||
if (this.mainContent) {
|
||||
|
@ -82,9 +83,14 @@ class App extends React.PureComponent<Props> {
|
|||
return (
|
||||
<div id="window">
|
||||
<Theme />
|
||||
<Header />
|
||||
<Router />
|
||||
<ModalRouter />
|
||||
<main className="page">
|
||||
<SideBar />
|
||||
<Header />
|
||||
<div className="content" id="content">
|
||||
<Router />
|
||||
<ModalRouter />
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -44,78 +44,6 @@ export class CurrencySymbol extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
export class CreditAmount extends React.PureComponent {
|
||||
static propTypes = {
|
||||
amount: PropTypes.number.isRequired,
|
||||
precision: PropTypes.number,
|
||||
isEstimate: PropTypes.bool,
|
||||
label: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
|
||||
showFree: PropTypes.bool,
|
||||
showFullPrice: PropTypes.bool,
|
||||
showPlus: PropTypes.bool,
|
||||
look: PropTypes.oneOf(['indicator', 'plain', 'fee']),
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
precision: 2,
|
||||
label: true,
|
||||
showFree: false,
|
||||
look: 'indicator',
|
||||
showFullPrice: false,
|
||||
showPlus: false,
|
||||
};
|
||||
|
||||
render() {
|
||||
const minimumRenderableAmount = Math.pow(10, -1 * this.props.precision);
|
||||
const { amount, precision, showFullPrice } = this.props;
|
||||
|
||||
let formattedAmount;
|
||||
const fullPrice = formatFullPrice(amount, 2);
|
||||
|
||||
if (showFullPrice) {
|
||||
formattedAmount = fullPrice;
|
||||
} else {
|
||||
formattedAmount =
|
||||
amount > 0 && amount < minimumRenderableAmount
|
||||
? `<${minimumRenderableAmount}`
|
||||
: formatCredits(amount, precision);
|
||||
}
|
||||
|
||||
let amountText;
|
||||
if (this.props.showFree && parseFloat(this.props.amount) === 0) {
|
||||
amountText = __('free');
|
||||
} else {
|
||||
if (this.props.label) {
|
||||
const label =
|
||||
typeof this.props.label === 'string'
|
||||
? this.props.label
|
||||
: parseFloat(amount) == 1 ? __('credit') : __('credits');
|
||||
|
||||
amountText = `${formattedAmount} ${label}`;
|
||||
} else {
|
||||
amountText = formattedAmount;
|
||||
}
|
||||
if (this.props.showPlus && amount > 0) {
|
||||
amountText = `+${amountText}`;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<span className={`credit-amount credit-amount--${this.props.look}`} title={fullPrice}>
|
||||
<span>{amountText}</span>
|
||||
{this.props.isEstimate ? (
|
||||
<span
|
||||
className="credit-amount__estimate"
|
||||
title={__('This is an estimate and does not include data fees')}
|
||||
>
|
||||
*
|
||||
</span>
|
||||
) : null}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class Thumbnail extends React.PureComponent {
|
||||
static propTypes = {
|
||||
src: PropTypes.string,
|
||||
|
|
|
@ -200,7 +200,7 @@ class CategoryList extends React.PureComponent<Props, State> {
|
|||
<h3>
|
||||
{categoryLink ? (
|
||||
<Button
|
||||
className="button-text no-underline"
|
||||
noStyle
|
||||
label={category}
|
||||
navigate="/show"
|
||||
navigateParams={{ uri: categoryLink }}
|
||||
|
@ -219,20 +219,20 @@ class CategoryList extends React.PureComponent<Props, State> {
|
|||
/>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<div className="card-row__scroll-btns">
|
||||
<Button
|
||||
inverse
|
||||
circle
|
||||
disabled={!canScrollPrevious}
|
||||
onClick={this.handleScrollPrevious}
|
||||
icon="chevron-left"
|
||||
icon="ChevronLeft"
|
||||
/>
|
||||
<Button
|
||||
inverse
|
||||
circle
|
||||
disabled={!canScrollNext}
|
||||
onClick={this.handleScrollNext}
|
||||
icon="chevron-right"
|
||||
icon="ChevronRight"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
76
src/renderer/component/common/credit-amount.jsx
Normal file
|
@ -0,0 +1,76 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { formatCredits, formatFullPrice } from 'util/formatCredits';
|
||||
|
||||
type Props = {
|
||||
amount: number,
|
||||
precision: number,
|
||||
showFree: boolean,
|
||||
showFullPrice: boolean,
|
||||
showPlus: boolean,
|
||||
isEstimate?: boolean,
|
||||
large?: boolean,
|
||||
};
|
||||
|
||||
class CreditAmount extends React.PureComponent<Props> {
|
||||
static defaultProps = {
|
||||
precision: 2,
|
||||
showFree: false,
|
||||
showFullPrice: false,
|
||||
showPlus: false,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { amount, precision, showFullPrice, showFree, showPlus, large, isEstimate } = this.props;
|
||||
|
||||
const minimumRenderableAmount = 10 ** (-1 * precision);
|
||||
const fullPrice = formatFullPrice(amount, 2);
|
||||
const isFree = parseFloat(amount) === 0;
|
||||
|
||||
let formattedAmount;
|
||||
if (showFullPrice) {
|
||||
formattedAmount = fullPrice;
|
||||
} else {
|
||||
formattedAmount =
|
||||
amount > 0 && amount < minimumRenderableAmount
|
||||
? `<${minimumRenderableAmount}`
|
||||
: formatCredits(amount, precision);
|
||||
}
|
||||
|
||||
let amountText;
|
||||
if (showFree && isFree) {
|
||||
amountText = __('FREE');
|
||||
} else {
|
||||
amountText = `${formattedAmount} ${__('LBC')}`;
|
||||
|
||||
if (showPlus && amount > 0) {
|
||||
amountText = `+${amountText}`;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
title={fullPrice}
|
||||
className={classnames('credit-amount', {
|
||||
'credit-amount--free': !large && isFree,
|
||||
'credit-amount--cost': !large && !isFree,
|
||||
'credit-amount--large': large,
|
||||
})}
|
||||
>
|
||||
{amountText}
|
||||
|
||||
{isEstimate ? (
|
||||
<span
|
||||
className="credit-amount__estimate"
|
||||
title={__('This is an estimate and does not include data fees')}
|
||||
>
|
||||
*
|
||||
</span>
|
||||
) : null}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default CreditAmount;
|
85
src/renderer/component/common/form.jsx
Normal file
|
@ -0,0 +1,85 @@
|
|||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
// @flow
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
/* eslint-disable react/no-multi-comp */
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
import * as React from 'react';
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
import Button from 'component/link';
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
type FormRowProps = {
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
children: React.Node,
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
};
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
export const FormRow = (props: FormRowProps) => {
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
const { children } = props;
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
return <div className="form-row">{children}</div>;
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
};
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
type FormFieldProps = {
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
render: () => React.Node,
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
label?: string,
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
prefix?: string,
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
postfix?: string,
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
error?: string | boolean,
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
};
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
export class FormField extends React.PureComponent<FormFieldProps> {
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
render() {
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
const { render, label, prefix, postfix, error } = this.props;
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
return (
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
<div className="form-field">
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
{label && (
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
<label className="form-field__label">
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
{label}
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
</label>
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
)}
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
<div className="form-field__wrapper">
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
{prefix && <span className="form-field__prefix">{prefix}</span>}
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
{render()}
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
{postfix && <span className="form-field__postfix">{postfix}</span>}
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
</div>
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
{error && (
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
<div className="form-field__error">
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
{typeof error === 'string' ? error : __('There was an error')}
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
</div>
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
)}
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
</div>
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
);
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
}
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
}
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
type SubmitProps = {
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
label: string,
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
disabled: boolean,
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
};
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
export class Submit extends React.PureComponent<SubmitProps> {
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
static defaultProps = {
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
label: 'Submit',
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
};
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
render() {
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
const { label, disabled } = this.props;
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
return <Button type="submit" label={label} disabled={disabled} />;
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
}
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
}
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
type FormProps = {
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
children: React.Node,
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
onSubmit: any => any,
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
};
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
export class Form extends React.PureComponent<FormProps> {
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
render() {
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
const { children, onSubmit } = this.props;
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
return (
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
<form
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
className="form"
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
onSubmit={event => {
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
event.preventDefault();
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
onSubmit(event);
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
}}
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
>
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
{children}
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
</form>
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
);
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
}
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
}
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
||||
/* eslint-enable react/no-multi-comp */
|
||||
Using Using `render` and `children` are really similar. Maybe we should just choose one and use it everywhere. The additional feature that `render` gives you is that you can pass state/computed values into the render function and allow consuming components to interact with it in a more customizable way.
|
|
@ -1,43 +1,22 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import classnames from 'classnames';
|
||||
import * as icons from 'constants/icons';
|
||||
// import * as icons from 'constants/icons';
|
||||
import * as Icons from 'react-feather';
|
||||
|
||||
type Props = {
|
||||
icon: string,
|
||||
fixed?: boolean,
|
||||
padded?: boolean,
|
||||
size?: number,
|
||||
};
|
||||
|
||||
class Icon extends React.PureComponent<Props> {
|
||||
getIconTitle() {
|
||||
const { icon } = this.props;
|
||||
|
||||
switch (icon) {
|
||||
case icons.FEATURED:
|
||||
return __('Watch this and earn rewards.');
|
||||
case icons.LOCAL:
|
||||
return __('You have a copy of this file.');
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
class IconComponent extends React.PureComponent<Props> {
|
||||
// TODO: Move all icons to constants and add titles for all
|
||||
// Add some some sort of hover flyout with the title?
|
||||
|
||||
render() {
|
||||
const { icon, fixed, padded } = this.props;
|
||||
const iconClassName = icon.startsWith('icon-') ? icon : `icon-${icon}`;
|
||||
const title = this.getIconTitle();
|
||||
|
||||
const spanClassName = classnames(
|
||||
{
|
||||
'icon--fixed-width': fixed,
|
||||
'icon--padded': padded,
|
||||
},
|
||||
iconClassName
|
||||
);
|
||||
|
||||
return <span className={spanClassName} title={title} />;
|
||||
const { icon, size = 14 } = this.props;
|
||||
const Icon = Icons[icon];
|
||||
return Icon ? <Icon size={size} className="icon" /> : null;
|
||||
}
|
||||
}
|
||||
|
||||
export default Icon;
|
||||
export default IconComponent;
|
||||
|
|
|
@ -46,7 +46,7 @@ class ToolTip extends React.PureComponent<Props, State> {
|
|||
<span className="tooltip">
|
||||
<Button fakeLink className="help tooltip__link" onClick={this.handleClick}>
|
||||
{label}
|
||||
{showTooltip && <Icon icon="times" fixed />}
|
||||
{showTooltip && <Icon icon="X" />}
|
||||
</Button>
|
||||
<div className={classnames('tooltip__body', { hidden: !showTooltip })}>{body}</div>
|
||||
</span>
|
||||
|
|
|
@ -78,6 +78,9 @@ class FileCard extends React.PureComponent<Props> {
|
|||
})}
|
||||
>
|
||||
<CardMedia thumbnail={thumbnail} />
|
||||
<div className="card-media__internal-links">
|
||||
<FilePrice uri={uri} />
|
||||
</div>
|
||||
|
||||
<div className="card__title-identity">
|
||||
<div className="card__title--small">
|
||||
|
@ -87,8 +90,8 @@ class FileCard extends React.PureComponent<Props> {
|
|||
<div className="card__subtitle">
|
||||
<UriIndicator uri={uri} link />
|
||||
<div className="card--file-subtitle">
|
||||
<FilePrice uri={uri} /> {isRewardContent && <Icon icon={icons.FEATURED} padded />}
|
||||
{fileInfo && <Icon icon={icons.LOCAL} padded />}
|
||||
{isRewardContent && <Icon icon={icons.FEATURED} />}
|
||||
{fileInfo && <Icon icon={icons.LOCAL} />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,35 +1,48 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import { CreditAmount } from 'component/common';
|
||||
import CreditAmount from 'component/common/credit-amount';
|
||||
|
||||
type Props = {
|
||||
showFullPrice: boolean,
|
||||
costInfo: ?{ includesData: boolean, cost: number },
|
||||
fetchCostInfo: string => void,
|
||||
uri: string,
|
||||
fetching: boolean,
|
||||
claim: ?{},
|
||||
};
|
||||
|
||||
class FilePrice extends React.PureComponent<Props> {
|
||||
static defaultProps = {
|
||||
showFullPrice: false,
|
||||
};
|
||||
|
||||
class FilePrice extends React.PureComponent {
|
||||
componentWillMount() {
|
||||
this.fetchCost(this.props);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
componentWillReceiveProps(nextProps: Props) {
|
||||
this.fetchCost(nextProps);
|
||||
}
|
||||
|
||||
fetchCost(props) {
|
||||
fetchCost = (props: Props) => {
|
||||
const { costInfo, fetchCostInfo, uri, fetching, claim } = props;
|
||||
|
||||
if (costInfo === undefined && !fetching && claim) {
|
||||
fetchCostInfo(uri);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { costInfo, look = 'indicator', showFullPrice = false } = this.props;
|
||||
const { costInfo, showFullPrice } = this.props;
|
||||
|
||||
const isEstimate = costInfo ? !costInfo.includesData : null;
|
||||
const isEstimate = costInfo ? !costInfo.includesData : false;
|
||||
|
||||
if (!costInfo) {
|
||||
return <span className={`credit-amount credit-amount--${look}`}>???</span>;
|
||||
return <span className="credit-amount">???</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<CreditAmount
|
||||
label={false}
|
||||
amount={costInfo.cost}
|
||||
isEstimate={isEstimate}
|
||||
showFree
|
||||
|
|
|
@ -1,186 +0,0 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import FormField from 'component/formField';
|
||||
import Icon from 'component/common/icon';
|
||||
|
||||
let formFieldCounter = 0;
|
||||
|
||||
export const formFieldNestedLabelTypes = ['radio', 'checkbox'];
|
||||
|
||||
export function formFieldId() {
|
||||
return `form-field-${++formFieldCounter}`;
|
||||
}
|
||||
|
||||
export class Form extends React.PureComponent {
|
||||
static propTypes = {
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
handleSubmit(event) {
|
||||
event.preventDefault();
|
||||
this.props.onSubmit();
|
||||
}
|
||||
|
||||
render() {
|
||||
return <form onSubmit={event => this.handleSubmit(event)}>{this.props.children}</form>;
|
||||
}
|
||||
}
|
||||
|
||||
export class FormRow extends React.PureComponent {
|
||||
static propTypes = {
|
||||
label: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
|
||||
errorMessage: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
// helper: PropTypes.html,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
isFocus: false,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this._field = null;
|
||||
|
||||
this._fieldRequiredText = __('This field is required');
|
||||
|
||||
this.state = this.getStateFromProps(props);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.setState(this.getStateFromProps(nextProps));
|
||||
}
|
||||
|
||||
getStateFromProps(props) {
|
||||
return {
|
||||
isError: !!props.errorMessage,
|
||||
errorMessage:
|
||||
typeof props.errorMessage === 'string'
|
||||
? props.errorMessage
|
||||
: props.errorMessage instanceof Error ? props.errorMessage.toString() : '',
|
||||
};
|
||||
}
|
||||
|
||||
showError(text) {
|
||||
this.setState({
|
||||
isError: true,
|
||||
errorMessage: text,
|
||||
});
|
||||
}
|
||||
|
||||
showRequiredError() {
|
||||
this.showError(this._fieldRequiredText);
|
||||
}
|
||||
|
||||
clearError(text) {
|
||||
this.setState({
|
||||
isError: false,
|
||||
errorMessage: '',
|
||||
});
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this._field.getValue();
|
||||
}
|
||||
|
||||
getSelectedElement() {
|
||||
return this._field.getSelectedElement();
|
||||
}
|
||||
|
||||
getOptions() {
|
||||
return this._field.getOptions();
|
||||
}
|
||||
|
||||
focus() {
|
||||
this._field.focus();
|
||||
}
|
||||
|
||||
onFocus() {
|
||||
this.setState({ isFocus: true });
|
||||
}
|
||||
|
||||
onBlur() {
|
||||
this.setState({ isFocus: false });
|
||||
}
|
||||
|
||||
render() {
|
||||
const fieldProps = Object.assign({}, this.props),
|
||||
elementId = formFieldId(),
|
||||
renderLabelInFormField = formFieldNestedLabelTypes.includes(this.props.type);
|
||||
|
||||
if (!renderLabelInFormField) {
|
||||
delete fieldProps.label;
|
||||
}
|
||||
delete fieldProps.helper;
|
||||
delete fieldProps.errorMessage;
|
||||
delete fieldProps.isFocus;
|
||||
|
||||
return (
|
||||
<div className={`form-row${this.state.isFocus ? ' form-row--focus' : ''}`}>
|
||||
{this.props.label && !renderLabelInFormField ? (
|
||||
<div
|
||||
className={`form-row__label-row ${
|
||||
this.props.labelPrefix ? 'form-row__label-row--prefix' : ''
|
||||
}`}
|
||||
>
|
||||
<label
|
||||
htmlFor={elementId}
|
||||
className={`form-field__label ${
|
||||
this.state.isError ? 'form-field__label--error' : ' '
|
||||
}`}
|
||||
>
|
||||
{this.props.label}
|
||||
</label>
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
<FormField
|
||||
ref={ref => {
|
||||
this._field = ref ? ref.getWrappedInstance() : null;
|
||||
}}
|
||||
hasError={this.state.isError}
|
||||
onFocus={this.onFocus.bind(this)}
|
||||
onBlur={this.onBlur.bind(this)}
|
||||
{...fieldProps}
|
||||
/>
|
||||
{!this.state.isError && this.props.helper ? (
|
||||
<div className="form-field__helper">{this.props.helper}</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
{this.state.isError ? (
|
||||
<div className="form-field__error">{this.state.errorMessage}</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const Submit = props => {
|
||||
const { title, label, icon, disabled } = props;
|
||||
|
||||
const className = `${'button-block' +
|
||||
' button-primary' +
|
||||
' button-set-item' +
|
||||
' button--submit'}${disabled ? ' disabled' : ''}`;
|
||||
|
||||
const content = (
|
||||
<span className="button__content">
|
||||
{'icon' in props ? <Icon icon={icon} fixed /> : null}
|
||||
{label ? <span className="button-label">{label}</span> : null}
|
||||
</span>
|
||||
);
|
||||
|
||||
return (
|
||||
<button type="submit" className={className} title={title}>
|
||||
{content}
|
||||
</button>
|
||||
);
|
||||
};
|
|
@ -1,8 +1,10 @@
|
|||
// This file is going to die
|
||||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import FileSelector from 'component/file-selector.js';
|
||||
import SimpleMDE from 'react-simplemde-editor';
|
||||
import { formFieldNestedLabelTypes, formFieldId } from '../form';
|
||||
import { formFieldNestedLabelTypes, formFieldId } from 'component/common/form';
|
||||
import style from 'react-simplemde-editor/dist/simplemde.min.css';
|
||||
|
||||
const formFieldFileSelectorTypes = ['file', 'directory'];
|
||||
|
@ -195,3 +197,4 @@ class FormField extends React.PureComponent {
|
|||
}
|
||||
|
||||
export default FormField;
|
||||
/* eslint-enable */
|
||||
|
|
|
@ -1,25 +1,17 @@
|
|||
import React from 'react';
|
||||
import { formatCredits } from 'util/formatCredits';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectIsBackDisabled, selectIsForwardDisabled } from 'redux/selectors/navigation';
|
||||
import { selectBalance } from 'redux/selectors/wallet';
|
||||
import { doNavigate, doHistoryBack, doHistoryForward } from 'redux/actions/navigation';
|
||||
import Header from './view';
|
||||
import { doNavigate } from 'redux/actions/navigation';
|
||||
import { selectIsUpgradeAvailable } from 'redux/selectors/app';
|
||||
import { doDownloadUpgrade } from 'redux/actions/app';
|
||||
import { formatCredits } from 'util/formatCredits';
|
||||
import { selectBalance } from 'redux/selectors/wallet';
|
||||
import Header from './view';
|
||||
|
||||
const select = state => ({
|
||||
isBackDisabled: selectIsBackDisabled(state),
|
||||
isForwardDisabled: selectIsForwardDisabled(state),
|
||||
isUpgradeAvailable: selectIsUpgradeAvailable(state),
|
||||
balance: formatCredits(selectBalance(state) || 0, 2),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
navigate: path => dispatch(doNavigate(path)),
|
||||
back: () => dispatch(doHistoryBack()),
|
||||
forward: () => dispatch(doHistoryForward()),
|
||||
downloadUpgrade: () => dispatch(doDownloadUpgrade()),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(Header);
|
||||
|
|
|
@ -5,78 +5,34 @@ import WunderBar from 'component/wunderbar';
|
|||
|
||||
type Props = {
|
||||
balance: string,
|
||||
back: any => void,
|
||||
forward: any => void,
|
||||
isBackDisabled: boolean,
|
||||
isForwardDisabled: boolean,
|
||||
isUpgradeAvailable: boolean,
|
||||
navigate: any => void,
|
||||
downloadUpgrade: any => void,
|
||||
isUpgradeAvailable: boolean,
|
||||
};
|
||||
|
||||
export const Header = (props: Props) => {
|
||||
const {
|
||||
balance,
|
||||
back,
|
||||
forward,
|
||||
isBackDisabled,
|
||||
isForwardDisabled,
|
||||
isUpgradeAvailable,
|
||||
navigate,
|
||||
downloadUpgrade,
|
||||
} = props;
|
||||
const Header = (props: Props) => {
|
||||
const { balance, isUpgradeAvailable, navigate, downloadUpgrade } = props;
|
||||
return (
|
||||
<header id="header">
|
||||
<div className="header__actions-left">
|
||||
<Button
|
||||
alt
|
||||
circle
|
||||
onClick={back}
|
||||
disabled={isBackDisabled}
|
||||
icon="arrow-left"
|
||||
description={__('Navigate back')}
|
||||
/>
|
||||
|
||||
<Button
|
||||
alt
|
||||
circle
|
||||
onClick={forward}
|
||||
disabled={isForwardDisabled}
|
||||
icon="arrow-right"
|
||||
description={__('Navigate forward')}
|
||||
/>
|
||||
|
||||
<Button alt onClick={() => navigate('/discover')} icon="home" description={__('Home')} />
|
||||
</div>
|
||||
|
||||
<header className="header">
|
||||
<WunderBar />
|
||||
|
||||
<div className="header__actions-right">
|
||||
<Button
|
||||
inverse
|
||||
onClick={() => navigate('/wallet')}
|
||||
icon="user"
|
||||
icon="User"
|
||||
label={isUpgradeAvailable ? `${balance} LBC` : `You have ${balance} LBC`}
|
||||
description={__('Your wallet')}
|
||||
/>
|
||||
|
||||
<Button
|
||||
onClick={() => navigate('/publish')}
|
||||
icon="cloud-upload"
|
||||
icon="UploadCloud"
|
||||
label={isUpgradeAvailable ? '' : __('Publish')}
|
||||
description={__('Publish content')}
|
||||
/>
|
||||
|
||||
<Button
|
||||
alt
|
||||
onClick={() => navigate('/settings')}
|
||||
icon="gear"
|
||||
description={__('Settings')}
|
||||
/>
|
||||
|
||||
<Button alt onClick={() => navigate('/help')} icon="question" description={__('Help')} />
|
||||
{isUpgradeAvailable && (
|
||||
<Button onClick={() => downloadUpgrade()} icon="arrow-up" label={__('Upgrade App')} />
|
||||
<Button onClick={() => downloadUpgrade()} icon="Download" label={__('Upgrade App')} />
|
||||
)}
|
||||
</div>
|
||||
</header>
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
// I'll come back to this
|
||||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import { BusyMessage, CreditAmount } from 'component/common';
|
||||
import { Form, FormRow, Submit } from 'component/form.js';
|
||||
import { BusyMessage } from 'component/common';
|
||||
import CreditAmount from 'component/common/credit-amount';
|
||||
// import { Form, FormField } from 'component/common/form';
|
||||
|
||||
class FormInviteNew extends React.PureComponent {
|
||||
constructor(props) {
|
||||
|
@ -24,25 +27,25 @@ class FormInviteNew extends React.PureComponent {
|
|||
|
||||
render() {
|
||||
const { errorMessage, isPending } = this.props;
|
||||
|
||||
return (
|
||||
<Form onSubmit={this.handleSubmit.bind(this)}>
|
||||
<FormRow
|
||||
type="text"
|
||||
label="Email"
|
||||
placeholder="youremail@example.org"
|
||||
name="email"
|
||||
value={this.state.email}
|
||||
errorMessage={errorMessage}
|
||||
onChange={event => {
|
||||
this.handleEmailChanged(event);
|
||||
}}
|
||||
/>
|
||||
<div className="form-row-submit">
|
||||
<Submit label={__('Send Invite')} disabled={isPending} />
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
return null;
|
||||
// return (
|
||||
// <Form onSubmit={this.handleSubmit.bind(this)}>
|
||||
// <FormRow
|
||||
// type="text"
|
||||
// label="Email"
|
||||
// placeholder="youremail@example.org"
|
||||
// name="email"
|
||||
// value={this.state.email}
|
||||
// errorMessage={errorMessage}
|
||||
// onChange={event => {
|
||||
// this.handleEmailChanged(event);
|
||||
// }}
|
||||
// />
|
||||
// <div className="form-row-submit">
|
||||
// <Submit label={__('Send Invite')} disabled={isPending} />
|
||||
// </div>
|
||||
// </Form>
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,3 +83,4 @@ class InviteNew extends React.PureComponent {
|
|||
}
|
||||
|
||||
export default InviteNew;
|
||||
/* eslint-enable */
|
||||
|
|
|
@ -22,6 +22,8 @@ type Props = {
|
|||
alt: ?boolean,
|
||||
flat: ?boolean,
|
||||
fakeLink: ?boolean,
|
||||
noStyle: ?boolean,
|
||||
noUnderline: ?boolean,
|
||||
description: ?string,
|
||||
};
|
||||
|
||||
|
@ -45,20 +47,25 @@ const Button = (props: Props) => {
|
|||
flat,
|
||||
fakeLink,
|
||||
description,
|
||||
noStyle,
|
||||
noUnderline,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
const combinedClassName = classnames(
|
||||
{
|
||||
btn: !fakeLink,
|
||||
'btn--link': fakeLink,
|
||||
'btn--primary': !fakeLink && !alt,
|
||||
'btn--alt': alt,
|
||||
'btn--inverse': inverse,
|
||||
'btn--disabled': disabled,
|
||||
'btn--circle': circle,
|
||||
'btn--flat': flat,
|
||||
},
|
||||
'btn',
|
||||
noStyle
|
||||
? 'btn--no-style'
|
||||
: {
|
||||
'btn--link': fakeLink,
|
||||
'btn--primary': !alt && !fakeLink,
|
||||
'btn--alt': alt,
|
||||
'btn--inverse': inverse,
|
||||
'btn--disabled': disabled,
|
||||
'btn--circle': circle,
|
||||
'btn--flat': flat,
|
||||
'btn--no-underline': fakeLink && noUnderline,
|
||||
},
|
||||
className
|
||||
);
|
||||
|
||||
|
@ -72,10 +79,10 @@ const Button = (props: Props) => {
|
|||
|
||||
const content = (
|
||||
<React.Fragment>
|
||||
{icon && <Icon icon={icon} fixed />}
|
||||
{icon && <Icon icon={icon} />}
|
||||
{label && <span className="btn__label">{label}</span>}
|
||||
{children && children}
|
||||
{iconRight && <Icon icon={iconRight} fixed />}
|
||||
{iconRight && <Icon icon={iconRight} />}
|
||||
</React.Fragment>
|
||||
);
|
||||
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
This wasn't being used anywhere This wasn't being used anywhere
This wasn't being used anywhere This wasn't being used anywhere
|
||||
import React from 'react';
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
import PropTypes from 'prop-types';
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
import Icon from 'component/common/icon';
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
import Link from 'component/link';
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
export class DropDownMenuItem extends React.PureComponent {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
static propTypes = {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
href: PropTypes.string,
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
label: PropTypes.string,
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
icon: PropTypes.string,
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
onClick: PropTypes.func,
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
};
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
static defaultProps = {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
iconPosition: 'left',
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
};
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
render() {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
const icon = this.props.icon ? <Icon icon={this.props.icon} fixed /> : null;
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
return (
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
<a
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
className="menu__menu-item"
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
onClick={this.props.onClick}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
href={this.props.href || 'javascript:'}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
label={this.props.label}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
>
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
{this.props.iconPosition == 'left' ? icon : null}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
{this.props.label}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
{this.props.iconPosition == 'left' ? null : icon}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
</a>
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
);
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
export class DropDownMenu extends React.PureComponent {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
constructor(props) {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
super(props);
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
this._isWindowClickBound = false;
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
this._menuDiv = null;
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
this.state = {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
menuOpen: false,
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
};
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
componentWillUnmount() {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
if (this._isWindowClickBound) {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
window.removeEventListener('click', this.handleWindowClick, false);
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
handleMenuIconClick(e) {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
this.setState({
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
menuOpen: !this.state.menuOpen,
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
});
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
if (!this.state.menuOpen && !this._isWindowClickBound) {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
this._isWindowClickBound = true;
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
window.addEventListener('click', this.handleWindowClick, false);
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
e.stopPropagation();
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
return false;
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
handleMenuClick(e) {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
// Event bubbles up to the menu after a link is clicked
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
this.setState({
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
menuOpen: false,
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
});
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
/* this will force "this" to always be the class, even when passed to an event listener */
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
handleWindowClick = e => {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
if (this.state.menuOpen && (!this._menuDiv || !this._menuDiv.contains(e.target))) {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
this.setState({
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
menuOpen: false,
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
});
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
};
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
render() {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
if (!this.state.menuOpen && this._isWindowClickBound) {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
this._isWindowClickBound = false;
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
window.removeEventListener('click', this.handleWindowClick, false);
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
return (
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
<div className="menu-container">
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
<Link
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
ref={span => (this._menuButton = span)}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
button="text"
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
icon="icon-ellipsis-v"
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
onClick={event => {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
this.handleMenuIconClick(event);
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
}}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
/>
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
{this.state.menuOpen ? (
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
<div
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
ref={div => (this._menuDiv = div)}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
className="menu"
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
onClick={event => {
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
this.handleMenuClick(event);
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
}}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
>
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
{this.props.children}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
</div>
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
) : null}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
</div>
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
);
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
||||
}
|
||||
This wasn't being used anywhere This wasn't being used anywhere
|
|
@ -1,9 +1,31 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { selectPageTitle } from 'redux/selectors/navigation';
|
||||
import {
|
||||
selectPageTitle,
|
||||
selectIsBackDisabled,
|
||||
selectIsForwardDisabled,
|
||||
selectNavLinks,
|
||||
} from 'redux/selectors/navigation';
|
||||
import { doNavigate, doHistoryBack, doHistoryForward } from 'redux/actions/navigation';
|
||||
import { doDownloadUpgrade } from 'redux/actions/app';
|
||||
import { selectIsUpgradeAvailable } from 'redux/selectors/app';
|
||||
import { formatCredits } from 'util/formatCredits';
|
||||
import { selectBalance } from 'redux/selectors/wallet';
|
||||
import Page from './view';
|
||||
|
||||
const select = state => ({
|
||||
title: selectPageTitle(state),
|
||||
pageTitle: selectPageTitle(state),
|
||||
navLinks: selectNavLinks(state),
|
||||
isBackDisabled: selectIsBackDisabled(state),
|
||||
isForwardDisabled: selectIsForwardDisabled(state),
|
||||
isUpgradeAvailable: selectIsUpgradeAvailable(state),
|
||||
balance: formatCredits(selectBalance(state) || 0, 2),
|
||||
});
|
||||
|
||||
export default connect(select, null)(Page);
|
||||
const perform = dispatch => ({
|
||||
navigate: path => dispatch(doNavigate(path)),
|
||||
back: () => dispatch(doHistoryBack()),
|
||||
forward: () => dispatch(doHistoryForward()),
|
||||
downloadUpgrade: () => dispatch(doDownloadUpgrade()),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(Page);
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
// @flow
|
||||
import * as React from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { BusyMessage } from 'component/common';
|
||||
|
||||
type Props = {
|
||||
children: React.Node,
|
||||
title: ?string,
|
||||
pageTitle: ?string,
|
||||
noPadding: ?boolean,
|
||||
isLoading: ?boolean,
|
||||
};
|
||||
|
||||
const Page = (props: Props) => {
|
||||
const { children, title, noPadding, isLoading } = props;
|
||||
const { pageTitle, children, noPadding } = props;
|
||||
return (
|
||||
<main id="main-content">
|
||||
<div className="page__header">
|
||||
{title && <h1 className="page__title">{title}</h1>}
|
||||
{isLoading && <BusyMessage message={__('Fetching content')} />}
|
||||
</div>
|
||||
<div className={classnames('main', { 'main--no-padding': noPadding })}>{children}</div>
|
||||
<main className={classnames('main', { 'main--no-padding': noPadding })}>
|
||||
{pageTitle && (
|
||||
<div className="page__header">
|
||||
{pageTitle && <h1 className="page__title">{pageTitle}</h1>}
|
||||
</div>
|
||||
)}
|
||||
{children}
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// I'll come back to this
|
||||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import { isNameValid } from 'lbryURI';
|
||||
import { FormRow } from 'component/form.js';
|
||||
import { FormRow } from 'component/common/form';
|
||||
import { BusyMessage } from 'component/common';
|
||||
import Link from 'component/link';
|
||||
|
||||
|
@ -167,3 +169,4 @@ class ChannelSection extends React.PureComponent {
|
|||
}
|
||||
|
||||
export default ChannelSection;
|
||||
/* eslint-enable */
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
// I'll come back to this
|
||||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import lbry from 'lbry';
|
||||
import { isNameValid, buildURI, regexInvalidURI } from 'lbryURI';
|
||||
import FormField from 'component/formField';
|
||||
import { Form, FormRow, Submit } from 'component/form.js';
|
||||
import { Form, FormRow } from 'component/common/form';
|
||||
import Link from 'component/link';
|
||||
import FormFieldPrice from 'component/formFieldPrice';
|
||||
import Modal from 'modal/modal';
|
||||
|
@ -832,7 +834,8 @@ class PublishForm extends React.PureComponent {
|
|||
</section>
|
||||
|
||||
<div className="card-series-submit">
|
||||
<Submit
|
||||
<Link
|
||||
type="submit"
|
||||
label={!this.state.submitting ? __('Publish') : __('Publishing...')}
|
||||
disabled={
|
||||
this.props.balance <= 0 ||
|
||||
|
@ -878,3 +881,4 @@ class PublishForm extends React.PureComponent {
|
|||
}
|
||||
|
||||
export default PublishForm;
|
||||
/* eslint-enable */
|
||||
|
|
|
@ -1,7 +1,20 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import LinkTransaction from 'component/linkTransaction';
|
||||
|
||||
const RewardListClaimed = props => {
|
||||
type Reward = {
|
||||
id: string,
|
||||
reward_title: string,
|
||||
reward_amount: number,
|
||||
transaction_id: string,
|
||||
created_at: string,
|
||||
};
|
||||
|
||||
type Props = {
|
||||
rewards: Array<Reward>,
|
||||
};
|
||||
|
||||
const RewardListClaimed = (props: Props) => {
|
||||
const { rewards } = props;
|
||||
|
||||
if (!rewards || !rewards.length) {
|
||||
|
@ -9,7 +22,7 @@ const RewardListClaimed = props => {
|
|||
}
|
||||
|
||||
return (
|
||||
<section className="card">
|
||||
<section className="card card--section">
|
||||
<div className="card__title-identity">
|
||||
<h3>Claimed Rewards</h3>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import Link from 'component/link';
|
||||
import { CreditAmount } from 'component/common';
|
||||
import * as React from 'react';
|
||||
import Button from 'component/link';
|
||||
import CreditAmount from 'component/common/credit-amount';
|
||||
|
||||
type Props = {
|
||||
unclaimedRewardAmount: number,
|
||||
|
@ -9,24 +9,25 @@ type Props = {
|
|||
|
||||
const RewardSummary = (props: Props) => {
|
||||
const { unclaimedRewardAmount } = props;
|
||||
const hasRewards = unclaimedRewardAmount > 0;
|
||||
|
||||
return (
|
||||
<section className="card">
|
||||
<div className="card__title-primary">
|
||||
<h3>{__('Rewards')}</h3>
|
||||
</div>
|
||||
<div className="card__content">
|
||||
{unclaimedRewardAmount > 0 ? (
|
||||
<p>
|
||||
<section className="card card--section">
|
||||
<h2>{__('Rewards')}</h2>
|
||||
<p className="card__subtitle">
|
||||
{hasRewards ? (
|
||||
<React.Fragment>
|
||||
{__('You have')} <CreditAmount amount={unclaimedRewardAmount} precision={8} />{' '}
|
||||
{__('in unclaimed rewards')}.
|
||||
</p>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<p>{__('There are no rewards available at this time, please check back later')}.</p>
|
||||
<React.Fragment>
|
||||
{__('There are no rewards available at this time, please check back later')}.
|
||||
</React.Fragment>
|
||||
)}
|
||||
</div>
|
||||
</p>
|
||||
<div className="card__actions">
|
||||
<Link button="primary" navigate="/rewards" label={__('Claim Rewards')} />
|
||||
<Button navigate="/rewards" label={hasRewards ? __('Claim Rewards') : __('View Rewards')} />
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
|
|
@ -1,16 +1,30 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import { CreditAmount, Icon } from 'component/common';
|
||||
import CreditAmount from 'component/common/credit-amount';
|
||||
import Icon from 'component/common/icon';
|
||||
import RewardLink from 'component/rewardLink';
|
||||
import Link from 'component/link';
|
||||
import Button from 'component/link';
|
||||
import rewards from 'rewards';
|
||||
|
||||
const RewardTile = props => {
|
||||
type Props = {
|
||||
reward: {
|
||||
id: string,
|
||||
reward_title: string,
|
||||
reward_amount: number,
|
||||
transaction_id: string,
|
||||
created_at: string,
|
||||
reward_description: string,
|
||||
reward_type: string,
|
||||
},
|
||||
};
|
||||
|
||||
const RewardTile = (props: Props) => {
|
||||
const { reward } = props;
|
||||
|
||||
const claimed = !!reward.transaction_id;
|
||||
|
||||
return (
|
||||
<section className="card">
|
||||
<section className="card card--section">
|
||||
<div className="card__inner">
|
||||
<div className="card__title-primary">
|
||||
<CreditAmount amount={reward.reward_amount} />
|
||||
|
@ -18,8 +32,8 @@ const RewardTile = props => {
|
|||
</div>
|
||||
<div className="card__content">{reward.reward_description}</div>
|
||||
<div className="card__actions ">
|
||||
{reward.reward_type == rewards.TYPE_REFERRAL && (
|
||||
<Link button="alt" navigate="/invite" label={__('Go To Invites')} />
|
||||
{reward.reward_type === rewards.TYPE_REFERRAL && (
|
||||
<Button alt navigate="/invite" label={__('Go To Invites')} />
|
||||
)}
|
||||
{reward.reward_type !== rewards.TYPE_REFERRAL &&
|
||||
(claimed ? (
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import Link from 'component/link';
|
||||
import { getExampleAddress } from 'util/shape_shift';
|
||||
import { Submit, FormRow } from 'component/form';
|
||||
import { FormField, Submit } from 'component/common/form';
|
||||
import type { ShapeShiftFormValues, Dispatch } from 'redux/actions/shape_shift';
|
||||
import ShiftMarketInfo from './market_info';
|
||||
|
||||
|
@ -12,7 +12,7 @@ type ShapeShiftFormErrors = {
|
|||
type Props = {
|
||||
values: ShapeShiftFormValues,
|
||||
errors: ShapeShiftFormErrors,
|
||||
touched: boolean,
|
||||
touched: { returnAddress: boolean },
|
||||
handleChange: Event => any,
|
||||
handleBlur: Event => any,
|
||||
handleSubmit: Event => any,
|
||||
|
@ -21,7 +21,6 @@ type Props = {
|
|||
originCoin: string,
|
||||
updating: boolean,
|
||||
getCoinStats: Dispatch,
|
||||
receiveAddress: string,
|
||||
originCoinDepositFee: number,
|
||||
originCoinDepositMin: string,
|
||||
originCoinDepositMax: number,
|
||||
|
@ -41,7 +40,6 @@ export default (props: Props) => {
|
|||
originCoin,
|
||||
updating,
|
||||
getCoinStats,
|
||||
receiveAddress,
|
||||
originCoinDepositMax,
|
||||
originCoinDepositMin,
|
||||
originCoinDepositFee,
|
||||
|
@ -49,23 +47,27 @@ export default (props: Props) => {
|
|||
} = props;
|
||||
return (
|
||||
I think I'm going to change this to I think I'm going to change this to `FormElement` and keep `FormRow` which just allows several `FormElement`s side by side
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="form-field">
|
||||
<span>{__('Exchange')} </span>
|
||||
<select
|
||||
className="form-field__input form-field__input-select"
|
||||
name="originCoin"
|
||||
onChange={e => {
|
||||
getCoinStats(e.target.value);
|
||||
handleChange(e);
|
||||
}}
|
||||
>
|
||||
{shiftSupportedCoins.map(coin => (
|
||||
<option key={coin} value={coin}>
|
||||
{coin}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<span> {__('for LBC')}</span>
|
||||
<FormField
|
||||
prefix={__('Exchange')}
|
||||
postfix={__('for LBC')}
|
||||
render={() => (
|
||||
<select
|
||||
className="form-field__input form-field__input-select"
|
||||
name="originCoin"
|
||||
onChange={e => {
|
||||
getCoinStats(e.target.value);
|
||||
handleChange(e);
|
||||
}}
|
||||
>
|
||||
{shiftSupportedCoins.map(coin => (
|
||||
<option key={coin} value={coin}>
|
||||
{coin}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
)}
|
||||
/>
|
||||
<div>
|
||||
<div className="shapeshift__tx-info">
|
||||
{!updating &&
|
||||
originCoinDepositMax && (
|
||||
|
@ -80,16 +82,19 @@ export default (props: Props) => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<FormRow
|
||||
type="text"
|
||||
name="returnAddress"
|
||||
placeholder={getExampleAddress(originCoin)}
|
||||
<FormField
|
||||
label={__('Return address')}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
value={values.returnAddress}
|
||||
errorMessage={errors.returnAddress}
|
||||
hasError={touched.returnAddress && !!errors.returnAddress}
|
||||
error={touched.returnAddress && !!errors.returnAddress && errors.returnAddress}
|
||||
render={() => (
|
||||
<input
|
||||
type="text"
|
||||
name="returnAddress"
|
||||
placeholder={getExampleAddress(originCoin)}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
value={values.returnAddress}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<span className="help">
|
||||
<span>
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
// @flow
|
||||
import * as React from 'react';
|
||||
import { shell } from 'electron';
|
||||
import { Formik } from 'formik';
|
||||
import classnames from 'classnames';
|
||||
import * as statuses from 'constants/shape_shift';
|
||||
import { validateShapeShiftForm } from 'util/shape_shift';
|
||||
import Link from 'component/link';
|
||||
import Spinner from 'component/common/spinner';
|
||||
import { BusyMessage } from 'component/common';
|
||||
import ShapeShiftForm from './internal/form';
|
||||
import ActiveShapeShift from './internal/active-shift';
|
||||
|
||||
import type { ShapeShiftState } from 'redux/reducers/shape_shift';
|
||||
import type { Dispatch, ShapeShiftFormValues } from 'redux/actions/shape_shift';
|
||||
import ShapeShiftForm from './internal/form';
|
||||
import ActiveShapeShift from './internal/active-shift';
|
||||
|
||||
type Props = {
|
||||
shapeShift: ShapeShiftState,
|
||||
|
@ -72,28 +66,17 @@ class ShapeShift extends React.PureComponent<Props> {
|
|||
};
|
||||
|
||||
return (
|
||||
// add the "shapeshift__intital-wrapper class so we can avoid content jumping once everything loads"
|
||||
// it just gives the section a min-height equal to the height of the content when the form is rendered
|
||||
// if the markup below changes for the initial render (form.jsx) there will be content jumping
|
||||
// the styling in shapeshift.scss will need to be updated to the correct min-height
|
||||
<section
|
||||
className={classnames('card shapeshift__wrapper', {
|
||||
'shapeshift__initial-wrapper': loading,
|
||||
})}
|
||||
>
|
||||
<div className="card__title-primary">
|
||||
<h3>{__('Convert Crypto to LBC')}</h3>
|
||||
<p className="help">
|
||||
{__('Powered by ShapeShift. Read our FAQ')}{' '}
|
||||
<Link href="https://lbry.io/faq/shapeshift">{__('here')}</Link>.
|
||||
{hasActiveShift &&
|
||||
shiftState !== 'complete' && <span>{__('This will update automatically.')}</span>}
|
||||
</p>
|
||||
</div>
|
||||
<section className="card card--section">
|
||||
<h2>{__('Convert Crypto to LBC')}</h2>
|
||||
<p className="card__subtitle">
|
||||
{__('Powered by ShapeShift. Read our FAQ')}{' '}
|
||||
<Link fakeLink label={__('here')} href="https://lbry.io/faq/shapeshift" />.
|
||||
{hasActiveShift &&
|
||||
shiftState !== 'complete' && <span>{__('This will update automatically.')}</span>}
|
||||
</p>
|
||||
|
||||
<div className="card__content shapeshift__content">
|
||||
{error && <div className="form-field__error">{error}</div>}
|
||||
{loading && <Spinner dark />}
|
||||
{!loading &&
|
||||
!hasActiveShift &&
|
||||
!!shiftSupportedCoins.length && (
|
||||
|
@ -113,7 +96,6 @@ class ShapeShift extends React.PureComponent<Props> {
|
|||
originCoinDepositMin={originCoinDepositMin}
|
||||
originCoinDepositFee={originCoinDepositFee}
|
||||
shapeShiftRate={shapeShiftRate}
|
||||
updating={updating}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
@ -124,7 +106,6 @@ class ShapeShift extends React.PureComponent<Props> {
|
|||
shiftCoinType={shiftCoinType}
|
||||
shiftReturnAddress={shiftReturnAddress}
|
||||
shiftDepositAddress={shiftDepositAddress}
|
||||
originCoinDepositMax={originCoinDepositMax}
|
||||
shiftOrderId={shiftOrderId}
|
||||
shiftState={shiftState}
|
||||
clearShapeShift={clearShapeShift}
|
||||
|
|
24
src/renderer/component/sideBar/index.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doNavigate, doHistoryBack, doHistoryForward } from 'redux/actions/navigation';
|
||||
import {
|
||||
selectIsBackDisabled,
|
||||
selectIsForwardDisabled,
|
||||
selectIsHome,
|
||||
selectNavLinks,
|
||||
} from 'redux/selectors/navigation';
|
||||
import SideBar from './view';
|
||||
|
||||
const select = state => ({
|
||||
navLinks: selectNavLinks(state),
|
||||
isBackDisabled: selectIsBackDisabled(state),
|
||||
isForwardDisabled: selectIsForwardDisabled(state),
|
||||
isHome: selectIsHome(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
navigate: path => dispatch(doNavigate(path)),
|
||||
back: () => dispatch(doHistoryBack()),
|
||||
forward: () => dispatch(doHistoryForward()),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(SideBar);
|
101
src/renderer/component/sideBar/view.jsx
Normal file
|
@ -0,0 +1,101 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import Button from 'component/link';
|
||||
import classnames from 'classnames';
|
||||
|
||||
type SideBarLink = {
|
||||
label: string,
|
||||
path: string,
|
||||
active: boolean,
|
||||
icon: ?string,
|
||||
subLinks: Array<SideBarLink>,
|
||||
};
|
||||
|
||||
type Props = {
|
||||
navigate: any => void,
|
||||
back: any => void,
|
||||
forward: any => void,
|
||||
isBackDisabled: boolean,
|
||||
isForwardDisabled: boolean,
|
||||
isHome: boolean,
|
||||
navLinks: {
|
||||
primary: Array<SideBarLink>,
|
||||
secondary: Array<SideBarLink>,
|
||||
},
|
||||
};
|
||||
|
||||
const SideBar = (props: Props) => {
|
||||
const { navigate, back, forward, isBackDisabled, isForwardDisabled, isHome, navLinks } = props;
|
||||
return (
|
||||
<nav className="nav">
|
||||
<div className="nav__actions-top">
|
||||
<Button
|
||||
alt
|
||||
icon="Home"
|
||||
description={__('Home')}
|
||||
onClick={() => navigate('/discover')}
|
||||
disabled={isHome}
|
||||
/>
|
||||
<div className="nav__actions-history">
|
||||
<Button
|
||||
alt
|
||||
icon="ArrowLeft"
|
||||
description={__('Navigate back')}
|
||||
onClick={back}
|
||||
disabled={isBackDisabled}
|
||||
/>
|
||||
<Button
|
||||
alt
|
||||
icon="ArrowRight"
|
||||
description={__('Navigate forward')}
|
||||
onClick={forward}
|
||||
disabled={isForwardDisabled}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="nav__links">
|
||||
<ul className="nav__primary">
|
||||
{navLinks.primary.map(({ label, path, active, icon }) => (
|
||||
<li
|
||||
key={path}
|
||||
className={classnames('nav__link nav__primary-link', { 'nav__link--active': active })}
|
||||
>
|
||||
<Button noStyle navigate={path} label={label} icon={icon} />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<hr />
|
||||
<ul className="nav__secondary">
|
||||
{navLinks.secondary.map(({ label, path, active, icon, subLinks = [] }) => (
|
||||
<li
|
||||
key={path}
|
||||
className={classnames('nav__link nav__secondary-link', {
|
||||
'nav__link--active': active && !subLinks.length,
|
||||
})}
|
||||
>
|
||||
<Button noStyle navigate={path} label={label} icon={icon} />
|
||||
{!!subLinks.length &&
|
||||
active && (
|
||||
<ul className="nav__sub">
|
||||
{subLinks.map(({ label: subLabel, path: subPath, active: subLinkActive }) => (
|
||||
<li
|
||||
key={subPath}
|
||||
className={classnames('nav__link nav__sub-link', {
|
||||
'nav__link--active': subLinkActive,
|
||||
})}
|
||||
>
|
||||
<Button noStyle navigate={subPath} label={subLabel} />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
export default SideBar;
|
|
@ -1,16 +0,0 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectCurrentPage, selectHeaderLinks } from 'redux/selectors/navigation';
|
||||
import { doNavigate } from 'redux/actions/navigation';
|
||||
import SubHeader from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
currentPage: selectCurrentPage(state),
|
||||
subLinks: selectHeaderLinks(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
navigate: path => dispatch(doNavigate(path)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(SubHeader);
|
|
@ -1,34 +0,0 @@
|
|||
import React from 'react';
|
||||
import Link from 'component/link';
|
||||
import classnames from 'classnames';
|
||||
|
||||
const SubHeader = props => {
|
||||
const { subLinks, currentPage, navigate, fullWidth, smallMargin } = props;
|
||||
|
||||
const links = [];
|
||||
|
||||
for (const link of Object.keys(subLinks)) {
|
||||
links.push(
|
||||
<Link
|
||||
onClick={event => navigate(`/${link}`, event)}
|
||||
key={link}
|
||||
className={link == currentPage ? 'sub-header-selected' : 'sub-header-unselected'}
|
||||
>
|
||||
{subLinks[link]}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<nav
|
||||
className={classnames('sub-header', {
|
||||
'sub-header--full-width': fullWidth,
|
||||
'sub-header--small-margin': smallMargin,
|
||||
})}
|
||||
>
|
||||
{links}
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
export default SubHeader;
|
|
@ -1,6 +1,8 @@
|
|||
// I'll come back to this
|
||||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import LinkTransaction from 'component/linkTransaction';
|
||||
import { CreditAmount } from 'component/common';
|
||||
import CreditAmount from 'component/common/credit-amount';
|
||||
import DateTime from 'component/dateTime';
|
||||
import Link from 'component/link';
|
||||
import { buildURI } from 'lbryURI';
|
||||
|
@ -89,3 +91,4 @@ class TransactionListItem extends React.PureComponent {
|
|||
}
|
||||
|
||||
export default TransactionListItem;
|
||||
/* eslint-disable */
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// I'll come back to this
|
||||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import TransactionListItem from './internal/TransactionListItem';
|
||||
import FormField from 'component/formField';
|
||||
import { FormRow } from 'component/common/form';
|
||||
import Link from 'component/link';
|
||||
import * as icons from 'constants/icons';
|
||||
import * as modals from 'constants/modal_types';
|
||||
|
@ -44,20 +46,24 @@ class TransactionList extends React.PureComponent {
|
|||
return (
|
||||
<div>
|
||||
{(transactionList.length || this.state.filter) && (
|
||||
<span className="sort-section">
|
||||
{__('Filter')}{' '}
|
||||
<FormField type="select" onChange={this.handleFilterChanged.bind(this)}>
|
||||
<option value="">{__('All')}</option>
|
||||
<option value="spend">{__('Spends')}</option>
|
||||
<option value="receive">{__('Receives')}</option>
|
||||
<option value="publish">{__('Publishes')}</option>
|
||||
<option value="channel">{__('Channels')}</option>
|
||||
<option value="tip">{__('Tips')}</option>
|
||||
<option value="support">{__('Supports')}</option>
|
||||
<option value="update">{__('Updates')}</option>
|
||||
</FormField>{' '}
|
||||
<Link href="https://lbry.io/faq/transaction-types" icon={icons.HELP_CIRCLE} />
|
||||
</span>
|
||||
<FormRow
|
||||
prefix={__('Filter')}
|
||||
postfix={
|
||||
<Link fakeLink href="https://lbry.io/faq/transaction-types" label={__('Help')} />
|
||||
}
|
||||
render={() => (
|
||||
<select>
|
||||
<option value="">{__('All')}</option>
|
||||
<option value="spend">{__('Spends')}</option>
|
||||
<option value="receive">{__('Receives')}</option>
|
||||
<option value="publish">{__('Publishes')}</option>
|
||||
<option value="channel">{__('Channels')}</option>
|
||||
<option value="tip">{__('Tips')}</option>
|
||||
<option value="support">{__('Supports')}</option>
|
||||
<option value="update">{__('Updates')}</option>
|
||||
</select>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{!transactionList.length && (
|
||||
<div className="empty">{emptyMessage || __('No transactions to list.')}</div>
|
||||
|
@ -92,3 +98,4 @@ class TransactionList extends React.PureComponent {
|
|||
}
|
||||
|
||||
export default TransactionList;
|
||||
/* eslint-enable */
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import { BusyMessage } from 'component/common';
|
||||
import Link from 'component/link';
|
||||
import Button from 'component/link';
|
||||
import TransactionList from 'component/transactionList';
|
||||
import * as icons from 'constants/icons';
|
||||
|
||||
class TransactionListRecent extends React.PureComponent {
|
||||
type Props = {
|
||||
fetchTransactions: () => void,
|
||||
fetchingTransactions: boolean,
|
||||
hasTransactions: boolean,
|
||||
transactions: Array<{}>, // Will iron this out when I work on transactions page - Sean
|
||||
};
|
||||
|
||||
class TransactionListRecent extends React.PureComponent<Props> {
|
||||
componentWillMount() {
|
||||
this.props.fetchTransactions();
|
||||
}
|
||||
|
@ -13,28 +21,20 @@ class TransactionListRecent extends React.PureComponent {
|
|||
const { fetchingTransactions, hasTransactions, transactions } = this.props;
|
||||
|
||||
return (
|
||||
<section className="card">
|
||||
<div className="card__title-primary">
|
||||
<h3>{__('Recent Transactions')}</h3>
|
||||
</div>
|
||||
<section className="card card--section">
|
||||
<h2>{__('Recent Transactions')}</h2>
|
||||
<div className="card__content">
|
||||
{fetchingTransactions && <BusyMessage message={__('Loading transactions')} />}
|
||||
{!fetchingTransactions && (
|
||||
<TransactionList
|
||||
transactions={transactions}
|
||||
emptyMessage={__('You have no recent transactions.')}
|
||||
emptyMessage={__("Looks like you don't have any recent transactions.")}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{hasTransactions && (
|
||||
<div className="card__actions card__actions--bottom">
|
||||
<Link
|
||||
navigate="/history"
|
||||
label={__('Full History')}
|
||||
icon={icons.HISTORY}
|
||||
className="no-underline"
|
||||
button="text"
|
||||
/>
|
||||
<div className="card__actions">
|
||||
<Button navigate="/history" label={__('Full History')} icon="Clock" />
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
|
|
@ -3,7 +3,7 @@ import React from 'react';
|
|||
import Button from 'component/link';
|
||||
import { buildURI } from 'lbryURI';
|
||||
import classnames from 'classnames';
|
||||
import Icon from 'component/common/icon';
|
||||
// import Icon from 'component/common/icon';
|
||||
|
||||
i assume you will remove the commented code here and elsewhere before we merge i assume you will remove the commented code here and elsewhere before we merge
I wasn't planning on it. Mostly they are just reminders to come back to something. I'm not sure if I need to keep this, but I will know when I start on the File Page (next) I wasn't planning on it. Mostly they are just reminders to come back to something. I'm not sure if I need to keep this, but I will know when I start on the File Page (next)
sounds good sounds good
|
||||
type Props = {
|
||||
isResolvingUri: boolean,
|
||||
|
@ -57,7 +57,8 @@ class UriIndicator extends React.PureComponent<Props> {
|
|||
return <span>Anonymous</span>;
|
||||
}
|
||||
|
||||
let icon;
|
||||
// I'll look at this when working on the file page
|
||||
// let icon;
|
||||
let channelLink;
|
||||
let modifier;
|
||||
|
||||
|
@ -65,8 +66,8 @@ class UriIndicator extends React.PureComponent<Props> {
|
|||
modifier = 'valid';
|
||||
channelLink = link ? buildURI({ channelName, claimId: channelClaimId }, false) : false;
|
||||
} else {
|
||||
icon = 'icon-times-circle';
|
||||
modifier = 'invalid';
|
||||
// icon = 'icon-times-circle';
|
||||
// modifier = 'invalid';
|
||||
}
|
||||
|
||||
// {!signatureIsValid ? (
|
||||
|
@ -94,7 +95,7 @@ class UriIndicator extends React.PureComponent<Props> {
|
|||
}
|
||||
|
||||
return (
|
||||
<Button navigate="/show" navigateParams={{ uri: channelLink }} fakeLink>
|
||||
<Button navigate="/show" navigateParams={{ uri: channelLink }} noStyle>
|
||||
{inner}
|
||||
</Button>
|
||||
);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// I'll come back to this
|
||||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import { Form, FormRow, Submit } from 'component/form.js';
|
||||
import { Form, FormRow, Submit } from 'component/common/form';
|
||||
|
||||
class UserEmailNew extends React.PureComponent {
|
||||
constructor(props) {
|
||||
|
@ -53,3 +55,4 @@ class UserEmailNew extends React.PureComponent {
|
|||
}
|
||||
|
||||
export default UserEmailNew;
|
||||
/* eslint-enable */
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// I'll come back to this
|
||||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import Link from 'component/link';
|
||||
import { Form, FormRow, Submit } from 'component/form.js';
|
||||
import { Form, FormField, Submit } from 'component/common/form';
|
||||
|
||||
class UserEmailVerify extends React.PureComponent {
|
||||
constructor(props) {
|
||||
|
@ -29,19 +31,22 @@ class UserEmailVerify extends React.PureComponent {
|
|||
|
||||
render() {
|
||||
const { cancelButton, errorMessage, email, isPending } = this.props;
|
||||
// <FormField
|
||||
// label={__('Verification Code')}
|
||||
// errorMessage={errorMessage}
|
||||
// render{() => (
|
||||
// <input
|
||||
// name="code"
|
||||
// value={this.state.code}
|
||||
// onChange={event => {
|
||||
// this.handleCodeChanged(event);
|
||||
// }}
|
||||
// />
|
||||
// )}
|
||||
// />
|
||||
return (
|
||||
<Form onSubmit={this.handleSubmit.bind(this)}>
|
||||
<p>Please enter the verification code emailed to {email}.</p>
|
||||
<FormRow
|
||||
type="text"
|
||||
label={__('Verification Code')}
|
||||
name="code"
|
||||
value={this.state.code}
|
||||
onChange={event => {
|
||||
this.handleCodeChanged(event);
|
||||
}}
|
||||
errorMessage={errorMessage}
|
||||
/>
|
||||
{/* render help separately so it always shows */}
|
||||
<div className="form-field__helper">
|
||||
<p>
|
||||
|
@ -60,3 +65,4 @@ class UserEmailVerify extends React.PureComponent {
|
|||
}
|
||||
|
||||
export default UserEmailVerify;
|
||||
/* eslint-enable */
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// I'll come back to this
|
||||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import { Form, FormRow, Submit } from 'component/form.js';
|
||||
import FormField from 'component/formField';
|
||||
import { Form, FormRow, FormField } from 'component/common/form';
|
||||
|
||||
const os = require('os').type();
|
||||
const countryCodes = require('country-data')
|
||||
|
@ -77,29 +78,36 @@ class UserPhoneNew extends React.PureComponent {
|
|||
</p>
|
||||
<Form onSubmit={this.handleSubmit.bind(this)}>
|
||||
<div className="form-row-phone">
|
||||
<FormField type="select" onChange={this.handleSelect.bind(this)}>
|
||||
{countryCodes.map((country, index) => (
|
||||
<option key={index} value={country.countryCallingCode}>
|
||||
{os === 'Darwin' ? country.emoji : `(${country.alpha2})`}{' '}
|
||||
{country.countryCallingCode}
|
||||
</option>
|
||||
))}
|
||||
</FormField>
|
||||
<FormRow
|
||||
type="text"
|
||||
placeholder={this.state.country_code === '+1' ? '(555) 555-5555' : '5555555555'}
|
||||
name="phone"
|
||||
value={this.state.phone}
|
||||
<FormField
|
||||
onChange={this.handleSelect.bind(this)}
|
||||
render={() => (
|
||||
<select>
|
||||
{countryCodes.map((country, index) => (
|
||||
<option key={index} value={country.countryCallingCode}>
|
||||
{os === 'Darwin' ? country.emoji : `(${country.alpha2})`}{' '}
|
||||
{country.countryCallingCode}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
errorMessage={phoneErrorMessage}
|
||||
onChange={event => {
|
||||
this.handleChanged(event);
|
||||
}}
|
||||
render={() => (
|
||||
<input
|
||||
type="text"
|
||||
placeholder={this.state.country_code === '+1' ? '(555) 555-5555' : '5555555555'}
|
||||
name="phone"
|
||||
value={this.state.phone}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="form-row-submit">
|
||||
<Submit label="Submit" disabled={isPending} />
|
||||
{cancelButton}
|
||||
</div>
|
||||
<Submit label="Submit" disabled={isPending} />
|
||||
{cancelButton}
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
|
@ -107,3 +115,4 @@ class UserPhoneNew extends React.PureComponent {
|
|||
}
|
||||
|
||||
export default UserPhoneNew;
|
||||
/* eslint-enable */
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// I'll come back to this
|
||||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import Link from 'component/link';
|
||||
import { Form, FormRow, Submit } from 'component/form.js';
|
||||
import { Form, FormElement, Submit } from 'component/common/form';
|
||||
|
||||
class UserPhoneVerify extends React.PureComponent {
|
||||
constructor(props) {
|
||||
|
@ -33,21 +35,23 @@ class UserPhoneVerify extends React.PureComponent {
|
|||
<Form onSubmit={this.handleSubmit.bind(this)}>
|
||||
<p>
|
||||
{__(
|
||||
`Please enter the verification code sent to +${countryCode}${
|
||||
phone
|
||||
}. Didn't receive it? `
|
||||
`Please enter the verification code sent to +${countryCode}${phone}. Didn't receive it? `
|
||||
)}
|
||||
<Link onClick={this.reset.bind(this)} label="Go back." />
|
||||
</p>
|
||||
<FormRow
|
||||
type="text"
|
||||
<FormElement
|
||||
label={__('Verification Code')}
|
||||
name="code"
|
||||
value={this.state.code}
|
||||
onChange={event => {
|
||||
this.handleCodeChanged(event);
|
||||
}}
|
||||
errorMessage={phoneErrorMessage}
|
||||
render={() => (
|
||||
<input
|
||||
type="text"
|
||||
name="code"
|
||||
value={this.state.code}
|
||||
onChange={event => {
|
||||
this.handleCodeChanged(event);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{/* render help separately so it always shows */}
|
||||
<div className="form-field__helper">
|
||||
|
@ -67,3 +71,4 @@ class UserPhoneVerify extends React.PureComponent {
|
|||
}
|
||||
|
||||
export default UserPhoneVerify;
|
||||
/* eslint-enable */
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// I'll come back to This
|
||||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import Link from 'component/link';
|
||||
import CardVerify from 'component/cardVerify';
|
||||
|
@ -25,8 +27,8 @@ class UserVerify extends React.PureComponent {
|
|||
render() {
|
||||
const { errorMessage, isPending, navigate, verifyPhone, modal } = this.props;
|
||||
return (
|
||||
<div>
|
||||
<section className="card card--form">
|
||||
<React.Fragment>
|
||||
<section className="card card--section">
|
||||
<div className="card__title-primary">
|
||||
<h1>{__('Final Human Proof')}</h1>
|
||||
</div>
|
||||
|
@ -36,7 +38,7 @@ class UserVerify extends React.PureComponent {
|
|||
</p>
|
||||
</div>
|
||||
</section>
|
||||
<section className="card card--form">
|
||||
<section className="card card--section">
|
||||
<div className="card__title-primary">
|
||||
<h3>{__('1) Proof via Credit')}</h3>
|
||||
</div>
|
||||
|
@ -64,7 +66,7 @@ class UserVerify extends React.PureComponent {
|
|||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className="card card--form">
|
||||
<section className="card card--section">
|
||||
<div className="card__title-primary">
|
||||
<h3>{__('2) Proof via Phone')}</h3>
|
||||
</div>
|
||||
|
@ -117,7 +119,7 @@ class UserVerify extends React.PureComponent {
|
|||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className="card card--form">
|
||||
<section className="card card--section">
|
||||
<div className="card__title-primary">
|
||||
<h3>{__('4) Proof via Chat')}</h3>
|
||||
</div>
|
||||
|
@ -142,7 +144,7 @@ class UserVerify extends React.PureComponent {
|
|||
/>
|
||||
</div>
|
||||
</section>
|
||||
<section className="card card--form">
|
||||
<section className="card card--section">
|
||||
<div className="card__title-primary">
|
||||
<h5>{__('Or, Skip It Entirely')}</h5>
|
||||
</div>
|
||||
|
@ -157,9 +159,10 @@ class UserVerify extends React.PureComponent {
|
|||
<Link onClick={() => navigate('/discover')} button="alt" label={__('Skip Rewards')} />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default UserVerify;
|
||||
/* eslint-enable */
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import Link from 'component/link';
|
||||
import Address from 'component/address';
|
||||
|
||||
class WalletAddress extends React.PureComponent {
|
||||
type Props = {
|
||||
checkAddressIsMine: string => void,
|
||||
receiveAddress: string,
|
||||
getNewAddress: () => void,
|
||||
gettingNewAddress: boolean,
|
||||
};
|
||||
|
||||
class WalletAddress extends React.PureComponent<Props> {
|
||||
componentWillMount() {
|
||||
this.props.checkAddressIsMine(this.props.receiveAddress);
|
||||
}
|
||||
|
@ -11,21 +19,22 @@ class WalletAddress extends React.PureComponent {
|
|||
const { receiveAddress, getNewAddress, gettingNewAddress } = this.props;
|
||||
|
||||
return (
|
||||
<section className="card">
|
||||
<section className="card card--section">
|
||||
<div className="card__title-primary">
|
||||
<h3>{__('Receive Credits')}</h3>
|
||||
<h2>{__('Receive Credits')}</h2>
|
||||
</div>
|
||||
<p className="card__subtitle">
|
||||
{__('Use this wallet address to receive credits sent by another user (or yourself).')}
|
||||
</p>
|
||||
|
||||
<div className="card__content">
|
||||
<p>
|
||||
{__('Use this wallet address to receive credits sent by another user (or yourself).')}
|
||||
</p>
|
||||
<Address address={receiveAddress} showCopyButton />
|
||||
</div>
|
||||
|
||||
<div className="card__actions">
|
||||
<Link
|
||||
label={__('Get New Address')}
|
||||
button="primary"
|
||||
icon="icon-refresh"
|
||||
icon="RefreshCw"
|
||||
onClick={getNewAddress}
|
||||
disabled={gettingNewAddress}
|
||||
/>
|
||||
|
|
|
@ -1,33 +1,19 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import Link from 'component/link';
|
||||
import { CreditAmount } from 'component/common';
|
||||
import CreditAmount from 'component/common/credit-amount';
|
||||
|
||||
const WalletBalance = props => {
|
||||
const { balance, navigate } = props;
|
||||
/*
|
||||
<div className="help">
|
||||
<Link
|
||||
onClick={() => navigate("/backup")}
|
||||
label={__("Backup Your Wallet")}
|
||||
/>
|
||||
</div>
|
||||
*/
|
||||
type Props = {
|
||||
balance: number,
|
||||
};
|
||||
|
||||
const WalletBalance = (props: Props) => {
|
||||
const { balance } = props;
|
||||
return (
|
||||
<section className="card">
|
||||
<div className="card__title-primary">
|
||||
<h3>{__('Balance')}</h3>
|
||||
</div>
|
||||
<section className="card card--section">
|
||||
<h2>{__('Balance')}</h2>
|
||||
<span className="card__subtitle">{__('You currently have')}</span>
|
||||
<div className="card__content">
|
||||
{(balance || balance === 0) && <CreditAmount amount={balance} precision={8} />}
|
||||
</div>
|
||||
<div className="card__actions">
|
||||
<Link button="alt" navigate="/getcredits" label={__('Get Credits')} />
|
||||
<Link
|
||||
button="alt"
|
||||
disabled={balance === 0}
|
||||
navigate="/backup"
|
||||
label={__('Backup Wallet')}
|
||||
/>
|
||||
{(balance || balance === 0) && <CreditAmount large amount={balance} precision={8} />}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
|
|
@ -1,28 +1,9 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
doSendDraftTransaction,
|
||||
doSetDraftTransactionAmount,
|
||||
doSetDraftTransactionAddress,
|
||||
} from 'redux/actions/wallet';
|
||||
import {
|
||||
selectDraftTransactionAmount,
|
||||
selectDraftTransactionAddress,
|
||||
selectDraftTransactionError,
|
||||
} from 'redux/selectors/wallet';
|
||||
|
||||
import { doSendDraftTransaction } from 'redux/actions/wallet';
|
||||
import WalletSend from './view';
|
||||
|
||||
const select = state => ({
|
||||
address: selectDraftTransactionAddress(state),
|
||||
amount: selectDraftTransactionAmount(state),
|
||||
error: selectDraftTransactionError(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
sendToAddress: () => dispatch(doSendDraftTransaction()),
|
||||
setAmount: event => dispatch(doSetDraftTransactionAmount(event.target.value)),
|
||||
setAddress: event => dispatch(doSetDraftTransactionAddress(event.target.value)),
|
||||
sendToAddress: values => dispatch(doSendDraftTransaction(values)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(WalletSend);
|
||||
export default connect(null, perform)(WalletSend);
|
||||
|
|
|
@ -1,55 +1,105 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import { Form, FormRow, Submit } from 'component/form';
|
||||
import { regexAddress } from 'lbryURI';
|
||||
import Button from 'component/link';
|
||||
import { Form, FormRow, FormField } from 'component/common/form';
|
||||
import { Formik } from 'formik';
|
||||
import { validateSendTx } from 'util/form-validation';
|
||||
|
||||
class WalletSend extends React.PureComponent {
|
||||
handleSubmit() {
|
||||
const { amount, address, sendToAddress } = this.props;
|
||||
const validSubmit = parseFloat(amount) > 0.0 && address;
|
||||
type DraftTransaction = {
|
||||
address: string,
|
||||
amount: number | string, // So we can use a placeholder in the input
|
||||
};
|
||||
|
||||
if (validSubmit) {
|
||||
sendToAddress();
|
||||
}
|
||||
type Props = {
|
||||
sendToAddress: DraftTransaction => void,
|
||||
};
|
||||
|
||||
class WalletSend extends React.PureComponent<Props> {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
(this: any).handleSubmit = this.handleSubmit.bind(this);
|
||||
}
|
||||
|
||||
handleSubmit(values: DraftTransaction) {
|
||||
const { sendToAddress } = this.props;
|
||||
sendToAddress(values);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { closeModal, modal, setAmount, setAddress, amount, address, error } = this.props;
|
||||
|
||||
return (
|
||||
<section className="card">
|
||||
<Form onSubmit={this.handleSubmit.bind(this)}>
|
||||
<div className="card__title-primary">
|
||||
<h3>{__('Send Credits')}</h3>
|
||||
</div>
|
||||
<div className="card__content">
|
||||
<FormRow
|
||||
label={__('Amount')}
|
||||
postfix={__('LBC')}
|
||||
step="any"
|
||||
min="0"
|
||||
type="number"
|
||||
placeholder="1.23"
|
||||
size="10"
|
||||
onChange={setAmount}
|
||||
value={amount}
|
||||
/>
|
||||
</div>
|
||||
<div className="card__content">
|
||||
<FormRow
|
||||
label={__('Recipient Address')}
|
||||
placeholder="bbFxRyXXXXXXXXXXXZD8nE7XTLUxYnddTs"
|
||||
type="text"
|
||||
size="60"
|
||||
onChange={setAddress}
|
||||
value={address}
|
||||
regexp={regexAddress}
|
||||
trim
|
||||
/>
|
||||
<div className="form-row-submit">
|
||||
<Submit label={__('Send')} disabled={!(parseFloat(amount) > 0.0) || !address} />
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
<section className="card card--section">
|
||||
<div className="card__title-primary">
|
||||
<h2>{__('Send Credits')}</h2>
|
||||
</div>
|
||||
<div className="card__content">
|
||||
<Formik
|
||||
initialValues={{
|
||||
address: '',
|
||||
amount: '',
|
||||
}}
|
||||
onSubmit={this.handleSubmit}
|
||||
validate={validateSendTx}
|
||||
render={({
|
||||
values,
|
||||
errors,
|
||||
touched,
|
||||
handleChange,
|
||||
handleBlur,
|
||||
handleSubmit,
|
||||
isSubmitting,
|
||||
}) => (
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<FormRow>
|
||||
<FormField
|
||||
label={__('Amount')}
|
||||
postfix={__('LBC')}
|
||||
error={!!values.amount && touched.amount && errors.amount}
|
||||
render={() => (
|
||||
<input
|
||||
className="input--lbc-amount"
|
||||
type="number"
|
||||
name="amount"
|
||||
min="0"
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
value={values.amount}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
label={__('Recipient address')}
|
||||
error={!!values.address && touched.address && errors.address}
|
||||
render={() => (
|
||||
<input
|
||||
className="input--address"
|
||||
type="text"
|
||||
name="address"
|
||||
placeholder="bbFxRyXXXXXXXXXXXZD8nE7XTLUxYnddTs"
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
value={values.address}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormRow>
|
||||
<div className="card__actions">
|
||||
<Button
|
||||
type="submit"
|
||||
icon="Send"
|
||||
label={__('Send')}
|
||||
disabled={
|
||||
!values.address ||
|
||||
!!Object.keys(errors).length ||
|
||||
!(parseFloat(values.amount) > 0.0)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// I'll come back to this
|
||||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import Link from 'component/link';
|
||||
import { FormRow } from 'component/form';
|
||||
import { FormRow } from 'component/common/form';
|
||||
import UriIndicator from 'component/uriIndicator';
|
||||
|
||||
class WalletSendTip extends React.PureComponent {
|
||||
|
@ -67,3 +69,4 @@ class WalletSendTip extends React.PureComponent {
|
|||
}
|
||||
|
||||
export default WalletSendTip;
|
||||
/* eslint-enable */
|
||||
|
|
|
@ -466,6 +466,7 @@ export default class Autocomplete extends React.Component {
|
|||
const menu = this.props.renderMenu(items, this.props.value, style);
|
||||
return React.cloneElement(menu, {
|
||||
ref: e => (this.refs.menu = e),
|
||||
className: 'wunderbar__menu',
|
||||
// Ignore blur to prevent menu from de-rendering before we can process click
|
||||
onMouseEnter: () => this.setIgnoreBlur(true),
|
||||
onMouseLeave: () => this.setIgnoreBlur(false),
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
import React from 'react';
|
||||
import { normalizeURI } from 'lbryURI';
|
||||
import classnames from 'classnames';
|
||||
import throttle from 'util/throttle';
|
||||
import Icon from 'component/common/icon';
|
||||
import Autocomplete from './internal/autocomplete';
|
||||
|
||||
type Props = {
|
||||
|
@ -16,29 +18,22 @@ type Props = {
|
|||
};
|
||||
|
||||
class WunderBar extends React.PureComponent<Props> {
|
||||
constructor() {
|
||||
super();
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
(this: any).handleSubmit = this.handleSubmit.bind(this);
|
||||
(this: any).handleChange = this.handleChange.bind(this);
|
||||
(this: any).focus = this.focus.bind(this);
|
||||
(this: any).throttledGetSearchSuggestions = throttle(this.props.getSearchSuggestions, 1000);
|
||||
this.input = undefined;
|
||||
}
|
||||
|
||||
input: ?HTMLInputElement;
|
||||
|
||||
handleChange(e: SyntheticInputEvent<*>) {
|
||||
const { updateSearchQuery, getSearchSuggestions } = this.props;
|
||||
const { value } = e.target;
|
||||
|
||||
updateSearchQuery(value);
|
||||
getSearchSuggestions(value);
|
||||
}
|
||||
|
||||
focus() {
|
||||
const { input } = this;
|
||||
if (input) {
|
||||
input.focus();
|
||||
}
|
||||
this.throttledGetSearchSuggestions(value);
|
||||
}
|
||||
|
||||
handleSubmit(value: string) {
|
||||
|
@ -70,6 +65,16 @@ class WunderBar extends React.PureComponent<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
focus() {
|
||||
const { input } = this;
|
||||
if (input) {
|
||||
input.focus();
|
||||
}
|
||||
}
|
||||
|
||||
input: ?HTMLInputElement;
|
||||
throttledGetSearchSuggestions: string => void;
|
||||
|
||||
render() {
|
||||
const { searchQuery, isActive, address, suggestions } = this.props;
|
||||
|
||||
|
@ -83,12 +88,13 @@ class WunderBar extends React.PureComponent<Props> {
|
|||
'header__wunderbar--active': isActive,
|
||||
})}
|
||||
>
|
||||
<Icon icon="Search" />
|
||||
<Autocomplete
|
||||
autoHighlight
|
||||
ref={ref => {
|
||||
this.input = ref;
|
||||
}}
|
||||
wrapperStyle={{ flex: 1, minHeight: 0 }}
|
||||
wrapperStyle={{ flex: 1 }}
|
||||
value={wunderbarValue}
|
||||
items={suggestions}
|
||||
getItemValue={item => item.value}
|
||||
|
@ -108,7 +114,8 @@ class WunderBar extends React.PureComponent<Props> {
|
|||
'wunderbar__active-suggestion': isHighlighted,
|
||||
})}
|
||||
>
|
||||
{item.label}
|
||||
<Icon icon={item.icon} />
|
||||
<span className="wunderbar__suggestion-label">{item.label}</span>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
|
|
|
@ -37,8 +37,6 @@ export const FETCH_TRANSACTIONS_COMPLETED = 'FETCH_TRANSACTIONS_COMPLETED';
|
|||
export const UPDATE_BALANCE = 'UPDATE_BALANCE';
|
||||
export const CHECK_ADDRESS_IS_MINE_STARTED = 'CHECK_ADDRESS_IS_MINE_STARTED';
|
||||
export const CHECK_ADDRESS_IS_MINE_COMPLETED = 'CHECK_ADDRESS_IS_MINE_COMPLETED';
|
||||
export const SET_DRAFT_TRANSACTION_AMOUNT = 'SET_DRAFT_TRANSACTION_AMOUNT';
|
||||
export const SET_DRAFT_TRANSACTION_ADDRESS = 'SET_DRAFT_TRANSACTION_ADDRESS';
|
||||
export const SEND_TRANSACTION_STARTED = 'SEND_TRANSACTION_STARTED';
|
||||
export const SEND_TRANSACTION_COMPLETED = 'SEND_TRANSACTION_COMPLETED';
|
||||
export const SEND_TRANSACTION_FAILED = 'SEND_TRANSACTION_FAILED';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export const FEATURED = 'rocket';
|
||||
export const LOCAL = 'folder';
|
||||
export const FEATURED = 'Award';
|
||||
export const LOCAL = 'Folder';
|
||||
export const FILE = 'file';
|
||||
Going to add every icon to this file and only change every Icon use to constants Going to add every icon to this file and only change every Icon use to constants
* at a later time
is there a reason why the ones you just added are upper case but the others are lower? is there a reason why the ones you just added are upper case but the others are lower?
|
||||
export const HISTORY = 'history';
|
||||
export const HELP_CIRCLE = 'question-circle';
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
// I'll come back to this
|
||||
/* esline-disable */
|
||||
import React from 'react';
|
||||
import { Modal } from 'modal/modal';
|
||||
import { CreditAmount, CurrencySymbol } from 'component/common';
|
||||
import { CurrencySymbol } from 'component/common';
|
||||
import CreditAmount from 'component/common/credit-amount';
|
||||
import Link from 'component/link/index';
|
||||
|
||||
const ModalCreditIntro = props => {
|
||||
|
@ -46,3 +49,4 @@ const ModalCreditIntro = props => {
|
|||
};
|
||||
|
||||
export default ModalCreditIntro;
|
||||
/* esline-enable */
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// I"ll come back to This
|
||||
/* esline-disable */
|
||||
import React from 'react';
|
||||
import { Modal } from 'modal/modal';
|
||||
import { CreditAmount } from 'component/common';
|
||||
import CreditAmount from 'component/common/credit-amount';
|
||||
|
||||
class ModalFirstReward extends React.PureComponent {
|
||||
render() {
|
||||
|
@ -42,3 +44,4 @@ class ModalFirstReward extends React.PureComponent {
|
|||
}
|
||||
|
||||
export default ModalFirstReward;
|
||||
/* eslint-enable */
|
||||
|
|
|
@ -4,6 +4,7 @@ import Link from 'component/link';
|
|||
import UserEmailNew from 'component/userEmailNew';
|
||||
import UserEmailVerify from 'component/userEmailVerify';
|
||||
import UserVerify from 'component/userVerify';
|
||||
import Page from 'component/page';
|
||||
|
||||
export class AuthPage extends React.PureComponent {
|
||||
componentWillMount() {
|
||||
|
@ -58,25 +59,27 @@ export class AuthPage extends React.PureComponent {
|
|||
const { email, user, isPending, navigate } = this.props;
|
||||
const [innerContent, useTemplate] = this.renderMain();
|
||||
|
||||
return useTemplate ? (
|
||||
<main>
|
||||
<section className="card card--form">
|
||||
<div className="card__title-primary">
|
||||
<h1>{this.getTitle()}</h1>
|
||||
</div>
|
||||
<div className="card__content">{innerContent}</div>
|
||||
<div className="card__content">
|
||||
<div className="help">
|
||||
{`${__(
|
||||
'This information is disclosed only to LBRY, Inc. and not to the LBRY network. It is only required to earn LBRY rewards.'
|
||||
)} `}
|
||||
<Link onClick={() => navigate('/discover')} label={__('Return home')} />.
|
||||
return (
|
||||
<Page>
|
||||
{useTemplate ? (
|
||||
<section className="card card--section">
|
||||
<div className="card__title-primary">
|
||||
<h1>{this.getTitle()}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
) : (
|
||||
innerContent
|
||||
<div className="card__content">{innerContent}</div>
|
||||
<div className="card__content">
|
||||
<div className="help">
|
||||
{`${__(
|
||||
'This information is disclosed only to LBRY, Inc. and not to the LBRY network. It is only required to earn LBRY rewards.'
|
||||
)} `}
|
||||
<Link onClick={() => navigate('/discover')} label={__('Return home')} />.
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
) : (
|
||||
innerContent
|
||||
)}
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import SubHeader from 'component/subHeader';
|
||||
import Link from 'component/link';
|
||||
import Page from 'component/page';
|
||||
|
||||
class BackupPage extends React.PureComponent {
|
||||
render() {
|
||||
|
@ -16,9 +16,8 @@ class BackupPage extends React.PureComponent {
|
|||
}
|
||||
|
||||
return (
|
||||
<main className="main--single-column">
|
||||
<SubHeader />
|
||||
<section className="card">
|
||||
<Page>
|
||||
<section className="card card--section">
|
||||
<div className="card__title-primary">
|
||||
<h3>{__('Backup Your LBRY Credits')}</h3>
|
||||
</div>
|
||||
|
@ -57,7 +56,7 @@ class BackupPage extends React.PureComponent {
|
|||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ import Link from 'component/link';
|
|||
import { FileTile } from 'component/fileTile';
|
||||
import { BusyMessage, Thumbnail } from 'component/common.js';
|
||||
import FileList from 'component/fileList';
|
||||
import SubHeader from 'component/subHeader';
|
||||
|
||||
class FileListDownloaded extends React.PureComponent {
|
||||
componentWillMount() {
|
||||
|
@ -31,12 +30,7 @@ class FileListDownloaded extends React.PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="main--single-column">
|
||||
<SubHeader />
|
||||
{content}
|
||||
</main>
|
||||
);
|
||||
return <main className="main--single-column">{content}</main>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ import Link from 'component/link';
|
|||
import FileTile from 'component/fileTile';
|
||||
import { BusyMessage, Thumbnail } from 'component/common.js';
|
||||
import FileList from 'component/fileList';
|
||||
import SubHeader from 'component/subHeader';
|
||||
|
||||
class FileListPublished extends React.PureComponent {
|
||||
componentWillMount() {
|
||||
|
@ -41,12 +40,7 @@ class FileListPublished extends React.PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="main--single-column">
|
||||
<SubHeader />
|
||||
{content}
|
||||
</main>
|
||||
);
|
||||
return <main className="main--single-column">{content}</main>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,25 +1,24 @@
|
|||
import React from 'react';
|
||||
import SubHeader from 'component/subHeader';
|
||||
import Link from 'component/link';
|
||||
import RewardSummary from 'component/rewardSummary';
|
||||
import ShapeShift from 'component/shapeShift';
|
||||
import Page from 'component/page';
|
||||
|
||||
const GetCreditsPage = props => (
|
||||
<main className="main--single-column">
|
||||
<SubHeader />
|
||||
<Page>
|
||||
<RewardSummary />
|
||||
<ShapeShift />
|
||||
<section className="card">
|
||||
<section className="card card--section">
|
||||
<div className="card__title-primary">
|
||||
<h3>{__('From External Wallet')}</h3>
|
||||
<h2>{__('From External Wallet')}</h2>
|
||||
</div>
|
||||
<div className="card__actions">
|
||||
<Link button="alt" navigate="/send" icon="icon-send" label={__('Send / Receive')} />
|
||||
<Link navigate="/send" label={__('Send / Receive')} />
|
||||
</div>
|
||||
</section>
|
||||
<section className="card">
|
||||
<section className="card card--section">
|
||||
<div className="card__title-primary">
|
||||
<h3>{__('More ways to get LBRY Credits')}</h3>
|
||||
<h2>{__('More ways to get LBRY Credits')}</h2>
|
||||
</div>
|
||||
<div className="card__content">
|
||||
<p>
|
||||
|
@ -29,10 +28,10 @@ const GetCreditsPage = props => (
|
|||
</p>
|
||||
</div>
|
||||
<div className="card__actions">
|
||||
<Link button="alt" href="https://lbry.io/faq/earn-credits" label={__('Read More')} />
|
||||
<Link fakeLink href="https://lbry.io/faq/earn-credits" label={__('Read More')} />
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</Page>
|
||||
);
|
||||
|
||||
export default GetCreditsPage;
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
import React from 'react';
|
||||
import lbry from 'lbry.js';
|
||||
import Link from 'component/link';
|
||||
import SubHeader from 'component/subHeader';
|
||||
import { BusyMessage } from 'component/common';
|
||||
import Icon from 'component/common/icon';
|
||||
import Page from 'component/page';
|
||||
|
||||
class HelpPage extends React.PureComponent {
|
||||
constructor(props) {
|
||||
|
@ -70,8 +70,7 @@ class HelpPage extends React.PureComponent {
|
|||
}
|
||||
|
||||
return (
|
||||
<main className="main--single-column">
|
||||
<SubHeader />
|
||||
<Page>
|
||||
<section className="card">
|
||||
<div className="card__title-primary">
|
||||
<h3>{__('Read the FAQ')}</h3>
|
||||
|
@ -210,7 +209,7 @@ class HelpPage extends React.PureComponent {
|
|||
)}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
import { BusyMessage } from 'component/common';
|
||||
import SubHeader from 'component/subHeader';
|
||||
import InviteNew from 'component/inviteNew';
|
||||
import InviteList from 'component/inviteList';
|
||||
|
||||
|
@ -14,7 +13,6 @@ class InvitePage extends React.PureComponent {
|
|||
|
||||
return (
|
||||
<main className="main--single-column">
|
||||
<SubHeader />
|
||||
{isPending && <BusyMessage message={__('Checking your invite status')} />}
|
||||
{!isPending &&
|
||||
isFailed && <span className="empty">{__('Failed to retrieve invite status.')}</span>}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import Link from 'component/link';
|
||||
import { FormRow } from 'component/form';
|
||||
import { FormRow } from 'component/common/form';
|
||||
import { doShowSnackBar } from 'redux/actions/app';
|
||||
import lbry from '../lbry.js';
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@ import React from 'react';
|
|||
import { BusyMessage } from 'component/common';
|
||||
import RewardListClaimed from 'component/rewardListClaimed';
|
||||
import RewardTile from 'component/rewardTile';
|
||||
import SubHeader from 'component/subHeader';
|
||||
import Link from 'component/link';
|
||||
import Page from 'component/page';
|
||||
|
||||
class RewardsPage extends React.PureComponent {
|
||||
/*
|
||||
|
@ -34,7 +34,7 @@ class RewardsPage extends React.PureComponent {
|
|||
if (user && !user.is_reward_approved) {
|
||||
if (!user.primary_email || !user.has_verified_email || !user.is_identity_verified) {
|
||||
return (
|
||||
<section className="card">
|
||||
<section className="card card--section">
|
||||
<div className="card__title-primary">
|
||||
<h3>{__('Humans Only')}</h3>
|
||||
</div>
|
||||
|
@ -102,6 +102,7 @@ class RewardsPage extends React.PureComponent {
|
|||
);
|
||||
}
|
||||
return (
|
||||
// TODO: come back to me and actually implement a grid
|
||||
<div className="card-grid">
|
||||
{rewards.map(reward => <RewardTile key={reward.reward_type} reward={reward} />)}
|
||||
</div>
|
||||
|
@ -110,12 +111,11 @@ class RewardsPage extends React.PureComponent {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<main className="main--single-column">
|
||||
<SubHeader />
|
||||
<Page>
|
||||
{this.renderPageHeader()}
|
||||
{this.renderUnclaimedRewards()}
|
||||
{<RewardListClaimed />}
|
||||
</main>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import React from 'react';
|
||||
import SubHeader from 'component/subHeader';
|
||||
import WalletSend from 'component/walletSend';
|
||||
import WalletAddress from 'component/walletAddress';
|
||||
import Page from 'component/page';
|
||||
|
||||
const SendReceivePage = props => (
|
||||
<main className="main--single-column">
|
||||
<SubHeader />
|
||||
<Page>
|
||||
<WalletSend />
|
||||
<WalletAddress />
|
||||
</main>
|
||||
</Page>
|
||||
);
|
||||
|
||||
export default SendReceivePage;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import React from 'react';
|
||||
import FormField from 'component/formField';
|
||||
import { FormRow } from 'component/form.js';
|
||||
import SubHeader from 'component/subHeader';
|
||||
import { FormRow } from 'component/common/form';
|
||||
import * as settings from 'constants/settings';
|
||||
import lbry from 'lbry.js';
|
||||
import Link from 'component/link';
|
||||
import FormFieldPrice from 'component/formFieldPrice';
|
||||
import Page from 'component/page';
|
||||
|
||||
class SettingsPage extends React.PureComponent {
|
||||
constructor(props) {
|
||||
|
@ -144,8 +144,7 @@ class SettingsPage extends React.PureComponent {
|
|||
);
|
||||
}
|
||||
return (
|
||||
<main className="main--single-column">
|
||||
<SubHeader />
|
||||
<Page>
|
||||
{/*
|
||||
<section className="card">
|
||||
<div className="card__content">
|
||||
|
@ -348,7 +347,7 @@ class SettingsPage extends React.PureComponent {
|
|||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import SubHeader from 'component/subHeader';
|
||||
import Page from 'component/page';
|
||||
import { BusyMessage } from 'component/common';
|
||||
import CategoryList from 'component/common/category-list';
|
||||
import type { Subscription } from 'redux/reducers/subscriptions';
|
||||
|
@ -61,16 +61,10 @@ export default class extends React.PureComponent<Props> {
|
|||
(subscriptions.length !== savedSubscriptions.length || someClaimsNotLoaded);
|
||||
|
||||
return (
|
||||
<main className="main main--no-margin">
|
||||
<SubHeader fullWidth smallMargin />
|
||||
<Page noPadding isLoading={fetchingSubscriptions}>
|
||||
{!savedSubscriptions.length && (
|
||||
<span>{__("You haven't subscribed to any channels yet")}</span>
|
||||
)}
|
||||
{fetchingSubscriptions && (
|
||||
<div className="card-row__placeholder">
|
||||
<BusyMessage message={__('Fetching subscriptions')} />
|
||||
</div>
|
||||
)}
|
||||
{!!savedSubscriptions.length && (
|
||||
<div>
|
||||
{!!subscriptions.length &&
|
||||
|
@ -93,7 +87,7 @@ export default class extends React.PureComponent<Props> {
|
|||
})}
|
||||
</div>
|
||||
)}
|
||||
</main>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import { BusyMessage } from 'component/common';
|
||||
import SubHeader from 'component/subHeader';
|
||||
import TransactionList from 'component/transactionList';
|
||||
import Page from 'component/page';
|
||||
|
||||
class TransactionHistoryPage extends React.PureComponent {
|
||||
componentWillMount() {
|
||||
|
@ -12,9 +12,8 @@ class TransactionHistoryPage extends React.PureComponent {
|
|||
const { fetchingTransactions, transactions } = this.props;
|
||||
|
||||
return (
|
||||
<main className="main--single-column">
|
||||
<SubHeader />
|
||||
<section className="card">
|
||||
<Page>
|
||||
<section className="card card--section">
|
||||
<div
|
||||
className={`card__title-primary ${
|
||||
fetchingTransactions && transactions.length ? 'reloading' : ''
|
||||
|
@ -35,7 +34,7 @@ class TransactionHistoryPage extends React.PureComponent {
|
|||
)}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
import React from 'react';
|
||||
import SubHeader from 'component/subHeader';
|
||||
import WalletBalance from 'component/walletBalance';
|
||||
import RewardSummary from 'component/rewardSummary';
|
||||
import TransactionListRecent from 'component/transactionListRecent';
|
||||
import WalletAddress from 'component/walletAddress';
|
||||
import Page from 'component/page';
|
||||
|
||||
const WalletPage = props => (
|
||||
<main className="main--single-column page--wallet">
|
||||
<SubHeader />
|
||||
<div className="card-grid">
|
||||
const WalletPage = () => (
|
||||
<Page>
|
||||
<div className="columns">
|
||||
<WalletBalance />
|
||||
<RewardSummary />
|
||||
</div>
|
||||
<WalletAddress />
|
||||
<TransactionListRecent />
|
||||
</main>
|
||||
</Page>
|
||||
);
|
||||
|
||||
export default WalletPage;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as ACTIONS from 'constants/action_types';
|
||||
import { normalizeURI } from 'lbryURI';
|
||||
import { normalizeURI, buildURI } from 'lbryURI';
|
||||
import { doResolveUri } from 'redux/actions/content';
|
||||
import { doNavigate } from 'redux/actions/navigation';
|
||||
import { selectCurrentPage } from 'redux/selectors/navigation';
|
||||
|
@ -89,10 +89,17 @@ export const getSearchSuggestions = value => dispatch => {
|
|||
fetch(`https://lighthouse.lbry.io/autocomplete?s=${searchValue}`)
|
||||
.then(handleSearchApiResponse)
|
||||
.then(suggestions => {
|
||||
const formattedSuggestions = suggestions.slice(0, 5).map(suggestion => ({
|
||||
label: suggestion,
|
||||
value: suggestion,
|
||||
}));
|
||||
const formattedSuggestions = suggestions.slice(0, 5).map(suggestion => {
|
||||
// This will need to be more robust when the api starts returning lbry uris
|
||||
const isChannel = suggestion.startsWith('@');
|
||||
const suggestionObj = {
|
||||
value: suggestion,
|
||||
label: isChannel ? suggestion.slice(1) : suggestion,
|
||||
icon: isChannel ? 'AtSign' : 'Search',
|
||||
};
|
||||
|
||||
return suggestionObj;
|
||||
});
|
||||
|
||||
// Should we add lbry://{query} as the first result?
|
||||
// If it's not a valid uri, then add a "search for {query}" result
|
||||
|
@ -100,12 +107,12 @@ export const getSearchSuggestions = value => dispatch => {
|
|||
try {
|
||||
const uri = normalizeURI(value);
|
||||
formattedSuggestions.unshift(
|
||||
{ label: uri, value: uri },
|
||||
{ label: searchLabel, value: `${value}?search` }
|
||||
{ label: uri, value: uri, icon: 'Compass' },
|
||||
{ label: searchLabel, value: `${value}?search`, icon: 'Search' }
|
||||
);
|
||||
} catch (e) {
|
||||
if (value) {
|
||||
formattedSuggestions.unshift({ label: searchLabel, value });
|
||||
formattedSuggestions.unshift({ label: searchLabel, value, icon: 'Search' });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,6 @@ import { doOpenModal, doShowSnackBar } from 'redux/actions/app';
|
|||
import { doNavigate } from 'redux/actions/navigation';
|
||||
import {
|
||||
selectBalance,
|
||||
selectDraftTransaction,
|
||||
selectDraftTransactionAmount,
|
||||
} from 'redux/selectors/wallet';
|
||||
|
||||
export function doUpdateBalance() {
|
||||
|
@ -89,12 +87,10 @@ export function doCheckAddressIsMine(address) {
|
|||
};
|
||||
}
|
||||
|
||||
export function doSendDraftTransaction() {
|
||||
export function doSendDraftTransaction({ amount, address }) {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const draftTx = selectDraftTransaction(state);
|
||||
const balance = selectBalance(state);
|
||||
const amount = selectDraftTransactionAmount(state);
|
||||
|
||||
if (balance - amount <= 0) {
|
||||
dispatch(doOpenModal(MODALS.INSUFFICIENT_CREDITS));
|
||||
|
@ -135,26 +131,12 @@ export function doSendDraftTransaction() {
|
|||
};
|
||||
|
||||
Lbry.wallet_send({
|
||||
amount: draftTx.amount,
|
||||
address: draftTx.address,
|
||||
amount,
|
||||
address,
|
||||
}).then(successCallback, errorCallback);
|
||||
};
|
||||
}
|
||||
|
||||
export function doSetDraftTransactionAmount(amount) {
|
||||
return {
|
||||
type: ACTIONS.SET_DRAFT_TRANSACTION_AMOUNT,
|
||||
data: { amount },
|
||||
};
|
||||
}
|
||||
|
||||
export function doSetDraftTransactionAddress(address) {
|
||||
return {
|
||||
type: ACTIONS.SET_DRAFT_TRANSACTION_ADDRESS,
|
||||
data: { address },
|
||||
};
|
||||
}
|
||||
|
||||
export function doSendSupport(amount, claimId, uri) {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
|
|
|
@ -2,10 +2,6 @@ import * as ACTIONS from 'constants/action_types';
|
|||
|
||||
const reducers = {};
|
||||
const receiveAddress = localStorage.getItem('receiveAddress');
|
||||
const buildDraftTransaction = () => ({
|
||||
amount: undefined,
|
||||
address: undefined,
|
||||
});
|
||||
|
||||
const defaultState = {
|
||||
balance: undefined,
|
||||
|
@ -14,8 +10,8 @@ const defaultState = {
|
|||
fetchingTransactions: false,
|
||||
receiveAddress,
|
||||
gettingNewAddress: false,
|
||||
draftTransaction: buildDraftTransaction(),
|
||||
sendingSupport: false,
|
||||
sendingTx: false
|
||||
};
|
||||
|
||||
reducers[ACTIONS.FETCH_TRANSACTIONS_STARTED] = state =>
|
||||
|
@ -68,51 +64,21 @@ reducers[ACTIONS.CHECK_ADDRESS_IS_MINE_COMPLETED] = state =>
|
|||
checkingAddressOwnership: false,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.SET_DRAFT_TRANSACTION_AMOUNT] = (state, action) => {
|
||||
const oldDraft = state.draftTransaction;
|
||||
const newDraft = Object.assign({}, oldDraft, {
|
||||
amount: parseFloat(action.data.amount),
|
||||
});
|
||||
|
||||
return Object.assign({}, state, {
|
||||
draftTransaction: newDraft,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[ACTIONS.SET_DRAFT_TRANSACTION_ADDRESS] = (state, action) => {
|
||||
const oldDraft = state.draftTransaction;
|
||||
const newDraft = Object.assign({}, oldDraft, {
|
||||
address: action.data.address,
|
||||
});
|
||||
|
||||
return Object.assign({}, state, {
|
||||
draftTransaction: newDraft,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[ACTIONS.SEND_TRANSACTION_STARTED] = state => {
|
||||
const newDraftTransaction = Object.assign({}, state.draftTransaction, {
|
||||
sending: true,
|
||||
});
|
||||
|
||||
return Object.assign({}, state, {
|
||||
draftTransaction: newDraftTransaction,
|
||||
sendingTx: true,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[ACTIONS.SEND_TRANSACTION_COMPLETED] = state =>
|
||||
Object.assign({}, state, {
|
||||
draftTransaction: buildDraftTransaction(),
|
||||
sendingTx: false,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.SEND_TRANSACTION_FAILED] = (state, action) => {
|
||||
const newDraftTransaction = Object.assign({}, state.draftTransaction, {
|
||||
sending: false,
|
||||
error: action.data.error,
|
||||
});
|
||||
|
||||
return Object.assign({}, state, {
|
||||
draftTransaction: newDraftTransaction,
|
||||
sendingTx: false,
|
||||
error: action.data.error
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { createSelector } from 'reselect';
|
||||
import { parseQueryParams, toQueryString } from 'util/query_params';
|
||||
import { normalizeURI } from 'lbryURI';
|
||||
import { parseQueryParams } from 'util/query_params';
|
||||
|
||||
export const selectState = state => state.navigation || {};
|
||||
|
||||
|
@ -22,72 +21,6 @@ export const selectCurrentParams = createSelector(selectCurrentPath, path => {
|
|||
export const makeSelectCurrentParam = param =>
|
||||
createSelector(selectCurrentParams, params => (params ? params[param] : undefined));
|
||||
|
||||
export const selectHeaderLinks = createSelector(selectCurrentPage, page => {
|
||||
// This contains intentional fall throughs
|
||||
switch (page) {
|
||||
case 'wallet':
|
||||
case 'history':
|
||||
case 'send':
|
||||
case 'getcredits':
|
||||
case 'invite':
|
||||
case 'rewards':
|
||||
case 'backup':
|
||||
return {
|
||||
wallet: __('Overview'),
|
||||
getcredits: __('Get Credits'),
|
||||
send: __('Send / Receive'),
|
||||
rewards: __('Rewards'),
|
||||
invite: __('Invites'),
|
||||
history: __('History'),
|
||||
};
|
||||
case 'downloaded':
|
||||
case 'published':
|
||||
return {
|
||||
downloaded: __('Downloaded'),
|
||||
published: __('Published'),
|
||||
};
|
||||
case 'settings':
|
||||
case 'help':
|
||||
return {
|
||||
settings: __('Settings'),
|
||||
help: __('Help'),
|
||||
};
|
||||
case 'discover':
|
||||
case 'subscriptions':
|
||||
return {
|
||||
discover: __('Discover'),
|
||||
subscriptions: __('Subscriptions'),
|
||||
};
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
export const selectPageTitle = createSelector(
|
||||
selectCurrentPage,
|
||||
selectCurrentParams,
|
||||
(page, params) => {
|
||||
switch (page) {
|
||||
case 'show': {
|
||||
const parts = [normalizeURI(params.uri)];
|
||||
// If the params has any keys other than "uri"
|
||||
if (Object.keys(params).length > 1) {
|
||||
parts.push(toQueryString(Object.assign({}, params, { uri: null })));
|
||||
}
|
||||
return parts.join('?');
|
||||
}
|
||||
case 'discover':
|
||||
return __('Discover');
|
||||
case false:
|
||||
case null:
|
||||
case '':
|
||||
return '';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const selectPathAfterAuth = createSelector(selectState, state => state.pathAfterAuth);
|
||||
|
||||
export const selectIsBackDisabled = createSelector(selectState, state => state.index === 0);
|
||||
|
@ -97,6 +30,8 @@ export const selectIsForwardDisabled = createSelector(
|
|||
state => state.index === state.stack.length - 1
|
||||
);
|
||||
|
||||
export const selectIsHome = createSelector(selectCurrentPage, page => page === 'discover');
|
||||
|
||||
export const selectHistoryIndex = createSelector(selectState, state => state.index);
|
||||
|
||||
export const selectHistoryStack = createSelector(selectState, state => state.stack);
|
||||
|
@ -106,3 +41,126 @@ export const selectActiveHistoryEntry = createSelector(
|
|||
selectState,
|
||||
state => state.stack[state.index]
|
||||
);
|
||||
|
||||
export const selectPageTitle = createSelector(
|
||||
selectCurrentPage,
|
||||
(page) => {
|
||||
switch (page) {
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const selectNavLinks = createSelector(
|
||||
selectCurrentPage,
|
||||
selectHistoryStack,
|
||||
(currentPage, historyStack) => {
|
||||
const isWalletPage = page =>
|
||||
page === 'wallet' ||
|
||||
page === 'send' ||
|
||||
page === 'getcredits' ||
|
||||
page === 'rewards' ||
|
||||
page === 'history';
|
||||
|
||||
let walletLink;
|
||||
if (isWalletPage(currentPage)) {
|
||||
// If they are on a wallet page, the top level link should direct them to the overview page
|
||||
walletLink = '/wallet';
|
||||
} else {
|
||||
// check to see if they've recently been on a wallet sub-link
|
||||
const previousStack = historyStack.slice().reverse();
|
||||
for (let i = 0; i < previousStack.length; i += 1) {
|
||||
const currentStackItem = previousStack[i];
|
||||
|
||||
// Trim off the "/" from the path
|
||||
const pageInStack = currentStackItem.path.slice(1);
|
||||
if (isWalletPage(pageInStack)) {
|
||||
walletLink = currentStackItem.path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const walletSubLinks = [
|
||||
{
|
||||
label: 'Overview',
|
||||
path: '/wallet',
|
||||
active: currentPage === 'wallet',
|
||||
},
|
||||
{
|
||||
label: 'Send & Recieve',
|
||||
path: '/send',
|
||||
active: currentPage === 'send',
|
||||
},
|
||||
{
|
||||
label: 'Get Credits',
|
||||
path: '/getcredits',
|
||||
active: currentPage === 'getcredits',
|
||||
},
|
||||
{
|
||||
label: 'Rewards',
|
||||
path: '/rewards',
|
||||
active: currentPage === 'rewards',
|
||||
},
|
||||
{
|
||||
label: 'My Transactions',
|
||||
path: '/history',
|
||||
active: currentPage === 'history',
|
||||
},
|
||||
];
|
||||
|
||||
const navLinks = {
|
||||
primary: [
|
||||
{
|
||||
label: 'Explore',
|
||||
path: '/discover',
|
||||
active: currentPage === 'discover',
|
||||
icon: 'Compass',
|
||||
},
|
||||
{
|
||||
label: 'Subscriptions',
|
||||
path: '/subscriptions',
|
||||
active: currentPage === 'subscriptions',
|
||||
icon: 'AtSign',
|
||||
},
|
||||
],
|
||||
secondary: [
|
||||
{
|
||||
label: 'Wallet',
|
||||
path: walletLink || '/wallet', // If they've never been to a wallet page, take them to the overview
|
||||
active:
|
||||
currentPage === 'wallet' ||
|
||||
!!walletSubLinks.find(({ path }) => currentPage === path.slice(1)),
|
||||
subLinks: walletSubLinks,
|
||||
icon: 'CreditCard',
|
||||
},
|
||||
{
|
||||
label: 'Publish',
|
||||
path: '/publish',
|
||||
active: currentPage === 'publish',
|
||||
icon: 'UploadCloud',
|
||||
},
|
||||
{
|
||||
label: 'Settings',
|
||||
path: '/settings',
|
||||
active: currentPage === 'settings',
|
||||
icon: 'Settings',
|
||||
},
|
||||
{
|
||||
label: 'Backup Wallet',
|
||||
path: '/backup',
|
||||
active: currentPage === 'backup',
|
||||
icon: 'Save',
|
||||
},
|
||||
{
|
||||
label: 'Help',
|
||||
path: '/help',
|
||||
active: currentPage === 'help',
|
||||
icon: 'HelpCircle',
|
||||
},
|
||||
],
|
||||
};
|
||||
return navLinks;
|
||||
}
|
||||
);
|
||||
|
|
|
@ -96,26 +96,6 @@ export const selectGettingNewAddress = createSelector(
|
|||
state => state.gettingNewAddress
|
||||
);
|
||||
|
||||
export const selectDraftTransaction = createSelector(
|
||||
selectState,
|
||||
state => state.draftTransaction || {}
|
||||
);
|
||||
|
||||
export const selectDraftTransactionAmount = createSelector(
|
||||
selectDraftTransaction,
|
||||
draft => draft.amount
|
||||
);
|
||||
|
||||
export const selectDraftTransactionAddress = createSelector(
|
||||
selectDraftTransaction,
|
||||
draft => draft.address
|
||||
);
|
||||
|
||||
export const selectDraftTransactionError = createSelector(
|
||||
selectDraftTransaction,
|
||||
draft => draft.error
|
||||
);
|
||||
|
||||
export const selectBlocks = createSelector(selectState, state => state.blocks);
|
||||
|
||||
export const makeSelectBlockDate = block =>
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
// Generic html styles used accross the App
|
||||
// component specific styling should go in the component scss file
|
||||
|
||||
// The actual fonts used will change ex: medium vs regular
|
||||
@font-face {
|
||||
font-family: 'Metropolis';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
text-rendering: optimizeLegibility;
|
||||
src: url('../../../static/font/metropolis/Metropolis-Regular.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Metropolis';
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
text-rendering: optimizeLegibility;
|
||||
src: url('../../../static/font/metropolis/Metropolis-Medium.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Metropolis';
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
text-rendering: optimizeLegibility;
|
||||
src: url('../../../static/font/metropolis/Metropolis-SemiBold.woff2') format('woff2');
|
||||
|
@ -63,19 +70,6 @@ h5 {
|
|||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
sup,
|
||||
sub {
|
||||
vertical-align: baseline;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.4em;
|
||||
}
|
||||
sub {
|
||||
top: 0.4em;
|
||||
}
|
||||
|
||||
code {
|
||||
font: 0.8em Consolas, 'Lucida Console', 'Source Sans', monospace;
|
||||
background-color: var(--color-bg-alt);
|
||||
|
@ -83,35 +77,61 @@ code {
|
|||
|
||||
// Without this buttons don't have the Metropolis font
|
||||
button {
|
||||
font-weight: inherit;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
#window {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
ul {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
#main-content {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
// don't use {bottom/top} here
|
||||
// they cause flashes of un-rendered content when scrolling
|
||||
margin-top: var(--header-height);
|
||||
// TODO: fix this scrollbar extends beyond screen at the bottom
|
||||
padding-bottom: var(--header-height);
|
||||
input {
|
||||
width: 100%;
|
||||
cursor: text;
|
||||
border-bottom: var(--input-border-size) solid var(--input-border-color);
|
||||
color: var(--input-color);
|
||||
line-height: 1;
|
||||
|
||||
&.input-copyable {
|
||||
background: var(--input-bg);
|
||||
color: var(--input-disabled-color);
|
||||
width: 100%;
|
||||
font-family: 'Consolas', 'Lucida Console', 'Adobe Source Code Pro', monospace;
|
||||
border-bottom: 1px dotted var(--color-divider);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
.page {
|
||||
display: grid;
|
||||
grid-template-rows: var(--header-height) calc(100vh - var(--header-height));
|
||||
grid-template-columns: 170px auto;
|
||||
grid-template-areas:
|
||||
'nav header'
|
||||
'nav content';
|
||||
background-color: var(--color-bg);
|
||||
}
|
||||
|
||||
/*
|
||||
Page content
|
||||
*/
|
||||
.content {
|
||||
grid-area: content;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 0 $spacing-vertical * 2/3;
|
||||
padding: 0 $spacing-vertical $spacing-vertical;
|
||||
max-width: 900px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.main--no-padding {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
margin: 0;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.page__header {
|
||||
|
@ -124,26 +144,66 @@ button {
|
|||
font-size: 3em;
|
||||
}
|
||||
|
||||
.columns {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
> * {
|
||||
flex-grow: 1;
|
||||
flex-basis: 0;
|
||||
|
||||
&:not(:first-of-type):not(:last-of-type) {
|
||||
margin: 0 $spacing-vertical / 3;
|
||||
}
|
||||
|
||||
&:first-of-type {
|
||||
margin-right: $spacing-vertical / 3;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
margin-left: $spacing-vertical / 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Custom text selection */
|
||||
*::selection {
|
||||
background: var(--text-selection-bg);
|
||||
color: var(--text-selection-color);
|
||||
}
|
||||
|
||||
.credit-amount--indicator {
|
||||
font-weight: 500;
|
||||
color: var(--color-money);
|
||||
}
|
||||
|
||||
.credit-amount--fee {
|
||||
font-size: 0.9em;
|
||||
color: var(--color-meta-light);
|
||||
}
|
||||
|
||||
.credit-amount--bold {
|
||||
.credit-amount {
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
font-weight: 700;
|
||||
font-size: 0.7em;
|
||||
}
|
||||
|
||||
.credit-amount--free {
|
||||
color: var(--color-black);
|
||||
background-color: var(--color-secondary);
|
||||
}
|
||||
|
||||
.credit-amount--cost {
|
||||
color: var(--color-black);
|
||||
background-color: var(--color-third);
|
||||
}
|
||||
|
||||
.credit-amount--large {
|
||||
font-size: 2em;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
//
|
||||
// .credit-amount--fee {
|
||||
// font-size: 0.9em;
|
||||
// color: var(--color-meta-light);
|
||||
// }
|
||||
//
|
||||
// .credit-amount--bold {
|
||||
// font-weight: 700;
|
||||
// }
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -3,33 +3,39 @@ Both of these should probably die and become variables as well
|
|||
*/
|
||||
$spacing-vertical: 24px;
|
||||
$width-page-constrained: 800px;
|
||||
$text-color: #000;
|
||||
|
||||
:root {
|
||||
--spacing-vertical: 24px;
|
||||
|
||||
/* Colors */
|
||||
--color-white: #fff;
|
||||
--color-black: #000; // I shouldn't use color names like this
|
||||
--color-grey: #d6d6d6;
|
||||
--color-grey-dark: #8e8e8e;
|
||||
--color-primary: #44b098;
|
||||
--color-primary-dark: #2c6e60;
|
||||
--color-secondary: #6afbda;
|
||||
--color-third: #fbd55e;
|
||||
--color-divider: #e3e3e3;
|
||||
|
||||
--text-color: var(--color-black);
|
||||
--color-brand: #155b4a;
|
||||
--color-primary: #155b4a;
|
||||
--color-primary-light: saturate(lighten(#155b4a, 50%), 20%);
|
||||
--color-light-alt: hsl(hue(#155b4a), 15, 85);
|
||||
--color-dark-overlay: rgba(32, 32, 32, 0.9);
|
||||
// --color-dark-overlay: rgba(32, 32, 32, 0.9);
|
||||
--color-help: rgba(0, 0, 0, 0.54);
|
||||
--color-notice: #8a6d3b;
|
||||
// --color-notice: #8a6d3b;
|
||||
--color-error: #a94442;
|
||||
--color-load-screen-text: #c3c3c3;
|
||||
--color-meta-light: #505050;
|
||||
--color-money: #216c2a;
|
||||
--color-download: rgba(0, 0, 0, 0.75);
|
||||
--color-canvas: #f5f5f5;
|
||||
--color-bg: #ffffff;
|
||||
// --color-load-screen-text: #c3c3c3;
|
||||
// --color-meta-light: #505050;
|
||||
// --color-money: #216c2a;
|
||||
// --color-download: rgba(0, 0, 0, 0.75);
|
||||
// --color-canvas: #f5f5f5;
|
||||
--color-bg: #fafafa;
|
||||
--color-bg-alt: #f6f6f6;
|
||||
--color-placeholder: #ececec;
|
||||
--color-nav-bg: #f6f6f6;
|
||||
|
||||
/* Misc */
|
||||
--content-max-width: 1000px;
|
||||
--nsfw-blur-intensity: 20px;
|
||||
--height-video-embedded: $width-page-constrained * 9 / 16;
|
||||
// --content-max-width: 1000px;
|
||||
// --nsfw-blur-intensity: 20px;
|
||||
// --height-video-embedded: $width-page-constrained * 9 / 16;
|
||||
|
||||
/* Font */
|
||||
--font-size: 16px;
|
||||
|
@ -37,16 +43,10 @@ $text-color: #000;
|
|||
--font-size-subtext-multiple: 0.82;
|
||||
|
||||
/* Shadows */
|
||||
--box-shadow-layer: 0px 1px 3px 0px rgba(0, 0, 0, 0.2);
|
||||
--box-shadow-focus: 2px 4px 4px 0 rgba(0, 0, 0, 0.14), 2px 5px 3px -2px rgba(0, 0, 0, 0.2),
|
||||
2px 3px 7px 0 rgba(0, 0, 0, 0.12);
|
||||
|
||||
/* Transition */
|
||||
--transition-duration: 0.225s;
|
||||
--transition-type: ease;
|
||||
// --box-shadow-layer: 0px 1px 3px 0px rgba(0, 0, 0, 0.2);
|
||||
--box-shadow-layer: 0 4px 9px -2px var(--color-grey);
|
||||
|
||||
/* Text */
|
||||
--text-color: $text-color;
|
||||
--text-help-color: #eee;
|
||||
--text-max-width: 660px;
|
||||
--text-link-padding: 4px;
|
||||
|
@ -58,10 +58,10 @@ $text-color: #000;
|
|||
|
||||
/* Input */
|
||||
--input-bg: transparent;
|
||||
--input-width: 330px;
|
||||
--input-label-color: var(--color-grey-dark);
|
||||
--input-color: var(--text-color);
|
||||
--input-border-size: 2px;
|
||||
--input-border-color: rgba(0, 0, 0, 0.54);
|
||||
--input-border-size: 1px;
|
||||
--input-border-color: var(--color-grey-dark);
|
||||
|
||||
/* input:active */
|
||||
--input-active-bg: transparent;
|
||||
|
@ -81,39 +81,28 @@ $text-color: #000;
|
|||
--select-color: var(--text-color);
|
||||
--select-height: 30px;
|
||||
|
||||
//TODO: determine proper button variables;
|
||||
/* Button */
|
||||
--btn-primary-color: #fff;
|
||||
--button-alt-color: var(--text-color);
|
||||
--btn-primary-bg: var(--color-primary);
|
||||
--btn-alt-bg: red;
|
||||
--btn-radius: 10px;
|
||||
// below needed?
|
||||
--btn-padding: $spacing-vertical * 2/3;
|
||||
--btn-height: $spacing-vertical * 1.5;
|
||||
--btn-intra-margin: $spacing-vertical;
|
||||
--btn-primary-bg: var(--color-primary-dark);
|
||||
--btn-inverse-color: var(--color-primary-dark);
|
||||
--btn-inverse-bg: var(--color-white);
|
||||
--btn-radius: 20px;
|
||||
--btn-height: 40px;
|
||||
|
||||
/* Header */
|
||||
--header-bg: var(--color-bg);
|
||||
--header-color: #666;
|
||||
--header-bg: var(--color-white);
|
||||
--header-color: var(--color-text);
|
||||
--header-active-color: rgba(0, 0, 0, 0.85);
|
||||
--header-height: 65px;
|
||||
--header-height: $spacing-vertical * 3;
|
||||
--header-button-bg: transparent; //var(--button-bg);
|
||||
--header-button-hover-bg: rgba(100, 100, 100, 0.15);
|
||||
|
||||
/* Header -> search */
|
||||
--search-bg: rgba(255, 255, 255, 0.7);
|
||||
--search-border: 1px solid #ccc;
|
||||
--search-color: #666;
|
||||
--search-bg-color: #fff;
|
||||
--search-active-color: var(--header-active-color);
|
||||
--search-active-shadow: 0 0 3px 0px var(--text-selection-bg);
|
||||
|
||||
/* Tabs */
|
||||
--tab-bg: transparent;
|
||||
--tab-color: rgba(0, 0, 0, 0.5);
|
||||
--tab-active-color: var(--color-primary);
|
||||
--tab-border-size: 2px;
|
||||
--tab-border: var(--tab-border-size) solid var(--tab-active-color);
|
||||
--search-active-shadow: 0 6px 9px -2px var(--color-grey--dark);
|
||||
|
||||
/* Table */
|
||||
--table-border: 1px solid #e2e2e2;
|
||||
|
@ -121,13 +110,10 @@ $text-color: #000;
|
|||
--table-item-odd: #f4f4f4;
|
||||
|
||||
/* Card */
|
||||
--card-bg: var(--color-bg);
|
||||
--card-hover-translate: 10px;
|
||||
--card-margin: $spacing-vertical * 2/3;
|
||||
--card-max-width: $width-page-constrained;
|
||||
--card-padding: $spacing-vertical * 2/3;
|
||||
--card-radius: 2px;
|
||||
--card-link-scaling: 1.1;
|
||||
--card-small-width: $spacing-vertical * 10;
|
||||
|
||||
/* Modal */
|
||||
|
@ -136,12 +122,7 @@ $text-color: #000;
|
|||
--modal-overlay-bg: rgba(#f5f5f5, 0.75); // --color-canvas: #F5F5F5
|
||||
--modal-border: 1px solid rgb(204, 204, 204);
|
||||
|
||||
/* Menu */
|
||||
--menu-bg: var(--color-bg);
|
||||
--menu-radius: 2px;
|
||||
--menu-item-hover-bg: var(--color-bg-alt);
|
||||
|
||||
/* Tooltip */
|
||||
// /* Tooltip */
|
||||
--tooltip-width: 300px;
|
||||
--tooltip-bg: var(--color-bg);
|
||||
--tooltip-color: var(--text-color);
|
||||
|
@ -153,10 +134,10 @@ $text-color: #000;
|
|||
--scrollbar-thumb-active-bg: var(--color-primary);
|
||||
--scrollbar-track-bg: transparent;
|
||||
|
||||
/* Divider */
|
||||
--divider: 1px solid rgba(0, 0, 0, 0.12);
|
||||
|
||||
/* Animation :) */
|
||||
--animation-duration: 0.3s;
|
||||
--animation-style: cubic-bezier(0.55, 0, 0.1, 1);
|
||||
// /* Divider */
|
||||
// --divider: 1px solid rgba(0, 0, 0, 0.12);
|
||||
//
|
||||
// /* Animation :) */
|
||||
// --animation-duration: 0.3s;
|
||||
// --animation-style: cubic-bezier(0.55, 0, 0.1, 1);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
@charset "UTF-8";
|
||||
@import '_reset';
|
||||
@import '_vars';
|
||||
@import '_icons';
|
||||
@import '_gui';
|
||||
@import 'component/_table';
|
||||
@import 'component/_button.scss';
|
||||
|
@ -28,4 +27,5 @@
|
|||
@import 'component/_radio.scss';
|
||||
@import 'component/_shapeshift.scss';
|
||||
@import 'component/_spinner.scss';
|
||||
@import 'component/_nav.scss';
|
||||
@import 'page/_show.scss';
|
||||
|
|
|
@ -3,34 +3,35 @@ TODO:
|
|||
Determine [disabled] or .disabled
|
||||
Add <a> support (probably just get rid of button prefix)
|
||||
*/
|
||||
|
||||
button {
|
||||
.btn {
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
button:disabled.btn--disabled {
|
||||
cursor: default;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
button.btn {
|
||||
font-weight: 600;
|
||||
padding: 10px;
|
||||
margin: 0 5px;
|
||||
height: var(--btn-height);
|
||||
min-width: var(--btn-height);
|
||||
border-radius: var(--btn-radius);
|
||||
color: var(--btn-primary-color);
|
||||
background-color: var(--btn-primary-bg);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
fill: currentColor; // for proper icon color
|
||||
|
||||
&:hover:not(.btn--disabled) {
|
||||
&:hover {
|
||||
box-shadow: var(--box-shadow-layer);
|
||||
}
|
||||
|
||||
.icon + .btn__label {
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
button.btn.btn--alt {
|
||||
.btn.btn--alt {
|
||||
color: var(--btn-alt-color);
|
||||
background-color: #efefef;
|
||||
background-color: var(--color-white);
|
||||
|
||||
&:hover {
|
||||
color: #111;
|
||||
|
@ -46,30 +47,71 @@ button.btn.btn--alt {
|
|||
}
|
||||
}
|
||||
|
||||
button.btn.btn--circle {
|
||||
border-radius: 50%;
|
||||
transition: all 0.2s;
|
||||
.btn.btn--inverse {
|
||||
background-color: transparent;
|
||||
color: var(--btn-inverse-color);
|
||||
|
||||
&:hover:not([disabled]) {
|
||||
border-radius: var(--btn-radius);
|
||||
&:hover {
|
||||
background-color: var(--btn-inverse-bg);
|
||||
}
|
||||
}
|
||||
|
||||
button.btn.btn--inverse {
|
||||
box-shadow: none;
|
||||
background-color: transparent;
|
||||
color: var(--btn-primary-bg);
|
||||
}
|
||||
|
||||
button.btn--link {
|
||||
.btn.btn--link {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: inherit;
|
||||
font-size: 0.9em;
|
||||
color: var(--btn-primary-bg); // this should be a different color
|
||||
font-size: 1em;
|
||||
color: var(--btn-inverse-color);
|
||||
border-radius: 0;
|
||||
display: inline;
|
||||
|
||||
&:hover {
|
||||
border-bottom: 1px solid;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.btn--no-style {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
color: inherit;
|
||||
background-color: inherit;
|
||||
border-radius: 0;
|
||||
padding: 5px 0;
|
||||
margin: 0;
|
||||
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.btn.btn--link.btn--no-underline:hover {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.btn--link,
|
||||
.btn--no-style {
|
||||
height: auto;
|
||||
|
||||
.btn__label {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.btn.btn--disabled:disabled {
|
||||
cursor: default;
|
||||
|
||||
&.btn--primary {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
&.btn--alt {
|
||||
// Come back to me
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,23 @@
|
|||
.card {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: var(--card-max-width);
|
||||
border-radius: var(--card-radius);
|
||||
overflow: auto;
|
||||
user-select: text;
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.card--placeholder {
|
||||
background-color: black;
|
||||
.card--section {
|
||||
flex-direction: column;
|
||||
background-color: var(--color-white);
|
||||
padding: $spacing-vertical;
|
||||
margin-top: $spacing-vertical * 2/3;
|
||||
box-shadow: var(--box-shadow-layer);
|
||||
}
|
||||
|
||||
.card--small {
|
||||
width: var(--card-small-width);
|
||||
min-height: var(--card-small-width);
|
||||
overflow-x: hidden;
|
||||
white-space: normal;
|
||||
}
|
||||
|
@ -48,7 +51,8 @@
|
|||
margin-top: $spacing-vertical * 1/3;
|
||||
}
|
||||
|
||||
// TODO: regular .card__title for show page
|
||||
// TODO: regular .card__title
|
||||
// maybe not needed?
|
||||
.card__title--small {
|
||||
font-weight: 600;
|
||||
font-size: 0.9em;
|
||||
|
@ -60,145 +64,24 @@
|
|||
padding-top: $spacing-vertical * 1/3;
|
||||
}
|
||||
|
||||
// .card__title-primary .meta {
|
||||
// white-space: nowrap;
|
||||
// overflow: hidden;
|
||||
// text-overflow: ellipsis;
|
||||
// }
|
||||
//
|
||||
.card-media__internal-links {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
//
|
||||
// .card__actions {
|
||||
// margin-top: var(--card-margin);
|
||||
// margin-bottom: var(--card-margin);
|
||||
// user-select: none;
|
||||
// }
|
||||
//
|
||||
// .card__actions--bottom {
|
||||
// margin-top: $spacing-vertical * 1/3;
|
||||
// margin-bottom: $spacing-vertical * 1/3;
|
||||
// border-top: var(--divider);
|
||||
// }
|
||||
//
|
||||
// .card__actions--form-submit {
|
||||
// margin-top: $spacing-vertical;
|
||||
// margin-bottom: var(--card-margin);
|
||||
// }
|
||||
//
|
||||
// .card__action--right {
|
||||
// float: right;
|
||||
// }
|
||||
//
|
||||
// .card__content {
|
||||
// margin-top: var(--card-margin);
|
||||
// margin-bottom: var(--card-margin);
|
||||
// table:not(:last-child) {
|
||||
// margin-bottom: var(--card-margin);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// .card__actions--only-vertical {
|
||||
// margin-left: 0;
|
||||
// margin-right: 0;
|
||||
// padding-left: 0;
|
||||
// padding-right: 0;
|
||||
// }
|
||||
//
|
||||
// .card__content--extra-vertical-space {
|
||||
// margin: $spacing-vertical 0;
|
||||
// }
|
||||
//
|
||||
// $font-size-subtext-multiple: 0.82;
|
||||
// .card__subtext {
|
||||
// color: var(--color-meta-light);
|
||||
// font-size: calc(var(--font-size-subtext-multiple) * 1em);
|
||||
// margin-top: $spacing-vertical * 1/3;
|
||||
// margin-bottom: $spacing-vertical * 1/3;
|
||||
// }
|
||||
// .card__subtext--allow-newlines {
|
||||
// white-space: pre-wrap;
|
||||
// }
|
||||
// .card__subtext--two-lines {
|
||||
// height: calc(
|
||||
// var(--font-size) * var(--font-size-subtext-multiple) * var(--font-line-height) * 2
|
||||
// ); /*this is so one line text still has the proper height*/
|
||||
// }
|
||||
// .card-overlay {
|
||||
// position: absolute;
|
||||
// left: 0px;
|
||||
// right: 0px;
|
||||
// top: 0px;
|
||||
// bottom: 0px;
|
||||
// padding: 20px;
|
||||
// background-color: var(--color-dark-overlay);
|
||||
// color: #fff;
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// font-weight: 600;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// .card__media--autothumb {
|
||||
// position: relative;
|
||||
// }
|
||||
// .card__media--autothumb.purple {
|
||||
// background-color: #9c27b0;
|
||||
// }
|
||||
// .card__media--autothumb.red {
|
||||
// background-color: #e53935;
|
||||
// }
|
||||
// .card__media--autothumb.pink {
|
||||
// background-color: #e91e63;
|
||||
// }
|
||||
// .card__media--autothumb.indigo {
|
||||
// background-color: #3f51b5;
|
||||
// }
|
||||
// .card__media--autothumb.blue {
|
||||
// background-color: #2196f3;
|
||||
// }
|
||||
// .card__media--autothumb.light-blue {
|
||||
// background-color: #039be5;
|
||||
// }
|
||||
// .card__media--autothumb.cyan {
|
||||
// background-color: #00acc1;
|
||||
// }
|
||||
// .card__media--autothumb.teal {
|
||||
// background-color: #009688;
|
||||
// }
|
||||
// .card__media--autothumb.green {
|
||||
// background-color: #43a047;
|
||||
// }
|
||||
// .card__media--autothumb.yellow {
|
||||
// background-color: #ffeb3b;
|
||||
// }
|
||||
// .card__media--autothumb.orange {
|
||||
// background-color: #ffa726;
|
||||
// }
|
||||
//
|
||||
// .card__media--autothumb .card__autothumb__text {
|
||||
// font-size: 2em;
|
||||
// width: 100%;
|
||||
// color: #ffffff;
|
||||
// text-align: center;
|
||||
// position: absolute;
|
||||
// top: 36%;
|
||||
// }
|
||||
//
|
||||
// .card--form {
|
||||
// width: calc(var(--input-width) + var(--card-padding) * 2);
|
||||
// }
|
||||
//
|
||||
.card__content {
|
||||
margin-top: var(--card-margin);
|
||||
margin-bottom: var(--card-margin);
|
||||
}
|
||||
|
||||
//
|
||||
// .card-series-submit {
|
||||
// margin-left: auto;
|
||||
// margin-right: auto;
|
||||
// max-width: var(--card-max-width);
|
||||
// padding: $spacing-vertical / 2;
|
||||
// }
|
||||
.card__actions {
|
||||
margin-top: var(--card-margin);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/*
|
||||
.card-row is used on the discover page
|
||||
.card-row is used on the discover/subscriptions page
|
||||
It is a list of cards that extend past the right edge of the screen
|
||||
There are left/right arrows to scroll the cards and view hidden content
|
||||
*/
|
||||
|
@ -208,6 +91,14 @@
|
|||
width: 100%;
|
||||
min-width: var(--card-small-width);
|
||||
padding-top: $spacing-vertical;
|
||||
|
||||
&:first-of-type {
|
||||
padding-top: $spacing-vertical * 2/3;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
padding-bottom: $spacing-vertical * 2/3;
|
||||
}
|
||||
}
|
||||
|
||||
.card-row__header {
|
||||
|
@ -225,6 +116,10 @@
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.card-row__scroll-btns {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.card-row__scrollhouse {
|
||||
padding-top: $spacing-vertical * 2/3;
|
||||
overflow: hidden;
|
||||
|
@ -233,26 +128,10 @@
|
|||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-left: $spacing-vertical * 2/3;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.card:last-of-type {
|
||||
padding-right: $spacing-vertical * 2/3;
|
||||
margin-right: $spacing-vertical * 2/3;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if we keep doing things like this, we should add a real grid system, but I'm going to be a selective dick about it - Jeremy
|
||||
*/
|
||||
//TODO: css grid
|
||||
// .card-grid {
|
||||
// $margin-card-grid: $spacing-vertical * 2/3;
|
||||
// display: flex;
|
||||
// flex-wrap: wrap;
|
||||
// > .card {
|
||||
// width: $width-page-constrained / 2 - $margin-card-grid / 2;
|
||||
// flex-grow: 1;
|
||||
// }
|
||||
// > .card:nth-of-type(2n - 1):not(:last-child) {
|
||||
// margin-right: $margin-card-grid;
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -1,195 +1,40 @@
|
|||
.form-row-submit {
|
||||
margin-top: $spacing-vertical;
|
||||
}
|
||||
.form-row-submit--with-footer {
|
||||
margin-bottom: $spacing-vertical;
|
||||
}
|
||||
|
||||
.form-row-phone {
|
||||
.form-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.form-field__input-text {
|
||||
margin-left: 5px;
|
||||
width: calc(0.85 * var(--input-width));
|
||||
.form-field:not(:first-of-type) {
|
||||
padding-left: $spacing-vertical;
|
||||
}
|
||||
}
|
||||
|
||||
.form-row__label-row {
|
||||
margin-top: $spacing-vertical * 5/6;
|
||||
margin-bottom: 0px;
|
||||
line-height: 1;
|
||||
font-size: calc(0.9 * var(--font-size));
|
||||
}
|
||||
.form-row__label-row--prefix {
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.form-row--focus {
|
||||
.form-field__label,
|
||||
.form-field__prefix {
|
||||
color: var(--color-primary) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.form-field {
|
||||
display: inline-block;
|
||||
margin: 8px 0;
|
||||
|
||||
select {
|
||||
transition: outline var(--transition-duration) var(--transition-type);
|
||||
box-sizing: border-box;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
height: var(--select-height);
|
||||
background: var(--select-bg);
|
||||
color: var(--select-color);
|
||||
&:focus {
|
||||
outline: var(--input-border-size) solid var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
input[type='radio'],
|
||||
input[type='checkbox'] {
|
||||
&:checked + .form-field__label {
|
||||
color: var(--text-color);
|
||||
}
|
||||
}
|
||||
|
||||
input[type='text'].input-copyable {
|
||||
background: var(--input-bg);
|
||||
color: var(--input-disabled-color);
|
||||
line-height: 1;
|
||||
padding-top: $spacing-vertical * 1/3;
|
||||
padding-bottom: $spacing-vertical * 1/3;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
width: 100%;
|
||||
font-family: 'Consolas', 'Lucida Console', 'Adobe Source Code Pro', monospace;
|
||||
|
||||
&.input-copyable--with-copy-btn {
|
||||
width: 85%;
|
||||
}
|
||||
}
|
||||
|
||||
input[readonly] {
|
||||
color: var(--input-disabled-color) !important;
|
||||
border-bottom: 1px dashed var(--input-disabled-border-color) !important;
|
||||
}
|
||||
|
||||
input[readonly]:focus {
|
||||
background: var(--input-bg) !important;
|
||||
border-bottom: 1px dashed var(--input-disabled-border-color) !important;
|
||||
}
|
||||
|
||||
textarea,
|
||||
input[type='text'],
|
||||
input[type='password'],
|
||||
input[type='email'],
|
||||
input[type='number'],
|
||||
input[type='search'],
|
||||
input[type='date'] {
|
||||
background: var(--input-bg);
|
||||
border-bottom: var(--input-border-size) solid var(--input-border-color);
|
||||
caret-color: var(--color-primary);
|
||||
color: var(--input-color);
|
||||
cursor: pointer;
|
||||
line-height: 1;
|
||||
padding: 0 1px 8px 1px;
|
||||
box-sizing: border-box;
|
||||
-webkit-appearance: none;
|
||||
transition: all var(--transition-duration) var(--transition-type);
|
||||
|
||||
&::-webkit-input-placeholder {
|
||||
color: var(--input-placeholder-color);
|
||||
opacity: var(--input-placeholder-opacity) !important;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: var(--color-primary);
|
||||
background: var(--input-active-bg);
|
||||
}
|
||||
|
||||
&:hover:not(:focus) {
|
||||
border-color: var(--input-hover-border-color);
|
||||
}
|
||||
|
||||
&.form-field__input--error {
|
||||
border-color: var(--color-error);
|
||||
}
|
||||
|
||||
&.form-field__input--inline {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
border-bottom-width: var(--input-border-size);
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
padding: 2px;
|
||||
border: var(--input-border-size) solid var(--input-border-color);
|
||||
}
|
||||
}
|
||||
.form-field--address {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-field--SimpleMDE {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.form-field__label,
|
||||
.form-row__label {
|
||||
color: var(--form-label-color);
|
||||
&[for] {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.form-row__label-row .form-field__label--error {
|
||||
/*the row restriction is to prevent coloring checkboxes and radio labels*/
|
||||
color: var(--color-error);
|
||||
}
|
||||
|
||||
.form-field__input-text {
|
||||
width: var(--input-width);
|
||||
}
|
||||
|
||||
.form-field__prefix {
|
||||
margin-right: 4px;
|
||||
}
|
||||
.form-field__postfix {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.form-field__input-number {
|
||||
width: 70px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.form-field--textarea {
|
||||
width: 100%;
|
||||
}
|
||||
.form-field__input-textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-field__error,
|
||||
.form-field__helper {
|
||||
margin-top: $spacing-vertical * 1/3;
|
||||
font-size: 0.8em;
|
||||
transition: opacity var(--transition-duration) var(--transition-type);
|
||||
.form-field__wrapper {
|
||||
display: flex;
|
||||
padding: $spacing-vertical / 3 0;
|
||||
}
|
||||
|
||||
.form-field__error {
|
||||
color: var(--color-error);
|
||||
}
|
||||
.form-field__helper {
|
||||
color: var(--color-help);
|
||||
|
||||
.form-field__label {
|
||||
color: var(--color-grey-dark);
|
||||
}
|
||||
|
||||
.form-field__input.form-field__input-SimpleMDE .CodeMirror-scroll {
|
||||
height: auto;
|
||||
.form-field__prefix {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.form-field__postfix {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
// Not sure if I like these
|
||||
// Maybe this should be in gui.scss?
|
||||
.input--lbc-amount {
|
||||
width: 75px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.input--address {
|
||||
width: 370px;
|
||||
}
|
||||
|
|
|
@ -1,60 +1,86 @@
|
|||
#header {
|
||||
.header {
|
||||
grid-area: header;
|
||||
display: flex;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: var(--header-height);
|
||||
z-index: 3;
|
||||
box-sizing: border-box;
|
||||
color: var(--header-color);
|
||||
background-color: var(--header-bg);
|
||||
}
|
||||
|
||||
.header__actions-left {
|
||||
display: flex;
|
||||
padding: 0 5px;
|
||||
justify-content: space-between;
|
||||
padding: 0 $spacing-vertical;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
background-color: var(--color-bg);
|
||||
}
|
||||
|
||||
.header__actions-right {
|
||||
margin-left: auto;
|
||||
padding-left: $spacing-vertical / 2;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.header__wunderbar {
|
||||
z-index: 1;
|
||||
flex: 1;
|
||||
max-width: 325px;
|
||||
min-width: 175px;
|
||||
overflow: hidden;
|
||||
overflow: visible;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 5px;
|
||||
cursor: text;
|
||||
}
|
||||
position: relative;
|
||||
|
||||
.wunderbar__input {
|
||||
height: 50%;
|
||||
width: 100%;
|
||||
color: var(--search-color);
|
||||
padding: 10px;
|
||||
background-color: #f3f3f3;
|
||||
border-radius: 10px;
|
||||
font-size: 0.9em;
|
||||
|
||||
&:focus {
|
||||
// TODO: focus style
|
||||
.icon {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.wunderbar__input {
|
||||
height: var(--btn-height);
|
||||
border-radius: var(--btn-radius);
|
||||
width: 100%;
|
||||
max-width: 700px;
|
||||
color: var(--search-color);
|
||||
background-color: var(--search-bg-color);
|
||||
box-shadow: var(--box-shadow-layer);
|
||||
padding: 10px;
|
||||
padding-left: 30px;
|
||||
font-size: 0.9em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-bottom: none;
|
||||
|
||||
&:focus {
|
||||
background-color: var(--color-bg);
|
||||
border-radius: 0;
|
||||
border-bottom: 1px solid var(--color-grey);
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.wunderbar__menu {
|
||||
max-width: 100px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.wunderbar__suggestion {
|
||||
padding: 5px;
|
||||
padding: 10px;
|
||||
background-color: var(--header-bg);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
&:not(:first-of-type) {
|
||||
border-top: 1px solid var(--color-divider);
|
||||
}
|
||||
}
|
||||
|
||||
.wunderbar__suggestion-label {
|
||||
padding-left: $spacing-vertical;
|
||||
}
|
||||
|
||||
.wunderbar__active-suggestion {
|
||||
background-color: #a3ffb0;
|
||||
background-color: var(--color-secondary);
|
||||
}
|
||||
|
|
51
src/renderer/scss/component/_nav.scss
Normal file
|
@ -0,0 +1,51 @@
|
|||
.nav {
|
||||
grid-area: nav;
|
||||
background-color: var(--color-nav-bg);
|
||||
padding-top: 16px;
|
||||
|
||||
hr {
|
||||
width: 40px;
|
||||
border: solid 1px var(--color-grey);
|
||||
margin: $spacing-vertical $spacing-vertical * 2/3 $spacing-vertical * 2;
|
||||
}
|
||||
}
|
||||
|
||||
.nav__actions-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.nav__actions-history {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.nav__primary {
|
||||
padding-top: $spacing-vertical * 3;
|
||||
}
|
||||
|
||||
.nav__link {
|
||||
padding: $spacing-vertical / 3 0 $spacing-vertical / 3 $spacing-vertical * 2/3;
|
||||
font-weight: bold;
|
||||
color: var(--color-grey-dark);
|
||||
|
||||
// The hover effect should be on the li
|
||||
// Need to have the button grow
|
||||
& .btn:hover {
|
||||
color: var(--color-black);
|
||||
}
|
||||
}
|
||||
|
||||
.nav__link--active {
|
||||
color: var(--color-black);
|
||||
}
|
||||
|
||||
.nav__sub {
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.nav__sub-link {
|
||||
padding: 5px $spacing-vertical * 2/3;
|
||||
font-size: 0.8em;
|
||||
}
|
|
@ -1,17 +1,3 @@
|
|||
// Can't think of a better way to do this
|
||||
// The initial shapeshift form is 311px tall
|
||||
// the .shapeshift__initial-wrapper class is only added when the form is being loaded
|
||||
// Once the form is rendered, there is a very smooth transition because the height doesn't change
|
||||
.shapeshift__wrapper.shapeshift__initial-wrapper {
|
||||
min-height: 346px;
|
||||
}
|
||||
|
||||
.shapeshift__content {
|
||||
.spinner {
|
||||
margin-top: $spacing-vertical * 3;
|
||||
}
|
||||
}
|
||||
|
||||
.shapeshift__tx-info {
|
||||
min-height: 63px;
|
||||
}
|
||||
|
|
23
src/renderer/util/form-validation.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
// @flow
|
||||
/* eslint-disable prefer-default-export */
|
||||
import { REGEXP_ADDRESS } from 'lbryURI';
|
||||
|
||||
type DraftTxValues = {
|
||||
address: string,
|
||||
// amount: number
|
||||
}
|
||||
|
||||
export const validateSendTx = (formValues: DraftTxValues) => {
|
||||
const { address } = formValues
|
||||
const errors = {};
|
||||
|
||||
// All we need to check is if the address is valid
|
||||
// If values are missing, users wont' be able to submit the form
|
||||
if (address && !REGEXP_ADDRESS.test(address)) {
|
||||
errors.address = __('Not a valid LBRY address');
|
||||
}
|
||||
|
||||
return errors;
|
||||
};
|
||||
|
||||
/* eslint-enable prefer-default-export */
|
Before Width: | Height: | Size: 434 KiB |
12
yarn.lock
|
@ -5960,11 +5960,7 @@ moment@^2.20.1:
|
|||
version "2.20.1"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.20.1.tgz#d6eb1a46cbcc14a2b2f9434112c1ff8907f313fd"
|
||||
|
||||
<<<<<<< HEAD
|
||||
move-concurrently@^1.0.1, move-concurrently@~1.0.1:
|
||||
=======
|
||||
move-concurrently@^1.0.1:
|
||||
>>>>>>> Merge master branch in to 'redesign'
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
|
||||
dependencies:
|
||||
|
@ -7490,6 +7486,10 @@ react-dom@^16.2.0:
|
|||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.0"
|
||||
|
||||
react-feather@^1.0.8:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/react-feather/-/react-feather-1.0.8.tgz#69b13d5c729949f194d33201dee91bab67fa31a2"
|
||||
|
||||
react-markdown@^2.5.0:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-2.5.1.tgz#f7a6c26a3a5faf5d4c2098155d9775e826fd56ee"
|
||||
|
@ -9100,11 +9100,10 @@ unc-path-regex@^0.1.0:
|
|||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa"
|
||||
|
||||
<<<<<<< HEAD
|
||||
underscore@>1.4.4:
|
||||
version "1.8.3"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
|
||||
=======
|
||||
|
||||
union-value@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4"
|
||||
|
@ -9113,7 +9112,6 @@ union-value@^1.0.0:
|
|||
get-value "^2.0.6"
|
||||
is-extendable "^0.1.1"
|
||||
set-value "^0.4.3"
|
||||
>>>>>>> Merge master branch in to 'redesign'
|
||||
|
||||
uniq@^1.0.1:
|
||||
version "1.0.1"
|
||||
|
|
Using render props makes it really simple add additional items to the form field like this button. Instead of having a huge
FormField
element that can do everything, allowing the user of the component to do whatever they want can be really nice.