Skip to content

Commit

Permalink
Release 1.8.0-RC1 back into develop (#94)
Browse files Browse the repository at this point in the history
* prepare release 1.8.0-RC1

* Feature/money filter (#92)

* Replace concept nodes by concept lists (#88)

* Make concept lists the default node type, remove special handling

* Add code list resolution to demo data

* initial money range filter

* update moneyRange

* remove accounting
update yarn.lock

* update demo data

* update formatted value for money range

* fix decimal scale expect number

* fixed wrong result display position (#93)

* update money range

* fix type imports

* update demo data

* reset max-len in eslintrc.json
  • Loading branch information
MarcusBaitz authored and rs22 committed Mar 26, 2018
1 parent fa07bb4 commit 75912f9
Show file tree
Hide file tree
Showing 20 changed files with 749 additions and 595 deletions.
12 changes: 11 additions & 1 deletion frontend/app/api/stored-queries/25.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,17 @@
"type": "CONCEPT",
"tables": [
{
"id": "feature_films"
"id": "feature_films",
"filters": [
{
"id": "budget",
"type": "MONEY_RANGE",
"value": {
"min": 10000000,
"max": 150000000
}
}
]
},
{
"id": "tv_series"
Expand Down
6 changes: 4 additions & 2 deletions frontend/lib/js/common/types/backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@ export type InfoType = {
}

export type RangeFilterValueType = { min?: number, max?: number, exact?: number }
export type RangeFilterFormattedValueType = { min?: number, max?: number, exact?: number }
export type RangeFilterType = {
id: number,
label: string,
description?: string,
type: 'INTEGER_RANGE' | 'REAL_RANGE',
type: 'INTEGER_RANGE' | 'REAL_RANGE' | 'MONEY_RANGE',
value: ?RangeFilterValueType,
formattedValue: ?RangeFilterFormattedValueType,
unit?: string,
mode: 'range' | 'exact',
precision?: number,
min?: number,
max?: number,
defaultValue: ?RangeFilterValueType
}

export type MultiSelectFilterValueType = (string | number)[];
Expand Down
47 changes: 39 additions & 8 deletions frontend/lib/js/form-components/ClearableInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,59 @@

import React from 'react';
import T from 'i18n-react';
import NumberFormat from 'react-number-format';

import { isEmpty } from '../common/helpers';
import { MONEY_RANGE } from './filterTypes';

type PropsType = {
inputType: string,
valueType?: string,
placeholder?: string,
value: ?(number | string),
formattedValue?: string,
inputProps?: Object,
onChange: Function,
};

type NumberFormatValueType = {
floatValue:number,
formattedValue: string,
value: string
};

const ClearableInput = (props: PropsType) => {
return (
<span className="clearable-input">
<input
className="clearable-input__input"
placeholder={props.placeholder}
type={props.inputType}
onChange={(e) => props.onChange(e.target.value)}
value={props.value}
{...props.inputProps}
/>
{
props.valueType === MONEY_RANGE
? <NumberFormat
prefix={T.translate('moneyRange.prefix')}
thousandSeparator={T.translate('moneyRange.thousandSeparator')}
decimalSeparator={T.translate('moneyRange.decimalSeparator')}
decimalScale={parseInt(T.translate('moneyRange.decimalScale'))}
className="clearable-input__input"
placeholder={props.placeholder}
type={props.inputType}
onValueChange={(values: NumberFormatValueType) => {
const { formattedValue, floatValue } = values;
props.onChange({
formattedValue,
raw: floatValue * (T.translate('moneyRange.factor') || 1)
});
}}
value={props.formattedValue}
{...props.inputProps}
/>
: <input
className="clearable-input__input"
placeholder={props.placeholder}
type={props.inputType}
onChange={(e) => props.onChange(e.target.value)}
value={props.value}
{...props.inputProps}
/>
}
{
!isEmpty(props.value) &&
<span
Expand Down
57 changes: 35 additions & 22 deletions frontend/lib/js/form-components/InputRange.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
// @flow

import React from 'react';
import T from 'i18n-react';
import classnames from 'classnames';
import React from 'react';
import T from 'i18n-react';
import classnames from 'classnames';
import { type FieldPropsType } from 'redux-form';

import InputWithLabel from './InputWithLabel';
import ToggleButton from './ToggleButton';
import InputRangeHeader from './InputRangeHeader';
import InputWithLabel from './InputWithLabel';
import ToggleButton from './ToggleButton';
import InputRangeHeader from './InputRangeHeader';

type PropsType = FieldPropsType & {
inputType: string,
valueType?: string,
label: string,
unit?: string,
limits?: {
Expand All @@ -30,15 +31,26 @@ type PropsType = FieldPropsType & {
min?: number,
max?: number
},
formattedValue: ?{
exact?: string,
min?: string,
max?: string
}
}
};

const InputRange = (props: PropsType) => {
const { value } = props.input;
const { value, formattedValue } = props.input;
// Make sure undefined / null is never set as a value, but an empty string instead
const minValue = (value && value.min) || '';
const maxValue = (value && value.max) || '';
const exactValue = (value && value.exact) || '';

const factor = T.translate('moneyRange.factor') || 1;
const minFormattedValue = ((formattedValue && formattedValue.min) || (parseInt(minValue) / factor)) || '';
const maxFormattedValue = ((formattedValue && formattedValue.max) || (parseInt(maxValue) / factor)) || '';
const exactFormattedValue = ((formattedValue && formattedValue.exact) || (parseInt(exactValue) / factor)) || '';

const isRangeMode = props.mode === 'range';
const inputProps = {
step: props.stepSize || null,
Expand All @@ -48,28 +60,23 @@ const InputRange = (props: PropsType) => {

const onChangeValue = (type, newValue) => {
const { value } = props.input;
const nextValue = newValue || null;
const { formattedValue, raw } = newValue;
const nextValue = raw || null;

if (type === 'exact')
// SET ENTIRE VALUE TO NULL IF POSSIBLE
if (nextValue === null)
props.input.onChange(null);
else
props.input.onChange({ exact: nextValue });
props.input.onChange({
exact: nextValue
});
else if (type === 'min' || type === 'max')
// SET ENTIRE VALUE TO NULL IF POSSIBLE
if (
nextValue === null && (
(value && value.min == null && type === 'max') ||
(value && value.max == null && type === 'min')
)
)
props.input.onChange(null);
else
props.input.onChange({
min: value ? value.min : null,
max: value ? value.max : null,
[type]: nextValue
},
{
min: props.input.formattedValue ? props.input.formattedValue.min : null,
max: props.input.formattedValue ? props.input.formattedValue.max : null,
[type]: formattedValue
});
else
props.input.onChange(null);
Expand Down Expand Up @@ -102,12 +109,14 @@ const InputRange = (props: PropsType) => {
<div className="input-range__input-container">
<InputWithLabel
inputType={props.inputType}
valueType={props.valueType}
className="input-range__input-with-label"
placeholder="-"
label={T.translate('inputRange.exactLabel')}
tinyLabel={props.smallLabel || true}
input={{
value: exactValue,
formattedValue: exactFormattedValue,
onChange: (value) => onChangeValue('exact', value)
}}
inputProps={inputProps}
Expand All @@ -119,24 +128,28 @@ const InputRange = (props: PropsType) => {
<div className="input-range__input-container">
<InputWithLabel
inputType={props.inputType}
valueType={props.valueType}
className="input-range__input-with-label"
placeholder={props.placeholder}
label={T.translate('inputRange.minLabel')}
tinyLabel={props.smallLabel || true}
input={{
value: minValue,
formattedValue: minFormattedValue,
onChange: value => onChangeValue('min', value),
}}
inputProps={inputProps}
/>
<InputWithLabel
inputType={props.inputType}
valueType={props.valueType}
className="input-range__input-with-label"
placeholder={props.placeholder}
label={T.translate('inputRange.maxLabel')}
tinyLabel={props.smallLabel || true}
input={{
value: maxValue,
formattedValue: maxFormattedValue,
onChange: value => onChangeValue('max', value),
}}
inputProps={inputProps}
Expand Down
3 changes: 3 additions & 0 deletions frontend/lib/js/form-components/InputWithLabel.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ClearableInput from './ClearableInput';
type PropsType = FieldPropsType & {
label: string,
inputType: string,
valueType?: string,
className?: string,
placeholder?: string,
tinyLabel?: boolean,
Expand Down Expand Up @@ -38,8 +39,10 @@ const InputWithLabel = (props: PropsType) => {
</span>
<ClearableInput
inputType={props.inputType}
valueType={props.valueType}
placeholder={props.placeholder}
value={props.input.value || ""}
formattedValue={props.input.formattedValue || ""}
onChange={props.input.onChange}
inputProps={props.inputProps}
/>
Expand Down
3 changes: 2 additions & 1 deletion frontend/lib/js/form-components/filterTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const INTEGER_RANGE = 'INTEGER_RANGE';
export const REAL_RANGE = 'REAL_RANGE';
export const STRING = 'STRING';
export const BIG_MULTI_SELECT = 'BIG_MULTI_SELECT';
export const MONEY_RANGE = 'MONEY_RANGE';

export const SUPPORTED_FILTERS = {
SELECT: SELECT,
Expand All @@ -14,8 +15,8 @@ export const SUPPORTED_FILTERS = {
REAL_RANGE: REAL_RANGE,
STRING: STRING,
BIG_MULTI_SELECT: BIG_MULTI_SELECT,
MONEY_RANGE: MONEY_RANGE,
// Maybe later:
// 'MONEY_RANGE'
// 'DATE_RANGE'
// 'BOOLEAN'
};
20 changes: 20 additions & 0 deletions frontend/lib/js/query-node-editor/ParameterTableFilters.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// @flow

import React from 'react';
import T from 'i18n-react';

import {
includes,
Expand All @@ -19,6 +20,7 @@ import {
REAL_RANGE,
STRING,
BIG_MULTI_SELECT,
MONEY_RANGE,
} from '../form-components';

import {
Expand Down Expand Up @@ -134,6 +136,24 @@ const ParameterTableFilters = (props: PropsType) => (
tooltip={filter.description}
/>
);
case MONEY_RANGE:
return (
<InputRange
inputType="text"
valueType={MONEY_RANGE}
input={{
value: filter.value || "",
formattedValue: filter.formattedValue,
onChange: (value, formattedValue) => props.onSetFilterValue(filterIdx, value, formattedValue),
}}
label={filter.label}
mode={filter.mode || 'range'}
disabled={!!props.excludeTable}
onSwitchMode={(mode) => props.onSwitchFilterMode(filterIdx, mode)}
placeholder="-"
tooltip={filter.description}
/>
);
case STRING:
return (
<InputWithLabel
Expand Down
5 changes: 3 additions & 2 deletions frontend/lib/js/query-node-editor/QueryNodeEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,11 @@ const QueryNodeEditor = (props: PropsType) => {
tableIdx,
!table.exclude
)}
onSetFilterValue={(filterIdx, value) => props.onSetFilterValue(
onSetFilterValue={(filterIdx, value, formattedValue) => props.onSetFilterValue(
tableIdx,
filterIdx,
value
value,
formattedValue
)}
onSwitchFilterMode={(filterIdx, mode) => props.onSwitchFilterMode(
tableIdx,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,12 @@ const mapDispatchToProps = (dispatch) => ({
tableIdx,
isExcluded
)),
onSetFilterValue: (tableIdx, filterIdx, value) =>
onSetFilterValue: (tableIdx, filterIdx, value, formattedValue) =>
dispatch(setFilterValue(
tableIdx,
filterIdx,
value
value,
formattedValue
)),
onSwitchFilterMode: (tableIdx, filterIdx, mode) =>
dispatch(switchFilterMode(
Expand Down
4 changes: 2 additions & 2 deletions frontend/lib/js/standard-query-editor/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,9 @@ export const toggleTable = (tableIdx, isExcluded) => ({
payload: { tableIdx, isExcluded }
});

export const setFilterValue = (tableIdx, filterIdx, value) => ({
export const setFilterValue = (tableIdx, filterIdx, value, formattedValue) => ({
type: SET_FILTER_VALUE,
payload: { tableIdx, filterIdx, value }
payload: { tableIdx, filterIdx, value, formattedValue }
});

export const resetAllFilters = (andIdx: number, orIdx: number) => ({
Expand Down
4 changes: 2 additions & 2 deletions frontend/lib/js/standard-query-editor/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,9 +342,9 @@ const setNodeFilterProperties = (state, action, obj) => {
};

const setNodeFilterValue = (state, action) => {
const { value } = action.payload;
const { value, formattedValue } = action.payload;

return setNodeFilterProperties(state, action, { value });
return setNodeFilterProperties(state, action, { value, formattedValue });
};

const switchNodeFilterMode = (state, action) => {
Expand Down
1 change: 0 additions & 1 deletion frontend/lib/js/standard-query-editor/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export type ConceptType = {
matchingEntries?: number
};


export type SelectOptionType = {
label: string,
value: number | string,
Expand Down
7 changes: 7 additions & 0 deletions frontend/lib/localization/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ inputRange:
minLabel: 'min'
maxLabel: 'max'

moneyRange:
factor: "100"
thousandSeparator: "."
decimalSeparator: ","
decimalScale: "2"
prefix: ""

previousQueries:
loading: "Lade Anfragen"
error: "Konnte Anfragen nicht laden"
Expand Down

0 comments on commit 75912f9

Please sign in to comment.