Creating combo input with label, naming and input for Text, Select and DateRange (#1553)

* Issues: OHIF-46, OHIF-47, OHIF-48
This commit is contained in:
Gustavo André Lelis 2020-03-27 16:28:36 -03:00 committed by James A. Petts
parent 3fe3634475
commit de484275e8
18 changed files with 646 additions and 218 deletions

View File

@ -15,6 +15,10 @@ export {
Button, Button,
ButtonGroup, ButtonGroup,
DateRange, DateRange,
InputDateRange,
InputMultiSelect,
InputText,
InputLabelWrapper,
EmptyStudies, EmptyStudies,
Icon, Icon,
IconButton, IconButton,

View File

@ -0,0 +1,52 @@
import React from 'react';
import PropTypes from 'prop-types';
import { DateRange, InputLabelWrapper } from '@ohif/ui';
const InputDateRange = ({
label,
isSortable,
sortDirection,
onLabelClick,
value,
onChange,
}) => {
const { startDate, endDate } = value;
return (
<InputLabelWrapper
label={label}
isSortable={isSortable}
sortDirection={sortDirection}
onLabelClick={onLabelClick}
>
<div className="relative">
<DateRange
startDate={startDate}
endDate={endDate}
onChange={onChange}
/>
</div>
</InputLabelWrapper>
);
};
InputDateRange.defaultProps = {
value: {},
};
InputDateRange.propTypes = {
label: PropTypes.string.isRequired,
isSortable: PropTypes.bool.isRequired,
sortDirection: PropTypes.oneOf(['ascending', 'descending', 'none'])
.isRequired,
onLabelClick: PropTypes.func.isRequired,
value: PropTypes.shape({
/** Start date moment object */
startDate: PropTypes.object, // moment date is an object
/** End date moment object */
endDate: PropTypes.object, // moment date is an object
}),
onChange: PropTypes.func.isRequired,
};
export default InputDateRange;

View File

@ -0,0 +1,43 @@
---
name: InputDateRange
menu: Components
route: components/InputDateRange
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import InputDateRange from './';
# Input Date Range
## Import
```javascript
import { InputDateRange } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
const [dates, setDates] = useState({
startDate: null,
endDate: null,
});
return (
<div className="p-4 flex flex-col items-center">
<div className="w-56">
<InputDateRange
label="Dates"
value={dates}
onChange={dates => setDates(dates)}
/>
</div>
</div>
);
}}
</Playground>
## Properties
<Props of={InputDateRange} />

View File

@ -0,0 +1,2 @@
import InputDateRange from './InputDateRange';
export default InputDateRange;

View File

@ -0,0 +1,63 @@
import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { Icon } from '@ohif/ui';
const baseLabelClassName =
'flex flex-col flex-1 text-white text-lg pl-1 select-none';
const spanClassName = 'flex flex-row items-center cursor-pointer';
const sortIconMap = {
ascending: 'sorting-active-up',
descending: 'sorting-active-down',
none: 'sorting',
};
const InputLabelWrapper = ({
label,
isSortable,
sortDirection,
onLabelClick,
className,
children,
}) => {
return (
<label className={classnames(baseLabelClassName, className)}>
<span
className={spanClassName}
onClick={onLabelClick}
onKeyDown={onLabelClick}
>
{label}
{isSortable && (
<Icon
name={sortIconMap[sortDirection]}
className={classnames(
'mx-2 w-2',
sortDirection !== 'none'
? 'text-custom-aquaBright'
: 'text-custom-blue'
)}
/>
)}
</span>
<span>{children}</span>
</label>
);
};
InputLabelWrapper.defaultProps = {
className: '',
};
InputLabelWrapper.propTypes = {
label: PropTypes.string.isRequired,
isSortable: PropTypes.bool.isRequired,
sortDirection: PropTypes.oneOf(['ascending', 'descending', 'none'])
.isRequired,
onLabelClick: PropTypes.func.isRequired,
className: PropTypes.string,
children: PropTypes.node,
};
export default InputLabelWrapper;

View File

@ -0,0 +1,2 @@
import InputLabelWrapper from './InputLabelWrapper';
export default InputLabelWrapper;

View File

@ -0,0 +1,84 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Select, InputLabelWrapper } from '@ohif/ui';
const InputMultiSelect = ({
label,
isSortable,
sortDirection,
onLabelClick,
value,
placeholder,
options,
onChange,
}) => {
return (
<InputLabelWrapper
label={label}
isSortable={isSortable}
sortDirection={sortDirection}
onLabelClick={onLabelClick}
>
<Select
placeholder={placeholder}
className="mt-2"
options={options}
value={value}
isMulti={true}
isClearable={false}
isSearchable={false}
closeMenuOnSelect={false}
hideSelectedOptions={false}
onChange={(inputvalues, { action }) => {
switch (action) {
case 'select-option':
case 'remove-value':
case 'deselect-option':
case 'clear':
onChange(inputvalues);
break;
default:
break;
}
}}
/>
</InputLabelWrapper>
);
};
InputMultiSelect.defaultProps = {
value: [],
placeholder: '',
options: [],
};
InputMultiSelect.propTypes = {
label: PropTypes.string.isRequired,
isSortable: PropTypes.bool.isRequired,
sortDirection: PropTypes.oneOf(['ascending', 'descending', 'none'])
.isRequired,
onLabelClick: PropTypes.func.isRequired,
placeholder: PropTypes.string,
options: PropTypes.arrayOf(
PropTypes.shape({
value: PropTypes.string,
label: PropTypes.string,
})
),
value: PropTypes.oneOfType([
PropTypes.arrayOf(
PropTypes.shape({
value: PropTypes.string,
label: PropTypes.string,
})
),
PropTypes.shape({
value: PropTypes.string,
label: PropTypes.string,
}),
]),
onChange: PropTypes.func.isRequired,
};
export default InputMultiSelect;

View File

@ -0,0 +1,48 @@
---
name: InputMultiSelect
menu: Components
route: components/InputMultiSelect
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import InputMultiSelect from './';
# Input Multi Select
## Import
```javascript
import { InputMultiSelect } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
const [values, setValues] = useState([]);
return (
<div className="flex flex-col flex-1 p-4 items-center">
<div className="w-56">
<InputMultiSelect
label="Modality"
options={[
{ value: 'SEG', label: 'SEG' },
{ value: 'CT', label: 'CT' },
{ value: 'MR', label: 'MR' },
{ value: 'SR', label: 'SR' },
]}
value={values}
onChange={values => {
setValues(values);
}}
/>
</div>
</div>
);
}}
</Playground>
## Properties
<Props of={InputMultiSelect} />

