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

Update app.R

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