diff --git a/.lintr b/.lintr index 934db5c..26589b1 100644 --- a/.lintr +++ b/.lintr @@ -1,3 +1,4 @@ linters: linters_with_defaults( - line_length_linter = line_length_linter(100L) # limit CRAN sets for lines in PDF documentation + line_length_linter = line_length_linter(100L), # limit CRAN sets for lines in PDF documentation + cyclocomp_linter = cyclocomp_linter(25L) ) diff --git a/DESCRIPTION b/DESCRIPTION index a648b2b..8e8724c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: dfeshiny Title: DfE R Shiny Standards -Version: 0.5.2 +Version: 0.5.3 Authors@R: c( person("Rich", "Bielby", , "richard.bielby@education.gov.uk", role = c("aut", "cre"), comment = c(ORCID = "0000-0001-9070-9969")), @@ -18,8 +18,8 @@ Imports: checkmate, glue, htmltools, + lubridate, magrittr, - RCurl, shiny, shinyGovstyle, shinyjs, diff --git a/NAMESPACE b/NAMESPACE index 433f608..0ba2b68 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,6 @@ # Generated by roxygen2: do not edit by hand +export(a11y_panel) export(cookies_banner_server) export(cookies_banner_ui) export(cookies_panel_server) diff --git a/NEWS.md b/NEWS.md index b10baaf..f5e0b64 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,8 @@ +# dfeshiny 0.5.3 + +* Added `dfeshiny::a11y_panel()` to create model accessibility statement with custom +issue listings. + # dfeshiny 0.5.2 * Added `dfeshiny::header()` function to produce a standardised header incorporating diff --git a/R/a11y_panel.R b/R/a11y_panel.R new file mode 100644 index 0000000..6be0393 --- /dev/null +++ b/R/a11y_panel.R @@ -0,0 +1,325 @@ +#' Accessibility panel +#' +#' @description +#' Create an accessibility statement for a dashboard. This should always be completed +#' - for all live public dashboards +#' - by or in conjunction with the Explore education statistics and platforms team +#' +#' Note that this model statement has been created based on the +#' [GDS model accessibility statement](https://www.gov.uk/guidance/model-accessibility-statement) +#' +#' @param dashboard_title Title of the host dashboard +#' @param dashboard_url URL for the host dashboard +#' @param issues_contact URL for the GitHub Issues log or contact e-mail address +#' for users to flag accessibility issues +#' @param publication_name The parent publication name (optional) +#' @param publication_slug The parent publication slug on Explore Education +#' Statistics (optional) +#' @param non_accessible_components String vector containing a list of non accessible components +#' @param specific_issues String vector containing descriptions of specific accessibility issues +#' that have been identified as part of testing +#' @param date_tested Date the application was last tested +#' @param date_prepared Date the statement was prepared in it's current form +#' @param date_reviewed Date the statement was last reviewed +#' @param date_template_reviewed Date the underlying template was reviewed +#' (default: 12th March 2024) +#' +#' @return shiny$tags$div element containing the HTML tags and content for the standard +#' accessibility statement +#' @export +#' +#' @examples +#' a11y_panel( +#' "DfE Shiny template", +#' "https://department-for-education.shinyapps.io/dfe-shiny-template", +#' "25th April 2024", +#' "26th April 2024", +#' "2nd November 2024", +#' issues_contact = "https://github.com/dfe-analytical-services/shiny-template", +#' publication_slug = "la-and-school-expenditure", +#' publication_name = "LA and school expenditure" +#' ) +a11y_panel <- function( + dashboard_title, + dashboard_url, + date_tested, + date_prepared, + date_reviewed, + date_template_reviewed = "12 March 2024", + issues_contact = NULL, + publication_name = NULL, + publication_slug = NULL, + non_accessible_components = c( + "Keyboard navigation through the interactive charts is currently limited", + "Alternative text in interactive charts is limited to titles" + ), + specific_issues = c( + "Charts have non-accessible components that are inaccessible for keyboard users.", + "Chart tooltips are not compatible with screen reader use.", + "Some decorative images are not labelled appropriately as yet.", + "Some links are not appropriately labelled." + )) { + # Validate inputs + date_tested <- validate_date(date_tested) + date_prepared <- validate_date(date_prepared) + date_reviewed <- validate_date(date_reviewed) + date_template_reviewed <- validate_date(date_template_reviewed) + validate_dashboard_url(dashboard_url) + if ( + lubridate::interval( + lubridate::dmy(date_prepared), lubridate::dmy(date_reviewed) + ) / lubridate::days(1) < 0 + ) { + stop("date_reviewed should be later than date_prepared") + } + if ( + lubridate::interval( + lubridate::dmy(date_tested), lubridate::dmy(date_reviewed) + ) / lubridate::days(1) < 0 + ) { + stop("date_reviewed should be later than date_tested") + } + if ( + lubridate::interval( + lubridate::dmy(date_template_reviewed), lubridate::dmy(date_reviewed) + ) / lubridate::days(1) < 0 + ) { + warning( + "The template has been through a review more recently than your dashboard, please get in ", + "touch with the explore education statistics platforms team to request a re-review." + ) + } + if (!is_valid_repo_url(issues_contact)) { + if (!is_valid_dfe_email(issues_contact)) { + stop( + paste0( + "\"", + issues_contact, + "\" should either be a valid repository URL or a valid DfE e-mail address" + ) + ) + } + } + if (is.null(publication_name) && !is.null(publication_slug)) { + stop("Error: If publication_name is provided, then so should publication_slug.") + } + if (!is.null(publication_name) && is.null(publication_slug)) { + stop("Error: If publication_slug is provided, then so should publication_name.") + } + shiny::tags$div( + "Accessibility", + shiny::tags$div( + shiny::tags$h1(paste0("Accessibility statement for ", dashboard_title)), + shiny::tags$p( + "This accessibility statement applies to the", + dashboard_url, + "website. This website is run by the ", + external_link( + href = "https://www.gov.uk/government/organisations/department-for-education", + "Department for Education (DfE)" + ), + ".", + "This statement does not cover any other services run by the Department for Education ", + "(DfE) or GOV.UK." + ), + shiny::tags$h2("How you should be able to use this website"), + shiny::tags$p( + "We want as many people as possible to be able to use this website. You should be able to:" + ), + shiny::tags$div(tags$ul( + shiny::tags$li( + "change colours, contrast levels and fonts using browser or device settings" + ), + shiny::tags$li( + "zoom in up to 400% without the text spilling off the screen" + ), + shiny::tags$li( + "navigate most of the website using a keyboard or speech recognition software" + ), + shiny::tags$li( + "listen to most of the website using a screen reader + (including the most recent versions of JAWS, NVDA and VoiceOver)" + ) + )), + shiny::tags$p("We've also made the website text as simple as possible to understand."), + shiny::tags$p( + external_link(href = "https://mcmw.abilitynet.org.uk/", "AbilityNet"), + " has advice on making your device easier to use if you have a disability." + ), + shiny::tags$h2("How accessible this website is"), + if (all(is.null(non_accessible_components))) { + shiny::tags$p("This website is fully compliant with accessibility standards.") + } else { + shiny::tagList( + shiny::tags$p("We know some parts of this website are not fully accessible:"), + shiny::tags$div(tags$ol( + tagList(lapply(non_accessible_components, shiny::tags$li)) + )) + ) + }, + shiny::tags$h2("Feedback and contact information"), + if (!is.null(publication_slug)) { + shiny::tagList( + shiny::tags$p( + "If you need information on this website in a different format please see the", + " parent publication, ", + external_link( + href = paste0( + "https://explore-education-statistics.service.gov.uk/find-statistics/", + publication_slug + ), + link_text = publication_name + ), + "." + ), + shiny::tags$p( + "More details are available on that service for alternative formats of this ", + "data." + ) + ) + }, + shiny::tags$p("We're always looking to improve the accessibility of this website. + If you find any problems not listed on this page or think we're not meeting + accessibility requirements, contact us:"), + shiny::tags$ul(tags$li( + shiny::tags$a( + href = "mailto:explore.statistics@education.gov.uk", + "explore.statistics@education.gov.uk" + ) + )), + shiny::tags$h2("Enforcement procedure"), + shiny::tags$p( + "The Equality and Human Rights Commission (EHRC) is responsible for enforcing the Public ", + "Sector Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018", + "(the \"accessibility regulations\")." + ), + shiny::tags$p( + "If you are not happy with how we respond to your complaint, contact the ", + external_link( + href = "https://www.equalityadvisoryservice.com/", + "Equality Advisory and Support Service (EASS)" + ), + "." + ), + shiny::tags$h2("Technical information about this website's accessibility"), + shiny::tags$p( + "The Department for Education (DfE) is committed to making its website accessible, in ", + "accordance with the Public Sector Bodies (Websites and Mobile Applications) (No. 2) ", + "Accessibility Regulations 2018." + ), + shiny::tags$h3("Compliance status"), + if (all(is.null(specific_issues))) { + shiny::tags$p( + "This website is fully compliant with the ", + external_link( + href = "https://www.w3.org/TR/WCAG22/", + "Web Content Accessibility Guidelines version 2.2 AA standard" + ), + "." + ) + } else { + shiny::tagList( + shiny::tags$p( + "This website is partially compliant with the ", + external_link( + href = "https://www.w3.org/TR/WCAG22/", + "Web Content Accessibility Guidelines version 2.2 AA standard" + ), + " due to the non-compliances listed below." + ), + shiny::tags$h3("Non accessible content"), + shiny::tags$p("The content listed below is non-accessible for the following reasons. + We will address these issues to ensure our content is accessible."), + shiny::tags$div(tags$ol( + tagList(lapply(specific_issues, shiny::tags$li)) + )) + ) + }, + shiny::tags$h3("Disproportionate burden"), + shiny::tags$p("Not applicable."), + shiny::tags$h2("How we tested this website"), + shiny::tags$p( + "The template used for this website was last tested on", + date_template_reviewed, + " against ", + external_link( + href = "https://www.w3.org/TR/WCAG22/", + "Accessibility Guidelines WCAG2.2" + ), + ". The test was carried out by the ", + external_link( + href = "https://digitalaccessibilitycentre.org/", + "Digital accessibility centre (DAC)" + ), + "." + ), + shiny::tags$p( + "DAC tested a sample of pages to cover the core functionality of the service including:" + ), + shiny::tags$div(tags$ul( + shiny::tags$li("navigation"), + shiny::tags$li("interactive dropdown selections"), + shiny::tags$li("charts, maps, and tables") + )), + shiny::tags$p( + "This specific website was was last tested on ", date_tested, " against ", + external_link( + href = "https://www.w3.org/TR/WCAG22/", + "Accessibility Guidelines WCAG2.2" + ), + ". The test was carried out by the ", + external_link( + href = "https://www.gov.uk/government/organisations/department-for-education", + "Department for Education (DfE)" + ), + "." + ), + shiny::tags$h2("What we're doing to improve accessibility"), + shiny::tags$p( + "We plan to continually test the service for accessibility issues, and are working ", + "through a prioritised list of issues to resolve." + ), + shiny::tags$p( + if (!is.null(issues_contact)) { + if (is_valid_repo_url(issues_contact)) { + shiny::tagList( + "Our current list of issues to be resolved is available on our ", + external_link( + href = paste0(issues_contact, "/issues"), + "GitHub issues page" + ), + "." + ) + } else { + shiny::tagList( + "To discuss our current list of issues to be resolved contact us at", + shiny::tags$a( + href = paste0("mailto:", issues_contact), + issues_contact + ), + "." + ) + } + } else { + " " + }, + ), + shiny::tags$h2("Preparation of this accessibility statement"), + shiny::tags$p( + paste0( + "This statement was prepared on ", + date_prepared, + " and last reviewed on ", + date_reviewed, + "." + ), + "The statement was produced based on a combination of testing carried out by the ", + external_link( + href = "https://digitalaccessibilitycentre.org/", + "Digital accessibility centre (DAC)" + ), + " and our own testing." + ) + ) + ) +} diff --git a/R/cookies.R b/R/cookies.R index 56f65f7..4225b75 100644 --- a/R/cookies.R +++ b/R/cookies.R @@ -159,8 +159,10 @@ cookies_banner_ui <- function(id = "cookies_banner", name = "DfE R-Shiny dashboa #' always be `parent_session = session` #' @param google_analytics_key Provide the GA 10 digit key of the form #' "ABCDE12345" -#' @param cookies_link_panel name of the navlistPanel that the cookie banner +#' @param cookies_link_panel name of the navigation panel that the cookie banner #' provides a link to, usually "cookies_panel_ui" +#' @param cookies_nav_id ID of the navigation panel the cookie panel page is +#' within, defaults to "navlistPanel" #' #' @family cookies #' @return NULL @@ -172,7 +174,8 @@ cookies_banner_server <- function( input_cookies, parent_session, google_analytics_key = NULL, - cookies_link_panel = "cookies_panel_ui") { + cookies_link_panel = "cookies_panel_ui", + cookies_nav_id = "navlistPanel") { shiny::moduleServer(id, function(input, output, session) { if (is.null(google_analytics_key)) { warning("Please provide a valid Google Analytics key") @@ -230,7 +233,7 @@ cookies_banner_server <- function( # updateTabsetPanel to have a cookie page for instance shiny::updateTabsetPanel( session = parent_session, - "navlistPanel", + inputID = cookies_nav_id, selected = cookies_link_panel ) }) diff --git a/R/custom_disconnect_message.R b/R/custom_disconnect_message.R index 2c51d4a..c26ad0f 100644 --- a/R/custom_disconnect_message.R +++ b/R/custom_disconnect_message.R @@ -11,6 +11,11 @@ #' @param publication_link The link to the publication on Explore Education #' Statistics #' @param dashboard_title Title of the dashboard +#' @param support_contact Email address for support contact, defaults to +#' explore.statistics@@education.gov.uk +#' @param custom_refresh Custom refresh link, defaults to refreshing the page, main value is if you +#' have bookmarking enabled and want the refresh to send to the initial view instead of reloading +#' any bookmarks #' #' @importFrom htmltools tags tagList #' @@ -39,14 +44,19 @@ #' ) #' ) #' +#' custom_disconnect_message( +#' support_contact = "my.team@education.gov.uk", +#' custom_refresh = "https://department-for-education.shinyapps.io/my-dashboard" +#' ) custom_disconnect_message <- function( refresh = "Refresh page", dashboard_title = NULL, links = NULL, publication_name = NULL, - publication_link = NULL) { + publication_link = NULL, + support_contact = "explore.statistics@education.gov.uk", + custom_refresh = NULL) { # Check links are valid - is_valid_sites_list <- function(sites) { lapply( stringr::str_trim(sites), startsWith, @@ -59,12 +69,27 @@ custom_disconnect_message <- function( stop("You have entered an invalid site link in the links argument.") } + if (!is.null(custom_refresh)) { + is_valid_refresh <- function(refresh) { + startsWith(stringr::str_trim(refresh), "https://department-for-education.shinyapps.io/") + } + + if (is_valid_refresh(custom_refresh) == FALSE) { + stop( + paste0( + "You have entered an invalid site link in the custom_refresh argument. It must be a site", + " on shinyapps.io." + ) + ) + } + } pub_prefix <- c( "https://explore-education-statistics.service.gov.uk/find-statistics/", "https://www.explore-education-statistics.service.gov.uk/find-statistics/", "https://www.gov.uk/", - "https://gov.uk/" + "https://gov.uk/", + "https://github.com/dfe-analytical-services/" ) if (!is.null(publication_link)) { @@ -72,14 +97,15 @@ custom_disconnect_message <- function( startsWith(stringr::str_trim(link), pub_prefix) } - if (RCurl::url.exists(publication_link) == FALSE || - (TRUE %in% is_valid_publication_link(publication_link)) == FALSE || # nolint: [indentation_linter] - publication_link %in% pub_prefix) { + if (TRUE %in% is_valid_publication_link(publication_link) == FALSE || + publication_link %in% pub_prefix) { # nolint: [indentation_linter] stop("You have entered an invalid publication link in the publication_link argument.") } } + # TODO: Add email validation once a11y panel PR is in + checkmate::assert_string(refresh) # Attach CSS from inst/www/css/visually-hidden.css @@ -111,12 +137,22 @@ custom_disconnect_message <- function( "Sorry, you have lost connection to the", dashboard_title, "dashboard at the moment, please ", - tags$a( - id = "ss-reload-link", - href = "#", "refresh the page", - onclick = "window.location.reload(true);", - .noWS = c("after") - ), + if (is.null(custom_refresh)) { + tags$a( + id = "ss-reload-link", + href = "#", + refresh, + onclick = "window.location.reload(true);", + .noWS = c("after") + ) + } else { + tags$a( + id = "ss-reload-link", + href = custom_refresh, + refresh, + .noWS = c("after") + ) + }, "." ), if (length(links) > 1) { @@ -126,21 +162,29 @@ custom_disconnect_message <- function( ". Apologies for the inconvenience." ) }, - if (!is.null(publication_name)) { + if (!is.null(publication_name) && grepl("explore-education-statistics", publication_link)) { tags$p( - "All the data used in this dashboard can also be viewed or downloaded via the ", + "The data used in this dashboard can also be viewed or downloaded via the ", dfeshiny::external_link( href = publication_link, publication_name ), - " on Explore Education Statistics." + " on explore education statistics." + ) + } else if (!is.null(publication_name)) { + tags$p( + "The data used in this dashboard can also be viewed or downloaded from ", + dfeshiny::external_link( + href = publication_link, + publication_name + ) ) }, tags$p( "Feel free to contact ", dfeshiny::external_link( - href = "mailto:explore.statistics@education.gov.uk", - "explore.statistics@education.gov.uk", + href = paste0("mailto:", support_contact), + support_contact, add_warning = FALSE ), " if you require further support." diff --git a/R/header.R b/R/header.R index 4f6d736..4f7142b 100644 --- a/R/header.R +++ b/R/header.R @@ -24,7 +24,7 @@ #' } header <- function(header) { shinyGovstyle::header( - logo = "/dfeshiny/DfE_logo_landscape.png", + logo = "dfeshiny/DfE_logo_landscape.png", main_text = "", secondary_text = header, main_link = "https://www.gov.uk/government/organisations/department-for-education", diff --git a/R/support_panel.R b/R/support_panel.R index 58147af..fb3c263 100644 --- a/R/support_panel.R +++ b/R/support_panel.R @@ -141,15 +141,6 @@ support_panel <- function( form_url = NULL, custom_data_info = NULL, extra_text = NULL) { - # Check that the team_email is a valid dfe email ---------------------------- - is_valid_dfe_email <- function(email) { - grepl( - "\\<[A-Z0-9._%+-]+@education.gov.uk\\>", - as.character(email), - ignore.case = TRUE - ) - } - if (is_valid_dfe_email(team_email) == FALSE) { stop( "You have entered an invalid email in the team_email argument. @@ -157,23 +148,13 @@ support_panel <- function( ) } - # Check that the repo_name is a valid dfe repo ------------------------------ - # TODO: Use RCurl to check another step further, if the URL is valid - is_valid_repo_name <- function(url) { - grepl( - "\\https://github.com/dfe-analytical-services/+.", - as.character(url), - ignore.case = TRUE - ) - } - if (repo_name == "") { stop( "The repo_name argument is empty, please specify a value for repo_name" ) } - if (is_valid_repo_name(repo_name) == FALSE) { + if (is_valid_repo_url(repo_name) == FALSE) { stop( "Please ensure the repo_name argument is a valid URL for a repository on the dfe-analytical-services GitHub area. For example: @@ -182,9 +163,6 @@ support_panel <- function( ) } - - - # check for extra text # if it's null, provide an empty string if (is.null(extra_text)) { @@ -194,9 +172,6 @@ support_panel <- function( extra_text <- extra_text } - - - # Build the support page ---------------------------------------------------- shiny::tags$div( shiny::tags$h1("Support and feedback"), diff --git a/R/validation.R b/R/validation.R new file mode 100644 index 0000000..0265756 --- /dev/null +++ b/R/validation.R @@ -0,0 +1,63 @@ +# Some standard checks on something that's expected to be a date: +# - Can lubridate parse it as a date? +# - Does it occur in the past / today? +# Where it's valid, the function will return it in a format of dd month yyyy +validate_date <- function(date) { + date_ld <- lubridate::dmy(date, quiet = TRUE) + date_template <- lubridate::stamp("1 January 2020", orders = "dmy", quiet = TRUE) + if (is.na(date_ld)) { + valid <- FALSE + validation_message <- "is not in a valid date format, e.g. 8th August 2024 or 08/08/2024." + } else if (date_ld > Sys.time()) { + valid <- FALSE + validation_message <- "is in the future." + } else { + valid <- TRUE + validation_message <- "is a valid date." + } + if (!valid) { + stop(paste0("\"", date, "\" ", validation_message)) + } + return(date_template(date_ld)) +} + +# Some of the standard panels have text referring back to the dashboard repo, so +# this function checks for strings being passed to those variables being a link +# to one of our DevOps areas, i.e. DfE Analytical Services on GitHub or our Azure +# platform. I've included both as some teams are starting to use dfeshiny for +# internal dasboards as well. +is_valid_repo_url <- function(url) { + # Check that the repo_name is a valid dfe repo ------------------------------ + # TODO: Use RCurl to check another step further, if the URL is valid + grepl( + "\\https://github.com/dfe-analytical-services/+.|dfe-gov-uk", + as.character(url), + ignore.case = TRUE + ) +} + +# Some of the standard panels have links to the dashboard they're embedded in. This +# validation checks that those links are correctly set to one of our domains. +validate_dashboard_url <- function(url) { + valid_deploys <- c( + "^https://department-for-education.shinyapps.io/", + "^https://rsconnect/rsc/" + ) + valid <- grepl( + paste(valid_deploys, collapse = "|"), + as.character(url), + ignore.case = TRUE + ) + if (!valid) { + stop(paste(url, "is not a valid DfE dashboard deployment URL")) + } +} + +# Check that the team_email is a valid dfe email ---------------------------- +is_valid_dfe_email <- function(email) { + grepl( + "\\<[A-Z0-9._%+-]+@education.gov.uk\\>", + as.character(email), + ignore.case = TRUE + ) +} diff --git a/_pkgdown.yml b/_pkgdown.yml index 7e34b2b..1e51cb2 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -25,6 +25,7 @@ reference: - tidy_code - title: Standard panels contents: + - a11y_panel - support_panel - section_tags - title: Header diff --git a/inst/WORDLIST b/inst/WORDLIST index ee64012..b2c3057 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -6,7 +6,6 @@ DfE GDS Lifecycle README -RSConnect UI WCAG analytics @@ -22,6 +21,7 @@ javascript js lockfile md +nav navlistPanel pkgdown renv diff --git a/man/a11y_panel.Rd b/man/a11y_panel.Rd new file mode 100644 index 0000000..16955da --- /dev/null +++ b/man/a11y_panel.Rd @@ -0,0 +1,79 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/a11y_panel.R +\name{a11y_panel} +\alias{a11y_panel} +\title{Accessibility panel} +\usage{ +a11y_panel( + dashboard_title, + dashboard_url, + date_tested, + date_prepared, + date_reviewed, + date_template_reviewed = "12 March 2024", + issues_contact = NULL, + publication_name = NULL, + publication_slug = NULL, + non_accessible_components = + c("Keyboard navigation through the interactive charts is currently limited", + "Alternative text in interactive charts is limited to titles"), + specific_issues = + c("Charts have non-accessible components that are inaccessible for keyboard users.", + "Chart tooltips are not compatible with screen reader use.", + "Some decorative images are not labelled appropriately as yet.", + "Some links are not appropriately labelled.") +) +} +\arguments{ +\item{dashboard_title}{Title of the host dashboard} + +\item{dashboard_url}{URL for the host dashboard} + +\item{date_tested}{Date the application was last tested} + +\item{date_prepared}{Date the statement was prepared in it's current form} + +\item{date_reviewed}{Date the statement was last reviewed} + +\item{date_template_reviewed}{Date the underlying template was reviewed +(default: 12th March 2024)} + +\item{issues_contact}{URL for the GitHub Issues log or contact e-mail address +for users to flag accessibility issues} + +\item{publication_name}{The parent publication name (optional)} + +\item{publication_slug}{The parent publication slug on Explore Education +Statistics (optional)} + +\item{non_accessible_components}{String vector containing a list of non accessible components} + +\item{specific_issues}{String vector containing descriptions of specific accessibility issues +that have been identified as part of testing} +} +\value{ +shiny$tags$div element containing the HTML tags and content for the standard +accessibility statement +} +\description{ +Create an accessibility statement for a dashboard. This should always be completed +\itemize{ +\item for all live public dashboards +\item by or in conjunction with the Explore education statistics and platforms team +} + +Note that this model statement has been created based on the +\href{https://www.gov.uk/guidance/model-accessibility-statement}{GDS model accessibility statement} +} +\examples{ +a11y_panel( + "DfE Shiny template", + "https://department-for-education.shinyapps.io/dfe-shiny-template", + "25th April 2024", + "26th April 2024", + "2nd November 2024", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template", + publication_slug = "la-and-school-expenditure", + publication_name = "LA and school expenditure" +) +} diff --git a/man/cookies_banner_server.Rd b/man/cookies_banner_server.Rd index dd94f30..52188cd 100644 --- a/man/cookies_banner_server.Rd +++ b/man/cookies_banner_server.Rd @@ -9,7 +9,8 @@ cookies_banner_server( input_cookies, parent_session, google_analytics_key = NULL, - cookies_link_panel = "cookies_panel_ui" + cookies_link_panel = "cookies_panel_ui", + cookies_nav_id = "navlistPanel" ) } \arguments{ @@ -25,8 +26,11 @@ always be \code{parent_session = session}} \item{google_analytics_key}{Provide the GA 10 digit key of the form "ABCDE12345"} -\item{cookies_link_panel}{name of the navlistPanel that the cookie banner +\item{cookies_link_panel}{name of the navigation panel that the cookie banner provides a link to, usually "cookies_panel_ui"} + +\item{cookies_nav_id}{ID of the navigation panel the cookie panel page is +within, defaults to "navlistPanel"} } \description{ cookies_banner_server() provides the server module to be used alongside diff --git a/man/custom_disconnect_message.Rd b/man/custom_disconnect_message.Rd index 8797d10..94c6b0e 100644 --- a/man/custom_disconnect_message.Rd +++ b/man/custom_disconnect_message.Rd @@ -9,7 +9,9 @@ custom_disconnect_message( dashboard_title = NULL, links = NULL, publication_name = NULL, - publication_link = NULL + publication_link = NULL, + support_contact = "explore.statistics@education.gov.uk", + custom_refresh = NULL ) } \arguments{ @@ -24,6 +26,13 @@ but can be two URLs if an overflow site has been set up} \item{publication_link}{The link to the publication on Explore Education Statistics} + +\item{support_contact}{Email address for support contact, defaults to +explore.statistics@education.gov.uk} + +\item{custom_refresh}{Custom refresh link, defaults to refreshing the page, main value is if you +have bookmarking enabled and want the refresh to send to the initial view instead of reloading +any bookmarks} } \value{ A HTML overlay panel that appears when a user loses connection to a DfE R Shiny @@ -53,4 +62,8 @@ custom_disconnect_message( ) ) +custom_disconnect_message( + support_contact = "my.team@education.gov.uk", + custom_refresh = "https://department-for-education.shinyapps.io/my-dashboard" +) } diff --git a/tests/test_dashboard/ui.R b/tests/test_dashboard/ui.R index 1d01f12..285e6e9 100644 --- a/tests/test_dashboard/ui.R +++ b/tests/test_dashboard/ui.R @@ -38,6 +38,19 @@ ui <- function(input, output, session) { form_url = "https://forms.office.com" ) ), + ## Accessibility panel -------------------------------------------------------- + shiny::tabPanel( + value = "a11y_panel", + "Accessibility", + a11y_panel( + "DfE Shiny template", + "https://department-for-education.shinyapps.io/dfe-shiny-template", + "26th November 2023", + "28th November 2023", + "12th March 2024", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template" + ) + ), ## Cookies panel -------------------------------------------------------- shiny::tabPanel( diff --git a/tests/testthat/test-a11y_panel.R b/tests/testthat/test-a11y_panel.R new file mode 100644 index 0000000..f074a78 --- /dev/null +++ b/tests/testthat/test-a11y_panel.R @@ -0,0 +1,243 @@ +test_that("Accessibility dates are required", { + expect_no_error( + a11y_panel( + "DfE Shiny template", + "https://department-for-education.shinyapps.io/dfe-shiny-template", + date_tested = "26th March 2024", + date_prepared = "28th March 2024", + date_reviewed = "12th November 2024", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" + ) + ) + expect_no_error( + a11y_panel( + "DfE Shiny template", + "https://department-for-education.shinyapps.io/dfe-shiny-template", + date_tested = "26 March 2024", + date_prepared = "28/03/2024", + date_reviewed = "12-11-2024", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" + ) + ) + expect_error( + a11y_panel( + "DfE Shiny template", + "https://department-for-education.shinyapps.io/dfe-shiny-template", + date_prepared = "28th March 2024", + date_reviewed = "12th November 2024", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" + ), + "argument \"date_tested\" is missing, with no default" + ) + expect_error( + a11y_panel( + "DfE Shiny template", + "https://department-for-education.shinyapps.io/dfe-shiny-template", + date_tested = "26/03/24", + date_reviewed = "12th November 2024", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" + ), + "argument \"date_prepared\" is missing, with no default" + ) + expect_error( + a11y_panel( + "DfE Shiny template", + "https://department-for-education.shinyapps.io/dfe-shiny-template", + date_tested = "26th November 2024", + date_prepared = "28th November 2024", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" + ), + "argument \"date_reviewed\" is missing, with no default" + ) + expect_error( + a11y_panel( + "DfE Shiny template", + "https://department-for-education.shinyapps.io/dfe-shiny-template", + date_tested = "26th March 2099", + date_prepared = "28th March 2024", + date_reviewed = "12th November 2024", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" + ), + "\"26th March 2099\" is in the future." + ) + expect_error( + a11y_panel( + "DfE Shiny template", + "https://department-for-education.shinyapps.io/dfe-shiny-template", + date_tested = "13/11/2023", + date_prepared = "28th November 2024", + date_reviewed = "12th November 2024", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" + ), + "date_reviewed should be later than date_prepared" + ) + expect_error( + a11y_panel( + "DfE Shiny template", + "https://department-for-education.shinyapps.io/dfe-shiny-template", + date_tested = "13/11/2024", + date_prepared = "28th March 2024", + date_reviewed = "12th November 2024", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" + ), + "date_reviewed should be later than date_tested" + ) + expect_warning( + a11y_panel( + "DfE Shiny template", + "https://department-for-education.shinyapps.io/dfe-shiny-template", + date_tested = "13/03/2020", + date_prepared = "28th March 2020", + date_reviewed = "12th November 2020", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" + ), + paste0( + "The template has been through a review more recently than your dashboard, please get in ", + "touch with the explore education statistics platforms team to request a re-review." + ) + ) + expect_error( + a11y_panel( + "DfE Shiny template", + "https://department-for-education.shinyapps.io/dfe-shiny-template", + date_tested = "Geoff", + date_prepared = "28th March 2024", + date_reviewed = "12th November 2024", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" + ), + "\"Geoff\" is not in a valid date format, e.g. 8th August 2024 or 08/08/2024." + ) + expect_error( + a11y_panel( + "DfE Shiny template", + "https://department-for-education.shinyapps.io/dfe-shiny-template", + date_tested = "26th March 2024", + date_prepared = "Bob", + date_reviewed = "12th November 2024", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" + ), + "\"Bob\" is not in a valid date format, e.g. 8th August 2024 or 08/08/2024." + ) + expect_error( + a11y_panel( + "DfE Shiny template", + "https://department-for-education.shinyapps.io/dfe-shiny-template", + date_tested = "26 November 2024", + date_prepared = "28/11/24", + date_reviewed = "Daisy", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" + ), + "\"Daisy\" is not in a valid date format, e.g. 8th August 2024 or 08/08/2024." + ) +}) + +test_that("Accessibility name and URLs", { + expect_error( + a11y_panel( + dashboard_url = "https://department-for-education.shinyapps.io/dfe-shiny-template", + date_tested = "26/03/24", + date_prepared = "28/03/24", + date_reviewed = "12/11/24", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" + ), + "argument \"dashboard_title\" is missing, with no default" + ) + expect_error( + a11y_panel( + dashboard_title = "DfE Shiny template", + date_tested = "26/03/24", + date_prepared = "28/03/24", + date_reviewed = "12/11/24", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" + ), + "argument \"dashboard_url\" is missing, with no default" + ) + expect_error( + a11y_panel( + dashboard_title = "DfE Shiny template", + dashboard_url = "Cecil", + date_tested = "26/03/24", + date_prepared = "28/03/24", + date_reviewed = "12/11/24", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" + ), + paste("Cecil", "is not a valid DfE dashboard deployment URL") + ) + expect_error( + a11y_panel( + dashboard_title = "DfE Shiny template", + dashboard_url = "https://department-for-education.shinyapps.io/dfe-shiny-template", + date_tested = "26/03/24", + date_prepared = "28/03/24", + date_reviewed = "12/11/24", + issues_contact = "https://github.com/dfe-analytical-services/" + ), + paste0( + "\"", + "https://github.com/dfe-analytical-services/", + "\"", + " should either be a valid repository URL or a valid DfE e-mail address" + ) + ) +}) + +output <- a11y_panel( + "DfE Shiny template", + "https://department-for-education.shinyapps.io/dfe-shiny-template", + date_tested = "26th March 2024", + date_prepared = "28th March 2024", + date_reviewed = "12th November 2024", + issues_contact = "https://github.com/dfe-analytical-services/shiny-template/issues" +) + +test_that("HTML headings output from function", { + # This checks the headings are in the expected positions in the HTML output the function returns + expect_equal(paste(output$children[[1]]), "Accessibility") + expect_equal( + paste(output$children[[2]]$children[[1]]), + "