facets: add year range facet#289
Conversation
1572dd1 to
8a9c9c9
Compare
zzacharo
left a comment
There was a problem hiding this comment.
In general to follow some consistent pattern with the rest of the codebase here, you can have a look in BuggetAggregration component and see how we separate the Element from wrapper component.
c7aec02 to
6d7266d
Compare
6d7266d to
545a8ab
Compare
| const getPartConfig = (part) => { | ||
| switch (part) { | ||
| case "YYYY": | ||
| return { placeholder: "YYYY", maxLength: 4, width: "8.5ch" }; |
There was a problem hiding this comment.
what does 8.5ch translate to?
There was a problem hiding this comment.
8.5ch is about 8.5 characters wide so enough space for YYYY
| }; | ||
|
|
||
| DateRangeInputs.defaultProps = { | ||
| overridableId: "", |
There was a problem hiding this comment.
I am not sure about providing the empty string as a default... wouldn't it be better not to have the prop at all or to make it required? Otherwise we can cause some wrongly built overridableIDs
There was a problem hiding this comment.
It was the same for all the overridable classes in the repo, see. Should we keep like that or change?
| return this.setError(`Year must be between ${min} and ${max}`); | ||
| } | ||
| // Month bounds | ||
| if (from.m < 1 || from.m > 12 || to.m < 1 || to.m > 12) { | ||
| return this.setError("Month must be between 1 and 12"); | ||
| } |
There was a problem hiding this comment.
wouldn't it be better to use a date handling library to validate it? ping @zzacharo for opinion
There was a problem hiding this comment.
I found these libraries if we want to use :)
- luxon: https://github.com/moment/luxon
- date-fns: https://github.com/date-fns/date-fns
There was a problem hiding this comment.
We have quite some experience with luxon, and we use it in InvenioRDM.
| dateError={dateError} | ||
| > | ||
| <div className="range-custom-filter"> | ||
| {!expanded ? ( |
There was a problem hiding this comment.
I am not sure what does expanded do, could you describe?
| if (checked) { | ||
| this.setState({ activeLabel: null }); | ||
| onClear(); | ||
| return; |
There was a problem hiding this comment.
yes otherwise we can't uncheck it. Or below code can be in else block
| const areLabelsClose = minVal !== maxVal && diff < 20; | ||
| const areLabelsOverlapping = minVal !== maxVal && diff < 10; | ||
|
|
||
| const labelPlacement = (percentage) => percentage + ((-3 * percentage) / 50 + 3); |
There was a problem hiding this comment.
could you add a comment in the code explaining the math? why we have -3 for example, for a person first time reading, it is hard to figure out
There was a problem hiding this comment.
Added the comment, it would be great if you can check :)
| <div className="slider-track" /> | ||
| <div | ||
| className="slider-range" | ||
| style={{ left: `${minPercent}%`, width: `${diff}%` }} |
There was a problem hiding this comment.
please remove all inline styling, it is not a best practice (see in RDM docs). Sometimes it will cause errors if an instance has restritive CSP
There was a problem hiding this comment.
@zubeydecivelek can you explain here why do we need dynamic styling? Maybe with @kpsherva we can find a better way to handle this :)
There was a problem hiding this comment.
Selected range and label positions depend on the slider values and it's recalculates on every change.
Slider component is not written from scratch, it is based on the existing opendata implementation with minimal changes.
| style={{ left: `${minPercent}%`, width: `${diff}%` }} | ||
| /> | ||
|
|
||
| {isDegenerate ? ( |
There was a problem hiding this comment.
the variable name is quite interesting... what does it mean ? :)
There was a problem hiding this comment.
it means range collapses to a single point, in case the aggregation has only one value. I changed the variable name to isSingleValue
1c1e4fc to
0dab5ad
Compare
3d48339 to
6d55be2
Compare
ntarocco
left a comment
There was a problem hiding this comment.
Massive amount of work. From a quick review, it looks good to me. However I did not test it.
Do I ask too much if you could update the doc and example apps in this repo too? They will be really helpful for users testing this library out (you can even test it live with Zenodo/CDS Videos).
| const { value, min, max } = this.props; | ||
| const { checked } = this.state; | ||
|
|
||
| if (!checked) { |
There was a problem hiding this comment.
to be able watch the filter even if it's not checked but it's not needed I'm removing it thanks :)
| return this.setError(`Year must be between ${min} and ${max}`); | ||
| } | ||
| // Month bounds | ||
| if (from.m < 1 || from.m > 12 || to.m < 1 || to.m > 12) { | ||
| return this.setError("Month must be between 1 and 12"); | ||
| } |
There was a problem hiding this comment.
We have quite some experience with luxon, and we use it in InvenioRDM.
|
@ntarocco thank you for reviewing!
Example app update is ready (for opensearch and cern-videos demos), I'll push the code after the facet :) and I'll update the doc thanks! |
e2d55e9 to
e6dfda0
Compare
|
Clear button removed, to override it in invenio-search-ui. See here Should we still keep it in react-searchkit? |
| ...currentQueryState, | ||
| filters: [...filters, [agg.aggName, filterValue]], | ||
| }); | ||
| }, 500); |
There was a problem hiding this comment.
Nit: Should we have the delay parameter configurable as well or would it be an overkill?
There was a problem hiding this comment.
It makes sense, but I’d prefer to keep it fixed for now. It’s internal performance detail rather than a user facing behavior. We can make it parameter if it's needed in the future.
JakobMiesner
left a comment
There was a problem hiding this comment.
partial review together with @palkerecsenyi
| return `${from.toISODate()}${rangeSeparator}${to.toISODate()}`; | ||
| } | ||
|
|
||
| export const RANGE_MODES = Object.freeze({ |
There was a problem hiding this comment.
nit and probably out of scope: I think the active mode and RANGE_MODES could be avoided by only passing the current value and updateValue from RangeFacet to the custom and default filters.
On render they can check is props.value == myExpectedValue (e.g. [2025, 2025] for "last 1 Year" filter) and be checked in that case and unchecked otherwise. And when clicked they do props.updateValue(myExpectedValue)
| onClick={() => this.setState({ expanded: true })} | ||
| className="searchkit-daterange-custom-toggle" | ||
| > | ||
| Custom Dates |
There was a problem hiding this comment.
Do we have i18n support in this library?
There was a problem hiding this comment.
@zzacharo Should we add invenio-i18n to react-searchkit?
There was a problem hiding this comment.
We cannot because it is a python module... in priciple the user facing labels we expose them as props and we translate the values when we call the component. See for example here the requests searchbar
There was a problem hiding this comment.
I added them as props, so we can use i18n in invenio-search-ui. See the commit:42ff73e
@zzacharo @palkerecsenyi
Since we're not enabling the custom filters, do you think we still need to add the label customization in invenio-search-ui or should we enable everything as default?
d251dbc to
c4d2160
Compare
c4d2160 to
8cfcb84
Compare





Description
RFC: https://github.com/inveniosoftware/rfcs/blob/1f7ec435f144226e2463c38ffe899869a944eb15/rfcs/rdm-0100-facets.md#date-facets
Codimd for UI and dependency comparison: https://codimd.web.cern.ch/O2LVmzZAQduLmBNJVRUiVg
Similar implementation on Open Data: cernopendata/cernopendata-portal#171
New RangeFacet component implemented to support year/range filtering.
RangeFacet container includes:
@visx/scale,@visx/shape)Optional filters:
Last 5 years/Last 6 month)YYYY-MM-DD to YYYY-MM-DD)RangeFacet usage example:
Checklist
Ticks in all boxes and 🟢 on all GitHub actions status checks are required to merge:
Frontend
Reminder
By using GitHub, you have already agreed to the GitHub’s Terms of Service including that: