Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add filters to trade history #544

Merged
merged 43 commits into from
Nov 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
4c432d2
Add filters to trade history
kevva Oct 8, 2018
9ddfa21
Remove unused translations
kevva Oct 8, 2018
cce1990
Fix lint errors
kevva Oct 8, 2018
6b00ee2
Fix `border-radius` unsetting
kevva Oct 8, 2018
cdd1093
Use consistent color in inputs
kevva Oct 8, 2018
4421094
Use `default` cursor in date picker
kevva Oct 8, 2018
c7879ef
Improve disabled days styles
kevva Oct 8, 2018
ba2aca1
Use variable color instead of `#fff`
kevva Oct 8, 2018
d5990a1
Prevent date from getting unselected
kevva Oct 8, 2018
d24b633
Improve style loader regex
kevva Oct 8, 2018
c2bdf15
Align select arrow with clear icon
kevva Oct 8, 2018
68c6f78
Fix entering text in the date inputs (#549)
sindresorhus Oct 9, 2018
66321f3
Fix lock file
kevva Oct 9, 2018
6db13fa
Set date format to `YYYY-MM-DD`
kevva Oct 9, 2018
0c1fbd0
Forward `ref` to `WrappedInput`
kevva Oct 9, 2018
777ad7c
Merge remote-tracking branch 'origin/master' into filter
kevva Oct 9, 2018
81125fc
Add tests
kevva Oct 9, 2018
1db4ba7
Don't wrap months
kevva Oct 12, 2018
d801f15
Don't update values in `Input` if validation fails
kevva Oct 13, 2018
fc79276
Add validation pattern for date inputs
kevva Oct 13, 2018
0d57df7
Add initial values to date filters in swap list
kevva Oct 13, 2018
14611e5
Add test for initial state
kevva Oct 13, 2018
59eee8a
Disable selecting days after todays date
kevva Oct 13, 2018
779861a
Add border radius on hovered days
kevva Oct 13, 2018
0e50fe6
Merge remote-tracking branch 'origin/master' into filter
kevva Oct 13, 2018
8fe9092
Handle border radius for days next to selected days
kevva Oct 15, 2018
2b972c5
Merge remote-tracking branch 'origin/master' into filter
kevva Oct 15, 2018
0daf8a5
Merge remote-tracking branch 'origin/master' into filter
kevva Oct 21, 2018
40ecc37
index on filter: 0daf8a5 Merge remote-tracking branch 'origin/master'…
kevva Oct 22, 2018
cebd058
Merge remote-tracking branch 'origin/master' into filter
kevva Oct 28, 2018
16ad991
Set `level: error` when `pattern` isn't valid
kevva Oct 28, 2018
95bf89d
Add `autoCorrect` prop to `DateInput`
kevva Oct 30, 2018
8dc030c
Add prop types
kevva Oct 30, 2018
16bc8ee
Forward `inputProps`
kevva Oct 30, 2018
4bb6571
Remove margins
kevva Oct 30, 2018
e596f1a
Don't show future dates in calendar
kevva Oct 30, 2018
f2df084
Update input value on invalid input
kevva Nov 1, 2018
fc3de31
Merge remote-tracking branch 'origin/master' into filter
kevva Nov 4, 2018
1692fec
Decrease auto correction timeout
kevva Nov 6, 2018
63ba90f
Trigger `onChange` manually when autocorrecting value
kevva Nov 8, 2018
210a8ae
Accept function in `pattern` prop
kevva Nov 8, 2018
bc7f6f8
Fix tests
kevva Nov 8, 2018
08425fd
Don't validate empty input
kevva Nov 8, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions app/locales/en-US/swap.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,14 @@
"toggleAdvancedButton": {
"more": "More",
"less": "Less"
},
"filter": {
"buy": "Buy",
"date": "Date",
"dateFrom": "From",
"dateTo": "To",
"pair": "Pair",
"sell": "Sell",
"type": "Type"
}
}
104 changes: 104 additions & 0 deletions app/renderer/components/DateInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import React from 'react';
import PropTypes from 'prop-types';
import DayPickerInput from 'react-day-picker/DayPickerInput';
import moment from 'moment';
import MomentLocaleUtils, {formatDate, parseDate} from 'react-day-picker/moment';
import 'react-day-picker/lib/style.css';
import Input from 'components/Input';
import {instance} from '../translate';
import {setInputValue} from '../util';
import './DateInput.scss';

const WrappedInput = React.forwardRef((props, ref) => {
const onChange = (value, event) => props.onChange(event);
const validateInput = value => moment(value).isValid();

return <Input {...props} ref={ref} pattern={validateInput} onChange={onChange}/>;
});

