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

Cookie module #19

Merged
merged 45 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
f573459
Switching in cookie module code developed within the template
rmbielby Feb 12, 2024
2766a15
Documentation update with cookie module
rmbielby Feb 12, 2024
e2b5686
Clarifying some namespace issues
rmbielby Feb 12, 2024
ab2f6c6
Revert "Clarifying some namespace issues"
rmbielby Feb 12, 2024
21d5b6d
Updated cookie documentation
rmbielby Feb 12, 2024
70172f4
Adding cookie header script
rmbielby Feb 12, 2024
f70c63f
Adding cookie header script to docs
rmbielby Feb 12, 2024
1650f74
Renaming cookie script function
rmbielby Feb 12, 2024
4c30abe
Added cookie js script
rmbielby Feb 12, 2024
ea4b53d
Updated cookie script to point to remote consent script
rmbielby Feb 12, 2024
1cdc9f7
Making the references to dfe_cookie_script consistent
rmbielby Feb 12, 2024
2050c47
Rolling back to the local cookie-consent.js
rmbielby Feb 12, 2024
2b7c422
Removing some print() statements
rmbielby Feb 12, 2024
02c068d
Commenting in cookies.R
rmbielby Feb 12, 2024
b402b7b
Reverting to gov style button inputs.
rmbielby Feb 13, 2024
ed99f80
Updated styling of the cookies link in the banner
rmbielby Feb 13, 2024
fb05a29
Adjusting how the cookies link button is rendered
rmbielby Feb 13, 2024
d5f529d
Switched cookie link to actionLink instead of a button
rmbielby Feb 13, 2024
93c7741
Updating support and feedback id
rmbielby Feb 13, 2024
3ee22bb
Adjusing namespacing for updateTabsetPanel
rmbielby Feb 13, 2024
5dc3f9a
Updated cookie server function to pull in parent session
rmbielby Feb 13, 2024
a0fdc5c
Updated cookie module server to return cookie status text
rmbielby Feb 13, 2024
47bab1b
Updated references for input in cookie module
rmbielby Feb 13, 2024
d123654
Adjusting cookie status logic
rmbielby Feb 13, 2024
02eca50
Adding in the brackets for the reactives!
rmbielby Feb 13, 2024
2085897
Expanded description of how to use the cookie banner
rmbielby Feb 13, 2024
1c65605
Testing out defining parent package for functions to stop lintr compl…
rmbielby Feb 13, 2024
34f610c
Testing out defining parent package for functions to stop lintr compl…
rmbielby Feb 13, 2024
458a96f
Adding in the google analytics key!
rmbielby Feb 13, 2024
b3bbce4
A few styling changes to the cookie code based on lintr
rmbielby Feb 13, 2024
b3bcde1
Code styling clean up
rmbielby Feb 13, 2024
e2583f6
Updated readme with instructions on using the cookie functionality
rmbielby Feb 13, 2024
af0301a
Updating title hierarchy in readme
rmbielby Feb 13, 2024
0be14f9
Adding links to template examples
rmbielby Feb 13, 2024
d9c2016
Adding link to template global.R example
rmbielby Feb 13, 2024
4dbbace
Added shinytest2 tests and changed the language on the remove consent…
rmbielby Feb 13, 2024
35aa82e
Updated links to example dashboard code to the dfeshiny test dashboard
rmbielby Feb 13, 2024
12c1d5a
Updated links to example ui code to the dfeshiny test ui.R
rmbielby Feb 13, 2024
c9d790b
Little bit of code styling
rmbielby Feb 13, 2024
255c058
Adding shinytest2 and diffviewer to suggests
rmbielby Feb 13, 2024
8efeaea
Missed some commas in the description file
rmbielby Feb 13, 2024
255407e
Added NEWS.md with overview of updates intended for v0.2.0.
rmbielby Feb 15, 2024
50edb7f
Merge branch 'main' into cookie-module
rmbielby Feb 15, 2024
7de0416
Expanded NEWS.md to include testing improvements
rmbielby Feb 15, 2024
a3dc1c3
Merge branch 'cookie-module' of https://github.com/dfe-analytical-ser…
rmbielby Feb 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Generated by roxygen2: do not edit by hand

export(cookie_banner_server)
export(cookie_banner_ui)
export(dfe_cookie_script)
export(support_panel)
export(tidy_code)
244 changes: 244 additions & 0 deletions R/cookies.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
#' dfe_cookie_script
#'
#' @return shiny::tags$head()
#' @export
#'
#' @examples
#' dfe_cookie_script()
dfe_cookie_script <- function() {
shiny::tags$head(
shiny::tags$script(
src = paste0(
"https://cdn.jsdelivr.net/npm/js-cookie@rc/",
"dist/js.cookie.min.js"
)
),
shiny::tags$script(src = "cookie-consent.js") # Tried using a copy in the repo
# here, but it all stopped working at that point.
)
}

#' cookie_banner_ui
#'
#' @description
#' This function provides a cookie authorisation banner on DfE R-Shiny
#' dashboards for users to be able to accept or reject cookies. The server side
#' functionality is provided by cookie_banner_server(), whilst users will also
#' need to include the dfe_cookie_script() function in their ui.R file.
#'
#' To use the banner, first copy the file cookie-consent.js from the js/ folder
#' of this package to the www/ folder of your R-Shiny app. Then add the
#' following lines to your ui.R:
#' dfe_cookie_script()
#' cookie_banner_ui("cookies", name = "My DfE R-Shiny data dashboard")
#'
#' And add the following in server.R (after updating the google analytics key):
#' output$cookie_status <- dfeshiny::cookie_banner_server(
#' "cookies",
#' input.cookies = reactive(input$cookies),
#' input.remove = reactive(input$remove),
#' parent_session = session,
#' google_analytics_key = "ABCDE12345"
#' )
#'
#' Note that you should also include dfeshiny::support_panel() in your
#' navListPanel()
#'
#' @param id Shiny tag shared with cookie_banner_server()
#' @param name Name of the dashboard on which the cookie authorisation is being
#' applied
#'
#' @return shiny::tags$div()
#' @export
#'
#' @examples
#' cookie_banner_ui("cookies", name = "My DfE R-Shiny data dashboard")
cookie_banner_ui <- function(id, name = "DfE R-Shiny dashboard template") {
shiny::tags$div(
id = shiny::NS(id, "cookie_div"),
class = "govuk-cookie-banner",
`data-nosnippet role` = "region",
`aria-label` = "Cookies on name",
shiny::tags$div(
id = shiny::NS(id, "cookie_main"),
class = "govuk-cookie-banner__message govuk-width-container",
shiny::tags$div(
class = "govuk-grid-row",
shiny::tags$div(
class = "govuk-grid-column-two-thirds",
shiny::tags$h2(
class = "govuk-cookie-banner__heading govuk-heading-m",
name
),
shiny::tags$div(
class = "govuk-cookie-banner__content",
shiny::tags$p(
class = "govuk-body",
"We use some essential cookies to make this service work."
),
shiny::tags$p(
class = "govuk-body",
"We'd also like to use analytics cookies so we can understand
how you use the service and make improvements."
)
)
)
),
shiny::tags$div(
class = "govuk-button-group",
shinyGovstyle::button_Input(
shiny::NS(id, "cookie_accept"),
"Accept analytics cookies"
),
shinyGovstyle::button_Input(
shiny::NS(id, "cookie_reject"),
"Reject analytics cookies"
),
shiny::actionLink(
shiny::NS(id, "cookie_link"),
"View cookie information"
)
)
)
)
}

#' cookie_banner_server
#'
#' @description
#' cookie_banner_server() provides the server module to be used alongside
#' cookie_banner_ui(). Place cookie_banner_server() as a call in your server.R file
#' to provide the server functions to control users being able to accept or
#' reject cookie consent for the provision of Google Analytics tracking on DfE
#' R-Shiny dashboards.
#'
#' To use the banner, first copy the file cookie-consent.js from the js/ folder
#' of this package to the www/ folder of your R-Shiny app. Then add the
#' following lines to your ui.R:
#' dfe_cookie_script()
#' cookie_banner_ui("cookies", name = "My DfE R-Shiny data dashboard")
#'
#' And add the following in server.R (after updating the google analytics key):
#' output$cookie_status <- dfeshiny::cookie_banner_server(
#' "cookies",
#' input.cookies = reactive(input$cookies),
#' input.remove = reactive(input$remove),
#' parent_session = session,
#' google_analytics_key = "ABCDE12345"
#' )
#'
#' Note that you should also include dfeshiny::support_panel() in your
#' navListPanel()
#'
#' @param id Shiny tag shared with cookie_banner_ui()
#' @param input.cookies The cookie input passed from cookies.js (should always
#' be reactive(input$cookies))
#' @param input.remove The state of the cookie reset button provided by
#' dfeshiny::support_panel(). Should always be set to reactive(input$remove).
#' @param parent_session This should be the R Shiny app session
#' @param google_analytics_key Provide the GA 10 digit key of the form
#' "ABCDE12345"
#'
#' @return NULL
#' @export
#'
#' @examples
#' output$cookie_status <- cookie_banner_server(
#' "cookies",
#' input.cookies = reactive(input$cookies),
#' input.remove = reactive(input$remove),
#' parent_session = session,
#' google_analytics_key = ""
#' )
cookie_banner_server <- function(
id,
input.cookies,
input.remove,
parent_session,
google_analytics_key = NULL) {
shiny::moduleServer(id, function(input, output, session) {
if (is.null(google_analytics_key)) {
warning("Please provide a valid Google Analytics key")
}
shiny::observeEvent(input.cookies(), {
if (!is.null(input.cookies())) {
if (!("dfe_analytics" %in% names(input.cookies()))) {
shinyjs::show(id = "cookie_main")
} else {
shinyjs::hide(id = "cookie_main")
msg <- list(
name = "dfe_analytics",
value = input.cookies()$dfe_analytics
)
session$sendCustomMessage("analytics-consent", msg)
if ("cookies" %in% names(input)) {
if ("dfe_analytics" %in% names(input.cookies())) {
if (input.cookies()$dfe_analytics == "denied") {
ga_msg <- list(name = paste0("_ga_", google_analytics_key))
session$sendCustomMessage("cookie-remove", ga_msg)
}
}
}
}
} else {
shinyjs::hide(id = "cookie_main", asis = TRUE)
shinyjs::toggle(id = "cookie_div", asis = TRUE)
}
})

# Check for the cookies being authorised
shiny::observeEvent(input$cookie_accept, {
msg <- list(
name = "dfe_analytics",
value = "granted"
)
session$sendCustomMessage("cookie-set", msg)
session$sendCustomMessage("analytics-consent", msg)
shinyjs::hide(id = "cookie_main", asis = TRUE)
})

# Check for the cookies being rejected
shiny::observeEvent(input$cookie_reject, {
msg <- list(
name = "dfe_analytics",
value = "denied"
)
session$sendCustomMessage("cookie-set", msg)
session$sendCustomMessage("analytics-consent", msg)
shinyjs::hide(id = "cookie_main", asis = TRUE)
})

shiny::observeEvent(input$cookie_link, {
# Need to link here to where further info is located. You can
# updateTabsetPanel to have a cookie page for instance
shiny::updateTabsetPanel(
session = parent_session,
"navlistPanel",
selected = "support_panel"
)
})

shiny::observeEvent(input.remove(), {
shinyjs::toggle(id = "cookie_main")
msg <- list(name = "dfe_analytics", value = "denied")
session$sendCustomMessage("cookie-remove", msg)
session$sendCustomMessage("analytics-consent", msg)
})

return(shiny::renderText({
cookie_text_stem <- "You have chosen to"
cookie_text_tail <- "the use of cookies on this website."
if (!is.null(input.cookies())) {
if ("dfe_analytics" %in% names(input.cookies())) {
if (input.cookies()$dfe_analytics == "granted") {
paste(cookie_text_stem, "accept", cookie_text_tail)
} else {
paste(cookie_text_stem, "reject", cookie_text_tail)
}
}
} else {
"Cookies consent has not been confirmed."
}
}))
})
}
58 changes: 31 additions & 27 deletions R/standard_panels.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
alt_href = NULL,
form_url = NULL) {
tabPanel(
value = "support_panel",
"Support and feedback",
gov_main_layout(
gov_row(
Expand Down Expand Up @@ -54,38 +55,38 @@
tags$a(href = paste0("mailto:", team_email), team_email, .noWS = c("after")), "."
),
h2("Find more information on the data"),
if (ees_publication) {
p(
"The parent statistical release of this dashboard, along with methodological information, is available at the following link: ",
tags$a(
href = paste0("https://explore-education-statistics.service.gov.uk/find-statistics/", publication_stub),
ifelse(!is.null(publication_name), publication_name, "Explore Education Statistics"),
.noWS = c("after")
),
". The statistical release provides additional ",
tags$a(
href = paste0("https://explore-education-statistics.service.gov.uk/find-statistics/", publication_stub, "/data guidance"),
"data guidance",
.noWS = c("after")
),
" and ",
tags$a(
href = paste0("https://explore-education-statistics.service.gov.uk/find-statistics/", publication_stub,'#explore-data-and-files'),
"tools to access and interogate the underling data",
.noWS = c("after")
),
if (ees_publication) {
p(
"The parent statistical release of this dashboard, along with methodological information, is available at the following link: ",
tags$a(
href = paste0("https://explore-education-statistics.service.gov.uk/find-statistics/", publication_stub),
ifelse(!is.null(publication_name), publication_name, "Explore Education Statistics"),
.noWS = c("after")
),
". The statistical release provides additional ",
tags$a(
href = paste0("https://explore-education-statistics.service.gov.uk/find-statistics/", publication_stub, "/data guidance"),
"data guidance",
.noWS = c("after")
),
" and ",
tags$a(
href = paste0("https://explore-education-statistics.service.gov.uk/find-statistics/", publication_stub, "#explore-data-and-files"),
"tools to access and interogate the underling data",
.noWS = c("after")
),
" contained in this dashboard."
)
} else {
p(
"The parent statistical release of this dashboard, along with methodological information, is available at the following link: ",
a(
)
} else {
p(
"The parent statistical release of this dashboard, along with methodological information, is available at the following link: ",
a(
href = alt_href,
publication_name,
.noWS = c("after")
)
)
},
)
},
h2("Contact us"),
p(
"If you have questions about the dashboard or data within it, please contact us at ",
Expand All @@ -98,6 +99,9 @@
"."
),
h2("Use of cookies"),
p("To better understand the reach of our dashboard tools, this site
uses cookies to identify numbers of unique users as part of Google
Analytics."),
textOutput("cookie_status"),
actionButton("remove", "Reset cookie consent"),
)
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ This will create a new script within the package R/ folder.

This will create a new script within the package R/ folder.

## Testing an update to the package in a host dashboard



## Updating the package version

Once changes have been completed, reviewed and are ready for use in the wild, you
Expand Down
26 changes: 26 additions & 0 deletions js/cookie-consent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
function getCookies(){
var res = Cookies.get();
Shiny.setInputValue('cookies', res);
}

Shiny.addCustomMessageHandler('cookie-set', function(msg){
Cookies.set(msg.name, msg.value);
getCookies();
})

Shiny.addCustomMessageHandler('cookie-remove', function(msg){
Cookies.remove(msg.name);
getCookies();
})

$(document).on('shiny:connected', function(ev){
getCookies();
})

Shiny.addCustomMessageHandler('analytics-consent', function(msg){
gtag('consent', 'update', {
'analytics_storage': msg.value
});
})


Loading
Loading