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

Support date ranges in calendars #366

Closed
wants to merge 4 commits into from

Conversation

rszymanski
Copy link
Contributor

@rszymanski rszymanski commented May 11, 2021

Resolves #363

This PR adds support for using range calendars (https://fomantic-ui.com/modules/calendar.html#range). When creating a calendar instance users can now pass the id of calendars corresponding to the start or end of the date range for example:

calendar(
  input_id = "start_date",
  type = "date",
  value = "2020-02-20",
  min = "2020-01-01",
  max = "2020-03-01",
  end_calendar_id = "end_date"
)

calendar(
  input_id = "end_date",
  type = "date",
  value = "2020-02-23",
  min = "2020-01-01",
  max = "2020-03-01",
  start_calendar_id = "start_date"
)

An example app showcasing the new feature has been added to examples/calendar_range

DoD

  • Major project work has a corresponding task. If there’s no task for what you are doing, create it. Each task needs to be well defined and described.

  • Change has been tested (manually or with automated tests), everything runs correctly and works as expected. No existing functionality is broken.

  • No new error or warning messages are introduced.

  • All interaction with a semantic functions, examples and docs are written from the perspective of the person using or receiving it. They are understandable and helpful to this person.

  • If the change affects code or repo sctructure, README, documentation and code comments should be updated.

  • All code has been peer-reviewed before merging into any main branch.

  • All changes have been merged into the main branch we use for development (develop).

  • Continuous integration checks (linter, unit tests) are configured and passed.

  • Unit tests added for all new or changed logic.

  • All task requirements satisfied. The reviewer is responsible to verify each aspect of the task.

  • Any added or touched code follows our style-guide.

@rszymanski rszymanski requested a review from dokato May 11, 2021 08:42
@rszymanski rszymanski self-assigned this May 11, 2021
@mdubel
Copy link
Contributor

mdubel commented May 12, 2021

Did you consider making one widget (function) to create date range? I mean, it makes sense that to display two calendars I create two widgets, but it also seems to me vulnerable (like min date of start calendar if later than max of end) and not dry. How about making it more user friendly by having the wrapper e.g. calendar_range that creates the two widgets with matching id's for the user? It seems to me much more convenient and reliable.

@rszymanski
Copy link
Contributor Author

@mdubel Thank your the comments! I actually thought about adding a wrapper like this:

calendar_range(
    input_id = "date_range", 
    min = "2020-01-01", 
    max = "2020-03-01",
    start_value = "2020-01-02",
    end_value = "2020-01-05",
    start_placeholder = "Select start",
    end_placeholder = "Select end"
)

That would create 2 calendars with ids: date_range_start , date_range_end.

We might want to take into consideration the following:

  • This wrapper removes the flexibility of how we want those calendars to be presented in the UI (for example: in a form horizontally)
  • It might be confusing as then in the server we would be using input$date_range_start and input$date_range_end which are implicitly created by the wrapper

Is that more or less what you had in mind or did you have a different idea? :)

@dokato dokato removed their request for review May 12, 2021 09:28
@rszymanski rszymanski requested a review from przytu1 May 12, 2021 13:27
@rszymanski
Copy link
Contributor Author

@mdubel I have added a wrapper in form of a separate component (that way we avoid creating implicit ids). Now you can create a calendar range like this:

        calendar_range(
          input_id = "calendar_range",
          start_value = "2020-02-20",
          end_value = "2020-03-20",
          min = "2020-01-01",
          max = "2020-12-01",
          start_placeholder = "Select range start",
          end_placeholder = "Select range end"
        )

It creates a form with 2 calendars and on the server side the data range values are passed in input$calendar_range which is a vector containing 2 values (similar to the dataRangeInput from base shiny).

The difference is in when events are triggered. A change event is triggered only when the end range changes not whenever any of the calendar values changes. In a Semantic UI calendar range, the end calendar is popped up whenever the start calendar changes. Therefore a change in the start calendar forces an interaction with the end calendar.

Please, let me know if you have other suggestions! :D

@przytu1 przytu1 force-pushed the ryszard.support_for_calendar_ranges branch from 13190a9 to c4b0c8e Compare May 20, 2021 10:38
@@ -9,6 +9,8 @@
#' @param type Select from \code{'year'}, \code{'month'}, \code{'date'} and \code{'time'}
#' @param min Minimum allowed value.
#' @param max Maximum allowed value.
#' @param start_calendar_id id of the calendar that defines the range start.
#' @param end_calendar_id id of the calendar that defines the range end.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should create additional function that uses the original calendar() function and adds new parameters instead of adding the parameters to exported function. It may be confusing, especially that in the examples it seems like the user needs to provide start and end calendar id

#' available under \code{input[[input_id]]}.
#'
#' @details The Semantic UI calendar range automatically pops up the end range
#' calendar when changing the start range. Therefore events are only sent on
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be 'when changing the start date' -> not 'start range'

#' It creates a form composed of two calendars. The selected range values are
#' available under \code{input[[input_id]]}.
#'
#' @details The Semantic UI calendar range automatically pops up the end range
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest changing 'end range calendar' to 'range end calendar' or 'end date calendar'

#' @param start_placeholder Text visible in the start calendar input when nothing is inputted.
#' @param end_placeholder Text visible in the end calendar input when nothing is inputted.
#' @param min Minimum allowed value in both calendars.
#' @param max Maximum allowed value in both calendars.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest having the same order of the arguments as in the calendar() function: id, value, placeholder, type, min, max

if (!is.na(min)) min <- format(as.Date(min), "%Y/%m/%d")
if (!is.na(max)) max <- format(as.Date(max), "%Y/%m/%d")

create_cal_widget <- function(type, value, placeholder, min, max) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For readability, it's worth extracting this function outside of calendar_range()

div(
class = "ui input left icon",
tags$i(class = "calendar icon"),
tags$input(type = "text", placeholder = start_placeholder)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be: placeholder = placeholder

cal_widget <- div(
class = "ui calendar ss-input-date-range-item",
`data-type` = type,
`data-date` = start_value,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be:

`data-date` = value,

@jakubsob
Copy link
Contributor

@rszymanski I tested the component using examples/calendar_range/app.R and it seems like max doesn't prevent you from selecting a greater value. Works after you update it from server though. min works as expected.

Screen.Recording.2021-11-18.at.14.57.47.mov

This was referenced Jul 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support calendar_range
5 participants