class DateInput extends React.Component {
static propTypes = {
autoCorrect: PropTypes.bool,
forwardedRef: PropTypes.oneOfType([
PropTypes.func,
PropTypes.object,
]),
onDayChange: PropTypes.func,
}

constructor(props) {
super(props);
this.inputRef = this.props.forwardedRef || React.createRef();
this.state = {
hasError: false,
isInvalid: false,
value: this.props.value,
};
}

handleBlur = event => {
const {autoCorrect, onBlur} = this.props;
const {value} = this.state;

if (autoCorrect && this.state.isInvalid) {
this.setState({hasError: true});

setTimeout(() => {
const {dayPickerProps, format, formatDate} = this.inputRef.current.props;
setInputValue(event.target, formatDate(value, format, dayPickerProps.locale));
}, 600);
}

if (typeof onBlur === 'function') {
onBlur(event);
}
}

handleDayChange = (day, modifiers, input) => {
const {onDayChange} = this.props;
const inputValue = input.getInput().value;
const isInvalid = modifiers.disabled || (!day && inputValue);

this.setState(state => ({
hasError: false,
isInvalid,
value: isInvalid ? state.value : day,
}), () => {
onDayChange(day, modifiers, input);
});
};

render() {
const {hasError} = this.state;

return (
<DayPickerInput
{...this.props}
ref={this.inputRef}
component={WrappedInput}
format="YYYY-MM-DD"
formatDate={formatDate}
onDayChange={this.handleDayChange}
parseDate={parseDate}
dayPickerProps={{
...this.props.dayPickerProps,
locale: instance.language,
localeUtils: MomentLocaleUtils,
}}
inputProps={{
...this.props.inputProps,
className: hasError ? 'shake-animation' : '',
onBlur: this.handleBlur,
}}
/>
);
}
}

export default React.forwardRef((props, ref) => (
<DateInput {...props} forwardedRef={ref}/>
));

export {
WrappedInput,
};
49 changes: 49 additions & 0 deletions app/renderer/components/DateInput.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* stylelint-disable selector-class-pattern */
.DayPickerInput-Overlay {
margin-top: 4px;
text-align: center;
color: var(--text-color);
background-color: var(--input-background-color);
border: 1px solid var(--input-border-color);
border-radius: 4px;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
}

.DayPicker-Months {
flex-wrap: unset;
}

.DayPicker-NavButton,
.DayPicker-Day {
cursor: default;
}

.DayPicker:not(.DayPicker--interactionDisabled) .DayPicker-Day:not(.DayPicker-Day--disabled):not(.DayPicker-Day--selected):not(.DayPicker-Day--outside):hover {
color: var(--text-color2);
background-color: var(--primary-color);
border-radius: 2px;
}

.DayPicker-Day--today {
color: var(--secondary-color);
font-weight: normal;

&:hover:not(.DayPicker-Day--disabled):not(.DayPicker-Day--outside) {
color: var(--text-color2);
}
}

.DayPicker-Day--selected:not(.DayPicker-Day--disabled):not(.DayPicker-Day--outside) {
color: var(--text-color2);
background-color: var(--primary-color);

&:hover {
background-color: var(--primary-color);
}
}

.DayPicker-Day--disabled:not(.DayPicker-Day--today),
.DayPicker-Day--outside:not(.DayPicker-Day--today) {
color: var(--text-color);
opacity: 0.5;
}
39 changes: 35 additions & 4 deletions app/renderer/components/Input.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import {classNames} from 'react-extras';
import propTypesRange from 'prop-types-range';
import _ from 'lodash';
import './Input.scss';

const stripLeadingZeros = string => string.replace(/^0+(?=\d)/, '');
Expand Down Expand Up @@ -46,13 +47,27 @@ class Input extends React.Component {
}

static getDerivedStateFromProps(props, state) {
return props.value === state.prevValue ? null : {
value: props.value,
prevValue: props.value,
const isValueChanged = props.value !== state.prevValue;
const isLevelChanged = props.level !== state.prevLevel;

if (!isValueChanged && !isLevelChanged) {
return null;
}

return {
...isValueChanged && {
value: props.value,
prevValue: props.value,
},
...isLevelChanged && {
level: props.level,
prevLevel: props.level,
},
};
}

state = {
level: this.props.level,
value: this.props.value || '',
};

Expand All @@ -76,13 +91,23 @@ class Input extends React.Component {
event.persist();
}

this._checkValidity(event);

this.setState({value}, () => {
if (onChange) {
onChange(value, event);
}
});
};

_checkValidity = _.debounce(event => {
const {pattern} = this.props;
const {value} = event.target;
const isValid = typeof pattern === 'function' ? (!value || pattern(value)) : event.target.checkValidity();

this.setState({level: isValid ? null : 'error'});
}, 500);

_shouldTruncateFractions(value) {
const {fractionalDigits} = this.props;

Expand Down Expand Up @@ -113,7 +138,6 @@ class Input extends React.Component {
let {
forwardedRef,
className,
level,
message,
errorMessage,
disabled,
Expand All @@ -125,10 +149,12 @@ class Input extends React.Component {
icon,
iconSize,
iconName,
pattern,
view: View,
button: Button,
...props
} = this.props;
let {level} = this.state;

if (errorMessage) {
level = 'error';
Expand All @@ -143,6 +169,10 @@ class Input extends React.Component {
icon = `/assets/${iconName}-icon.svg`;
}

if (typeof pattern === 'function') {
pattern = null;
}

const containerClassName = classNames(
'Input',
{
Expand Down Expand Up @@ -182,6 +212,7 @@ class Input extends React.Component {
value={value}
type={type}
disabled={disabled}
pattern={pattern}
readOnly={readOnly}
onChange={this.handleChange}
/>
Expand Down
2 changes: 1 addition & 1 deletion app/renderer/components/Select.scss
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@
height: 5px;
position: absolute;
top: 50%;
margin: -3px 0 0 -3px;
margin: -4px 0 0 -3px;
transform: rotate(45deg);
border-left: none;
border-top: none;
Expand Down
Loading