View File

@ -0,0 +1,2 @@
import InputMultiSelect from './InputMultiSelect';
export default InputMultiSelect;

View File

@ -0,0 +1,48 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Input, InputLabelWrapper } from '@ohif/ui';
const InputText = ({
label,
isSortable,
sortDirection,
onLabelClick,
value,
onChange,
}) => {
return (
<InputLabelWrapper
label={label}
isSortable={isSortable}
sortDirection={sortDirection}
onLabelClick={onLabelClick}
>
<Input
className="border-custom-blue mt-2 bg-black"
type="text"
containerClassName="mr-2"
value={value}
onChange={event => {
onChange(event.target.value);
}}
/>
</InputLabelWrapper>
);
};
InputText.defaultProps = {
value: '',
};
InputText.propTypes = {
label: PropTypes.string.isRequired,
isSortable: PropTypes.bool.isRequired,
sortDirection: PropTypes.oneOf(['ascending', 'descending', 'none'])
.isRequired,
onLabelClick: PropTypes.func.isRequired,
value: PropTypes.string,
onChange: PropTypes.func.isRequired,
};
export default InputText;

View File

@ -0,0 +1,41 @@
---
name: InputText
menu: Components
route: components/InputText
---
import { useState } from 'react';
import { Playground, Props } from 'docz';
import InputText from './';
# Input Text
## Import
```javascript
import { InputText } from '@ohif/ui';
```
## Basic usage
<Playground>
{() => {
const [text, setText] = useState('');
return (
<div className="flex flex-col flex-1 p-4 items-center">
<div className="w-56">
<InputText
label='Name'
value={text}
onChange={value => {setText(value)}}
/>
</div>
</div>
)
}}
</Playground>
## Properties
<Props of={InputText} />

