|
options(error = NULL) |
|
library(shiny) |
|
library(shinydashboard) |
|
library(dplyr) |
|
library(readr) |
|
library(sf) |
|
|
|
library(ggplot2) |
|
library(rnaturalearth) |
|
library(rnaturalearthdata) |
|
library(countrycode) |
|
|
|
|
|
|
|
|
|
ui <- dashboardPage( |
|
|
|
|
|
skin = "black", |
|
|
|
dashboardHeader( |
|
title = span( |
|
style = "font-weight: 600; font-size: 18px;", |
|
"Country Representation" |
|
) |
|
), |
|
|
|
dashboardSidebar( |
|
sidebarMenu( |
|
menuItem("Map Type", tabName = "cartogramTab", icon = icon("globe")) |
|
), |
|
div( |
|
style = "margin: 15px;", |
|
selectInput( |
|
inputId = "indexChoice", |
|
label = "Select Representation Index:", |
|
choices = c("Overall", "RepresentationGap", "Ethnicity", |
|
"Gender", "Religion", "Language"), |
|
selected = "Overall" |
|
) |
|
) |
|
), |
|
|
|
dashboardBody( |
|
|
|
tags$head( |
|
tags$link( |
|
href = "https://fonts.googleapis.com/css2?family=OCR+A+Extended&display=swap", |
|
rel = "stylesheet" |
|
), |
|
tags$style(HTML(" |
|
/* Force OCR A Extended font across the entire UI and all HTML elements */ |
|
html, body, h1, h2, h3, h4, h5, h6, p, div, span, label, input, button, select, |
|
.box, .content-wrapper, .main-sidebar, .main-header .navbar, .main-header .logo, |
|
.sidebar-menu, .sidebar-menu li a, .sidebar-menu .fa { |
|
font-family: 'OCR A Extended', monospace !important; |
|
} |
|
|
|
/* Header gradient background */ |
|
.main-header .navbar { |
|
background: linear-gradient(to right, #3b6978, #204051) !important; |
|
} |
|
|
|
/* Logo area (left corner of the header) */ |
|
.main-header .logo { |
|
background: #1b2a2f !important; |
|
color: #ffffff !important; |
|
border-bottom: none; |
|
font-size: 18px; |
|
font-weight: 600; |
|
} |
|
|
|
/* Sidebar background */ |
|
.main-sidebar { |
|
background-color: #1b2a2f !important; |
|
} |
|
|
|
/* Active or hovered tab in the sidebar */ |
|
.sidebar-menu > li.active > a, |
|
.sidebar-menu > li:hover > a { |
|
background-color: #344e5c !important; |
|
border-left-color: #78cdd7 !important; |
|
color: #ffffff !important; |
|
} |
|
|
|
/* Sidebar menu item icons */ |
|
.sidebar-menu .fa { |
|
color: #78cdd7 !important; |
|
} |
|
|
|
/* Sidebar menu item text */ |
|
.sidebar-menu > li > a { |
|
color: #b8c7ce !important; |
|
font-size: 15px; |
|
font-weight: 500; |
|
} |
|
|
|
/* Customize the boxes */ |
|
.box { |
|
border-top: none !important; |
|
box-shadow: 0 4px 8px rgba(0,0,0,0.1); |
|
border-radius: 6px; |
|
} |
|
.box.box-solid > .box-header { |
|
background-color: #204051; |
|
color: #fff; |
|
border-radius: 6px 6px 0 0; |
|
} |
|
|
|
/* Plot box spacing */ |
|
.box .box-body { |
|
padding: 0 !important; |
|
} |
|
|
|
/* Footer text styling (plot captions, etc.) */ |
|
.small, small { |
|
font-size: 75%; |
|
} |
|
")) |
|
), |
|
|
|
tabItems( |
|
tabItem( |
|
tabName = "cartogramTab", |
|
fluidRow( |
|
box( |
|
width = 12, |
|
title = strong("Global Leadership Project (GLP)"), |
|
solidHeader = TRUE, |
|
div(style = "height: 80vh; padding: 10px;", |
|
plotOutput("cartogramPlot", height = "100%") |
|
) |
|
) |
|
) |
|
) |
|
) |
|
) |
|
) |
|
|
|
|
|
|
|
|
|
server <- function(input, output, session) { |
|
|
|
|
|
rankings_data <- reactive({ |
|
read_csv("CountryRepresentationRankings.csv") %>% |
|
mutate(iso_a3 = countrycode(Country, origin = "country.name", destination = "iso3c")) |
|
}) |
|
|
|
|
|
world_sf <- reactive({ |
|
ne_countries(scale = "medium", returnclass = "sf") %>% |
|
dplyr::select(name, iso_a3, pop_est, geometry) %>% |
|
st_transform(crs = "ESRI:54009") |
|
}) |
|
|
|
|
|
cartogram_sf <- reactive({ |
|
merged_sf <- world_sf() %>% |
|
left_join(rankings_data(), by = "iso_a3") |
|
|
|
merged_sf <- merged_sf[!is.na(merged_sf$Overall),] |
|
return(merged_sf) |
|
}) |
|
|
|
|
|
output$cartogramPlot <- renderPlot({ |
|
req(input$indexChoice) |
|
|
|
index_col <- input$indexChoice |
|
plot_data <- cartogram_sf() |
|
|
|
ggplot(plot_data) + |
|
geom_sf(aes_string(fill = index_col), color = "grey20", size = 0.1) + |
|
scale_fill_viridis_c(option = "D", na.value = "white") + |
|
coord_sf(expand = FALSE) + |
|
|
|
|
|
theme_void(base_size = 14, base_family = "Courier New") + |
|
labs( |
|
fill = paste(index_col, "Index"), |
|
title = "Country Representation Rankings", |
|
subtitle = "Map Colored by Selected Representation Index", |
|
caption = "Source: Global Leadership Project (GLP) & Natural Earth" |
|
) + |
|
theme( |
|
plot.title = element_text(face = "bold", hjust = 0.5, size = 20), |
|
plot.subtitle = element_text(hjust = 0.5, size = 14), |
|
plot.caption = element_text(hjust = 1, size = 10), |
|
legend.position = "bottom", |
|
legend.direction = "horizontal", |
|
legend.key.width = unit(2, "cm") |
|
) |
|
}) |
|
} |
|
|
|
|
|
|
|
|
|
shinyApp(ui = ui, server = server) |
|
|
|
|