diff --git a/dev/deploiment_sur_dataviz.R b/dev/deploiment_sur_dataviz.R index b41652ec1546e3c71085d59fbf1038129f9b204b..7abc3ee62655cf61dd6e4d60ed49156cfc7267ae 100644 --- a/dev/deploiment_sur_dataviz.R +++ b/dev/deploiment_sur_dataviz.R @@ -12,6 +12,6 @@ to_svr_dataviz_ftp <- function(fic = "app/shiny_siclop.RData") { # fichiers à transférer app_files <- c(list.files("R/", full.names = TRUE, recursive = TRUE), - "dataviz_gitlabr.Rproj","github.RData","gitlab_forge.RData","gitlab.RData") + "dataviz_gitlabr.Rproj","github.RData","gitlab_forge.RData","gitlab.RData","date_MAJ.RData") # Exécution des transferts lapply(X = app_files, FUN = to_svr_dataviz_ftp) diff --git a/dev/github_extraire.R b/dev/github_extraire.R index 3f96c5a382cefba47d42c4cac4b6283e97b41502..e8763ce2f054bb9a872951c6c46f431188c7f809 100644 --- a/dev/github_extraire.R +++ b/dev/github_extraire.R @@ -1,16 +1,17 @@ -#dernier ----- # Charger les packages nécessaires library(httr) library(jsonlite) library(dplyr) library(DT) # Récupérer le token GitHub depuis l'environnement -api_key <- Sys.getenv("GITHUB_PAT") +extract_before_at <- function(email) { + sub("@.*", "", email) +} # Fonction pour récupérer les commits d'un projet GitHub avec clé API get_github_commits <- function(repo) { url <- paste0("https://api.github.com/repos/", repo, "/commits") - response <- GET(url, authenticate(api_key, "")) # Utilisation de la clé API + response <- GET(url, authenticate(Sys.getenv("GITHUB_PAT"), "")) # Utilisation de la clé API if (status_code(response) != 200) { stop("Failed to fetch commits from GitHub API") } @@ -19,15 +20,16 @@ get_github_commits <- function(repo) { mutate(project_name = repo, # Ajouter le nom du projet type = "commit", # Spécifier le type comme "commit" message = commit.message, # Utiliser le message du commit - last_updated = commit.committer.date) %>% # Date de la dernière mise à jour - select(project_name, type, message, last_updated) # Conserver les colonnes pertinentes + author = extract_before_at(commit.committer.email) , # Ajout de l'auteur + updated_at = commit.committer.date) %>% # Date de la dernière mise à jour + select(project_name, type, message, updated_at,author) # Conserver les colonnes pertinentes return(commits) } # Fonction pour récupérer les issues d'un projet GitHub avec clé API get_github_issues <- function(repo) { url <- paste0("https://api.github.com/repos/", repo, "/issues?state=all") - response <- GET(url, authenticate(api_key, "")) # Utilisation de la clé API + response <- GET(url, authenticate(Sys.getenv("GITHUB_PAT"), "")) # Utilisation de la clé API if (status_code(response) != 200) { stop("Failed to fetch issues from GitHub API") } @@ -36,11 +38,23 @@ get_github_issues <- function(repo) { mutate(project_name = repo, # Ajouter le nom du projet type = "issue", # Spécifier le type comme "issue" message = title, # Utiliser le titre de l'issue - last_updated = updated_at) %>% # Date de la dernière mise à jour - select(project_name, type, message, last_updated) # Conserver les colonnes pertinentes + author = user.login , # Ajout de l'auteur + updated_at = updated_at) %>% # Date de la dernière mise à jour + select(project_name, type, message, updated_at,author) # Conserver les colonnes pertinentes return(issues) } +get_github_topics <- function(repo) { + url <- paste0("https://api.github.com/repos/", repo, "/topics") + response <- GET(url, authenticate(Sys.getenv("GITHUB_PAT"), ""), add_headers(Accept = "application/vnd.github.mercy-preview+json")) + if (status_code(response) != 200) { + stop("Failed to fetch topics from GitHub API for repo: ", repo) + } + topics <- fromJSON(content(response, "text"), flatten = TRUE)$names + return(data.frame(project_name = repo, topics = paste(topics, collapse = ", "))) # Combine topics en une chaîne unique +} + + # Récupérer les commits et les issues pour le projet spyrales/shinygouv repo_shinygouv <- "spyrales/shinygouv" commits_shinygouv <- get_github_commits(repo_shinygouv) @@ -64,46 +78,62 @@ get_github_issues <- function(repo) { # parcours_r_module_analyse_multi_dimensionnelles repo_analyse_multi_dimensionnelles <- "MTES-MCT/parcours_r_module_analyse_multi_dimensionnelles" commits_multi_dim <- get_github_commits(repo_analyse_multi_dimensionnelles) - issues_multi_dim <- get_github_commits(repo_analyse_multi_dimensionnelles) + issues_multi_dim <- get_github_issues(repo_analyse_multi_dimensionnelles) # parcours_r_module_statistiques_descriptives repo_stat_desc <- "MTES-MCT/parcours_r_module_statistiques_descriptives" commits_stat_desc <- get_github_commits(repo_stat_desc) - issues_stat_desc <- get_github_commits(repo_stat_desc) + issues_stat_desc <- get_github_issues(repo_stat_desc) # parcours_r_module_publication_rmarkdown repo_rmarkdown <- "MTES-MCT/parcours_r_module_publication_rmarkdown" commits_rmarkdown <- get_github_commits(repo_rmarkdown) - issues_rmarkdown <- get_github_commits(repo_rmarkdown) + issues_rmarkdown <- get_github_issues(repo_rmarkdown) # parcours_r_socle_introduction repo_introduction <- "MTES-MCT/parcours_r_socle_introduction" commits_introduction <- get_github_commits(repo_introduction) - issues_introduction <- get_github_commits(repo_introduction) + issues_introduction <- get_github_issues(repo_introduction) # parcours_r_socle_preparation_des_donnees repo_preparation_des_donnees <- "MTES-MCT/parcours_r_socle_preparation_des_donnees" commits_preparation_des_donnees <- get_github_commits(repo_preparation_des_donnees) - issues_preparation_des_donnees <- get_github_commits(repo_preparation_des_donnees) + issues_preparation_des_donnees <- get_github_issues(repo_preparation_des_donnees) # savoirfR repo_savoirfR <- "MTES-MCT/savoirfR" commits_savoirfR <- get_github_commits(repo_savoirfR) - issues_savoirfR <- get_github_commits(repo_savoirfR) + issues_savoirfR <- get_github_issues(repo_savoirfR) # parcours-r repo_parcours_r <- "MTES-MCT/parcours-r" commits_parcours_r <- get_github_commits(repo_parcours_r) - issues_parcours_r <- get_github_commits(repo_parcours_r) + issues_parcours_r <- get_github_issues(repo_parcours_r) # parcours_r_module_datavisualisation repo_datavisualisation <- "MTES-MCT/parcours_r_module_datavisualisation" commits_datavisualisation <- get_github_commits(repo_datavisualisation) - issues_datavisualisation <- get_github_commits(repo_datavisualisation) + issues_datavisualisation <- get_github_issues(repo_datavisualisation) # parcours_r_module_analyse_spatiale repo_analyse_spatiale <- "MTES-MCT/parcours_r_module_analyse_spatiale" commits_analyse_spatiale <- get_github_commits(repo_analyse_spatiale) - issues_analyse_spatiale <- get_github_commits(repo_analyse_spatiale) + issues_analyse_spatiale <- get_github_issues(repo_analyse_spatiale) + + repos <- c( + "spyrales/shinygouv", "spyrales/gouvdown", + "MTES-MCT/parcours_r_module_applications_shiny", + "MTES-MCT/parcours-r_ateliers_rpackage", + "MTES-MCT/parcours_r_module_analyse_multi_dimensionnelles", + "MTES-MCT/parcours_r_module_statistiques_descriptives", + "MTES-MCT/parcours_r_module_publication_rmarkdown", + "MTES-MCT/parcours_r_socle_introduction", + "MTES-MCT/parcours_r_socle_preparation_des_donnees", + "MTES-MCT/savoirfR", "MTES-MCT/parcours-r", + "MTES-MCT/parcours_r_module_datavisualisation", + "MTES-MCT/parcours_r_module_analyse_spatiale" + ) + + topics_list <- do.call(rbind, lapply(repos, get_github_topics)) # Combiner les dataframes de commits et issues pour les deux dépôts combined_data <- bind_rows(commits_shinygouv, issues_shinygouv, @@ -120,8 +150,13 @@ get_github_issues <- function(repo) { commits_datavisualisation, issues_datavisualisation, commits_analyse_spatiale, issues_analyse_spatiale ) -combined_data <- rename(combined_data, "updated_at" = 'last_updated') + combined_data <- combined_data %>% + left_join(topics_list, by = "project_name") %>% + mutate(origine = "Github") %>% + unique() + # Afficher les premières lignes du tableau combiné date_datamart <-format.Date(Sys.Date(), '%d/%m/%Y') #save.image("github.RData") save(combined_data, file = "github.RData") +save(date_datamart, file = "date_MAJ.RData") diff --git a/dev/gitlab_classique.R b/dev/gitlab_classique.R index 0dd21fce1a995949a2ec9105616bf62256e301aa..bfb98f42cea725322ebdadaec9ef0b17d855d3f5 100644 --- a/dev/gitlab_classique.R +++ b/dev/gitlab_classique.R @@ -1,145 +1,152 @@ -# Charger les packages nécessaires library(httr) library(jsonlite) library(dplyr) library(DT) library(stringr) +library(gitlabr) -# Variables pour l'API GitLab ----- +set_gitlab_connection( + gitlab_url = "https://gitlab.com" , + private_token = Sys.getenv("GITLAB_PAT") +) +project_ids <- c(41600697, 19859695, 49118792, 21138017, 44145525, 18441361, 17610613,18439010) + +get_project_name <- function(base_url, project_id, private_token) { + api_url <- paste0(base_url, "/api/v4/projects/", project_id) + response <- GET(api_url, add_headers("PRIVATE-TOKEN" = private_token)) + + if (status_code(response) == 200) { + project_info <- content(response, as = "parsed", type = "application/json") + return(data.frame(id = project_id, name = project_info$name)) + } else { + warning("Impossible de récupérer le projet ID: ", project_id, " - Code: ", status_code(response)) + return(data.frame(id = project_id, name = NA)) + } +} + +# Boucle pour récupérer tous les noms de projets +name_gitlab <- bind_rows(lapply(project_ids, get_project_name, + base_url = "https://gitlab.com", + private_token = Sys.getenv("GITLAB_PAT"))) +name_gitlab$id <- as.character(name_gitlab$id) + +# Variables pour l'API GitLab base_url <- "https://gitlab.com" private_token <- Sys.getenv("GITLAB_PAT") # Récupération du token depuis Renviron -# Fonction pour gérer la pagination de l'API GitLab avec retry et timeout -get_all_pages <- function(url, private_token, max_retries = 3) { - # Fonction interne pour récupérer une page avec retry - get_page <- function(page) { + +# Fonction pour gérer la pagination de l'API GitLab avec une limite stricte à 160 pages, en vérifiant la présence de pages suivantes +# Fonction pour gérer la pagination de l'API GitLab avec une limite stricte à 160 pages +get_all_pages <- function(url, private_token, max_retries = 3, max_pages = 159) { + all_data <- list() + page <- 1 + + repeat { + # Vérification de la condition de fin dans la boucle while + if (page > max_pages) { + message("Limite de pages atteinte (", max_pages, "). Arrêt de la récupération.") + break + } + retries <- 0 success <- FALSE - while (!success && retries < max_retries) { + message("Traitement de l'URL : ", url, " - Page: ", page) # Afficher l'URL et la page actuelle + + while (!success && retries < max_retries && page <= max_pages) { tryCatch({ - # Faire la requête GET pour une page spécifique response <- GET( url, - query = list(page = page, per_page = 100), + query = list(page = page, per_page = 20), add_headers("PRIVATE-TOKEN" = private_token), - timeout(120) # Timeout augmenté à 120 secondes + timeout(120) ) - # Vérification du statut de la réponse + # Sortie en cas d'erreur HTTP autre que 200 if (status_code(response) != 200) { stop("La requête API a échoué avec le statut: ", status_code(response)) } - # Extraire les données de la réponse avec l'encodage UTF-8 pour éviter le message - data <- fromJSON(content(response, "text", encoding = "UTF-8"), flatten = TRUE) - success <- TRUE # Si la requête réussit, sortir de la boucle - return(data) + # Récupération des données JSON + page_data <- fromJSON(content(response, "text", encoding = "UTF-8"), flatten = TRUE) + # Si aucune donnée n'est renvoyée, arrêt de la récupération pour ce projet + if (length(page_data) == 0) { + message("Aucune donnée sur la page ", page, ". Fin de la récupération pour ce projet.") + break + } + + # Ajouter les données de la page à all_data + all_data <- append(all_data, list(page_data)) + success <- TRUE # Succès de la récupération }, error = function(e) { retries <- retries + 1 message("Erreur de connexion, tentative: ", retries, ". Détails: ", e$message) - Sys.sleep(2 * retries) # Attendre avant de réessayer + Sys.sleep(2 * retries) }) } - if (!success) { - stop("Echec de récupération des données après ", max_retries, " tentatives.") + # Vérification de la présence d'une page suivante dans l'en-tête "Link" + link_header <- headers(response)[["link"]] + if (is.null(link_header) || !grepl("rel=\"next\"", link_header)) { + message("Pas de page suivante. Fin de la récupération pour ce projet.") + break } - } - # Initialiser la récupération des données avec la première page - first_page_data <- get_page(1) + # Passer à la page suivante + page <- page + 1 + } - # Vérifier s'il y a plusieurs pages en analysant l'en-tête "Link" - link_header <- headers(response)[["link"]] - if (!is.null(link_header) && str_detect(link_header, "rel=\"next\"")) { - # Trouver le nombre total de pages dans l'en-tête - num_pages <- max(str_extract_all(link_header, "page=\\d+")[[1]] %>% str_remove_all("page=") %>% as.integer()) + # Combiner toutes les pages récupérées en un seul dataframe + return(bind_rows(all_data)) +} - # Utiliser lapply pour récupérer les pages suivantes - other_pages_data <- lapply(2:num_pages, get_page) - # Combiner toutes les pages de données - all_data <- bind_rows(first_page_data, bind_rows(other_pages_data)) - } else { - # Si une seule page, renvoyer seulement les données de la première page - all_data <- first_page_data - } - return(all_data) -} # Fonction pour extraire le nom du projet à partir de l'URL extract_project_name <- function(web_url) { - # Utiliser une expression régulière pour capturer le dernier segment significatif avant "/-/" str_extract(web_url, "(?<=/)[^/]+(?=/-/)") } -# Fonction pour récupérer les commits d'un projet GitLab -get_gitlab_commits <- function(base_url, project_id, private_token) { - api_url <- paste0(base_url, "/api/v4/projects/", project_id, "/repository/commits") - - # Récupérer toutes les pages avec pagination - data <- get_all_pages(api_url, private_token) - - # Harmoniser les types de colonnes et sélectionner les colonnes pertinentes - data <- data %>% - mutate( - id = as.character(id), - project_name = extract_project_name(web_url), - data_type = "commit", - discussion = message, - updated_at = committed_date - ) - return(data %>% select(project_name, data_type, discussion, updated_at)) -} - # Fonction pour récupérer les issues d'un projet GitLab get_gitlab_issues <- function(base_url, project_id, private_token) { api_url <- paste0(base_url, "/api/v4/projects/", project_id, "/issues") - - # Récupérer toutes les pages avec pagination data <- get_all_pages(api_url, private_token) - - # Harmoniser les types de colonnes et sélectionner les colonnes pertinentes data <- data %>% mutate( - id = as.character(id), project_name = extract_project_name(web_url), - data_type = "issue", - discussion = title + type = "issue", + message = title, + author = author.username ) - return(data %>% select(project_name, data_type, discussion, updated_at)) + return(data %>% select(project_name, type, message, updated_at, author)) } # Fonction pour récupérer et filtrer les events d'un projet GitLab get_gitlab_events <- function(base_url, project_id, private_token) { api_url <- paste0(base_url, "/api/v4/projects/", project_id, "/events") - - # Récupérer toutes les pages avec pagination data <- get_all_pages(api_url, private_token) - - # Garder seulement les événements où action_name est "commented on" data <- data %>% - filter(action_name == "commented on") %>% mutate( - id = as.character(id), - project_name = extract_project_name(web_url), - data_type = "event", - discussion = note.body, - updated_at = note.updated_at - ) - return(data %>% select(project_name, data_type, discussion, updated_at)) + project_name = as.character(project_id), + type = if_else((is.null(target_type) | target_type == "") | as.character(target_type) == "Issue" | as.character(action_name) == "joined", # remplecer par | as.ch(target-type)=="Issue" + as.character(action_name), + as.character(target_type)), + message = note.body, + updated_at = created_at, + author = author.username + ) %>% + left_join(name_gitlab, by = c("project_name" = "id")) %>% + mutate(project_name = name) %>% + select(-name) + return(data %>% select(project_name, type, message, updated_at, author)) } # Fonction pour récupérer les données d'un projet get_data_for_project <- function(base_url, project_id, private_token) { - commits_data <- tryCatch(get_gitlab_commits(base_url, project_id, private_token), error = function(e) NULL) issues_data <- tryCatch(get_gitlab_issues(base_url, project_id, private_token), error = function(e) NULL) events_data <- tryCatch(get_gitlab_events(base_url, project_id, private_token), error = function(e) NULL) - - # Combiner les résultats en un seul dataframe - return(bind_rows(commits_data, issues_data, events_data)) + return(bind_rows(issues_data, events_data)) } # Fonction pour traiter plusieurs projets avec lapply @@ -147,34 +154,81 @@ get_data_from_multiple_projects <- function(base_url, project_ids, private_token all_data <- lapply(project_ids, function(project_id) { get_data_for_project(base_url, project_id, private_token) }) - - # Combiner tous les dataframes en un seul return(bind_rows(all_data)) } -# Define the query parameters pour récupérer les projets -params <- list( - include_subgroups = "true", - per_page = 100 -) +# Topics +get_project_topics <- function(base_url, project_id, private_token) { + api_url <- paste0(base_url, "/api/v4/projects/", project_id) + response <- GET(api_url, add_headers("PRIVATE-TOKEN" = private_token)) + + if (status_code(response) == 200) { + project_info <- fromJSON(content(response, "text", encoding = "UTF-8"), flatten = TRUE) + return(data.frame( + id = as.character(project_info$name), + topics = paste(project_info$topics, collapse = ", "), # Combine les topics en une chaîne de caractères + stringsAsFactors = FALSE + )) + } else { + warning("Impossible de récupérer les topics pour le projet ID: ", project_id, " - Code: ", status_code(response)) + return(data.frame( + id = project_id, + topics = NA, + stringsAsFactors = FALSE + )) + } +} +extract_before_at <- function(email) { + sub("@.*", "", email) +} +############################################################### ----- +# Fonction générique +process_projects <- function(project_ids) { + result_list <- lapply(project_ids, function(project_id) { + # Récupérer les branches du projet + branch <- gl_list_branches(project_id)$name + + # Récupérer les commits pour chaque branche + branch_results <- lapply(branch, function(b) { + data <- gl_get_commits(project_id, ref_name = b, max_page = NA) + data <- data %>% mutate(branche = b, project_id = project_id) + return(data) + }) + + # Combiner les résultats pour un seul projet + bind_rows(branch_results) + }) -# Fetch the projects avec pagination et retry -response <- GET( - "https://gitlab-forge.din.developpement-durable.gouv.fr/api/v4/groups/1013/projects", - add_headers(`PRIVATE-TOKEN` = Sys.getenv("GITLAB_COM_TOKEN")), - query = params, - timeout(120) # Timeout augmenté pour les projets -) + # Combiner tous les projets en un seul dataframe + final_result <- bind_rows(result_list) + + # Ajouter une colonne pour indiquer les doublons (en excluant "branche" et "project_id") + final_result <- final_result %>% + mutate(is_duplicate = duplicated(select(., -c(branche, project_id)))) + + return(final_result) +} -# Parse the JSON content -projects <- content(response, as = "text", encoding = "UTF-8") %>% fromJSON() +final_result <- process_projects(project_ids) +final_result$project_id <- as.character(final_result$project_id) +final_result <- final_result %>% left_join(name_gitlab, by = c("project_id" = "id")) %>% + mutate(project_name = name, type = "commit") %>% + select(-name) +final_result <- final_result %>% mutate(author = extract_before_at(committer_email)) +final_result <- final_result %>% rename( "updated_at" = 'committed_date' ) +fg <- final_result %>% filter(is_duplicate == FALSE) %>% select(project_name,type , message ,updated_at,author) +############################################################### -# Extract the project IDs -project_ids <- c(41600697, 19859695, 49118792, 21138017, 18439010, 44145525, 18441361, 17610613) +# Récupérer les topics pour tous les projets +projects_topics <- bind_rows(lapply(project_ids, get_project_topics, base_url = base_url, private_token = private_token)) # Récupérer les données pour tous les projets all_data_gitlab <- get_data_from_multiple_projects(base_url, project_ids, private_token) -all_data_gitlab <- rename(all_data_gitlab, "type" = 'data_type',"message" = 'discussion') -# Afficher un aperçu des données combinées +all_data_gitlab <- all_data_gitlab %>% + filter(!(is.na(all_data_gitlab$type) | is.na(all_data_gitlab$message)) | all_data_gitlab$type == "joined" | all_data_gitlab$type == "WikiPage::Meta") +all_data_gitlab <- bind_rows(fg,all_data_gitlab) +all_data_gitlab <- all_data_gitlab %>% + mutate(origine ="Gitlab") +all_data_gitlab <- left_join(all_data_gitlab, projects_topics, by = c("project_name" = "id")) # save.image("gitlab.RData") save(all_data_gitlab, file = "gitlab.RData") diff --git a/dev/gitlab_forge.R b/dev/gitlab_forge.R index d1688d3b1655fd2d80e62cbbfac825917a8209ae..c9baf8cb78189515bc9bde5d605e3ad448d2997a 100644 --- a/dev/gitlab_forge.R +++ b/dev/gitlab_forge.R @@ -1,200 +1,193 @@ -# Charger les packages nécessaires library(httr) library(jsonlite) library(dplyr) library(DT) library(stringr) +library(gitlabr) -# Variables pour l'API GitLab ----- -base_url <- "https://gitlab-forge.din.developpement-durable.gouv.fr" -private_token <- Sys.getenv("GITLAB_COM_TOKEN") # Récupération du token depuis Renviron +set_gitlab_connection( + gitlab_url = "https://gitlab-forge.din.developpement-durable.gouv.fr" , + private_token = Sys.getenv("GITLAB_COM_TOKEN") +) -# Faire la requête à l'API avec le token d'accès------ -get_all_projects <- function(base_url, gitlab_token) { - page <- 1 - all_projects <- data.frame() +response <- data.frame() +# on charge les projets du groupe CSD +buildres <- function(i){ + res_proj100 <- GET( + "https://gitlab-forge.din.developpement-durable.gouv.fr/api/v4/groups/1013/projects", + add_headers(`PRIVATE-TOKEN` = Sys.getenv("GITLAB_COM_TOKEN")), + query = list( + include_subgroups = "true", + per_page = 100, + page = i + ), + timeout(120) # Timeout augmenté pour les projets + ) + res <- content(res_proj100, as = "text", encoding = "UTF-8") %>% fromJSON() + return(res) +} +#on réalise une boucle si plus de 100 projets +x <- 1 +repeat { + res <- buildres(x) + if (length(res) == 0) { + break + } + response <- bind_rows(response, res) + x <- x + 1 +} +# response <- GET( +# "https://gitlab-forge.din.developpement-durable.gouv.fr/api/v4/groups/1013/projects", +# add_headers(`PRIVATE-TOKEN` = Sys.getenv("GITLAB_COM_TOKEN")), +# query = list( +# include_subgroups = "true", +# per_page = 1000 +# ), +# timeout(120) # Timeout augmenté pour les projets +# ) - repeat { - # Faire la requête avec paramètres pour inclure les sous-groupes et gérer la pagination - response <- GET( - "https://gitlab-forge.din.developpement-durable.gouv.fr/api/v4/groups/1013/projects" , - query = list(include_subgroups = "true", per_page = 100, page = page), - add_headers(Authorization = paste("Bearer", private_token)) - ) +# Parse the JSON content +projects <- response - # Vérifier si la requête a réussi - if (status_code(response) != 200) { - print(paste("Erreur : ", status_code(response))) - break - } +# Extract the project IDs +project_ids <- projects$id - # Convertir la réponse JSON en une structure R - projects <- fromJSON(content(response, as = "text", encoding = "UTF-8")) +get_project_name <- function(base_url, project_id, private_token) { + api_url <- paste0(base_url, "/api/v4/projects/", project_id) + response <- GET(api_url, add_headers("PRIVATE-TOKEN" = private_token)) - # Si la réponse est vide ou n'est pas une liste de projets, sortir de la boucle - if (length(projects) == 0 || !is.data.frame(projects)) { - break - } + if (status_code(response) == 200) { + project_info <- content(response, as = "parsed", type = "application/json") + return(data.frame(id = project_id, name = project_info$name)) + } else { + warning("Impossible de récupérer le projet ID: ", project_id, " - Code: ", status_code(response)) + return(data.frame(id = project_id, name = NA)) + } +} - # Extraire les IDs et les noms des projets - project_data <- data.frame( - id = projects$id, - name = projects$name - ) +# Boucle pour récupérer tous les noms de projets +name_gitlab <- bind_rows(lapply(project_ids, get_project_name, + base_url = "https://gitlab-forge.din.developpement-durable.gouv.fr", + private_token = Sys.getenv("GITLAB_COM_TOKEN"))) +name_gitlab$id <- as.character(name_gitlab$id) - # Ajouter les projets à la liste complète - all_projects <- rbind(all_projects, project_data) +# Variables pour l'API GitLab +base_url <- "https://gitlab-forge.din.developpement-durable.gouv.fr" +private_token <- Sys.getenv("GITLAB_COM_TOKEN") # Récupération du token depuis Renviron - # Vérifier si on est à la dernière page en regardant les en-têtes - if (is.null(headers(response)$`x-next-page`) || headers(response)$`x-next-page` == "") { - break - } - # Passer à la page suivante - page <- as.numeric(headers(response)$`x-next-page`) - } +# Fonction pour gérer la pagination de l'API GitLab avec une limite stricte à 160 pages, en vérifiant la présence de pages suivantes +# Fonction pour gérer la pagination de l'API GitLab avec une limite stricte à 160 pages +get_all_pages <- function(url, private_token, max_retries = 3, max_pages = 159) { + all_data <- list() + page <- 1 - return(all_projects) -} + repeat { + # Vérification de la condition de fin dans la boucle while + if (page > max_pages) { + message("Limite de pages atteinte (", max_pages, "). Arrêt de la récupération.") + break + } -# Récupérer tous les projets -project_data <- get_all_projects("https://gitlab-forge.din.developpement-durable.gouv.fr/api/v4/groups/1013/projects", private_token) -project_data$id <- as.character(project_data$id) -# Fonction pour gérer la pagination de l'API GitLab avec retry et timeout------ -get_all_pages <- function(url, private_token, max_retries = 3) { - # Fonction interne pour récupérer une page avec retry - get_page <- function(page) { retries <- 0 success <- FALSE - while (!success && retries < max_retries) { + message("Traitement de l'URL : ", url, " - Page: ", page) # Afficher l'URL et la page actuelle + + while (!success && retries < max_retries && page <= max_pages) { tryCatch({ - # Faire la requête GET pour une page spécifique response <- GET( url, - query = list(page = page, per_page = 100), + query = list(page = page, per_page = 20), add_headers("PRIVATE-TOKEN" = private_token), - timeout(120) # Timeout augmenté à 120 secondes + timeout(120) ) - # Vérification du statut de la réponse + # Sortie en cas d'erreur HTTP autre que 200 if (status_code(response) != 200) { stop("La requête API a échoué avec le statut: ", status_code(response)) } - # Extraire les données de la réponse avec l'encodage UTF-8 pour éviter le message - data <- fromJSON(content(response, "text", encoding = "UTF-8"), flatten = TRUE) - success <- TRUE # Si la requête réussit, sortir de la boucle - return(data) + # Récupération des données JSON + page_data <- fromJSON(content(response, "text", encoding = "UTF-8"), flatten = TRUE) + + # Si aucune donnée n'est renvoyée, arrêt de la récupération pour ce projet + if (length(page_data) == 0) { + message("Aucune donnée sur la page ", page, ". Fin de la récupération pour ce projet.") + break + } + # Ajouter les données de la page à all_data + all_data <- append(all_data, list(page_data)) + success <- TRUE # Succès de la récupération }, error = function(e) { retries <- retries + 1 message("Erreur de connexion, tentative: ", retries, ". Détails: ", e$message) - Sys.sleep(2 * retries) # Attendre avant de réessayer + Sys.sleep(2 * retries) }) } - if (!success) { - stop("Echec de récupération des données après ", max_retries, " tentatives.") + # Vérification de la présence d'une page suivante dans l'en-tête "Link" + link_header <- headers(response)[["link"]] + if (is.null(link_header) || !grepl("rel=\"next\"", link_header)) { + message("Pas de page suivante. Fin de la récupération pour ce projet.") + break } - } - # Initialiser la récupération des données avec la première page - first_page_data <- get_page(1) + # Passer à la page suivante + page <- page + 1 + } - # Vérifier s'il y a plusieurs pages en analysant l'en-tête "Link" - link_header <- headers(response)[["link"]] - if (!is.null(link_header) && str_detect(link_header, "rel=\"next\"")) { - # Trouver le nombre total de pages dans l'en-tête - num_pages <- max(str_extract_all(link_header, "page=\\d+")[[1]] %>% str_remove_all("page=") %>% as.integer()) + # Combiner toutes les pages récupérées en un seul dataframe + return(bind_rows(all_data)) +} - # Utiliser lapply pour récupérer les pages suivantes - other_pages_data <- lapply(2:num_pages, get_page) - # Combiner toutes les pages de données - all_data <- bind_rows(first_page_data, bind_rows(other_pages_data)) - } else { - # Si une seule page, renvoyer seulement les données de la première page - all_data <- first_page_data - } - return(all_data) -} # Fonction pour extraire le nom du projet à partir de l'URL extract_project_name <- function(web_url) { - # Utiliser une expression régulière pour capturer le dernier segment significatif avant "/-/" str_extract(web_url, "(?<=/)[^/]+(?=/-/)") } -# Fonction pour récupérer les commits d'un projet GitLab -get_gitlab_commits <- function(base_url, project_id, private_token) { - api_url <- paste0(base_url, "/api/v4/projects/", project_id, "/repository/commits") - # Récupérer toutes les pages avec pagination - data <- get_all_pages(api_url, private_token) - - # Harmoniser les types de colonnes et sélectionner les colonnes pertinentes - data <- data %>% - mutate( - id = as.character(id), - project_name = as.character(project_id), - data_type = "commit", - discussion = message, - updated_at = committed_date - ) - return(data %>% select(project_name, data_type, discussion, updated_at)) -} - # Fonction pour récupérer les issues d'un projet GitLab get_gitlab_issues <- function(base_url, project_id, private_token) { api_url <- paste0(base_url, "/api/v4/projects/", project_id, "/issues") - - # Récupérer toutes les pages avec pagination data <- get_all_pages(api_url, private_token) - - # Harmoniser les types de colonnes et sélectionner les colonnes pertinentes data <- data %>% mutate( - id = as.character(id), - project_name = as.character(project_id), - data_type = "issue", - discussion = title + project_name = extract_project_name(web_url), + type = "issue", + message = title, + author = author.username ) - return(data %>% select(project_name, data_type, discussion, updated_at)) + return(data %>% select(project_name, type, message, updated_at, author)) } # Fonction pour récupérer et filtrer les events d'un projet GitLab get_gitlab_events <- function(base_url, project_id, private_token) { api_url <- paste0(base_url, "/api/v4/projects/", project_id, "/events") - - # Récupérer toutes les pages avec pagination data <- get_all_pages(api_url, private_token) - - # Garder seulement les événements où action_name est "commented on" - data <- data %>% mutate( - id = as.character(id), project_name = as.character(project_id), - data_type = if_else((is.na(target_type) | target_type == "") & as.character(action_name) == "joined", - as.character(action_name), - as.character(target_type)), - discussion = as.character(target_title), - updated_at = created_at + type = if_else((is.null(target_type) | target_type == "") | as.character(target_type) == "Issue" | as.character(action_name) == "joined", # remplecer par | as.ch(target-type)=="Issue" + as.character(action_name), + as.character(target_type)), + message = ifelse(as.character(target_type) == "WikiPage::Meta",target_title,note.body), + updated_at = created_at, + author = author.username ) %>% - filter(data_type != "" & !is.na(data_type)) - - - return(data %>% select(project_name, data_type, discussion, updated_at)) + left_join(name_gitlab, by = c("project_name" = "id")) %>% + mutate(project_name = name) %>% + select(-name) + return(data %>% select(project_name, type, message, updated_at, author)) } # Fonction pour récupérer les données d'un projet get_data_for_project <- function(base_url, project_id, private_token) { - commits_data <- tryCatch(get_gitlab_commits(base_url, project_id, private_token), error = function(e) NULL) issues_data <- tryCatch(get_gitlab_issues(base_url, project_id, private_token), error = function(e) NULL) events_data <- tryCatch(get_gitlab_events(base_url, project_id, private_token), error = function(e) NULL) - - # Combiner les résultats en un seul dataframe - return(bind_rows(commits_data, issues_data, events_data)) + return(bind_rows(issues_data, events_data)) } # Fonction pour traiter plusieurs projets avec lapply @@ -202,39 +195,79 @@ get_data_from_multiple_projects <- function(base_url, project_ids, private_token all_data <- lapply(project_ids, function(project_id) { get_data_for_project(base_url, project_id, private_token) }) - - # Combiner tous les dataframes en un seul return(bind_rows(all_data)) } -# Define the query parameters pour récupérer les projets -params <- list( - include_subgroups = "true", - per_page = 100 -) +get_project_topics <- function(base_url, project_id, private_token) { + api_url <- paste0(base_url, "/api/v4/projects/", project_id) + response <- GET(api_url, add_headers("PRIVATE-TOKEN" = private_token)) + + if (status_code(response) == 200) { + project_info <- fromJSON(content(response, "text", encoding = "UTF-8"), flatten = TRUE) + return(data.frame( + id = as.character(project_info$name), + topics = paste(project_info$topics, collapse = ", "), # Combine les topics en une chaîne de caractères + stringsAsFactors = FALSE + )) + } else { + warning("Impossible de récupérer les topics pour le projet ID: ", project_id, " - Code: ", status_code(response)) + return(data.frame( + id = project_id, + topics = NA, + stringsAsFactors = FALSE + )) + } +} +extract_before_at <- function(email) { + sub("@.*", "", email) +} +########################################################### +process_projects <- function(project_ids) { + result_list <- lapply(project_ids, function(project_id) { + # Récupérer les branches du projet + branch <- gl_list_branches(project_id)$name + + # Récupérer les commits pour chaque branche + branch_results <- lapply(branch, function(b) { + data <- gl_get_commits(project_id, ref_name = b, max_page = NA) + Sys.sleep(1) + data <- data %>% mutate(branche = b, project_id = project_id) + return(data) + }) + + # Combiner les résultats pour un seul projet + bind_rows(branch_results) + }) -# Fetch the projects avec pagination et retry -response <- GET( - "https://gitlab-forge.din.developpement-durable.gouv.fr/api/v4/groups/1013/projects", - add_headers(`PRIVATE-TOKEN` = Sys.getenv("GITLAB_COM_TOKEN")), - query = params, - timeout(120) # Timeout augmenté pour les projets -) + # Combiner tous les projets en un seul dataframe + final_result <- bind_rows(result_list) -# Parse the JSON content -projects <- content(response, as = "text", encoding = "UTF-8") %>% fromJSON() + # Ajouter une colonne pour indiquer les doublons (en excluant "branche" et "project_id") + final_result <- final_result %>% + mutate(is_duplicate = duplicated(select(., -c(branche, project_id)))) -# Extract the project IDs -project_ids <- projects$id + return(final_result) +} + +final_result <- process_projects(project_ids) +final_result$project_id <- as.character(final_result$project_id) +final_result <- final_result %>% left_join(name_gitlab, by = c("project_id" = "id")) %>% + mutate(project_name = name, type = "commit") %>% + select(-name) +final_result <- final_result %>% mutate(author = extract_before_at(committer_email)) +final_result <- final_result %>% rename( "updated_at" = 'committed_date' ) +ff <- final_result %>% filter(is_duplicate == FALSE) %>% select(project_name,type , message ,updated_at,author) +########################################################### + +# Récupérer les topics pour tous les projets +projects_topics <- bind_rows(lapply(project_ids, get_project_topics, base_url = base_url, private_token = private_token)) # Récupérer les données pour tous les projets all_data_forge <- get_data_from_multiple_projects(base_url, project_ids, private_token) -all_data_forge <- rename(all_data_forge, "type" = 'data_type',"message" = 'discussion') all_data_forge <- all_data_forge %>% - left_join(project_data, by = c("project_name" = "id")) %>% - mutate(project_name = name) %>% select(-name) %>% - dplyr::distinct() -# Afficher un aperçu des données combinées -# save.image("gitlab_forge.RData") + filter(!(is.na(all_data_forge$type) | is.na(all_data_forge$message)) | all_data_forge$type == "joined"|all_data_forge$type == "WikiPage::Meta") +all_data_forge <- bind_rows(ff,all_data_forge) +all_data_forge <- all_data_forge %>% + mutate(origine ="Gitlab_Forge") +all_data_forge <- left_join(all_data_forge, projects_topics, by = c("project_name" = "id")) save(all_data_forge, file = "gitlab_forge.RData") - diff --git a/global.R b/global.R index 39979328479f751ed16fe486c5daa17f5155e480..d35e2cbf44e6982971b1f5d0700edaff8302e403 100644 --- a/global.R +++ b/global.R @@ -1,6 +1,6 @@ # global ----- # les packages nécessaire - +library(stringr) library(gitlabr) library(DT) library(shiny) @@ -18,15 +18,29 @@ library(utils) library(lubridate) library(bizdays) library(shinyWidgets) +library(textclean) +library(stringi) # chargement des données (résultat du script "dev/script_chargement_rdata.R") load("github.RData") load("gitlab_forge.RData") load("gitlab.RData") +load("date_MAJ.RData") all_data <- bind_rows(all_data_gitlab, all_data_forge, combined_data) all_data$updated_at <- as.POSIXct(all_data$updated_at, format = ("%Y-%m-%dT%H:%M:%S")) -all_data <- all_data %>% mutate(message = paste0(type,sep = " : ",message)) +all_data <- all_data %>% mutate(message = paste0(type,sep = " : ",message), + categorie = case_when( + str_detect(project_name, "parcours_r") ~ "r-formation", + str_detect(project_name, "spyrales") ~ "spyrales", + TRUE ~ "autre" + )) +# transformation author ---- +all_data$author <- all_data$author %>% + tolower() %>% + stri_trans_general("Latin-ASCII") %>% + str_replace_all("[^a-z ]", "") +# transformation re_code ---- traduction <- c( "commit" = "Code", "DiffNote" = "Code", @@ -41,3 +55,7 @@ traduction <- c( "Milestone" = "Gestion de projet" ) all_data <- all_data %>% dplyr::mutate(re_code = dplyr::recode(type , !!!traduction)) + +#transformation message +all_data$message <- all_data$message %>% tolower() +min_all_data <- all_data %>% filter(str_detect(message,'commit : initial commit')) diff --git a/server.R b/server.R index ed07b45c333e6b41c6d34c95deb54c1353cc2d2f..90e2c87d46b24bc2179e0858e4943cd631b397b2 100644 --- a/server.R +++ b/server.R @@ -1,99 +1,118 @@ -server <- function(input, output, session) { # Ajout de `session` pour `updateSelectizeInput` +server <- function(input, output, session) { + r <- reactiveValues( + filteredData = all_data, + filteredByProject = all_data, # Étape intermédiaire filtrée par daterange et project_name + filteredTopics = NULL, + filteredProjects = NULL, + filteredAuthors = NULL, + filteredReCodes = NULL, + filteredCategories = NULL, + filteredByDate = NULL, + ) - # Initialisation des valeurs réactives - r <- reactiveValues(filteredData = NULL, filteredData2 = NULL) - - # Daterange ---- + # Filtrage par date et project_name uniquement observeEvent(input$daterange, { req(input$daterange) - r$filteredData <- all_data %>% - filter(updated_at >= as.Date(input$daterange[[1]]) & - updated_at <= as.Date(input$daterange[[2]])) - - # Initialiser filteredData2 avec les mêmes valeurs que filteredData - r$filteredData2 <- r$filteredData + r$filteredByDate <- all_data %>% + filter( + updated_at >= as.Date(input$daterange[[1]]) & + updated_at <= as.Date(input$daterange[[2]]) & + (if (length(input$project_name)) project_name %in% input$project_name else TRUE) + ) + updateFilters() # Mise à jour des choix basés sur le filtrage intermédiaire + }) - # Mettre à jour les choix de projets - updateSelectizeInput( - session, - inputId = "idprojet", - label = "Projet : ", - choices = unique(r$filteredData$project_name) - ) + # Mise à jour des autres filtres + observe({ + req(input$daterange) + r$filteredData <- r$filteredByDate %>% + filter( + (if (length(input$topics)) sapply(input$topics, function(t) grepl(t, topics)) %>% rowSums() > 0 else TRUE) & + (if (length(input$author)) author %in% input$author else TRUE) & + (if (length(input$re_code)) re_code %in% input$re_code else TRUE) & + (if (length(input$categorie)) categorie %in% input$categorie else TRUE) + ) + updateFilters() }) - # Affichage du bouton de réinitialisation ---- - output$button <- renderUI({ - actionButton_dsfr("reset_button", "Réinitialiser les projets") + # Fonction de mise à jour des choix pour les filtres + updateFilters <- reactive({ + # Basé sur les données filtrées par date et projet + updateSelectizeInput(session, "topics", choices = unique(r$filteredByDate$topics)%>% + 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ù) + .[. != ""] %>% # Supprime les chaînes vides + trimws() %>% # suppremie les espace avnt et apres + unique() , selected = input$topics) + updateSelectizeInput(session, "author", choices = unique(r$filteredByDate$author), selected = input$author) + updateSelectizeInput(session, "categorie", choices = unique(r$filteredByDate$categorie), selected = input$categorie) + + # Basé uniquement sur les données globales pour éviter que project_name soit affecté + updateSelectizeInput(session, "project_name", choices = sort(unique(r$filteredByDate$project_name)), selected = input$project_name) }) - # Réinitialisation de input$idprojet lorsque le bouton est cliqué ---- - observeEvent(input$reset_button, { - # Réinitialise la sélection de `idprojet` à vide - updateSelectizeInput( - session, - inputId = "idprojet", - selected = character(0) # Met à vide `input$idprojet` - ) - # Réinitialise `filteredData2` à toutes les données de `filteredData` - r$filteredData2 <- r$filteredData + # Réinitialisation des filtres + observeEvent(input$reset, { + r$filteredByDate <- all_data %>% + filter(updated_at >= as.Date(input$daterange[[1]]) & + updated_at <= as.Date(input$daterange[[2]])) + r$filteredData <- r$filteredByDate + updateSelectizeInput(session, "topics", selected = NULL) + updateSelectizeInput(session, "author", selected = NULL) + updateSelectizeInput(session, "categorie", selected = NULL) + updateFilters() }) + output$lien <- renderUI({ + projects_with_links <- r$filteredData %>% + filter(origine == "Gitlab_Forge" & project_name %in% input$project_name) - # Mise à jour de filteredData2 lorsque les projets sont sélectionnés/désélectionnés ---- - observeEvent(input$idprojet, { - if (is.null(input$idprojet) || length(input$idprojet) == 0) { - # Si aucun projet n'est sélectionné, afficher tous les projets - r$filteredData2 <- r$filteredData - } else { - # Sinon, filtrer par projets sélectionnés - r$filteredData2 <- r$filteredData %>% - filter(project_name %in% input$idprojet) + if (nrow(projects_with_links) == 0) { + return(NULL) # Aucun lien à afficher } - # Générer l'interface des liens pour chaque projet - output$lien <- renderUI({ - urls <- paste0("https://gitlab-forge.din.developpement-durable.gouv.fr/dreal-pdl/csd/", input$idprojet) - links <- lapply(seq_along(input$idprojet), function(i) { - a(href = urls[i], target = "_blank", input$idprojet[i]) - }) - do.call(tagList, c(links, list(br()))) + urls <- paste0("https://gitlab-forge.din.developpement-durable.gouv.fr/dreal-pdl/csd/", projects_with_links$project_name) + links <- lapply(seq_along(unique(projects_with_links$project_name)), function(i) { + a(href = urls[i], target = "_blank", projects_with_links$project_name[i]) }) + do.call(tagList, links) }) - # Graphique 1 basé sur filteredData ---- - output$filteredPlot <- plotly::renderPlotly({ + # Graphique interactif + output$filteredPlot2 <- plotly::renderPlotly({ req(r$filteredData) p <- ggplot2::ggplot(r$filteredData, ggplot2::aes(x = updated_at, y = as.factor(project_name))) + - ggplot2::geom_jitter(ggplot2::aes(color = re_code, text = paste(updated_at, message, sep = "\n")), - size = 3, alpha = 0.5, - height = 0, width = 0.75) + - ggplot2::labs(shape = "re_code", color = "re_code", x = "") + - ggplot2::scale_x_datetime(date_labels = "%d/%m", timezone = "Europe/Paris") + - gouvdown::theme_gouv() + - ggplot2::theme( - axis.text.x = ggplot2::element_text(angle = 0, hjust = 1), - axis.title.y = ggplot2::element_blank() - ) + - gouvdown::scale_color_gouv_discrete(palette = "pal_gouv_qual2") - - plotly::ggplotly(p, tooltip = "text") - }) - - # Graphique 2 basé sur filteredData2 ---- - output$filteredPlot2 <- plotly::renderPlotly({ - req(r$filteredData2) - p <- ggplot2::ggplot(r$filteredData2, 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) + - ggplot2::labs(shape = "re_code", color = "re_code", x = "") + + ggplot2::labs(shape = "Événement", color = "Événement", x = "") + ggplot2::scale_x_datetime(timezone = "Europe/Paris") + - gouvdown::theme_gouv() + + gouvdown::theme_gouv()+ ggplot2::theme( axis.text.x = ggplot2::element_text(angle = 0, hjust = 1), axis.title.y = ggplot2::element_blank() - ) + - gouvdown::scale_color_gouv_discrete(palette = "pal_gouv_qual2") + ) plotly::ggplotly(p, tooltip = "text") }) + + + output$table <- renderDataTable({ + req(r$filteredData) + datatable(r$filteredData , + options = list( + pageLength = 10, # Nombre de lignes affichées par page + lengthMenu = c(5, 10, 25, 50), # Choix du nombre de lignes + autoWidth = TRUE, # Ajuste automatiquement la largeur des colonnes + scrollX = TRUE, # Active le défilement horizontal + class = "display", # Ajoute du style CSS + rownames = FALSE, # Supprime les numéros de ligne, + searchHighlight = TRUE + ) + ) + }) + + + + + } diff --git a/ui.R b/ui.R index 1746958a6a5f98943ab052c1880d7bc014e058a9..5411578aa0bd77e044556d0ddd311d30b0ad0f28 100644 --- a/ui.R +++ b/ui.R @@ -1,4 +1,5 @@ -ui <- shinygouv::navbarPage_dsfr( # header & footer ------ +ui <- shinygouv::navbarPage_dsfr( + # header & footer ------ title = "Dataviz GitlabR", id = "nav", header = shinygouv::header_dsfr( @@ -16,32 +17,113 @@ ui <- shinygouv::navbarPage_dsfr( # header & footer ------ # First tab Projet --------- shinygouv::navbarPanel_dsfr( title = "Graphique des projets par durée", - htmltools::HTML("</div><div class=\"fr-m-2w\">"), + + htmltools::tags$head(tags$style(".fr-container { max-width: calc(100% - 2rem); }")), shinygouv::fluidRow_dsfr( - column_dsfr(2), - shinygouv::column_dsfr(4, shinygouv::dateRangeInput_dsfr( - inputId = "daterange", - label = "Sélectionnez une période :", - start = format(Sys.Date() - 7, format = "%Y-%m-%d"), - separator = "à" + shinygouv::column_dsfr( + 3, + shinygouv::dateRangeInput_dsfr( + inputId = "daterange", + label = "Sélectionnez une période :", + start = format(Sys.Date() - 7, format = "%Y-%m-%d"), + separator = "à" + ), + extra_class = "fr-mt-6w" + ), + shinygouv::column_dsfr( + 3, + selectizeInput( + inputId = "project_name", + label = "Projet : ", + choices = NULL, + multiple = TRUE + ),extra_class = "fr-mt-6w" + ), + column_dsfr( + 3, + selectizeInput( + inputId = "topics", + label = "Étiquette :", + choices = all_data$topics %>% + 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ù) + .[. != ""] %>% # Supprime les chaînes vides + trimws() %>% # suppremie les espace avnt et apres + unique() , + # Extrait les éléments uniques + multiple = TRUE + ),extra_class = "fr-mt-6w" + ), + column_dsfr( + 3, + selectizeInput( + inputId = "author", + label = "Auteur :", + choices = unique(str_to_title(replace_non_ascii(all_data$author))), + selected = NULL, + multiple = TRUE + ),extra_class = "fr-mt-6w" + ), + column_dsfr( + 3, + actionButton_dsfr("reset", "Réinitialiser les projets"), + extra_class = "fr-my-2w" + ), + column_dsfr( + 4, + checkboxGroupInput_dsfr( + inputId = "re_code", + label = "Type d'évènement :", + choices = unique(all_data$re_code), + inline = TRUE + ) ), - extra_class = "fr-my-6w"), - shinygouv::column_dsfr(4, - selectizeInput(inputId = "idprojet",label = "Projet : ", - choices = NULL, multiple = TRUE)), - column_dsfr(2), - column_dsfr(3), - column_dsfr(12,uiOutput("button")), - shinygouv::column_dsfr(9,uiOutput("lien"),extra_class = "fr-my-6w") + column_dsfr( + 4, + selectizeInput( + inputId = "categorie", + label = "Groupe: ", + choices = c( + "Autre" = "tous", + "Spyrales" = "spyrale", + "R Formation" = "github" + ), + selected = NULL, + multiple = TRUE + ) ), - tabsetPanel_dsfr("tableau_proj", - tabPanel_dsfr(id = "graph_input", title = "graphique par choix", - shinygouv::fluidRow_dsfr( - shinygouv::column_dsfr(12, plotly::plotlyOutput("filteredPlot2", height = "700px"), - extra_class = "fr-my-1w") + shinygouv::column_dsfr(9, uiOutput("lien"), extra_class = "fr-my-6w") + ), + tabsetPanel_dsfr( + "tableau_proj", + tabPanel_dsfr( + id = "graph_input", + title = "graphique par choix", + shinygouv::fluidRow_dsfr( + shinygouv::column_dsfr( + 12, + plotly::plotlyOutput("filteredPlot2", height = "700px"), + extra_class = "fr-my-1w" + ) - ) - )# tab graphique par choix ↑ - )#↑ tableau_proj + ) + ),# tab graphique par choix ↑ + tabPanel_dsfr( + id = "indicateur" , + title = "Indicateurs", + shinygouv::fluidRow_dsfr( + shinygouv::column_dsfr(12) + ) + ), + tabPanel_dsfr( + id = "table" , + title = "tableau", + shinygouv::fluidRow_dsfr( + shinygouv::column_dsfr(12, + DT::dataTableOutput("table")) + ) + ) + )#↑ tableau_proj )# ↑ Navbar )# ↑ UI