View File

@ -0,0 +1,2 @@
import InputText from './InputText';
export default InputText;

View File

@ -6,12 +6,13 @@
@apply border-gray-500; @apply border-gray-500;
} }
.customSelect__wrapper .customSelect__control:focus { .customSelect__wrapper .customSelect__control:focus,
.customSelect__wrapper .customSelect__control--menu-is-open {
@apply border-gray-500 outline-none; @apply border-gray-500 outline-none;
} }
.customSelect__wrapper .customSelect__control--menu-is-open { .customSelect--is-disabled .customSelect__control--is-disabled {
@apply border-gray-500 outline-none; @apply pointer-events-none;
} }
.customSelect__wrapper .customSelect__indicator-separator { .customSelect__wrapper .customSelect__indicator-separator {
@ -23,17 +24,25 @@
} }
.customSelect__wrapper .customSelect__option { .customSelect__wrapper .customSelect__option {
@apply text-black; @apply text-black flex flex-row items-center;
}
.customSelect__wrapper .customSelect__option:focus {
@apply bg-custom-blue;
}
.customSelect__wrapper .customSelect__option--is-selected {
@apply bg-transparent;
} }
.customSelect__wrapper .customSelect__single-value { .customSelect__wrapper .customSelect__single-value {
@apply text-white; @apply text-white;
} }
.customSelect--is-disabled .customSelect__control--is-disabled {
@apply pointer-events-none;
}
.customSelect__wrapper.customSelect--is-disabled { .customSelect__wrapper.customSelect--is-disabled {
@apply cursor-not-allowed pointer-events-auto; @apply cursor-not-allowed pointer-events-auto;
} }
.customSelect__wrapper .customSelect__value-container--is-multi {
@apply px-3 py-2 inline-block truncate;
}

View File

