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

812 landing popup #934

Merged
merged 108 commits into from
Oct 25, 2023
Merged

812 landing popup #934

merged 108 commits into from
Oct 25, 2023

Conversation

m7pr
Copy link
Contributor

@m7pr m7pr commented Oct 12, 2023

This resolves #812

CC @lcd2yyz

This is just a frontend proposition for the landing page functionality. This could be used to present a welcome statement or a disclaimer that requires a consent. Below is a code for the simple teal app that starts with a landing page specification.

Currently this PR is build upon shinyalert::shinyalert function, but once this is accepted I will take out just the ingredients out of this functions and put in teal so that we don't need to include another dependency in teal package.

A user is able to customize the landing page with title (1), text (2) and button (3) parameters of langing list argument in teal::init

image

R code ```r new_iris <- transform(iris, id = seq_len(nrow(iris))) new_mtcars <- transform(mtcars, id = seq_len(nrow(mtcars)))

app <- init(
data = teal_data(
dataset("new_iris", new_iris),
dataset("new_mtcars", new_mtcars),
code = "
new_iris <- transform(iris, id = seq_len(nrow(iris)))
new_mtcars <- transform(mtcars, id = seq_len(nrow(mtcars)))
"
),
modules = modules(
module(
label = "data source",
server = function(input, output, session, data) {},
ui = function(id, ...) div(p("information about data source")),
datanames = "all"
),
example_module(label = "example teal module"),
module(
"Iris Sepal.Length histogram",
server = function(input, output, session, data) {
output$hist <- renderPlot(
hist(data["new_iris"]$Sepal.Length)
)
},
ui = function(id, ...) {
ns <- NS(id)
plotOutput(ns("hist"))
},
datanames = "new_iris"
)
),
title = "App title",
filter = teal_slices(
teal_slice(dataname = "new_iris", varname = "Species"),
teal_slice(dataname = "new_iris", varname = "Sepal.Length"),
teal_slice(dataname = "new_mtcars", varname = "cyl"),
exclude_varnames = list(new_iris = c("Sepal.Width", "Petal.Width")),
mapping = list(
example teal module = "new_iris Species",
Iris Sepal.Length histogram = "new_iris Species",
global_filters = "new_mtcars cyl"
)
),
header = tags$h1("Sample App"),
footer = tags$p("Copyright 2017 - 2023"),
landing = list(
title = 'Disclaimer',
text = 'By agreeing to this statement you confirm you accept A, B and C.',
button = 'Agree'
)
)
if (interactive()) {
shinyApp(app$ui, app$server)
}

</details>

@m7pr m7pr added the core label Oct 12, 2023
@m7pr m7pr requested review from donyunardi and lcd2yyz October 12, 2023 13:44
@github-actions
Copy link
Contributor

github-actions bot commented Oct 12, 2023

badge

Code Coverage Summary

Filename                         Stmts    Miss  Cover    Missing
-----------------------------  -------  ------  -------  -------------------------------------------------------------------------------------------------------------------------------
R/dummy_functions.R                 88      63  28.41%   9-76, 101-104, 107-111
R/get_rcode_utils.R                 46       1  97.83%   49
R/include_css_js.R                  24       0  100.00%
R/init.R                            93      32  65.59%   140, 186-193, 198-219, 230-232, 235-237
R/landing_popup_module.R            25      25  0.00%    61-87
R/module_filter_manager.R          107      29  72.90%   62-70, 79-84, 228, 233-246
R/module_nested_tabs.R             170      16  90.59%   72, 119, 123-124, 138-145, 163, 216, 238, 271
R/module_snapshot_manager.R        209     157  24.88%   86-98, 126-135, 139-151, 153-160, 167-181, 185-187, 189-194, 197-207, 210-226, 235-250, 264-287, 290-301, 304-310, 324, 345-368
R/module_tabs_with_filters.R        67       1  98.51%   95
R/module_teal_with_splash.R         33       2  93.94%   65, 77
R/module_teal.R                    155       7  95.48%   68, 71, 158-159, 209-210, 230
R/modules_debugging.R               18      18  0.00%    25-44
R/modules.R                        143      24  83.22%   119, 132, 243-248, 259-263, 378-421
R/reporter_previewer_module.R       18       2  88.89%   26, 30
R/show_rcode_modal.R                20      20  0.00%    16-37
R/tdata.R                           41       2  95.12%   146, 172
R/teal_reporter.R                   60       5  91.67%   65, 116-117, 120, 137
R/teal_slices-store.R               25       0  100.00%
R/teal_slices.R                     59      12  79.66%   135-148
R/utils.R                           33       0  100.00%
R/validate_inputs.R                 32       0  100.00%
R/validations.R                     60      37  38.33%   111-373
R/zzz.R                             11       7  36.36%   3-14
TOTAL                             1537     460  70.07%

Diff against main

Filename                         Stmts    Miss  Cover
-----------------------------  -------  ------  --------
R/init.R                            +7      +4  -1.85%
R/landing_popup_module.R           +25     +25  +100.00%
R/module_teal.R                     -9      -5  +2.80%
R/modules.R                        +15      +2  +0.40%
R/reporter_previewer_module.R       +1       0  +0.65%
TOTAL                              +39     +26  -0.96%

Results for commit: 3300979

Minimum allowed coverage is 80%

♻️ This comment has been updated with latest results

@github-actions
Copy link
Contributor

github-actions bot commented Oct 12, 2023

Unit Tests Summary

    1 files    17 suites   15s ⏱️
178 tests 178 ✔️ 0 💤 0
359 runs  359 ✔️ 0 💤 0

Results for commit 3300979.

♻️ This comment has been updated with latest results.

@donyunardi
Copy link
Contributor

This is a great start!

One improvement that I can think of is to blur out the background.
This can easily be achieved by adding backdrop-filter: blur(10px) css on the div's class (overlay).

<div class="sweet-overlay" tabindex="-1" style="opacity: 1.17;display: block;backdrop-filter: blur(10px);"></div>

It will look like this.

image
When you click "Agree" the overlay will be removed and the blur will go away.

@lcd2yyz
Copy link
Contributor

lcd2yyz commented Oct 13, 2023

One improvement that I can think of is to blur out the background.

@donyunardi Love your suggestion!

This first version looks great already!
The circled-exclamation icon is a very nice added touch! But it looks to be hard-coded at the moment? Since we allow customizable title/msg, it would be really cool to allow a customizable icon or image being displayed. This opens up the possibility to display "Welcome" message or any other general usage that we may not have envisioned.

@donyunardi
Copy link
Contributor

I'm trying to pressure test this by adding 5 lorem ipsum paragraphs to text= argument, and it looks like this:

image

I can still scroll down and click "Agree", but the title got cut-off.
Also, all the text-align is center. Would it be better to make it left align?

@lcd2yyz
Copy link
Contributor

lcd2yyz commented Oct 13, 2023

Also, all the text-align is center. Would it be better to make it left align?

For short sentences/paragraphs, center would look better. But for 5 paragraphs, left-align would make more sense indeed. Could the text = argument take in divs or shiny$tags, so user can customize if desired?

@lcd2yyz
Copy link
Contributor

lcd2yyz commented Oct 13, 2023

Also I thought we are building a new module for this feature, instead of adding it as a new argument to teal::init? Was there some discussion I missed that resulted in this strategy change?

@m7pr
Copy link
Contributor Author

m7pr commented Oct 13, 2023

Also I thought we are building a new module for this feature, instead of adding it as a new argument to teal::init? Was there some discussion I missed that resulted in this strategy change?

Hey @lcd2yyz I'm not sure about the teal module approach anymore. It creates a separate tab in the app, like tm_front_page() does. Do we want to have a tab, just to present a popup that will remain in the app once the popup is dismissed/accepted?

@m7pr
Copy link
Contributor Author

m7pr commented Oct 13, 2023

I also have second thoughts on the approach of teal::init extension. I think we should be able to pass any function/shiny module or a list of them into a parameter that will be passed to the server part. We do not need to reserve the name and the structure just for landing page.

Just made a change in this commit f973beb, and it's possible to run the app with below code

R code
new_iris <- transform(iris, id = seq_len(nrow(iris)))
new_mtcars <- transform(mtcars, id = seq_len(nrow(mtcars)))

app <- init(
  data = teal_data(
    dataset("new_iris", new_iris),
    dataset("new_mtcars", new_mtcars),
    code = "
      new_iris <- transform(iris, id = seq_len(nrow(iris)))
      new_mtcars <- transform(mtcars, id = seq_len(nrow(mtcars)))
    "
  ),
  modules = modules(
    module(
      label = "data source",
      server = function(input, output, session, data) {},
      ui = function(id, ...) div(p("information about data source")),
      datanames = "all"
    ),
    example_module(label = "example teal module"),
    module(
      "Iris Sepal.Length histogram",
      server = function(input, output, session, data) {
        output$hist <- renderPlot(
          hist(data[["new_iris"]]()$Sepal.Length)
        )
      },
      ui = function(id, ...) {
        ns <- NS(id)
        plotOutput(ns("hist"))
      },
      datanames = "new_iris"
    )
  ),
  title = "App title",
  filter = teal_slices(
    teal_slice(dataname = "new_iris", varname = "Species"),
    teal_slice(dataname = "new_iris", varname = "Sepal.Length"),
    teal_slice(dataname = "new_mtcars", varname = "cyl"),
    exclude_varnames = list(new_iris = c("Sepal.Width", "Petal.Width")),
    mapping = list(
      `example teal module` = "new_iris Species",
      `Iris Sepal.Length histogram` = "new_iris Species",
      global_filters = "new_mtcars cyl"
    )
  ),
  header = tags$h1("Sample App"),
  footer = tags$p("Copyright 2017 - 2023"),
  extra_server = landing_modal(
    title = "Disclaimer",
    text = "By agreeing to this statement you confirm you accept A, B and C.",
    button = "Agree"
  )
)
if (interactive()) {
  shinyApp(app$ui, app$server)
}

m7pr added 2 commits October 13, 2023 12:35
Merge branch '812_landing_popup@main' of https://github.com/insightsengineering/teal into 812_landing_popup@main

# Conflicts:
#	R/utils.R
@m7pr
Copy link
Contributor Author

m7pr commented Oct 13, 2023

Just moved tm_landing_popup to insightsengineering/teal.modules.general#585 with a04ee4a and 3e4f3f00

Current R code
devtools::load_all('../teal.modules.general')
devtools::load_all('.')

new_iris <- transform(iris, id = seq_len(nrow(iris)))
new_mtcars <- transform(mtcars, id = seq_len(nrow(mtcars)))

app <- init(
  data = teal_data(
    dataset("new_iris", new_iris),
    dataset("new_mtcars", new_mtcars),
    code = "
      new_iris <- transform(iris, id = seq_len(nrow(iris)))
      new_mtcars <- transform(mtcars, id = seq_len(nrow(mtcars)))
    "
  ),
  modules = modules(
    module(
      label = "data source",
      server = function(input, output, session, data) {},
      ui = function(id, ...) div(p("information about data source")),
      datanames = "all"
    ),
    example_module(label = "example teal module"),
    module(
      "Iris Sepal.Length histogram",
      server = function(input, output, session, data) {
        output$hist <- renderPlot(
          hist(data[["new_iris"]]()$Sepal.Length)
        )
      },
      ui = function(id, ...) {
        ns <- NS(id)
        plotOutput(ns("hist"))
      },
      datanames = "new_iris"
    )
  ),
  title = "App title",
  filter = teal_slices(
    teal_slice(dataname = "new_iris", varname = "Species"),
    teal_slice(dataname = "new_iris", varname = "Sepal.Length"),
    teal_slice(dataname = "new_mtcars", varname = "cyl"),
    exclude_varnames = list(new_iris = c("Sepal.Width", "Petal.Width")),
    mapping = list(
      `example teal module` = "new_iris Species",
      `Iris Sepal.Length histogram` = "new_iris Species",
      global_filters = "new_mtcars cyl"
    )
  ),
  header = tags$h1("Sample App"),
  footer = tags$p("Copyright 2017 - 2023"),
  extra_server = teal.modules.general::tm_landing_popup(
    title = "Welcome",
    text = "A place for the welcome message or a disclaimer statement.",
    button = "Proceed"
  )
)
if (interactive()) {
  shinyApp(app$ui, app$server)
}

@m7pr
Copy link
Contributor Author

m7pr commented Oct 13, 2023

Hey, in the end I simplified the approach and we are able to achieve every customization with showModal(modalDialog( which should be pretty standard and popular.

teal.modules.general was equipped with landing_popup function cd41e1d020

and below is a couple of customizable examples of how you can create a landing popup

devtools::load_all('/teal.modules.general')
devtools::load_all('/teal')
app1 <- teal::init(
  data = teal.data::dataset("iris", iris),
  modules = teal::modules(
    teal.modules.general::tm_front_page('A')
  ),
  extra_server = teal.modules.general::landing_popup(
    title = "Welcome",
    content = "A place for the welcome message or a disclaimer statement.",
    buttons = modalButton("Proceed")
  )
)
if (interactive()) {
  shinyApp(app1$ui, app1$server)
}

app2 <- teal::init(
  data = teal.data::dataset("iris", iris),
  modules = teal::modules(
    teal.modules.general::tm_front_page('A')
  ),
  extra_server = teal.modules.general::landing_popup(
      title = "Welcome",
      content = div(tags$b("A place for the welcome message or a disclaimer statement.", style = "color: red;")),
      buttons = tagList(modalButton("Proceed"), actionButton('close', 'Read more', onclick  = "window.open('http://google.com', '_blank')"))
  )
)
  
if (interactive()) {
  shinyApp(app2$ui, app2$server)
}

image
image

@m7pr
Copy link
Contributor Author

m7pr commented Oct 13, 2023

I am just not sure if this should live in teal.modules.general or teal.widgets?

@m7pr
Copy link
Contributor Author

m7pr commented Oct 13, 2023

@donyunardi any recommendations on where to put
div(class="sweet-overlay", tabindex = "-1", style = "opacity: 1.17;display: block;backdrop-filter: blur(10px);")
to get the blur on the background in showModal(modalDialog( ?

@m7pr
Copy link
Contributor Author

m7pr commented Oct 25, 2023

@lcd2yyz any last words before we merge? Would love to get this merge before the end of the week.

R/landing_popup_module.R Outdated Show resolved Hide resolved
@m7pr m7pr requested a review from chlebowa October 25, 2023 10:55
R/landing_popup_module.R Outdated Show resolved Hide resolved
R/landing_popup_module.R Outdated Show resolved Hide resolved
@m7pr
Copy link
Contributor Author

m7pr commented Oct 25, 2023

Just received a verbal green light by @lcd2yyz so will merge, once the tests pass

@m7pr m7pr enabled auto-merge (squash) October 25, 2023 14:15
@m7pr m7pr merged commit 7c10cfa into main Oct 25, 2023
23 checks passed
@m7pr m7pr deleted the 812_landing_popup@main branch October 25, 2023 14:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature Request]: Enable a mechanism to display message that require app user action
6 participants