New: UI Updates (Backup Restore in App, Profile Cloning)

UI Pulls from Sonarr
This commit is contained in:
Qstick 2018-01-14 17:11:37 -05:00
parent 80a5701b99
commit 744742b5ff
80 changed files with 2376 additions and 795 deletions

View file

@ -1,4 +1,5 @@
.card {
position: relative;
margin: 10px;
padding: 10px;
border-radius: 3px;
@ -6,3 +7,13 @@
box-shadow: 0 0 10px 1px $cardShadowColor;
color: $defaultColor;
}
.underlay {
@add-mixin cover;
}
.overlay {
@add-mixin linkOverlay;
position: relative;
}

View file

@ -11,10 +11,27 @@ class Card extends Component {
render() {
const {
className,
overlayClassName,
overlayContent,
children,
onPress
} = this.props;
if (overlayContent) {
return (
<div className={className}>
<Link
className={styles.underlay}
onPress={onPress}
/>
<div className={overlayClassName}>
{children}
</div>
</div>
);
}
return (
<Link
className={className}
@ -28,12 +45,16 @@ class Card extends Component {
Card.propTypes = {
className: PropTypes.string.isRequired,
overlayClassName: PropTypes.string.isRequired,
overlayContent: PropTypes.bool.isRequired,
children: PropTypes.node.isRequired,
onPress: PropTypes.func.isRequired
};
Card.defaultProps = {
className: styles.card
className: styles.card,
overlayClassName: styles.overlay,
overlayContent: false
};
export default Card;

View file

@ -42,10 +42,8 @@ function CaptchaInput(props) {
onPress={onRefreshPress}
>
<Icon
name={classNames(
icons.REFRESH,
refreshing && 'fa-spin'
)}
name={icons.REFRESH}
isSpinning={refreshing}
/>
</FormInputButton>
</div>

View file

@ -5,14 +5,107 @@ import styles from './TextInput.css';
class TextInput extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this._input = null;
this._selectionStart = null;
this._selectionEnd = null;
this._selectionTimeout = null;
this._isMouseTarget = false;
}
componentDidMount() {
window.addEventListener('mouseup', this.onDocumentMouseUp);
}
componentWillUnmount() {
window.removeEventListener('mouseup', this.onDocumentMouseUp);
}
//
// Control
setInputRef = (ref) => {
this._input = ref;
}
selectionChange() {
if (this._selectionTimeout) {
this._selectionTimeout = clearTimeout(this._selectionTimeout);
}
this._selectionTimeout = setTimeout(() => {
const selectionStart = this._input.selectionStart;
const selectionEnd = this._input.selectionEnd;
const selectionChanged = (
this._selectionStart !== selectionStart ||
this._selectionEnd !== selectionEnd
);
this._selectionStart = selectionStart;
this._selectionEnd = selectionEnd;
if (this.props.onSelectionChange && selectionChanged) {
this.props.onSelectionChange(selectionStart, selectionEnd);
}
}, 10);
}
//
// Listeners
onChange = (event) => {
this.props.onChange({
name: this.props.name,
const {
name,
type,
onChange
} = this.props;
const payload = {
name,
value: event.target.value
});
};
// Also return the files for a file input type.
if (type === 'file') {
payload.files = event.target.files;
}
onChange(payload);
}
onFocus = (event) => {
if (this.props.onFocus) {
this.props.onFocus(event);
}
this.selectionChange();
}
onKeyUp = () => {
this.selectionChange();
}
onMouseDown = () => {
this._isMouseTarget = true;
}
onMouseUp = () => {
this.selectionChange();
}
onDocumentMouseUp = () => {
if (this._isMouseTarget) {
this.selectionChange();
}
this._isMouseTarget = false;
}
//
@ -29,12 +122,12 @@ class TextInput extends Component {
value,
hasError,
hasWarning,
hasButton,
onFocus
hasButton
} = this.props;
return (
<input
ref={this.setInputRef}
type={type}
readOnly={readOnly}
autoFocus={autoFocus}
@ -49,7 +142,10 @@ class TextInput extends Component {
name={name}
value={value}
onChange={this.onChange}
onFocus={onFocus}
onFocus={this.onFocus}
onKeyUp={this.onKeyUp}
onMouseDown={this.onMouseDown}
onMouseUp={this.onMouseUp}
/>
);
}
@ -67,7 +163,8 @@ TextInput.propTypes = {
hasWarning: PropTypes.bool,
hasButton: PropTypes.bool,
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func
onFocus: PropTypes.func,
onSelectionChange: PropTypes.func
};
TextInput.defaultProps = {

View file

@ -1,6 +1,6 @@
import PropTypes from 'prop-types';
import React from 'react';
import { kinds } from 'Helpers/Props';
import { icons, kinds } from 'Helpers/Props';
import classNames from 'classnames';
import styles from './Icon.css';
@ -10,7 +10,8 @@ function Icon(props) {
name,
kind,
size,
title
title,
isSpinning
} = props;
return (
@ -18,7 +19,8 @@ function Icon(props) {
className={classNames(
name,
className,
styles[kind]
styles[kind],
isSpinning && icons.SPIN
)}
title={title}
style={{
@ -33,12 +35,14 @@ Icon.propTypes = {
name: PropTypes.string.isRequired,
kind: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
title: PropTypes.string
title: PropTypes.string,
isSpinning: PropTypes.bool.isRequired
};
Icon.defaultProps = {
kind: kinds.DEFAULT,
size: 14
size: 14,
isSpinning: false
};
export default Icon;

View file

@ -11,6 +11,7 @@ function IconButton(props) {
name,
kind,
size,
isSpinning,
...otherProps
} = props;
@ -24,6 +25,7 @@ function IconButton(props) {
name={name}
kind={kind}
size={size}
isSpinning={isSpinning}
/>
</Link>
);
@ -34,7 +36,8 @@ IconButton.propTypes = {
iconClassName: PropTypes.string,
kind: PropTypes.string,
name: PropTypes.string.isRequired,
size: PropTypes.number
size: PropTypes.number,
isSpinning: PropTypes.bool
};
IconButton.defaultProps = {

View file

@ -29,10 +29,8 @@ function SpinnerButton(props) {
<span className={styles.spinnerContainer}>
<Icon
className={styles.spinner}
name={classNames(
spinnerIcon,
'fa-spin'
)}
name={spinnerIcon}
isSpinning={true}
/>
</span>

View file

@ -14,7 +14,7 @@ function SpinnerIconButton(props) {
return (
<IconButton
name={isSpinning ? `${spinningName || name} fa-spin` : name}
name={isSpinning ? (spinningName || name) : name}
isDisabled={isDisabled || isSpinning}
{...otherProps}
/>

View file

@ -26,7 +26,8 @@ function PageToolbarButton(props) {
{...otherProps}
>
<Icon
name={isSpinning ? `${spinningName || iconName} fa-spin` : iconName}
name={isSpinning ? (spinningName || iconName) : iconName}
isSpinning={isSpinning}
size={22}
/>

View file

@ -312,7 +312,8 @@ class SignalRConnector extends Component {
this.props.setAppValue({
isConnected: true,
isReconnecting: false,
isDisconnected: false
isDisconnected: false,
isRestarting: false
});
this.retryInterval = 5;

View file

@ -13,7 +13,7 @@ function SpinnerIcon(props) {
return (
<Icon
name={isSpinning ? `${spinningName || name} fa-spin` : name}
name={isSpinning ? (spinningName || name) : name}
{...otherProps}
/>
);