Skip to content

Commit

Permalink
start larger demo
Browse files Browse the repository at this point in the history
  • Loading branch information
DivadNojnarg committed Nov 12, 2023
1 parent 48150dd commit 00eaf9f
Show file tree
Hide file tree
Showing 7 changed files with 337 additions and 0 deletions.
35 changes: 35 additions & 0 deletions inst/showcase/app.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
library(shiny)
library(shinyNextUI)
library(echarts4r)
library(dplyr)

#sapply(list.files(
# "inst/showcase/modules",
# #system.file("showcase/modules", package = "shinyNextUI"),
# full.names = TRUE
#), source)

ui <- nextui_page(
dark_mode = TRUE,
mod_poke_select_ui("poke_select_1"),
spacer(y = 5),
div(
class = "flex flex-row",
mod_poke_info_ui("poke_info_1"),
mod_poke_evolve_ui("poke_evolve_1")
),
spacer(y = 5),
mod_poke_stats_ui("poke_stats_1"),
spacer(y = 5),
mod_poke_location_ui("poke_location_1")
)

server <- function(input, output, session) {
main <- mod_poke_select_server("poke_select_1")
mod_poke_info_server("poke_info_1", main$selected, main$is_shiny)
mod_poke_evolve_server("poke_evolve_1", main$selected, main$is_shiny)
mod_poke_stats_server("poke_stats_1", main$selected)
mod_poke_location_server("poke_location_1", main$selected)
}

shinyApp(ui, server)
41 changes: 41 additions & 0 deletions inst/showcase/modules/mod_poke_evolve.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
mod_poke_evolve_ui <- function(id) {
ns <- NS(id)
uiOutput(ns("poke_evolve"))
}

mod_poke_evolve_server <- function(id, selected, is_shiny) {
moduleServer(id, function(input, output, session) {

# treat data and generate the timeline
output$poke_evolve <- renderUI({
req(!is.null(selected()))
evol <- selected()$evolve_from

# If pokemon can't evolve ...
if (length(evol) == 0) {
tags$div(
tags$p("Base Pokemon"),
)
} else {
# Check that the evolution belongs to the first 151 pkmns ...
if (evol$id <= 151) {
tags$div(
tags$p("Evolves From"),
image(
src = if (is_shiny()) {
poke_data[[evol$id]]$sprites$front_shiny
} else {
poke_data[[evol$id]]$sprites$front_default
},
)
)
} else {
tags$div(
tags$p("Not first generation"),
)
}
}

})
})
}
26 changes: 26 additions & 0 deletions inst/showcase/modules/mod_poke_info.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
mod_poke_info_ui <- function(id) {
ns <- NS(id)
uiOutput(ns("poke_infos"))
}

mod_poke_info_server <- function(id, selected, is_shiny) {
moduleServer(id, function(input, output, session) {

# generate the profile cards (as many as the number of selected pokemons)
output$poke_infos <- renderUI({
req(!is.null(selected()))

pokemon <- selected()

card(
avatar(src = if (!is_shiny()) {
pokemon$sprites$front_default
} else {
pokemon$sprites$front_shiny
}, size = "lg"),
chip(pokemon$shape),
chip(pokemon$habitat, color = pokemon$color)
)
})
})
}
36 changes: 36 additions & 0 deletions inst/showcase/modules/mod_poke_location.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
mod_poke_location_ui <- function(id) {
ns <- NS(id)
uiOutput(ns("poke_locations"))
}

mod_poke_location_server <- function(id, selected) {
moduleServer(id, function(input, output, session) {
ns <- session$ns

output$poke_locations <- renderUI({
req(!is.null(selected()))

locations <- selected()$locations

if (is.null(locations)) {
location_content <- "This pokemon cannot be found in the wild."
} else {
location_content <- listbox(
class = "w-full max-w-[260px] border-small px-1 py-2 rounded-small border-default-200 dark:border-default-100",
inputId = "locations",
selectionMode = "none",
variant = "bordered",
lapply(locations, \(loc) {
listbox_item(
key = loc,
title = loc
)
})
)
}

location_content
})

})
}
56 changes: 56 additions & 0 deletions inst/showcase/modules/mod_poke_select.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
mod_poke_select_ui <- function(id) {
poke_names <- names(poke_data)
poke_sprites <- vapply(
lapply(poke_data, `[[`, "sprites"),
`[[`,
"front_default",
FUN.VALUE = character(1)
)

items <- lapply(poke_names, function(pokemon) {
autocomplete_item(
key = pokemon,
value = pokemon,
startContent = avatar(src = poke_sprites[[pokemon]]),
pokemon
)
})

ns <- NS(id)
div(
class = "flex flex-row",
autocomplete(
inputId = ns("selected"),
label = "Select a pokemon:",
items,
value = poke_names[[1]]
),
spacer(x = 5),
# because it's a shiny app ;)
switch_input(
inputId = ns("is_shiny"),
label = "Shiny?",
value = TRUE,
color = "danger"
)
)
}

