Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix v1.1.0 #117

Merged
merged 90 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from 81 commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
51203b0
fix #89 - fix colors for regions in trend plot
mvarewyck Apr 16, 2024
091adc8
version bump
mvarewyck Apr 16, 2024
70483ab
fix #87 - include descriptive legend gam
mvarewyck Apr 22, 2024
ca45a26
fix #89 - fix colors for regions in trend plot
mvarewyck Apr 16, 2024
747f1d7
version bump
mvarewyck Apr 16, 2024
760facd
fix #87 - include descriptive legend gam
mvarewyck Apr 22, 2024
171b12c
Merge branch 'fix_v1.1.0' of
mvarewyck Apr 25, 2024
34652bc
fix #87 - run R CMD check
mvarewyck Apr 25, 2024
92be270
fix #87 - dynamic title for GAM
mvarewyck Apr 25, 2024
b6b3b8c
fix #85 - remove year slider
mvarewyck Apr 25, 2024
d95f503
fix inbo/aspbo#121 - update code to handle split translations
mvarewyck Apr 26, 2024
8179801
fix #59 - include link to report missing data
mvarewyck Apr 29, 2024
2050475
fix #83 - allow custom bins
mvarewyck Apr 30, 2024
fe3019c
fix #83 - allow user-defined bins WIP
mvarewyck Apr 30, 2024
b474ed1
fix #83 - keep current bin values WIP
mvarewyck May 2, 2024
bd0616b
fix #83 - allow custom bins
mvarewyck May 21, 2024
f04a9d3
fix #83 - allow custom bins in UI + R CMD check
mvarewyck May 27, 2024
e751a22
fix #89 - fix colors for regions in trend plot
mvarewyck Apr 16, 2024
e3fd7da
version bump
mvarewyck Apr 16, 2024
51533ac
fix #87 - include descriptive legend gam
mvarewyck Apr 22, 2024
0641f6b
fix #87 - include descriptive legend gam
mvarewyck Apr 22, 2024
a020589
fix #87 - run R CMD check
mvarewyck Apr 25, 2024
8541929
fix #85 - remove year slider
mvarewyck Apr 25, 2024
825cef9
fix #59 - include link to report missing data
mvarewyck Apr 29, 2024
393f515
fix #83 - allow custom bins
mvarewyck Apr 30, 2024
35564f3
fix #83 - allow user-defined bins WIP
mvarewyck Apr 30, 2024
8ffc994
fix #83 - keep current bin values WIP
mvarewyck May 2, 2024
2337c4e
fix #83 - allow custom bins
mvarewyck May 21, 2024
c15ad71
fix #83 - allow custom bins in UI + R CMD check
mvarewyck May 27, 2024
99a930c
Merge branch 'fix_v1.1.0' of
mvarewyck May 27, 2024
f1be8e8
fix inbo/aspbo#165 - draft to populate the links page
mvarewyck May 30, 2024
d7bca4f
fix #73 - move invasion maps in tests WIP
mvarewyck Jun 10, 2024
12e64d0
fix #aspbo/165 - include links to files on uat
mvarewyck Jul 4, 2024
e8f6e3f
fix #aspbo/165 - include links to files on uat
mvarewyck Jul 4, 2024
7b8afce
fix inbo/aspbo#165 - links folder defined by git branch
mvarewyck Jul 5, 2024
690f340
Merge branch 'fix_v1.1.0' of
mvarewyck Jul 5, 2024
ed35d3f
fix #105 - include harmonia links
mvarewyck Jul 9, 2024
476f72e
fix #73 - invasion plots on indicators page - WIP tmp data
mvarewyck Jul 11, 2024
861f9fd
fix #106 - duplicate columns after rework timeseries
mvarewyck Jul 19, 2024
4cc0a36
R CMD check
mvarewyck Aug 23, 2024
9e645d7
fix #109 - display actual gbifkey in taxa table
mvarewyck Sep 11, 2024
6bd16d1
fix #109 - update gbif links
mvarewyck Sep 12, 2024
2eaa137
fix #89 - fix colors for regions in trend plot
mvarewyck Apr 16, 2024
1be588c
version bump
mvarewyck Apr 16, 2024
d47a03b
fix #87 - include descriptive legend gam
mvarewyck Apr 22, 2024
13f1625
fix #87 - include descriptive legend gam
mvarewyck Apr 22, 2024
a1e4249
fix #87 - run R CMD check
mvarewyck Apr 25, 2024
78a7e88
fix #85 - remove year slider
mvarewyck Apr 25, 2024
4272a10
fix #59 - include link to report missing data
mvarewyck Apr 29, 2024
82c41ac
fix #83 - allow custom bins
mvarewyck Apr 30, 2024
4c316e5
fix #83 - allow user-defined bins WIP
mvarewyck Apr 30, 2024
b9c97bf
fix #83 - keep current bin values WIP
mvarewyck May 2, 2024
35dae9b
fix #83 - allow custom bins
mvarewyck May 21, 2024
b05c941
fix #83 - allow custom bins in UI + R CMD check
mvarewyck May 27, 2024
64304ef
version bump
mvarewyck Apr 16, 2024
a4f3a97
fix #87 - include descriptive legend gam
mvarewyck Apr 22, 2024
e2cae1b
fix #87 - include descriptive legend gam
mvarewyck Apr 22, 2024
a9a95a6
fix #87 - dynamic title for GAM
mvarewyck Apr 25, 2024
2202235
fix #85 - remove year slider
mvarewyck Apr 25, 2024
7c0e27d
fix #59 - include link to report missing data
mvarewyck Apr 29, 2024
1fa06ed
fix #83 - allow custom bins
mvarewyck Apr 30, 2024
c6547b2
fix #83 - allow user-defined bins WIP
mvarewyck Apr 30, 2024
8596db5
fix #83 - keep current bin values WIP
mvarewyck May 2, 2024
b8dd6bc
fix #83 - allow custom bins
mvarewyck May 21, 2024
46849f7
fix #83 - allow custom bins in UI + R CMD check
mvarewyck May 27, 2024
20fed33
fix inbo/aspbo#165 - draft to populate the links page
mvarewyck May 30, 2024
bb39178
fix #73 - move invasion maps in tests WIP
mvarewyck Jun 10, 2024
a5cb9bd
fix #aspbo/165 - include links to files on uat
mvarewyck Jul 4, 2024
995a578
fix inbo/aspbo#165 - links folder defined by git branch
mvarewyck Jul 5, 2024
b4ed99a
fix #105 - include harmonia links
mvarewyck Jul 9, 2024
3ac69f6
fix #73 - invasion plots on indicators page - WIP tmp data
mvarewyck Jul 11, 2024
68a74ea
fix #106 - duplicate columns after rework timeseries
mvarewyck Jul 19, 2024
eff95ea
R CMD check
mvarewyck Aug 23, 2024
70e8b28
fix #109 - display actual gbifkey in taxa table
mvarewyck Sep 11, 2024
c9a718b
fix #109 - update gbif links
mvarewyck Sep 12, 2024
92d5b81
resolve merging conflicts
mvarewyck Sep 26, 2024
d9d2083
Merge branch 'fix_v1.1.0' of
mvarewyck Sep 27, 2024
ed29395
make temporary fix work for be_alientaxa_cube_processed.RData
mvarewyck Sep 27, 2024
4fec9e9
fix #118 - catch error if nBins is too large
mvarewyck Sep 27, 2024
d01ae81
Merge branch 'fix_v1.1.0' of
mvarewyck Sep 27, 2024
e2cb9ec
fix #117 - trigger facet plot when creating report
mvarewyck Sep 27, 2024
7ef98d6
fix #117 - harmonia link in risk assessment tab and change label url
mvarewyck Oct 2, 2024
880e732
fix #117 - update createBins: fixed legend + improve interactivity
mvarewyck Oct 7, 2024
51663ed
Merge branch 'uat' into fix_v1.1.0
SanderDevisscher Oct 8, 2024
aeb0c93
fix #123 - include translations for indicator_native_range_year()
mvarewyck Oct 23, 2024
0bc4920
index on fix_v1.1.0: aeb0c93 fix #123 - include translations for indi…
mvarewyck Oct 24, 2024
f9a75c0
wip - flexible labels for createBins
mvarewyck Oct 24, 2024
870a8b4
fix #117 - show harmonia or webpage
mvarewyck Oct 24, 2024
8942416
fix #117 - better reactivity createBins
mvarewyck Oct 25, 2024
c5b9699
Merge remote-tracking branch 'origin/createBins' into fix_v1.1.0
mvarewyck Oct 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions alienSpecies/DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Package: alienSpecies
Type: Package
Title: Portal for alien and invasive species indicators
Version: 1.0.1
Date: 2023-11-30
Version: 1.1.0
Date: 2024-04-16
Author: Machteld Varewyck, Yingjie Zhang, Eva Adriaensen
Maintainer: Machteld Varewyck <[email protected]>
Description: INBO shiny application based on the TRIAS package.
Expand Down Expand Up @@ -37,13 +37,13 @@ Imports:
testthat (>= 3.0.0),
tidyr,
tidyverse,
trias (>= 2.0.8),
trias (>= 2.1.0),
webshot2,
xtable
Suggests:
shinyjs
RoxygenNote: 7.3.1
Remotes:
inbo/[email protected],
trias-project/trias@v2.0.8
trias-project/trias@v2.1.0
Config/testthat/edition: 3
10 changes: 10 additions & 0 deletions alienSpecies/NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export(countOccurrence)
export(countYearGroup)
export(countYearGroupServer)
export(countYearGroupUI)
export(createBins)
export(createBinsServer)
export(createBinsUI)
export(createCubeData)
export(createDoubleChoices)
export(createKeyData)
Expand All @@ -34,9 +37,13 @@ export(drawBullet)
export(filterCombo)
export(filterSelectServer)
export(filterSelectUI)
export(footerSectionServer)
export(footerSectionUI)
export(getGbifOccurrence)
export(getPathLogo)
export(getRegionNames)
export(htmlSectionServer)
export(htmlSectionUI)
export(loadGbif)
export(loadMetaData)
export(loadOccupancyData)
Expand Down Expand Up @@ -147,7 +154,9 @@ importFrom(dplyr,summarise)
importFrom(dplyr,ungroup)
importFrom(ggplot2,ggsave)
importFrom(ggspatial,annotation_map_tile)
importFrom(graphics,barplot)
importFrom(htmltools,div)
importFrom(htmltools,includeHTML)
importFrom(htmlwidgets,saveWidget)
importFrom(httr,GET)
importFrom(httr,http_status)
Expand Down Expand Up @@ -187,6 +196,7 @@ importFrom(shinycssloaders,withSpinner)
importFrom(stats,aggregate)
importFrom(stats,as.formula)
importFrom(stats,complete.cases)
importFrom(stats,quantile)
importFrom(terra,rast)
importFrom(terra,values)
importFrom(testthat,test_file)
Expand Down
5 changes: 1 addition & 4 deletions alienSpecies/R/app_modules.R
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ tableModuleUI <- function(id, includeTotal = FALSE) {
#' @import shiny
#' @importFrom utils write.table tail
#' @importFrom DT datatable formatRound renderDT
#' @importFrom plotly ggplotly layout
#' @export
plotModuleServer <- function(id, plotFunction, data, uiText = NULL,
outputType = NULL, triasFunction = NULL, triasArgs = NULL, groupChoices = NULL,
Expand Down Expand Up @@ -156,12 +155,10 @@ plotModuleServer <- function(id, plotFunction, data, uiText = NULL,

timeRange <- range(data()$first_observed, na.rm = TRUE)

div(class = "sliderBlank",
sliderInput(inputId = ns("period"),
sliderInput(inputId = ns("period"),
label = translate(uiText(), "period")$title,
min = timeRange[1], max = timeRange[2], value = timeRange,
step = 1, sep = "", width = "100%")
)

})

Expand Down
143 changes: 141 additions & 2 deletions alienSpecies/R/app_sections.R
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,94 @@ welcomeSectionUI <- function(id) {
}


#' Shiny module for creating footer section - server side
#' @inheritParams welcomeSectionServer
#' @return reactive for creating the report
#'
#' @author mvarewyck
#' @import shiny
#' @export
footerSectionServer <- function(id, uiText) {

moduleServer(id, function(input, output, session) {

ns <- session$ns

## SUBMIT & DOWNLOAD report ##

observe({

updateActionButton(inputId = "createReport",
label = translate(data = uiText, id = "createReport")$title)

})


## REPORT missing and CONTACT ##
observeEvent(input$contact, {

showModal(
modalDialog(
title = "Contact",
footer = modalButton(label = NULL, icon = icon("xmark")),
easyClose = TRUE,

tags$h5(translate(data = uiText, "contactMissing"), ":"),
tags$a(href = "https://waarnemingen.be/fieldwork/observations/create/", target="_blank",
"https://waarnemingen.be/fieldwork/observations/create/"),
tags$br(),
tags$a(href = "https://www.inaturalist.org/observations/upload", target = "_blank",
"https://www.inaturalist.org/observations/upload"),
tags$h5(translate(data = uiText, "contactApp"), ":"),
tags$a(href="mailto:[email protected]?subject=Alien%20species%20web%20applicatie&body=**Describe%20the%20bug**%0AA%20clear%20and%20concise%20description%20of%20what%20the%20bug%20is.%0A%0A**To%20Reproduce**%0ASteps%20to%20reproduce%20the%20behavior%3A%0A1.%20Go%20to%20%27...%27%0A2.%20Click%20on%20%27....%27%0A3.%20Scroll%20down%20to%20%27....%27%0A4.%20See%20error%0A%0A**Expected%20behavior**%0AA%20clear%20and%20concise%20description%20of%20what%20you%20expected%20to%20happen.%0A%0A**Screenshots**%0AIf%20applicable%2C%20add%20screenshots%20to%20help%20explain%20your%20problem.%0A%0A**Desktop%20%28please%20complete%20the%20following%20information%29%3A**%0A%20-%20OS%3A%20%5Be.g.%20iOS%5D%0A%20-%20Browser%20%5Be.g.%20chrome%2C%20safari%5D%0A%20-%20Version%20%5Be.g.%2022%5D%0A%0A**Smartphone%20%28please%20complete%20the%20following%20information%29%3A**%0A%20-%20Device%3A%20%5Be.g.%20iPhone6%5D%0A%20-%20OS%3A%20%5Be.g.%20iOS8.1%5D%0A%20-%20Browser%20%5Be.g.%20stock%20browser%2C%20safari%5D%0A%20-%20Version%20%5Be.g.%2022%5D%0A%0A**Additional%20context**%0AAdd%20any%20other%20context%20about%20the%20problem%20here.", target="_blank",
"[email protected]")
)
)


})

return(reactive(input$createReport))


})

}

#' #' Shiny module for creating footer section - UI side
#' @param id character, unique identifier
#' @param showReport boolean, whether to show a button to download report
#' @return no return value
#'
#' @author mvarewyck
#' @import shiny
#' @export
footerSectionUI <- function(id, showReport = FALSE) {

ns <- NS(id)

tags$div(style = "margin-bottom: 70px;",

tags$div(class = "footer",
tags$div(class = "footer-content",

actionButton(inputId = ns("contact"), label = "Contact",
icon = icon("envelope")),

if (showReport)
tagList(
singleton(
tags$head(tags$script(src = "triggerDownload.js"))
),
actionButton(inputId = ns("createReport"), label = "Create report",
icon = icon("file-pdf")),
downloadLink(ns("downloadReport"), " ", class = "invisible")
)
)
)
)

}

#' Replace {{fields}} in title/description translations
#' @param text character, input from translation
Expand All @@ -64,8 +152,8 @@ decodeText <- function(text, params) {
for (iParam in names(params)) {

newText <- if (iParam == "period")
paste(newText, yearToTitleString(params[[iParam]])) else
gsub(paste0("\\{\\{", iParam, "\\}\\}"), params[[iParam]], newText)
paste(newText, yearToTitleString(params[[iParam]])) else
gsub(paste0("\\{\\{", iParam, "\\}\\}"), params[[iParam]], newText)

}

Expand Down Expand Up @@ -129,3 +217,54 @@ versionServer <- function(id, uiText) {

})
}


#' Shiny module for including html file - server side
#' @param id character, unique identifier
#' @param species reactive object, taxonkey for the selected species
#' @param language reactive object, language for UI content
#' @param url character, url to be displayed
#' @return no return value
#'
#' @author mvarewyck
#' @importFrom htmltools includeHTML
#' @export
htmlSectionServer <- function(id, species, language, url) {

moduleServer(id, function(input, output, session) {

output$addLinks <- renderUI({

dataPath <- file.path("https://raw.githubusercontent.com/inbo/aspbo",
if (Sys.getenv("R_CONFIG_ACTIVE") == "production") "main" else "uat",
"HTML_pages/HTML")
dataFile <- file.path(dataPath, paste0(species(), "_", language(), ".html"))

tagList(
if (!is.na(url))
tags$a(href = url, target = "_blank", url),
if (httr::http_status(httr::GET(dataFile))$category != "Client error")
includeHTML(dataFile)
)

})

})
}


#' Shiny module for including html file - UI side
#' @inherit welcomeSectionUI
#'
#' @author mvarewyck
#' @export
htmlSectionUI <- function(id) {

ns <- NS(id)

tags$div(style = "margin-top: 20px;",
uiOutput(ns("addLinks"))
)

}

25 changes: 14 additions & 11 deletions alienSpecies/R/data_create.R
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ createTimeseries <- function(


# For R CMD check
df_ts <- taxonKey <- NULL
df_ts <- taxonKey <- eea_cell_code <- NULL

# created from https://github.com/inbo/aspbo/blob/uat/src/05_occurrence_indicators_preprocessing.Rmd
## Data at 1km x 1km grid level
Expand Down Expand Up @@ -307,14 +307,14 @@ createTaxaChoices <- function(exotenData) {
#' }
#' @return data.table, loaded indicator/unionlist data;
#' and attribute 'Date', the date that this data file was created
#' @importFrom data.table fread := as.data.table
#' @importFrom data.table fread := as.data.table setnames
#' @importFrom utils tail
#' @importFrom stats complete.cases
#' @importFrom arrow write_parquet
#' @importFrom dplyr filter
#' @export
createTabularData <- function(
dataDir = "~/git/alien-species-portal/dataS3",
dataDir = "~/git/aspbo/data/output/UAT_processing",
bucket = config::get("bucket", file = system.file("config.yml", package = "alienSpecies")),
type = c("indicators", "unionlist", "occurrence")) {

Expand All @@ -324,6 +324,7 @@ createTabularData <- function(
i.scientificName <- NULL
i.classKey <- NULL
taxonKey <- variable <- eea_cell_code <- NULL
obs <- NULL

warningMessage <- NULL

Expand Down Expand Up @@ -379,12 +380,9 @@ createTabularData <- function(
## convert english names to names recognized by the translation file
rawData$locality <- getRegionNames(rawData$locality)

## Extract hyperlinks

### Extract gbif link
rawData$gbifLink <- sapply(strsplit(rawData$source, split = ": "), function(x) x[1])
rawData$gbifLink <- paste0("<a href='", rawData$gbifLink, "' target = '_blank'>",
sapply(strsplit(rawData$gbifLink, split = "/"), function(x) tail(x, n = 1)), "</a>")
## Construct gbif link
rawData$gbifLink <- paste0("<a href='https://www.gbif.org/species/", rawData$nubKey, "' target = '_blank'>",
rawData$nubKey, "</a>")
# common name and source: https://www.gbif.org/species/157131005

## recode `source` variable
Expand Down Expand Up @@ -471,8 +469,10 @@ createTabularData <- function(
by.y = c("variable", "taxonKey"), all.x = TRUE)
rawData$last_observed <- apply(rawData[, c("last_observed", "year")], 1,
function(x) if (all(is.na(x))) NA else max(x, na.rm = TRUE))

rawData$first_observed <- as.numeric(rawData$first_observed)
rawData$last_observed <- as.numeric(rawData$last_observed)


## replace missing "species" with "canonicalName" if available
# then drop "canonicalName"
ind <- which(is.na(rawData$species) & !is.na(rawData$canonicalName))
Expand Down Expand Up @@ -523,8 +523,11 @@ createTabularData <- function(
rawData$cell_code10 <- gsub(pattern = "1km", replacement = "10km",
paste0(substr(rawData$eea_cell_code, start = 1, stop = 7),
substr(rawData$eea_cell_code, start = 9, stop = 12)))
colnames(rawData)[colnames(rawData) == "eea_cell_code"] <- "cell_code1"

setnames(rawData, "eea_cell_code", "cell_code1", skip_absent = TRUE)
setnames(rawData, "gemeente", "NAAM", skip_absent = TRUE)
setnames(rawData, "gewest", "GEWEST", skip_absent = TRUE)

}

attr(rawData, "Date") <- file.mtime(dataFiles)
Expand Down
2 changes: 2 additions & 0 deletions alienSpecies/R/data_gbif.R
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ loadGbif <- function(dataFile,
rawData[, decimalLongitude := as.numeric(decimalLongitude)]
if ("decimalLatitude" %in% colnames(rawData))
rawData[, decimalLatitude := as.numeric(decimalLatitude)]
if ("count" %in% colnames(rawData))
rawData[, count := as.numeric(count)]


attr(rawData, "Date") <- file.mtime(dataFile)
Expand Down
14 changes: 9 additions & 5 deletions alienSpecies/R/data_load.R
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ loadTabularData <- function(
open_dataset(file.path("s3:/", bucket, dataFile)) else
read_parquet(file = file.path("s3:/", bucket, dataFile))

message(attr(rawData, "warning"))

if (type == "indicators")
attr(rawData, "habitats") <- c("marine", "freshwater", "terrestrial")

Expand All @@ -62,7 +64,7 @@ loadTabularData <- function(
#' Load meta data for the UI
#' @inheritParams loadTabularData
#' @param type character, which type of translations should be loaded;
#' should be one of \code{c("ui","keys")}
#' should be one of \code{c("ui", "keys", "harmonia")}
#' @param language character, which language data sheet should be loaded;
#' should be one of \code{c("nl", "fr", "en")}
#' @param local boolean, whether to use local translation file in
Expand All @@ -73,7 +75,7 @@ loadTabularData <- function(
#' @importFrom utils read.csv
#' @export

loadMetaData <- function(type = c("ui", "keys"),
loadMetaData <- function(type = c("ui", "keys", "harmonia"),
bucket = config::get("bucket", file = system.file("config.yml", package = "alienSpecies")),
language = c("nl", "fr", "en"),
local = FALSE) {
Expand All @@ -83,7 +85,8 @@ loadMetaData <- function(type = c("ui", "keys"),

fileNames <- switch(type,
ui = paste0("translations", c("", "_simple", "_regions")),
keys = "keys"
keys = "keys",
harmonia = "harmonia_info"
)

allData <- sapply(fileNames, function(iFile) {
Expand All @@ -92,7 +95,7 @@ loadMetaData <- function(type = c("ui", "keys"),
if (local)
read.csv(system.file("extdata", iFile, package = "alienSpecies"),
sep = if (type == "ui") ";" else ",", encoding = "UTF-8") else
readS3(FUN = read.csv, sep = if (type == "ui") ";" else ",", encoding = "UTF-8",
readS3(FUN = read.csv, sep = if (type == "keys") "," else ";", encoding = "UTF-8",
file = iFile)
}, error = function(err) NULL)
}, simplify = FALSE)
Expand Down Expand Up @@ -127,7 +130,8 @@ loadMetaData <- function(type = c("ui", "keys"),
uiText

},
keys = allData$keys
keys = allData$keys,
harmonia = allData$harmonia[, c("gbif_taxonkey", "harmonia_url")]
)

if (type == "ui")
Expand Down
Loading