diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..991c663
Binary files /dev/null and b/.DS_Store differ
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3a31c70
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+.Rproj.user
+.Rhistory
+.RData
+.Ruserdata
+.rds
+mapboxtoken_setup.R
\ No newline at end of file
diff --git a/Images/.DS_Store b/Images/.DS_Store
new file mode 100644
index 0000000..5008ddf
Binary files /dev/null and b/Images/.DS_Store differ
diff --git a/Images/green-job-mapping-logo-small.png b/Images/green-job-mapping-logo-small.png
new file mode 100644
index 0000000..5ad1a5e
Binary files /dev/null and b/Images/green-job-mapping-logo-small.png differ
diff --git a/Images/green-job-mapping-logo.png b/Images/green-job-mapping-logo.png
new file mode 100644
index 0000000..c1f88b8
Binary files /dev/null and b/Images/green-job-mapping-logo.png differ
diff --git a/README.md b/README.md
index 8ca0026..f35f327 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
-README
+README: CCRC Green Job Mapping
================
+
+
## Overview
docs for Mapbox GL JS :
@@ -8,6 +10,10 @@ docs for Mapbox GL JS :
This app built for Hover function for demand side, we will use the US
county population to have a try!
+
+
+---
+
## Data used for the app
data folder, private:
@@ -15,11 +21,19 @@ data folder, private:
Downlaod the data folder,rename it as raw-data.
+
+
+---
+
## Raw data used to create the data used for the app
`pre-county-population.R` is used to create fake “demand” side data,
which is US county level population data from tidycensus package.
+
+
+---
+
## Wei update the app on Feb 18th.
UI_app.R and www/mapbox-script.JS are main files for the app.
@@ -28,4 +42,9 @@ APP website:https://ed-analytics.shinyapps.io/CCRC_Mapping_JS/
To run this app locally, set up the map token as a source file.
-The hover UI: 
+
+---
+
+## The hover UI
+
+
diff --git a/UI_app.R b/UI_app.R
deleted file mode 100644
index 64e5fdc..0000000
--- a/UI_app.R
+++ /dev/null
@@ -1,140 +0,0 @@
-library(shiny)
-library(jsonlite)
-library(geojsonio)
-library(dplyr)
-source("mapboxtoken_setup.R")
-
-# Load data
-hdallyears <- readRDS("hdallyears.rds")
-ipeds_green_summed <- readRDS("ipeds_green_summed.rds")
-counties_sf <- readRDS("counties_sf_processed.rds")
-
-# Ensure GeoJSON data has unique IDs for feature-state
-counties_sf <- counties_sf %>%
- mutate(id = row_number()) # Assign unique IDs to each county
-
-# Merge data
-hdallyears_joined <- hdallyears %>%
- left_join(ipeds_green_summed, by = "unitid")
-
-# UI
-ui <- fluidPage(
- titlePanel("CCRC Green Job Seek Mapping"),
-
- # The entire page is divided into left and right columns:
- fluidRow(
- # Left: supply category selector, 3/12 of width
- column(3,
- wellPanel(
- selectInput("selected_green_category",
- "Select Supply Category:",
- choices = c("Green New & Emerging",
- "Green Enhanced Skills",
- "Green Increased Demand"))
- )
- ),
- # Right side: search controls above, map below, 9/12ths of width
- column(9,
- wellPanel(
- fluidRow(
- column(8,
- textInput("search_term", "Search by Institution:",
- placeholder = "Type institution here...", width = "100%")
- ),
- column(4,
- div(style = "margin-top: 25px;",
- actionButton("search_btn", "Search"),
- # The clearMap() function on the front-end using HTML button binding
- tags$button("Clear", onclick = "clearMap()",
- style = "margin-left: 10px;", class = "btn btn-default")
- )
- )
- )
- ),
- # Map area
- div(id = "map", style = "height: 700px;")
- )
- ),
-
- # footers
- fluidRow(
- column(
- 12, align = "center",
- tags$footer(
- style = "margin-top: 20px; padding: 10px; font-size: 12px; background-color: #f8f9fa; border-top: 1px solid #e9ecef;",
- HTML("Created by Wei Wang, Joshua Rosenberg, Cameron Sublet and Bret Staudt Willet with the Community College Research Center at Teachers College, Columbia.
- Source code at: GitHub.
- Thanks to funding from JC Morgan Chase.")
- )
- )
- ),
-
- # Introducing Mapbox GL JS Resources and Custom JS Files
- tags$head(
- tags$link(href = "https://api.mapbox.com/mapbox-gl-js/v2.14.1/mapbox-gl.css", rel = "stylesheet"),
- tags$script(src = "https://api.mapbox.com/mapbox-gl-js/v2.14.1/mapbox-gl.js"),
- tags$script(src = "mapbox-script.js"),
- tags$script(HTML(paste0("const mapboxToken = '", mapbox_token, "';")))
- )
-)
-
-
-
-# Server
-server <- function(input, output, session) {
- # Save counties_sf data to reactiveValues
- map_data <- reactiveValues(
- county_data = counties_sf
- )
-
- # Convert counties_sf to GeoJSON and send to front end
- observe({
- if (!inherits(map_data$county_data, "sf")) {
- stop("map_data$county_data must be an sf object")
- }
-
- counties_geojson <- geojsonio::geojson_json(map_data$county_data)
-
- # Debug: output partial GeoJSON data
- print("Sending GeoJSON data to frontend")
- print(substr(counties_geojson, 1, 500))
-
- session$sendCustomMessage(type = "updateCounties", counties_geojson)
- })
-
- # Search button: find records based on the entered school name and selected supply category
- observeEvent(input$search_btn, {
- req(input$search_term)
- req(input$selected_green_category)
-
- # Filter data by school name (instnm) and supply category (greencat)
- search_result <- hdallyears_joined %>%
- filter(grepl(input$search_term, instnm, ignore.case = TRUE),
- greencat == input$selected_green_category) %>%
- head(1)
-
- if (nrow(search_result) > 0) {
- # Constructing the HTML content of the popup window: displaying the name of the school, the selected category, and the size value
- popup_text <- paste0(
- "", search_result$instnm, "
",
- "Category: ", input$selected_green_category, "
",
- "Size: ", search_result$size
- )
- coords <- list(
- lng = search_result$longitud,
- lat = search_result$latitude,
- popup = popup_text
- )
- # Send search results to the front end
- session$sendCustomMessage(type = "updateSearch", coords)
- } else {
- showNotification("No Institution Found!", type = "error")
- }
- })
-
-
- # Note: The Clear button calls the front-end clearMap() function directly in the UI.
- # So there's no need for an additional observeEvent to handle the Clear button here.
-}
-
-shinyApp(ui, server)
diff --git a/app.R b/app.R
deleted file mode 100644
index 5c384e5..0000000
--- a/app.R
+++ /dev/null
@@ -1,132 +0,0 @@
-library(shiny)
-library(jsonlite)
-library(geojsonio)
-library(dplyr)
-
-# Load data
-hdallyears <- readRDS("hdallyears.rds")
-ipeds_green_summed <- readRDS("ipeds_green_summed.rds")
-counties_sf <- readRDS("counties_sf_processed.rds")
-
-# Ensure GeoJSON data has unique IDs for feature-state
-counties_sf <- counties_sf %>%
- mutate(id = row_number()) # Assign unique IDs to each county
-
-# Merge data
-hdallyears_joined <- hdallyears %>%
- left_join(ipeds_green_summed, by = "unitid")
-
-# UI
-ui <- fluidPage(
- titlePanel("CCRC Mapping with Mapbox GL JS"),
-
- fluidRow(
- column(
- width = 10,
- div(
- style = "display: flex; align-items: center;",
- textInput("search_term", "Search by Institution:",
- placeholder = "Type institution here...", width = "100%"),
- actionButton("search_btn", "Search", style = "margin-left: 10px;"),
- # Use HTML buttons and bind the clearMap() function directly to the frontend.
- tags$button("Clear", onclick = "clearMap()", style = "margin-left: 10px;", class = "btn btn-default")
- )
- )
- ),
-
- fluidRow(
- column(6, align = "center",
- selectInput("selected_green_category",
- "Select Supply Category:",
- choices = c("Green New & Emerging", "Green Enhanced Skills", "Green Increased Demand"))
- )
- ),
-
-
-
- # Map output with JavaScript integration
- fluidRow(
- column(12, tags$div(id = "map", style = "height: 700px;"))
- ),
-
- # Include Mapbox GL JS resources and our custom JS file
- tags$head(
- tags$link(href = "https://api.mapbox.com/mapbox-gl-js/v2.14.1/mapbox-gl.css", rel = "stylesheet"),
- tags$script(src = "https://api.mapbox.com/mapbox-gl-js/v2.14.1/mapbox-gl.js"),
- tags$script(src = "mapbox-script.js"),
- tags$script(HTML(paste0("const mapboxToken = '", Sys.getenv("MAPBOX_TOKEN"), "';")))
- ),
-
- fluidRow(
- column(
- width = 12, align = "center",
- tags$footer(
- style = "margin-top: 20px; padding: 10px; font-size: 12px; background-color: #f8f9fa; border-top: 1px solid #e9ecef;",
- HTML("Created by Wei Wang, Joshua Rosenberg, and Cameron Sublet at the University of Tennessee, Knoxville with the Community College Research Center at Teachers College, Columbia.
- Source code at: GitHub.
- Thanks to funding from JC Morgan Chase.")
- )
- )
- )
-
-
-)
-
-
-
-# Server
-server <- function(input, output, session) {
- # Save counties_sf data to reactiveValues
- map_data <- reactiveValues(
- county_data = counties_sf
- )
-
- # Convert counties_sf to GeoJSON and send to front end
- observe({
- if (!inherits(map_data$county_data, "sf")) {
- stop("map_data$county_data must be an sf object")
- }
-
- counties_geojson <- geojsonio::geojson_json(map_data$county_data)
-
- # Debug: output partial GeoJSON data
- print("Sending GeoJSON data to frontend")
- print(substr(counties_geojson, 1, 500))
-
- session$sendCustomMessage(type = "updateCounties", counties_geojson)
- })
-
- # Search button: find records based on the entered school name and selected supply category
- observeEvent(input$search_btn, {
- req(input$search_term)
- req(input$selected_green_category)
-
- # Filter data by school name (instnm) and supply category (greencat)
- search_result <- hdallyears_joined %>%
- filter(grepl(input$search_term, instnm, ignore.case = TRUE),
- greencat == input$selected_green_category) %>%
- head(1)
-
- if (nrow(search_result) > 0) {
- # Constructing the HTML content of the popup window: displaying the name of the school, the selected category, and the size value
- popup_text <- paste0(
- "", search_result$instnm, "
",
- "Category: ", input$selected_green_category, "
",
- "Size: ", search_result$size
- )
- coords <- list(
- lng = search_result$longitud,
- lat = search_result$latitude,
- popup = popup_text
- )
- # Send search results to the front end
- session$sendCustomMessage(type = "updateSearch", coords)
- } else {
- showNotification("No Institution Found!", type = "error")
- }
- })
- # Note: The Clear button calls the front-end clearMap() function directly in the UI.
- # So there's no need for an additional observeEvent to handle the Clear button here.
-}
-
-shinyApp(ui, server)
diff --git a/data/counties_sf_processed.rds b/data/counties_sf_processed.rds
new file mode 100644
index 0000000..075c847
Binary files /dev/null and b/data/counties_sf_processed.rds differ
diff --git a/data/hdallyears.rds b/data/hdallyears.rds
new file mode 100644
index 0000000..0e0e2ab
Binary files /dev/null and b/data/hdallyears.rds differ
diff --git a/data/ipeds_green_summed.rds b/data/ipeds_green_summed.rds
new file mode 100644
index 0000000..a97dacd
Binary files /dev/null and b/data/ipeds_green_summed.rds differ
diff --git a/pre-county-population.R b/pre-county-population.R
index e9c1615..f320e28 100644
--- a/pre-county-population.R
+++ b/pre-county-population.R
@@ -7,12 +7,13 @@ library(tidyverse)
library(haven)
library(tidycensus)
-county_population <- get_acs(
- geography = "county",
- variables = "B01003_001E", # Total population variable
- year = 2021,
- survey = "acs5" # 5-year data
-)
+county_population <-
+ get_acs(
+ geography = "county",
+ variables = "B01003_001E", # Total population variable
+ year = 2021,
+ survey = "acs5" # 5-year data
+ )
head(county_population)
@@ -46,7 +47,7 @@ counties_sf_size2 <- st_transform(counties_sf_size1, crs = 4326)
#counties_sf_size2 <- counties_sf_size2 %>%
#as_mapbox_source()
-counties_sf_size2 %>% write_rds("counties_sf_processed.rds")
+counties_sf_size2 %>% write_rds("data/counties_sf_processed.rds")
@@ -62,7 +63,7 @@ ipeds_green_summed <- ipeds_green %>%
ipeds_green_summed <- ipeds_green_summed %>%
pivot_longer(-unitid, names_to = "greencat", values_to = "size")
-write_rds(ipeds_green_summed, "ipeds_green_summed.rds")
+write_rds(ipeds_green_summed, "data/ipeds_green_summed.rds")
@@ -71,4 +72,4 @@ hdallyears <- read_dta("raw-data/hdallyears.dta")
hdallyears <- hdallyears %>%
filter(year == 2020)
-write_rds(hdallyears, "hdallyears.rds")
\ No newline at end of file
+write_rds(hdallyears, "data/hdallyears.rds")
\ No newline at end of file
diff --git a/server.R b/server.R
new file mode 100644
index 0000000..0063fd2
--- /dev/null
+++ b/server.R
@@ -0,0 +1,83 @@
+library(dplyr)
+library(geojsonio)
+library(jsonlite)
+
+
+
+################################################################################
+
+# Load data
+hdallyears <- readRDS("data/hdallyears.rds")
+ipeds_green_summed <- readRDS("data/ipeds_green_summed.rds")
+counties_sf <- readRDS("data/counties_sf_processed.rds")
+
+# Ensure GeoJSON data has unique IDs for feature-state
+counties_sf <-
+ counties_sf %>%
+ mutate(id = row_number()) # Assign unique IDs to each county
+
+# Merge data
+hdallyears_joined <-
+ hdallyears %>%
+ left_join(ipeds_green_summed, by = "unitid")
+
+
+
+################################################################################
+
+function(input, output, session) {
+ # Save counties_sf data to reactiveValues
+ map_data <-
+ reactiveValues(
+ county_data = counties_sf
+ )
+
+ # Convert counties_sf to GeoJSON and send to front end
+ observe({
+ if (!inherits(map_data$county_data, "sf")) {
+ stop("map_data$county_data must be an sf object")
+ }
+
+ counties_geojson <- geojsonio::geojson_json(map_data$county_data)
+
+ # Debug: output partial GeoJSON data
+ print("Sending GeoJSON data to frontend")
+ print(substr(counties_geojson, 1, 500))
+
+ session$sendCustomMessage(type = "updateCounties", counties_geojson)
+ })
+
+ # Search button: find records based on the entered school name and selected supply category
+ observeEvent(input$search_btn, {
+ req(input$search_term)
+ req(input$selected_green_category)
+
+ # Filter data by school name (instnm) and supply category (greencat)
+ search_result <- hdallyears_joined %>%
+ filter(grepl(input$search_term, instnm, ignore.case = TRUE),
+ greencat == input$selected_green_category) %>%
+ head(1)
+
+ if (nrow(search_result) > 0) {
+ # Constructing the HTML content of the popup window: displaying the name of the school, the selected category, and the size value
+ popup_text <- paste0(
+ "", search_result$instnm, "
",
+ "Category: ", input$selected_green_category, "
",
+ "Size: ", search_result$size
+ )
+ coords <- list(
+ lng = search_result$longitud,
+ lat = search_result$latitude,
+ popup = popup_text
+ )
+ # Send search results to the front end
+ session$sendCustomMessage(type = "updateSearch", coords)
+ } else {
+ showNotification("No Institution Found!", type = "error")
+ }
+ })
+
+
+ # Note: The Clear button calls the front-end clearMap() function directly in the UI.
+ # So there's no need for an additional observeEvent to handle the Clear button here.
+}
\ No newline at end of file
diff --git a/styles.css b/styles.css
new file mode 100644
index 0000000..0d7a367
--- /dev/null
+++ b/styles.css
@@ -0,0 +1,125 @@
+/* import Google fonts */
+@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap');
+
+@import url('https://fonts.googleapis.com/css2?family=Exo:ital,wght@0,100..900;1,100..900&display=swap');
+
+
+input[type="number"] {
+ max-width: 80%;
+}
+
+
+
+/* Customize the navbar background and font */
+.navbar {
+ background-color: #eeeae8; /* Change to your desired background color */
+}
+
+.navbar-brand {
+ font-family: 'Exo', sans-serif; /* Change to your desired font family */
+ color: #424c49; /* Change the font color */
+ font-size: 28px; /* Change the font size */
+}
+
+.navbar-nav > li > a.active,
+.navbar-nav > li.active > a,
+.navbar-nav > li > a:hover,
+.navbar-nav > li > a:focus {
+ background-color: #99ea85 !important; /* Change the hover and focus color */
+ font-weight: 600 !important;
+}
+
+/* Ensures the brand text and image align properly */
+.navbar-header .navbar-brand {
+ display: flex;
+ align-items: center;
+}
+
+.navbar-header .navbar-brand img {
+ margin-right: 6px; /* Space between the logo and the text */
+}
+
+
+
+
+div.outer {
+ position: fixed;
+ top: 42px;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ overflow: hidden;
+ padding: 0;
+}
+
+
+
+/* Customize fonts */
+body, label, input, button, select {
+ font-family: 'Roboto', sans-serif;
+ font-weight: 300;
+ font-size: 14px;
+ color: #424c49;
+}
+
+title, h1, h2 {
+ font-family: 'Exo', serif;
+ font-weight: 600;
+}
+
+h3, h4 {
+ font-family: 'Exo', serif;
+ font-weight: 400;
+}
+
+
+
+/* change hyperlink text */
+a {
+ color: #0645ad; /* standard blue hyperlink color */
+ font-weight: 400;
+}
+
+/* change hyperlink hover text */
+a:hover {
+ color: #e04300;
+ text-decoration: underline;
+}
+
+
+
+#controls {
+ /* Appearance */
+ background-color: #99ea85;
+ border: 1px solid #beb0a7;
+ padding: 0 20px 20px 20px;
+ cursor: move;
+ /* Fade out while not hovering */
+ opacity: 0.7;
+ zoom: 0.8;
+ transition: opacity 200ms 600ms;
+}
+
+#controls:hover {
+ /* Fade in while hovering */
+ opacity: 0.95;
+ transition-delay: 0;
+}
+
+/* Position and style footer */
+.footer {
+ font-size: 14px;
+ background-color: #eeeae8;
+ padding: 0px 20px;
+ width: 100%;
+ text-align: center;
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ border-top: 1px solid #beb0a7;
+}
+
+/* If not using map tiles, show a white background */
+.mapbox-container {
+ background-color: white !important;
+}
diff --git a/ui.R b/ui.R
new file mode 100644
index 0000000..dba8ed4
--- /dev/null
+++ b/ui.R
@@ -0,0 +1,136 @@
+source("mapboxtoken_setup.R")
+
+
+
+################################################################################
+## Navigation bar at top of window
+################################################################################
+
+navbarPage(
+
+ tags$head(
+ includeCSS("styles.css")
+ ),
+
+ title =
+ div(
+ img(src = "green-job-mapping-logo-small.png",
+ height = "28px"),
+ "CCRC Green Jobs Mapping"
+ ),
+ id="nav",
+
+
+################################################################################
+## First tab: Window for interactive map
+################################################################################
+
+ tabPanel("Interactive Map",
+ div(class="outer",
+ div(id = "map", style = "height: 100%;"),
+
+
+
+################################################################################
+## Floating panel for input controls
+################################################################################
+
+ absolutePanel(id = "controls",
+ class = "panel panel-default",
+ fixed = TRUE,
+ draggable = TRUE,
+ top = 60, left = "auto", right = 20, bottom = "auto",
+ width = 360, height = "auto",
+
+ h2("Green Jobs Explorer"),
+
+ selectInput("selected_green_category",
+ "Select Supply Category:",
+ choices = c("Green New & Emerging",
+ "Green Enhanced Skills",
+ "Green Increased Demand")
+ ),
+ textInput("search_term", "Search by Institution:",
+ placeholder = "Type institution here...",
+ width = "100%"
+ ),
+ actionButton("search_btn", "Search"),
+ tags$button("Clear", onclick = "clearMap()",
+ style = "margin-left: 10px;", class = "btn btn-default"
+ )
+ ),
+ )
+ ),
+
+
+
+
+
+
+################################################################################
+## Second Tab
+################################################################################
+
+ tabPanel("Background",
+ img(src = "green-job-mapping-logo-small.png",
+ height = "60px"),
+ h2("About the CCRC Green Jobs Mapping App"),
+ fluidRow(
+ column(3,
+ selectInput("states", "States", c("All states"="", structure(state.abb, names=state.name), "Washington, DC"="DC"), multiple=TRUE)
+ ),
+ column(3,
+ conditionalPanel("input.states",
+ selectInput("cities", "Cities", c("All cities"=""), multiple=TRUE)
+ )
+ ),
+ column(3,
+ conditionalPanel("input.states",
+ selectInput("zipcodes", "Zipcodes", c("All zipcodes"=""), multiple=TRUE)
+ )
+ )
+ ),
+ fluidRow(
+ column(1,
+ numericInput("minScore", "Min score", min=0, max=100, value=0)
+ ),
+ column(1,
+ numericInput("maxScore", "Max score", min=0, max=100, value=100)
+ )
+ )
+ ),
+
+
+
+################################################################################
+## Citation at bottom of window
+################################################################################
+
+ tags$footer(
+ class = "footer",
+ tags$p("Created by Wei Wang, Joshua Rosenberg, Cameron Sublet, and Bret Staudt Willet,",
+ "with the",
+ tags$a(href="https://ccrc.tc.columbia.edu/", "Community College Research Center"),
+ "at Teachers College, Columbia."),
+ tags$p("Source code on",
+ tags$a(href="https://github.com/wwang93/CCRC_Mapping_JS", "GitHub."),
+ "Thanks to funding from JC Morgan Chase."
+ )
+ ),
+
+
+
+
+################################################################################
+## Introducing Mapbox GL JS Resources and Custom JS Files
+################################################################################
+
+ tags$head(
+ tags$link(href = "https://api.mapbox.com/mapbox-gl-js/v2.14.1/mapbox-gl.css", rel = "stylesheet"),
+ tags$script(src = "https://api.mapbox.com/mapbox-gl-js/v2.14.1/mapbox-gl.js"),
+ tags$script(src = "mapbox-script.js"),
+ tags$script(HTML(paste0("const mapboxToken = '", mapbox_token, "';")))
+ )
+
+
+)
\ No newline at end of file
diff --git a/www/green-job-mapping-logo-small.png b/www/green-job-mapping-logo-small.png
new file mode 100644
index 0000000..5ad1a5e
Binary files /dev/null and b/www/green-job-mapping-logo-small.png differ