diff --git a/server.R b/server.R index 9a7b8cc9c151f6672e25282c45b174a8ab8614f3..f372f94b8b5bb052c32009d1aa969c2ebc42ea9d 100644 --- a/server.R +++ b/server.R @@ -1,52 +1,52 @@ server <- function(input, output, session) { # Stocker les valeurs réactives - r <- reactiveValues( + r <- shiny::reactiveValues( filteredByDate = NULL, # Filtrage uniquement par date filteredData = NULL # Filtrage final après application de tous les filtres ) # 1️⃣ Filtrage prioritaire par date ---- - observeEvent(input$daterange, { - req(input$daterange) # Vérifier que la sélection est valide + shiny::observeEvent(input$daterange, { + shiny::req(input$daterange) # Vérifier que la sélection est valide # Filtrage initial sur la plage de dates r$filteredByDate <- all_data %>% - filter( + dplyr::filter( updated_at >= as.Date(input$daterange[[1]]) & updated_at <= as.Date(input$daterange[[2]]) ) # Mise à jour dynamique des autres filtres en fonction des données filtrées par date - updateFilters() + DT::updateFilters() }) # 2️⃣ Mise à jour dynamique des filtres ---- - updateFilters <- reactive({ - req(r$filteredByDate) # Vérifier que les données sont disponibles - isolate({ - updateSelectizeInput(session, "project_name", + updateFilters <- shiny::reactive({ + shiny::req(r$filteredByDate) # Vérifier que les données sont disponibles + shiny::isolate({ + shiny::updateSelectizeInput(session, "project_name", choices = unique(r$filteredByDate$project_name), selected = input$project_name) - updateSelectizeInput(session, "etiquette", + shiny::updateSelectizeInput(session, "etiquette", choices = r$filteredByDate$etiquette %>% strsplit(split = ",") %>% unlist() %>% - na.omit() %>% + stats::na.omit() %>% .[. != ""] %>% trimws() %>% unique(), selected = input$etiquette) - updateSelectizeInput(session, "auteur", + shiny::updateSelectizeInput(session, "auteur", choices = unique(r$filteredByDate$auteur), selected = input$auteur) - updateSelectizeInput(session, "categorie", + shiny::updateSelectizeInput(session, "categorie", choices = unique(r$filteredByDate$type), selected = input$categorie) - updateCheckboxGroupInput_dsfr( inputId = "re_code", + shinygouv::updateCheckboxGroupInput_dsfr( inputId = "re_code", label = "Type d'évènement :", choices = unique(r$filteredByDate$re_code), selected = input$re_code, @@ -54,11 +54,11 @@ server <- function(input, output, session) { }) }) # 3️⃣ Filtrage final en fonction des autres filtres ---- - observe({ - req(r$filteredByDate) # Vérifier que les données de base sont filtrées par date + shiny::observe({ + shiny::req(r$filteredByDate) # Vérifier que les données de base sont filtrées par date r$filteredData <- r$filteredByDate %>% - filter( + dplyr::filter( (if (length(input$project_name)) project_name %in% input$project_name else TRUE) & (if (length(input$etiquette)) sapply(input$etiquette, function(t) grepl(t, etiquette)) %>% rowSums() > 0 else TRUE) & (if (length(input$auteur)) auteur %in% input$auteur else TRUE) & @@ -67,28 +67,28 @@ server <- function(input, output, session) { ) # Mettre à jour les filtres restants - updateFilters() + DT::updateFilters() }) # 4️⃣ Réinitialisation des filtres ---- - observeEvent(input$reset, { + shiny::observeEvent(input$reset, { r$filteredByDate <- all_data %>% - filter( + dplyr::filter( updated_at >= as.Date(input$daterange[[1]]) & updated_at <= as.Date(input$daterange[[2]]) ) r$filteredData <- r$filteredByDate # Reset total - updateSelectizeInput(session, "project_name", selected = NULL) - updateSelectizeInput(session, "etiquette", selected = NULL) - updateSelectizeInput(session, "auteur", selected = NULL) - updateSelectizeInput(session, "categorie", selected = NULL) - updateCheckboxGroupInput_dsfr( "re_code", selected = NULL,inline = TRUE) - updateFilters() + shiny::updateSelectizeInput(session, "project_name", selected = NULL) + shiny::updateSelectizeInput(session, "etiquette", selected = NULL) + shiny::updateSelectizeInput(session, "auteur", selected = NULL) + shiny::updateSelectizeInput(session, "categorie", selected = NULL) + shinygouv::updateCheckboxGroupInput_dsfr( "re_code", selected = NULL,inline = TRUE) + DT::updateFilters() }) # 5️⃣ Graphique interactif ---- output$filteredPlot2 <- plotly::renderPlotly({ - req(r$filteredData) # Vérifier qu'on a des données filtrées + shiny::req(r$filteredData) # Vérifier qu'on a des données filtrées p <- ggplot2::ggplot(r$filteredData, ggplot2::aes(x = updated_at, y = as.factor(project_name))) + ggplot2::geom_point(ggplot2::aes(color = re_code, text = paste(updated_at, message, sep = "\n")), size = 3, alpha = 0.5) + @@ -100,13 +100,13 @@ server <- function(input, output, session) { axis.title.y = ggplot2::element_blank() ) - plotly::ggplotly(p, tooltip = "text", dynamicTicks = TRUE) %>% + plotly::ggplotly(shiny::p, tooltip = "text", dynamicTicks = TRUE) %>% plotly::config(locale = "fr", displaylogo = FALSE) }) # 6️⃣ Graphique des indicateurs ---- - output$bar_chart <- renderPlotly({ - req(r$filteredData) + output$bar_chart <- plotly::renderPlotly({ + shiny::req(r$filteredData) percent_time <- as.numeric(max(r$filteredData$updated_at) - min(r$filteredData$updated_at)) / as.numeric(max(all_data$updated_at) - min(all_data$updated_at)) * 100 @@ -119,19 +119,19 @@ server <- function(input, output, session) { percent_time) ) plotly::ggplotly( - ggplot(data, aes(x = dataset, y = total, fill = dataset)) + - geom_bar(stat = "identity") + - coord_flip() + - scale_fill_manual(values = c("#3498db", "#e74c3c", "#2ecc71")) + - labs( + ggplot2::ggplot(data, ggplot2::aes(x = dataset, y = total, fill = dataset)) + + ggplot2::geom_bar(stat = "identity") + + ggplot2::coord_flip() + + ggplot2::scale_fill_manual(values = c("#3498db", "#e74c3c", "#2ecc71")) + + ggplot2::labs( x = "Comparaison", y = "Pourcentage / Nombre", title = "Comparaison des Commits, Projets et Temps" ) + - theme_minimal() + - theme(legend.position = "none") + - geom_text( - aes(label = paste0(round(total, 1),"%")), + ggplot2::theme_minimal() + + ggplot2::theme(legend.position = "none") + + ggplot2::geom_text( + ggplot2::aes(label = paste0(round(total, 1),"%")), hjust = -0.2 ) ) %>% @@ -139,25 +139,25 @@ server <- function(input, output, session) { displaylogo = FALSE) }) - output$nb_projet <- renderText({ - req(r$filteredData) + output$nb_projet <- shiny::renderText({ + shiny::req(r$filteredData) paste("Nombre de projets visualisés",length(unique(r$filteredData$project_name)),sep = " : ") }) - output$nb_commit <- renderText({ - req(r$filteredData) + output$nb_commit <- shiny::renderText({ + shiny::req(r$filteredData) paste("Nombre de commits",sum(r$filteredData$type == "commit"),sep = " : ") }) - output$nb_temps <- renderText({ - req(r$filteredData) + output$nb_temps <- shiny::renderText({ + shiny::req(r$filteredData) paste("Estimation du temps passé sur la période :",sep = " ",round(difftime( max(r$filteredData$updated_at) , min(r$filteredData$updated_at),units = "hours")), " heures") }) # 7️⃣ Table des résultats ---- - output$table <- renderDT({ - req(r$filteredData) - datatable(r$filteredData, options = list( + output$table <- DT::renderDT({ + shiny::req(r$filteredData) + DT::datatable(r$filteredData, options = list( pageLength = 10, lengthMenu = c(5, 10, 25, 50), autoWidth = TRUE, @@ -170,8 +170,8 @@ server <- function(input, output, session) { # 8️⃣ Graphique des indicateurs ----- - output$min_value <- renderText({ - req(input$project_name) # Vérifie que l'input existe + output$min_value <- shiny::renderText({ + shiny::req(input$project_name) # Vérifie que l'input existe # Nombre de projets sélectionnés selected_projects <- length(unique(input$project_name)) @@ -180,7 +180,7 @@ server <- function(input, output, session) { if (selected_projects == 1) { # Filtrer les données pour ce projet spécifique projet_data <- all_data %>% - filter(project_name == input$project_name) + dplyr::filter(project_name == input$project_name) min_value <- min(projet_data$updated_at, na.rm = TRUE) @@ -191,8 +191,8 @@ server <- function(input, output, session) { }) - output$temps <- renderText({ - req(input$project_name) # Vérifie que l'input existe + output$temps <- shiny::renderText({ + shiny::req(input$project_name) # Vérifie que l'input existe # Nombre de projets sélectionnés selected_projects <- length(unique(input$project_name)) @@ -200,7 +200,7 @@ server <- function(input, output, session) { if (selected_projects == 1) { # Filtrer les données pour ce projet spécifique projet_data <- all_data %>% - filter(project_name == input$project_name) + dplyr::filter(project_name == input$project_name) temps <- difftime(max(projet_data$updated_at), min(projet_data$updated_at), units = "secs") @@ -214,45 +214,45 @@ server <- function(input, output, session) { } }) - output$bar <- renderPlot({ - req(input$project_name) # Vérifie que l'input existe + output$bar <- shiny::renderPlot({ + shiny::req(input$project_name) # Vérifie que l'input existe selected_projects <- length(unique(input$project_name)) if (selected_projects == 1) { # Filtrer les données pour le project_name sélectionné filtered_data <- all_data %>% - filter(project_name == input$project_name) %>% - mutate(month = format(as.Date(updated_at), "%Y-%m")) + dplyr::filter(project_name == input$project_name) %>% + dplyr::mutate(month = format(as.Date(updated_at), "%Y-%m")) # Définir la plage de mois spécifique au projet sélectionné - first_month <- floor_date(min(as.Date(filtered_data$updated_at)), "month") - last_month <- ceiling_date(max(as.Date(filtered_data$updated_at)), "month") + first_month <- lubridate::floor_date(min(as.Date(filtered_data$updated_at)), "month") + last_month <- lubridate::ceiling_date(max(as.Date(filtered_data$updated_at)), "month") # Générer tous les mois entre le premier et le dernier full_months <- seq(first_month, last_month, by = "month") %>% - tibble(month = format(., "%Y-%m")) + dplyr::tibble(month = format(., "%Y-%m")) # Compter les entrées par mois et compléter les mois manquants complete_data <- full_months %>% - left_join(filtered_data %>% count(month), by = "month") %>% - replace_na(list(n = 0)) + dplyr::left_join(filtered_data %>% dplyr::count(month), by = "month") %>% + tidyr::replace_na(list(n = 0)) # Créer le bar plot - ggplot(complete_data, aes(x = month, y = n)) + - geom_bar(stat = "identity", fill = "#ff7f27", width = 0.7) + - theme_minimal() + - scale_x_discrete( + ggplot2::ggplot(complete_data, ggplot2::aes(x = month, y = n)) + + ggplot2::geom_bar(stat = "identity", fill = "#ff7f27", width = 0.7) + + ggplot2::theme_minimal() + + ggplot2::scale_x_discrete( name = "Mois", labels = function(x) format(as.Date(paste0(x, "-01")), "%B %Y") ) + - labs(y = "Nombre d'entrées") + + ggplot2::labs(y = "Nombre d'entrées") + gouvdown::theme_gouv() + - theme(axis.text.x = element_text(angle = 45, hjust = 1)) + ggplot2::theme(axis.text.x = ggplot2::element_text(angle = 45, hjust = 1)) }else{ - ggplot() + - annotate("text", x = 1, y = 1, label = "Sélectionnez un seul projet pour voir la timeline", size = 5) + - theme_void() + ggplot2::ggplot() + + ggplot2::annotate("text", x = 1, y = 1, label = "Sélectionnez un seul projet pour voir la timeline", size = 5) + + ggplot2::theme_void() } }) } diff --git a/ui.R b/ui.R index 7fc73230eb9f5734b88dc28b10d051a58fb8cf76..dfeb1df41bb96c4ca3eb2b20c31c9ec422614e69 100644 --- a/ui.R +++ b/ui.R @@ -7,12 +7,12 @@ ui <- shinygouv::navbarPage_dsfr( nom_site_service = "Visualisation des projets du CSD gérés avec git", baseline = "Les Projets du Centre de Services de la Donnée" ), - footer = footer_dsfr( + footer = shinygouv::footer_dsfr( intitule = c("DREAL", "Pays de la Loire"), description = paste("Site mis à jour le : " , date_datamart), accessibilite = "non", - add_extra_url_body = footer_extra_url_body_dsfr(), - add_extra_url_bottom = footer_extra_url_bottom_dsfr() + add_extra_url_body = shinygouv::footer_extra_url_body_dsfr(), + add_extra_url_bottom = shinygouv::footer_extra_url_bottom_dsfr() ), # First tab Projet --------- shinygouv::navbarPanel_dsfr( @@ -31,13 +31,13 @@ ui <- shinygouv::navbarPage_dsfr( ), shinygouv::column_dsfr( 3, - selectizeInput( + shiny::selectizeInput( inputId = "etiquette", label = "Étiquette :", choices = all_data$etiquette %>% strsplit(split = ",") %>% # Divise les chaînes en éléments séparés unlist() %>% # Aplatit la liste obtenue - na.omit() %>% # Supprime les NA (au cas où) + stats::na.omit() %>% # Supprime les NA (au cas où) .[. != ""] %>% # Supprime les chaînes vides trimws() %>% # suppremie les espace avnt et apres unique() , @@ -46,9 +46,9 @@ ui <- shinygouv::navbarPage_dsfr( ), extra_class = "fr-mt-6w" ), - column_dsfr( + shinygouv::column_dsfr( 3, - selectizeInput( + shiny::selectizeInput( inputId = "project_name", label = "Sélectionnez projet : ", choices = NULL, @@ -56,33 +56,33 @@ ui <- shinygouv::navbarPage_dsfr( ), extra_class = "fr-mt-6w" ), - column_dsfr( + shinygouv::column_dsfr( 3, - selectizeInput( + shiny::selectizeInput( inputId = "auteur", label = "Auteur :", - choices = unique(str_to_title(replace_non_ascii(all_data$auteur))), + choices = unique(stringr::str_to_title(textclean::replace_non_ascii(all_data$auteur))), selected = NULL, multiple = TRUE ),extra_class = "fr-mt-6w" ), - column_dsfr( + shinygouv::column_dsfr( 3, - actionButton_dsfr("reset", "Réinitialiser les projets"), + shinygouv::actionButton_dsfr("reset", "Réinitialiser les projets"), extra_class = "fr-my-2w" ), - column_dsfr( + shinygouv::column_dsfr( 4, - checkboxGroupInput_dsfr( + shinygouv::checkboxGroupInput_dsfr( inputId = "re_code", label = "Type d'évènement :", choices = unique(all_data$re_code), inline = TRUE ) ), - column_dsfr( + shinygouv::column_dsfr( 4, - selectizeInput( + shiny::selectizeInput( inputId = "categorie", label = " Évenement (précis) ", choices = unique(all_data$type), @@ -90,11 +90,11 @@ ui <- shinygouv::navbarPage_dsfr( multiple = TRUE ) ), - shinygouv::column_dsfr(9, uiOutput("lien"), extra_class = "fr-my-6w") + shinygouv::column_dsfr(9, shiny::uiOutput("lien"), extra_class = "fr-my-6w") ), - tabsetPanel_dsfr( + shinygouv::tabsetPanel_dsfr( "tableau_proj", - tabPanel_dsfr( + shinygouv::tabPanel_dsfr( id = "graph_input", title = "graphique par choix", shinygouv::fluidRow_dsfr( @@ -105,31 +105,31 @@ ui <- shinygouv::navbarPage_dsfr( ) ) ),# tab graphique par choix ↑ - tabPanel_dsfr( + shinygouv::tabPanel_dsfr( id = "indicateur" , title = "Indicateurs", shinygouv::fluidRow_dsfr( - column_dsfr(3, - textOutput("nb_projet"), - textOutput("nb_commit"), - textOutput("nb_temps"), extra_class = "fr-my-1w" + shinygouv::column_dsfr(3, + shiny::textOutput("nb_projet"), + shiny::textOutput("nb_commit"), + shiny::textOutput("nb_temps"), extra_class = "fr-my-1w" ), shinygouv::column_dsfr(9, - plotlyOutput("bar_chart"), + plotly::plotlyOutput("bar_chart"), extra_class = "fr-my-1w"), - column_dsfr(12,textOutput("min_value")), - column_dsfr(12,textOutput("temps")), - column_dsfr(12,plotOutput("bar"), + shinygouv::column_dsfr(12,shiny::textOutput("min_value")), + shinygouv::column_dsfr(12,shiny::textOutput("temps")), + shinygouv::column_dsfr(12,shiny::plotOutput("bar"), extra_class = "fr-my-1w") ) ),# tab indicateur par choix ↑ - tabPanel_dsfr( + shinygouv::tabPanel_dsfr( id = "Table" , title = "Table", shinygouv::fluidRow_dsfr( shinygouv::column_dsfr(12, - DTOutput('table')) + DT::DTOutput('table')) ) )# tab table par choix ↑ )#↑ tableau_proj