mod_poke_select_server <- function(id) {
moduleServer(id, function(input, output, session) {
ns <- session$ns

# WORKSHOP TODO
# Add user feedback to select_pokemon
selected_pokemon <- eventReactive(input$selected, {
poke_data[[input$selected]]
})

return(
list(
selected = selected_pokemon,
is_shiny = reactive(input$is_shiny)
)
)
})
}
142 changes: 142 additions & 0 deletions inst/showcase/modules/mod_poke_stats.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
other_stats_names <- function() {
names(poke_data[[1]]$other_stats)
}

extra_from_list <- function(l, key = "name", type = character(1)) {
vapply(
l,
`[[`,
key,
FUN.VALUE = type
)
}

get_max_stats <- function(stat = NULL) {
res <- lapply(
poke_data,
function(data) {
stats <- data$stats
tmp <- extra_from_list(
stats,
"base_stat",
numeric(1)
)
names(tmp) <- extra_from_list(stats)
tmp
}
)

# Merge lists into tibble
res <- do.call(rbind, res) |>
as_tibble()
if (is.null(stat)) res else pull(res, stat)
}

get_max_of_max <- function(data = get_max_stats()) {
cols <- colnames(data)
data |>
# get max of each stat
summarise(across(all_of(cols), max)) |>
rowwise() |>
# Max of max
max()
}

create_radar_stats <- function(pokemon) {
# R CMD check stop crying ...
x <- y <- z <- NULL

stats <- pokemon$stats
# Prepare data
data <- process_pokemon_stats(stats)

# Also adds previous pokemon stats to compare
# Check that the evolution belongs to the first 151 pkmns ...
if (length(pokemon$evolve_from) > 0 && pokemon$evolve_from$id <= 151) {
tmp <- process_pokemon_stats(
poke_data[[pokemon$evolve_from$name]]$stats
)
data$z <- tmp$y
data |>
e_charts(x) |>
e_radar(
y,
name = paste0(pokemon$name, " Stats"),
max = get_max_of_max()
) |>
e_radar(z, name = paste0(pokemon$evolve_from$name, " Stats")) |>
e_tooltip(trigger = "item")
} else {
data |>
e_charts(x) |>
e_radar(y, name = paste0(pokemon$name, " Stats"), max = get_max_of_max()) |>
e_tooltip(trigger = "item")
}
}

process_pokemon_stats <- function(stats) {
data.frame(
x = extra_from_list(stats),
y = extra_from_list(stats, "base_stat", numeric(1))
)
}


mod_poke_stats_ui <- function(id) {
ns <- NS(id)
tagList(
div(
class = "grid grid-cols-4 gap-4",
lapply(other_stats_names(), function(stat) {
uiOutput(ns(stat))
})
),
spacer(y = 2),
uiOutput(ns("poke_stats_card"))
)
}

mod_poke_stats_server <- function(id, selected) {
moduleServer(id, function(input, output, session) {
ns <- session$ns

# Programmatically generate stat cards
lapply(other_stats_names(), function(stat) {
output[[stat]] <- renderUI({
req(input$poke_basic_stats)
val <- selected()$other_stats[[stat]]

card(
card_header(h1(stat)),
card_body(val)
)
})
})

# Generate radar chart for pokemons
output$poke_stats <- renderEcharts4r({
req(!is.null(selected()))
create_radar_stats(selected())
})

# card wrapper for the charts
output$poke_stats_card <- renderUI({
req(!is.null(selected()))

card(
card_header(
class = "flex flex-row",
h1(paste0(selected()$name, " Stats")),
switch_input(
inputId = ns("poke_basic_stats"),
label = "Display Basic Stats?",
color = "warning"
)
),
divider(),
card_footer(tags$strong(sprintf("Sum of stats: %s (Mew is 500)", selected()$sum_stats))),
card_body(echarts4rOutput(outputId = ns("poke_stats")))
)
})
})
}
1 change: 1 addition & 0 deletions js/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module.exports = {
// ...
"./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}",
"../inst/examples/**/*.R",
"../inst/showcase/modules/*.R",
"../R/*.R"
],
extract: {
Expand Down

0 comments on commit 00eaf9f

Please sign in to comment.