cjerzak commited on
Commit
8061733
·
verified ·
1 Parent(s): a0659af

Update app.R

Browse files
Files changed (1) hide show
  1. app.R +65 -44
app.R CHANGED
@@ -10,19 +10,26 @@ library(rnaturalearth)
10
  library(rnaturalearthdata)
11
  library(countrycode)
12
  library(ggplot2)
13
- library(ggiraph)
 
 
 
14
 
15
  # =============================
16
  # UI
17
  # =============================
18
  ui <- dashboardPage(
 
 
19
  skin = "black",
 
20
  dashboardHeader(
21
  title = span(
22
  style = "font-weight: 600; font-size: 18px;",
23
  "Country Representation"
24
  )
25
  ),
 
26
  dashboardSidebar(
27
  sidebarMenu(
28
  menuItem("Map Type", tabName = "cartogramTab", icon = icon("globe"))
@@ -38,21 +45,27 @@ ui <- dashboardPage(
38
  )
39
  )
40
  ),
 
41
  dashboardBody(
 
42
  tags$head(
43
  tags$link(
44
  href = "https://fonts.googleapis.com/css2?family=OCR+A+Extended&display=swap",
45
  rel = "stylesheet"
46
  ),
47
  tags$style(HTML("
 
48
  html, body, h1, h2, h3, h4, h5, h6, p, div, span, label, input, button, select,
49
  .box, .content-wrapper, .main-sidebar, .main-header .navbar, .main-header .logo,
50
  .sidebar-menu, .sidebar-menu li a, .sidebar-menu .fa {
51
  font-family: 'OCR A Extended', monospace !important;
52
  }
 
 
53
  .main-header .navbar {
54
  background: linear-gradient(to right, #3b6978, #204051) !important;
55
  }
 
56
  .main-header .logo {
57
  background: #1b2a2f !important;
58
  color: #ffffff !important;
@@ -60,23 +73,31 @@ ui <- dashboardPage(
60
  font-size: 18px;
61
  font-weight: 600;
62
  }
 
63
  .main-sidebar {
64
  background-color: #1b2a2f !important;
65
  }
 
66
  .sidebar-menu > li.active > a,
67
  .sidebar-menu > li:hover > a {
68
  background-color: #344e5c !important;
69
  border-left-color: #78cdd7 !important;
70
  color: #ffffff !important;
71
  }
 
 
72
  .sidebar-menu .fa {
73
  color: #78cdd7 !important;
74
  }
 
 
75
  .sidebar-menu > li > a {
76
  color: #b8c7ce !important;
77
  font-size: 15px;
78
  font-weight: 500;
79
  }
 
 
80
  .box {
81
  border-top: none !important;
82
  box-shadow: 0 4px 8px rgba(0,0,0,0.1);
@@ -87,14 +108,17 @@ ui <- dashboardPage(
87
  color: #fff;
88
  border-radius: 6px 6px 0 0;
89
  }
 
90
  .box .box-body {
91
  padding: 0 !important;
92
  }
 
93
  .small, small {
94
  font-size: 75%;
95
  }
96
  "))
97
  ),
 
98
  tabItems(
99
  tabItem(
100
  tabName = "cartogramTab",
@@ -103,15 +127,11 @@ ui <- dashboardPage(
103
  width = 12,
104
  title = strong("Global Leadership Project (GLP)"),
105
  solidHeader = TRUE,
 
106
  div(
107
  style = "height: 80vh; padding: 10px;",
108
  girafeOutput("cartogramPlot", width = "100%", height = "100%")
109
  )
110
- ),
111
- box(
112
- width = 12,
113
- title = "Country Details",
114
- verbatimTextOutput("countryDetails")
115
  )
116
  )
117
  )
@@ -124,7 +144,28 @@ ui <- dashboardPage(
124
  # =============================
125
  server <- function(input, output, session) {
126
 
127
- custom_iso_matches <- c("Kosovo" = "XKX", "Somaliland" = "SOM")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  rankings_data <- reactive({
129
  read_csv("CountryRepresentationRankings.csv", show_col_types = FALSE) %>%
130
  mutate(iso_a3 = countrycode(
@@ -135,24 +176,31 @@ server <- function(input, output, session) {
135
  ))
136
  })
137
 
 
138
  world_sf <- reactive({
139
  ne_countries(scale = "medium", returnclass = "sf") %>%
140
  dplyr::select(name, iso_a3, pop_est, geometry) %>%
141
- st_transform(crs = "ESRI:54009")
142
  })
143
 
 
144
  cartogram_sf <- reactive({
145
  merged_sf <- world_sf() %>%
146
  left_join(rankings_data(), by = "iso_a3")
147
- merged_sf[!is.na(merged_sf$Overall),]
 
 
148
  })
149
 
 
150
  output$cartogramPlot <- renderGirafe({
151
  req(input$indexChoice)
152
 
153
  plot_data <- cartogram_sf()
154
  index_col <- input$indexChoice
 
155
 
 
156
  plot_data$tooltip_text <- paste0(
157
  "<b>Country:</b> ", plot_data$Country, "<br/>",
158
  "<b>Overall:</b> ", ifelse(!is.na(plot_data$Overall), plot_data$Overall, "N/A"), "<br/>",
@@ -163,6 +211,7 @@ server <- function(input, output, session) {
163
  "<b>Language:</b> ", ifelse(!is.na(plot_data$Language), plot_data$Language, "N/A")
164
  )
165
 
 
166
  p <- ggplot(plot_data) +
167
  geom_sf_interactive(
168
  aes(
@@ -175,6 +224,8 @@ server <- function(input, output, session) {
175
  ) +
176
  scale_fill_viridis_c(option = "D", na.value = "white") +
177
  coord_sf(expand = FALSE) +
 
 
178
  theme_void(base_size = 14, base_family = "sans") +
179
  labs(
180
  fill = paste(index_col, "Index"),
@@ -191,52 +242,22 @@ server <- function(input, output, session) {
191
  legend.key.width = unit(2, "cm")
192
  )
193
 
 
194
  girafe(
195
  ggobj = p,
196
  width_svg = 10,
197
  height_svg = 6,
198
  options = list(
199
  opts_tooltip(
200
- css = "background-color: white;
201
- font-family: 'OCR A Extended', monospace;
202
  color: black;"
203
  ),
204
- opts_selection(
205
- type = "single",
206
- css = "stroke:yellow;stroke-width:2px;"
207
- )
208
  )
209
  )
210
  })
211
-
212
- selected_country_data <- reactive({
213
- selected_iso <- input$cartogramPlot_selected
214
- if (length(selected_iso) == 0) {
215
- return(NULL)
216
- }
217
- plot_data <- cartogram_sf()
218
- country_data <- plot_data %>% filter(iso_a3 == selected_iso)
219
- if (nrow(country_data) == 0) {
220
- return(NULL)
221
- }
222
- country_data
223
- })
224
-
225
- output$countryDetails <- renderText({
226
- country_data <- selected_country_data()
227
- if (is.null(country_data)) {
228
- return("Click on a country to see details.")
229
- }
230
- paste0(
231
- "Country: ", country_data$Country, "\n",
232
- "Overall: ", ifelse(is.na(country_data$Overall), "N/A", country_data$Overall), "\n",
233
- "Representation Gap: ", ifelse(is.na(country_data$RepresentationGap), "N/A", country_data$RepresentationGap), "\n",
234
- "Ethnicity: ", ifelse(is.na(country_data$Ethnicity), "N/A", country_data$Ethnicity), "\n",
235
- "Gender: ", ifelse(is.na(country_data$Gender), "N/A", country_data$Gender), "\n",
236
- "Religion: ", ifelse(is.na(country_data$Religion), "N/A", country_data$Religion), "\n",
237
- "Language: ", ifelse(is.na(country_data$Language), "N/A", country_data$Language)
238
- )
239
- })
240
  }
241
 
242
  # =============================
 
10
  library(rnaturalearthdata)
11
  library(countrycode)
12
  library(ggplot2)
13
+ library(ggiraph) # For interactive hover tooltips
14
+ #library(extrafont)
15
+ #font_import() # run
16
+ #loadfonts() # load the fonts into R session
17
 
18
  # =============================
19
  # UI
20
  # =============================
21
  ui <- dashboardPage(
22
+
23
+ # Use black skin for the dashboard
24
  skin = "black",
25
+
26
  dashboardHeader(
27
  title = span(
28
  style = "font-weight: 600; font-size: 18px;",
29
  "Country Representation"
30
  )
31
  ),
32
+
33
  dashboardSidebar(
34
  sidebarMenu(
35
  menuItem("Map Type", tabName = "cartogramTab", icon = icon("globe"))
 
45
  )
46
  )
47
  ),
48
+
49
  dashboardBody(
50
+ # Bring in the OCR A Extended font from Google Fonts
51
  tags$head(
52
  tags$link(
53
  href = "https://fonts.googleapis.com/css2?family=OCR+A+Extended&display=swap",
54
  rel = "stylesheet"
55
  ),
56
  tags$style(HTML("
57
+ /* Force OCR A Extended font across the entire UI and all HTML elements */
58
  html, body, h1, h2, h3, h4, h5, h6, p, div, span, label, input, button, select,
59
  .box, .content-wrapper, .main-sidebar, .main-header .navbar, .main-header .logo,
60
  .sidebar-menu, .sidebar-menu li a, .sidebar-menu .fa {
61
  font-family: 'OCR A Extended', monospace !important;
62
  }
63
+
64
+ /* Header gradient background */
65
  .main-header .navbar {
66
  background: linear-gradient(to right, #3b6978, #204051) !important;
67
  }
68
+ /* Logo area (left corner of the header) */
69
  .main-header .logo {
70
  background: #1b2a2f !important;
71
  color: #ffffff !important;
 
73
  font-size: 18px;
74
  font-weight: 600;
75
  }
76
+ /* Sidebar background */
77
  .main-sidebar {
78
  background-color: #1b2a2f !important;
79
  }
80
+ /* Active or hovered tab in the sidebar */
81
  .sidebar-menu > li.active > a,
82
  .sidebar-menu > li:hover > a {
83
  background-color: #344e5c !important;
84
  border-left-color: #78cdd7 !important;
85
  color: #ffffff !important;
86
  }
87
+
88
+ /* Sidebar menu item icons */
89
  .sidebar-menu .fa {
90
  color: #78cdd7 !important;
91
  }
92
+
93
+ /* Sidebar menu item text */
94
  .sidebar-menu > li > a {
95
  color: #b8c7ce !important;
96
  font-size: 15px;
97
  font-weight: 500;
98
  }
99
+
100
+ /* Customize the boxes */
101
  .box {
102
  border-top: none !important;
103
  box-shadow: 0 4px 8px rgba(0,0,0,0.1);
 
108
  color: #fff;
109
  border-radius: 6px 6px 0 0;
110
  }
111
+ /* Plot box spacing */
112
  .box .box-body {
113
  padding: 0 !important;
114
  }
115
+ /* Footer text styling (plot captions, etc.) */
116
  .small, small {
117
  font-size: 75%;
118
  }
119
  "))
120
  ),
121
+
122
  tabItems(
123
  tabItem(
124
  tabName = "cartogramTab",
 
127
  width = 12,
128
  title = strong("Global Leadership Project (GLP)"),
129
  solidHeader = TRUE,
130
+ # Use girafeOutput instead of plotOutput
131
  div(
132
  style = "height: 80vh; padding: 10px;",
133
  girafeOutput("cartogramPlot", width = "100%", height = "100%")
134
  )
 
 
 
 
 
135
  )
136
  )
137
  )
 
144
  # =============================
145
  server <- function(input, output, session) {
146
 
147
+ # Reactive value to store the currently clicked country
148
+ clicked_country <- reactiveVal(NULL)
149
+
150
+ # Observe clicks on the map
151
+ observeEvent(input$cartogramPlot_selected, {
152
+ selected_id <- input$cartogramPlot_selected
153
+ current_clicked <- clicked_country()
154
+
155
+ if (identical(selected_id, current_clicked)) {
156
+ # Unclick: set clicked_country to NULL
157
+ clicked_country(NULL)
158
+ } else {
159
+ # Click new country: update clicked_country
160
+ clicked_country(selected_id)
161
+ }
162
+ }, ignoreNULL = FALSE)
163
+
164
+ # 1. Custom matches for countries not recognized by default in 'countrycode'
165
+ custom_iso_matches <- c("Kosovo" = "XKX",
166
+ "Somaliland" = "SOM") # or any valid code you prefer
167
+
168
+ # 2. Read CSV data and create ISO3 codes with custom matches
169
  rankings_data <- reactive({
170
  read_csv("CountryRepresentationRankings.csv", show_col_types = FALSE) %>%
171
  mutate(iso_a3 = countrycode(
 
176
  ))
177
  })
178
 
179
+ # 3. Read/prepare world map shapefile
180
  world_sf <- reactive({
181
  ne_countries(scale = "medium", returnclass = "sf") %>%
182
  dplyr::select(name, iso_a3, pop_est, geometry) %>%
183
+ st_transform(crs = "ESRI:54009") # Mollweide projection
184
  })
185
 
186
+ # 4. Create the joined sf object (currently just a regular map)
187
  cartogram_sf <- reactive({
188
  merged_sf <- world_sf() %>%
189
  left_join(rankings_data(), by = "iso_a3")
190
+ # Filter out rows with missing 'Overall', if you want to exclude them
191
+ merged_sf <- merged_sf[!is.na(merged_sf$Overall),]
192
+ merged_sf
193
  })
194
 
195
+ # 5. Render the interactive map with ggiraph
196
  output$cartogramPlot <- renderGirafe({
197
  req(input$indexChoice)
198
 
199
  plot_data <- cartogram_sf()
200
  index_col <- input$indexChoice
201
+ selected_country_id <- clicked_country()
202
 
203
+ # Build a tooltip string: customize to your preference
204
  plot_data$tooltip_text <- paste0(
205
  "<b>Country:</b> ", plot_data$Country, "<br/>",
206
  "<b>Overall:</b> ", ifelse(!is.na(plot_data$Overall), plot_data$Overall, "N/A"), "<br/>",
 
211
  "<b>Language:</b> ", ifelse(!is.na(plot_data$Language), plot_data$Language, "N/A")
212
  )
213
 
214
+ # Use geom_sf_interactive with aes() + get() instead of aes_string()
215
  p <- ggplot(plot_data) +
216
  geom_sf_interactive(
217
  aes(
 
224
  ) +
225
  scale_fill_viridis_c(option = "D", na.value = "white") +
226
  coord_sf(expand = FALSE) +
227
+ # Use a generic base_family to avoid font errors
228
+ #theme_void(base_size = 14, base_family = "Courier New") +
229
  theme_void(base_size = 14, base_family = "sans") +
230
  labs(
231
  fill = paste(index_col, "Index"),
 
242
  legend.key.width = unit(2, "cm")
243
  )
244
 
245
+ # Wrap the ggplot in a girafe object, including tooltip styling and click handling
246
  girafe(
247
  ggobj = p,
248
  width_svg = 10,
249
  height_svg = 6,
250
  options = list(
251
  opts_tooltip(
252
+ css = "background-color: white;
253
+ font-family: 'OCR A Extended', monospace;
254
  color: black;"
255
  ),
256
+ opts_selection(type = "single", selected = selected_country_id),
257
+ opts_zoom(max = 5)
 
 
258
  )
259
  )
260
  })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
  }
262
 
263
  # =============================