@ -1,52 +1,93 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classnames from 'classnames'; import classnames from 'classnames';
import ReactSelect from 'react-select'; import ReactSelect, { components } from 'react-select';
import './Select.css'; import './Select.css';
const MultiValue = props => {
const values = props.selectProps.value;
const lastValue = values[values.length - 1];
let label = props.data.label;
if (lastValue.label !== label) {
label += ', ';
}
return <span>{label}</span>;
};
const Option = props => {
return (
<div>
<components.Option {...props}>
<input
type="checkbox"
checked={props.isSelected}
className="w-6 h-6 mr-2"
onChange={e => null}
/>
<label>{props.value} </label>
</components.Option>
</div>
);
};
const Select = ({ const Select = ({
autoFocus,
className, className,
closeMenuOnSelect,
hideSelectedOptions,
isClearable,
isDisabled, isDisabled,
isMulti, isMulti,
isSearchable, isSearchable,
name,
onChange, onChange,
options, options,
placeholder, placeholder,
noOptionsMessage,
value, value,
}) => { }) => {
const _components = isMulti ? { Option, MultiValue } : {};
return ( return (
<ReactSelect <ReactSelect
autoFocus={autoFocus}
className={classnames( className={classnames(
className, className,
'flex flex-col flex-1 mt-2 customSelect__wrapper' 'flex flex-col flex-1 customSelect__wrapper'
)} )}
classNamePrefix="customSelect" classNamePrefix="customSelect"
isDisabled={isDisabled} isDisabled={isDisabled}
isClearable={isClearable}
isMulti={isMulti} isMulti={isMulti}
isSearchable={isSearchable} isSearchable={isSearchable}
name={name} closeMenuOnSelect={closeMenuOnSelect}
onChange={onChange} hideSelectedOptions={hideSelectedOptions}
options={options} components={_components}
placeholder={placeholder} placeholder={placeholder}
noOptionsMessage={noOptionsMessage} options={options}
value={value} value={value}
onChange={onChange}
></ReactSelect> ></ReactSelect>
); );
}; };
Select.defaultProps = {
className: '',
closeMenuOnSelect: true,
hideSelectedOptions: true,
isClearable: true,
isDisabled: false,
isMulti: false,
isSearchable: true,
};
Select.propTypes = { Select.propTypes = {
autoFocus: PropTypes.bool,
className: PropTypes.string, className: PropTypes.string,
closeMenuOnSelect: PropTypes.bool,
hideSelectedOptions: PropTypes.bool,
isClearable: PropTypes.bool,
isDisabled: PropTypes.bool, isDisabled: PropTypes.bool,
isMulti: PropTypes.bool, isMulti: PropTypes.bool,
isSearchable: PropTypes.bool, isSearchable: PropTypes.bool,
name: PropTypes.string, onChange: PropTypes.func.isRequired,
onChange: PropTypes.func,
options: PropTypes.arrayOf( options: PropTypes.arrayOf(
PropTypes.shape({ PropTypes.shape({
value: PropTypes.string, value: PropTypes.string,
@ -54,8 +95,18 @@ Select.propTypes = {
}) })
), ),
placeholder: PropTypes.string, placeholder: PropTypes.string,
noOptionsMessage: PropTypes.func, value: PropTypes.oneOfType([
value: PropTypes.string, PropTypes.arrayOf(
PropTypes.shape({
value: PropTypes.string,
label: PropTypes.string,
})
),
PropTypes.shape({
value: PropTypes.string,
label: PropTypes.string,
}),
]),
}; };
export default Select; export default Select;

View File

@ -19,13 +19,13 @@ import { Select } from '@ohif/ui';
<Playground> <Playground>
<div className="flex flex-col flex-1 p-4 items-center"> <div className="flex flex-col flex-1 p-4 items-center">
<div className="w-20"> <div className="w-56">
<Select <Select
options={[ options={[
{ value: 'one', label: 'one' }, { value: 'ONE', label: 'ONE' },
{ value: 'two', label: 'two' }, { value: 'TWO', label: 'TWO' },
{ value: 'three', label: 'three' }, { value: 'THREE', label: 'THREE' },
{ value: 'four', label: 'four' }, { value: 'FOUR', label: 'FOUR' },
]} ]}
/> />
</div> </div>
@ -36,14 +36,14 @@ import { Select } from '@ohif/ui';
<Playground> <Playground>
<div className="flex flex-col flex-1 p-4 items-center"> <div className="flex flex-col flex-1 p-4 items-center">
<div className="w-20"> <div className="w-56">
<Select <Select
isDisabled isDisabled
options={[ options={[
{ value: 'one', label: 'one' }, { value: 'ONE', label: 'ONE' },
{ value: 'two', label: 'two' }, { value: 'TWO', label: 'TWO' },
{ value: 'three', label: 'three' }, { value: 'THREE', label: 'THREE' },
{ value: 'four', label: 'four' }, { value: 'FOUR', label: 'FOUR' },
]} ]}
/> />
</div> </div>
@ -54,7 +54,7 @@ import { Select } from '@ohif/ui';
<Playground> <Playground>
<div className="flex flex-col flex-1 p-4 items-center"> <div className="flex flex-col flex-1 p-4 items-center">
<div className="w-20"> <div className="w-56">
<Select <Select
noOptionsMessage={() => { noOptionsMessage={() => {
'No Options'; 'No Options';

View File

@ -5,7 +5,10 @@ import EmptyStudies from './EmptyStudies';
import Icon from './Icon'; import Icon from './Icon';
import IconButton from './IconButton'; import IconButton from './IconButton';
import Input from './Input'; import Input from './Input';
import NavBar from './NavBar'; import InputDateRange from './InputDateRange';
import InputLabelWrapper from './InputLabelWrapper';
import InputMultiSelect from './InputMultiSelect';
import InputText from './InputText';
import Select from './Select'; import Select from './Select';
import Svg from './Svg'; import Svg from './Svg';
import Table from './Table'; import Table from './Table';
@ -24,7 +27,10 @@ export {
Icon, Icon,
IconButton, IconButton,
Input, Input,
NavBar, InputDateRange,
InputLabelWrapper,
InputMultiSelect,
InputText,
Select, Select,
Svg, Svg,
Table, Table,

View File

@ -11,60 +11,78 @@ const filtersMeta = [
{ {
name: 'patientName', name: 'patientName',
displayName: 'Patient Name', displayName: 'Patient Name',
inputType: 'text', inputType: 'Text',
isSortable: true, isSortable: true,
gridCol: 4, gridCol: 4,
}, },
{ {
name: 'mrn', name: 'mrn',
displayName: 'MRN', displayName: 'MRN',
inputType: 'text', inputType: 'Text',
isSortable: true, isSortable: true,
gridCol: 2, gridCol: 2,
}, },
{ {
name: 'studyDate', name: 'studyDate',
displayName: 'Study date', displayName: 'Study date',
inputType: 'date-range', inputType: 'DateRange',
isSortable: true, isSortable: true,
gridCol: 5, gridCol: 5,
}, },
{ {
name: 'description', name: 'description',
displayName: 'Description', displayName: 'Description',
inputType: 'text', inputType: 'Text',
isSortable: true, isSortable: true,
gridCol: 4, gridCol: 4,
}, },
{ {
name: 'modality', name: 'modality',
displayName: 'Modality', displayName: 'Modality',
inputType: 'select', inputType: 'MultiSelect',
selectOptions: [ inputProps: {
{ value: 'seg', label: 'seg' }, options: [
{ value: 'ct', label: 'ct' }, { value: 'SEG', label: 'SEG' },
{ value: 'mr', label: 'mr' }, { value: 'CT', label: 'CT' },
{ value: 'sr', label: 'sr' }, { value: 'MR', label: 'MR' },
], { value: 'SR', label: 'SR' },
],
},
isSortable: true, isSortable: true,
gridCol: 3, gridCol: 3,
}, },
{ {
name: 'accession', name: 'accession',
displayName: 'Accession', displayName: 'Accession',
inputType: 'text', inputType: 'Text',
isSortable: true, isSortable: true,
gridCol: 4, gridCol: 4,
}, },
{ {
name: 'instances', name: 'instances',
displayName: 'Instances', displayName: 'Instances',
inputType: 'none', inputType: 'None',
isSortable: false, isSortable: true,
gridCol: 2, gridCol: 2,
}, },
]; ];
const filtersValues = {
patientName: '',
mrn: '',
studyDate: {
startDate: null,
endDate: null,
},
description: '',
modality: undefined,
accession: '',
sortBy: '',
sortDirection: 'none',
page: 0,
resultsPerPage: 25,
};
const StudyList = ({ studies, perPage }) => { const StudyList = ({ studies, perPage }) => {
const studiesData = studies.slice(0, perPage); const studiesData = studies.slice(0, perPage);
const numOfStudies = studies.length; const numOfStudies = studies.length;
@ -76,7 +94,11 @@ const StudyList = ({ studies, perPage }) => {
})} })}
> >
<Header /> <Header />
<StudyListFilter numOfStudies={numOfStudies} filtersMeta={filtersMeta} /> <StudyListFilter
numOfStudies={numOfStudies}
filtersMeta={filtersMeta}
filtersValues={filtersValues}
/>
<StudyListTable <StudyListTable
studies={studiesData} studies={studiesData}
numOfStudies={numOfStudies} numOfStudies={numOfStudies}

View File

@ -2,100 +2,36 @@ import React, { useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classnames from 'classnames'; import classnames from 'classnames';
import { Button, Icon, Input, Typography, Select, DateRange } from '@ohif/ui'; import {
Button,
Icon,
Typography,
InputText,
InputDateRange,
InputMultiSelect,
InputLabelWrapper,
} from '@ohif/ui';
const sortIconMap = { const isFiltering = (currentFiltersValues, filtersValues) => {
'-1': 'sorting-active-down', return Object.keys(currentFiltersValues).some(name => {
0: 'sorting', const filterValue = currentFiltersValues[name];
1: 'sorting-active-up', return filterValue !== filtersValues[name];
});
}; };
const defaultProps = { const StudyListFilter = ({ filtersMeta, filtersValues, numOfStudies }) => {
filtersValues: {
patientName: '',
mrn: '',
startDate: null,
endDate: null,
description: '',
modality: '',
accession: '',
sortBy: '',
sortDirection: 0,
page: 0,
resultsPerPage: 25,
},
};
const FilterLabel = ({
label = '',
isSortable = false,
isBeingSorted = false,
sortDirection = 0,
onLabelClick,
className,
children,
}) => {
const handleLabelClick = () => {
if (onLabelClick) {
onLabelClick();
}
};
const iconProps = {
name: isBeingSorted ? sortIconMap[sortDirection] : 'sorting',
colorClass: isBeingSorted ? 'text-custom-aquaBright' : 'text-custom-blue',
};
return (
<label
className={classnames(
'flex flex-col flex-1 text-white text-lg pl-1 select-none',
className
)}
>
<span
className="flex flex-row items-center cursor-pointer"
onClick={handleLabelClick}
>
{label}
{isSortable && (
<Icon
name={iconProps.name}
className={classnames('mx-2 w-2', iconProps.colorClass)}
/>
)}
</span>
<span>{children}</span>
</label>
);
};
FilterLabel.propTypes = {
label: PropTypes.string,
isSortable: PropTypes.bool,
isBeingSorted: PropTypes.bool,
sortDirection: PropTypes.number,
onLabelClick: PropTypes.func,
className: PropTypes.string,
children: PropTypes.node,
};
const StudyListFilter = ({
filtersMeta = [],
filtersValues = defaultProps.filtersValues,
numOfStudies = 90,
}) => {
const [currentFiltersValues, setcurrentFiltersValues] = useState( const [currentFiltersValues, setcurrentFiltersValues] = useState(
filtersValues filtersValues
); );
const { sortBy, sortDirection } = currentFiltersValues; const { sortBy, sortDirection } = currentFiltersValues;
const handleFilterLabelClick = name => { const handleFilterLabelClick = name => {
let _sortDirection = 1; let _sortDirection = 'ascending';
if (sortBy === name) { if (sortBy === name) {
_sortDirection = sortDirection + 1; if (sortDirection === 'ascending') {
if (_sortDirection > 1) { _sortDirection = 'descending';
_sortDirection = -1; } else if (sortDirection === 'descending') {
_sortDirection = 'none';
} }
} }
@ -108,58 +44,88 @@ const StudyListFilter = ({
} }
}; };
const handleFilterValueChange = (event, name) => {
const { value } = event.target;
setcurrentFiltersValues(prevState => ({
...prevState,
[name]: value,
}));
};
const clearFilters = () => { const clearFilters = () => {
setcurrentFiltersValues(defaultProps.filtersValues); setcurrentFiltersValues(filtersValues);
}; };
const isFiltering = () => { const renderFieldInputComponent = ({
return Object.keys(currentFiltersValues).some(name => { name,
const filterValue = currentFiltersValues[name]; displayName,
return filterValue !== defaultProps.filtersValues[name]; inputProps,
}); isSortable,
}; inputType,
}) => {
const renderInput = (inputType, name, { selectOptions }) => { const _isSortable = isSortable && numOfStudies <= 100 && numOfStudies > 0;
const _sortDirection = sortBy !== name ? 'none' : sortDirection;
const onLabelClick = () => {
if (_isSortable) {
handleFilterLabelClick(name);
}
};
switch (inputType) { switch (inputType) {
case 'date-range': { case 'Text':
return ( return (
<div className="relative"> <InputText
<DateRange key={name}
startDate={currentFiltersValues.startDate} label={displayName}
endDate={currentFiltersValues.endDate} isSortable={_isSortable}
onChange={({ startDate, endDate, preset = false }) => { sortDirection={_sortDirection}
setcurrentFiltersValues(state => ({ onLabelClick={onLabelClick}
...state, value={currentFiltersValues[name]}
startDate, onChange={newValue => {
endDate, setcurrentFiltersValues(prevState => ({
})); ...prevState,
}} [name]: newValue,
/> }));
</div> }}
); />
} );
case 'select': { break;
return <Select options={selectOptions}></Select>; case 'MultiSelect':
} return (
case 'text': { <InputMultiSelect
return ( key={name}
<Input label={displayName}
className="border-custom-blue mt-2 bg-black" isSortable={_isSortable}
type="text" sortDirection={_sortDirection}
containerClassName="mr-2" onLabelClick={onLabelClick}
value={currentFiltersValues[name] || ''} options={inputProps.options}
onChange={event => handleFilterValueChange(event, name)} value={currentFiltersValues[name]}
onChange={newValue => {
setcurrentFiltersValues(prevState => ({
...prevState,
[name]: newValue,
}));
}}
/>
);
case 'DateRange':
return (
<InputDateRange
key={name}
label={displayName}
isSortable={_isSortable}
sortDirection={_sortDirection}
onLabelClick={onLabelClick}
value={currentFiltersValues[name]}
onChange={newValue => {
setcurrentFiltersValues(prevState => ({
...prevState,
[name]: newValue,
}));
}}
/>
);
case 'None':
return (
<InputLabelWrapper
key={name}
label={displayName}
isSortable={_isSortable}
sortDirection={_sortDirection}
onLabelClick={onLabelClick}
/> />
); );
}
default: default:
break; break;
} }
@ -194,7 +160,7 @@ const StudyListFilter = ({
</div> </div>
</div> </div>
<div className="flex flex-row"> <div className="flex flex-row">
{isFiltering() && ( {isFiltering(currentFiltersValues, filtersValues) && (
<Button <Button
rounded="full" rounded="full"
variant="outlined" variant="outlined"
@ -224,40 +190,19 @@ const StudyListFilter = ({
<div className="bg-custom-navyDark pt-3 pb-3 "> <div className="bg-custom-navyDark pt-3 pb-3 ">
<div className="container m-auto relative flex flex-col"> <div className="container m-auto relative flex flex-col">
<div className="flex flex-row w-full"> <div className="flex flex-row w-full">
{filtersMeta.map( {filtersMeta.map(filterMeta => {
({ return (
name, <div
displayName, key={filterMeta.name}
inputType, className={classnames(
isSortable, 'pl-4 first:pl-12',
gridCol, `w-${filterMeta.gridCol}/24`
selectOptions, )}
}) => { >
return ( {renderFieldInputComponent(filterMeta)}
<div </div>
key={name} );
className={classnames( })}
`w-${gridCol}/24`,
'pl-4 first:pl-12'
)}
>
<FilterLabel
key={name}
label={displayName}
isSortable={
isSortable && numOfStudies <= 100 && numOfStudies > 0
}
isBeingSorted={sortBy === name}
sortDirection={sortDirection}
onLabelClick={() => handleFilterLabelClick(name)}
inputType={inputType}
>
{renderInput(inputType, name, { selectOptions })}
</FilterLabel>
</div>
);
}
)}
</div> </div>
</div> </div>
</div> </div>
@ -275,20 +220,24 @@ const StudyListFilter = ({
); );
}; };
StudyListFilter.defaultProps = {
filtersMeta: [],
filtersValues: {},
numOfStudies: 0,
};
StudyListFilter.propTypes = { StudyListFilter.propTypes = {
filtersMeta: PropTypes.arrayOf( filtersMeta: PropTypes.arrayOf(
PropTypes.shape({ PropTypes.shape({
name: PropTypes.string, name: PropTypes.string,
dsplayName: PropTypes.string, dsplayName: PropTypes.string,
inputType: PropTypes.oneOf(['text', 'select', 'date-range', 'none']), inputType: PropTypes.oneOf(['Text', 'MultiSelect', 'DateRange', 'None']),
isSortable: PropTypes.bool, isSortable: PropTypes.bool,
gridCol: PropTypes.oneOf([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]), gridCol: PropTypes.oneOf([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]),
}) })
), ),
filtersValues: PropTypes.object, filtersValues: PropTypes.object,
numOfStudies: PropTypes.number, numOfStudies: PropTypes.number,
startDate: PropTypes.string,
endDate: PropTypes.string,
}; };
export default StudyListFilter; export default StudyListFilter;