ambhtmx.crud / app.R
jrosell's picture
work in pgroesss
12cb92c
raw
history blame
10.2 kB
if(!"rlang" %in% installed.packages()){
if(!interactive()) { stop("The package \"rlang\" is required.") }
cat("The package \"rlang\" is required.\n✖ Would you like to install it?\n\n1: Yes\n2: No\n\nSelection:")
if (readLines(n = 1) == "1"){
install.packages("rlang")
}
}
rlang::check_installed("remotes")
remotes::install_github("jrosell/ambhtmx", force = TRUE)
rlang::check_installed("ambiorix", action = \(pkg, ... ) remotes::install_github("devOpifex/ambiorix"))
rlang::check_installed("ambiorix", action = \(pkg, ... ) remotes::install_github("devOpifex/ambiorix"))
rlang::check_installed("scilis", action = \(pkg, ... ) remotes::install_github("devOpifex/scilis"))
rlang::check_installed("signaculum", action = \(pkg, ... ) remotes::install_github("devOpifex/signaculum"))
rlang::check_installed("tidyverse")
rlang::check_installed("zeallot")
rlang::check_installed("glue")
rlang::check_installed("htmltools")
rlang::check_installed("this.path")
options(
'ambiorix.host'=Sys.getenv('AMBHTMX_HOST'),
'ambiorix.port'=Sys.getenv('AMBHTMX_PORT')
)
library(ambhtmx)
# devtools::load_all()
library(ambiorix)
library(tidyverse)
library(zeallot)
library(glue)
library(htmltools)
library(signaculum)
page_title <- "Password protected CRUD (Create, Read, Update, and Delete) example with ambhtmx"
live_path <- tryCatch(
{this.path::this.path()},
error = function(e) return("")
)
print(live_path)
render_index <- \() {
main <- NULL
tryCatch({
index <- p("Add your first item.")
item_rows <- items$read_rows()
if(nrow(item_rows) > 0) {
index <- item_rows |>
rowwise() |>
group_split() |>
map(\(item) {
tags$li(
tags$a(
item$name,
href = glue("/items/{item$id}"),
`hx-get`= glue("/items/{item$id}"),
`hx-target` = "#main",
`hx-swap` = "innerHTML"
)
)
})
}
main <- withTags(div(id = "page", style = "margin: 50px",
div(style ="float:right", id = "logout", button("Logout", onclick = "void(location.href='/logout')")),
h1(page_title),
div(id = "main", style = "margin-top: 20px", tagList(
h2("Index of items"),
index,
button(
"New item",
style = "margin-top:20px",
`hx-get` = "/items/new",
`hx-target` = "#main",
`hx-swap` = "innerHTML"
)
))
))
},
error = \(e) print(e)
)
return(main)
}
render_row <- \(item) {
tags$div(
tags$strong(item$name),
tags$br(),
HTML(item$content)
)
}
#' Starting the app
counter <- 0
c(app, context, items) %<-%
ambhtmx_app(
dbname = getOption("ambiorix.dbname") %||% "items.sqlite",
host = getOption("ambiorix.host") %||% "127.0.0.1",
port = getOption("ambiorix.port")%||% "3000",
value = tibble(
id = character(1),
name = character(1),
content = character(1)
),
# live = live_path,
render_index = render_index,
render_row = render_row
)
#' Authentication feature with secret cookies and .Renviron variables
app$get("/login", \(req, res) {
process_login_get(
req,
res
)
})
app$post("/login", \(req, res) {
print(req$HTTP_HOST)
process_login_post(
req,
res,
user = Sys.getenv("AMBHTMX_USER"),
password = Sys.getenv("AMBHTMX_PASSWORD"),
)
})
app$get("/logout", \(req, res) {
process_logout_get(
req,
res
)
})
app$use(\(req, res){
process_loggedin_middleware(
req,
res,
user = Sys.getenv("AMBHTMX_USER")
)
})
#' Some CRUD operations examples
cat("\nBe sure is initially empty:\n")
items$read_rows(context = context) |> print()
# cat("\nNot, it should be empty:\n")
# walk(items$read_rows()$id, \(x) items$delete_row(id = x))
# items$read_rows() |> print()
# cat("\nAdd some items:\n")
# tibble(name = "Elis elis", content = "Putxinelis.",) |>
# items$add_row() -> first_id
# tibble(name = "Que bombolles", content = "T\'empatolles.") |>
# items$add_row() -> some_id
# tibble(name = "Holi", content = "Guapi.") |>
# items$add_row() -> last_id
# items$read_rows() |> print()
# cat(glue("\nDelete last item id={last_id}:\n"))
# items$delete_row(context = context, id = last_id)
# cat(glue("\nDelete last item id={last_id}:\n"))
# items$read_rows() |> print()
# cat("\nUpdate first items:\n")
# tibble(name = "First", content = "Hello in <span style='color:red'>red</span>.") |>
# items$update_row(id = first_id)
# items$read_rows() |> print()
# cat("\nRender the first item:\n")
# items$read_row(id = first_id) |>
# items$read_row() |>
# as.character() |>
# cat()
# cat("\nAdd an item with id 1:\n")
# tibble(id = "1", name = "Quines postres", content = "Tant bones.") |>
# items$add_row()
# items$read_rows() |> print()
# #' The main page
# app$get("/", \(req, res){
# # r <- process_loggedin_redirect(req, res)
# # if(!is.null(r)) return(r)
# if (!req$loggedin) {
# return(res$redirect("/login", status = 302L))
# }
# html <- ""
# tryCatch({
# html <- render_page(
# page_title = page_title,
# main = items$render_index()
# )
# },
# error = \(e) print(e)
# )
# res$send(html)
# })
# #' Read the index of the items
# app$get("/items", \(req, res){
# if (!req$loggedin) {
# return(res$redirect("/login", status = 302L))
# }
# res$send(items$render_index())
# })
# #' New item form
# app$get("/items/new", \(req, res){
# if (!req$loggedin) {
# return(res$redirect("/login", status = 302L))
# }
# errors <- process_error_get(req, res)
# html <- render_tags(withTags(tagList(
# h2("New item"),
# div(label("Name", p(input(name = "name")))),
# div(label("Content", p(textarea(name = "content")))),
# a(
# "Go back",
# href = "/",
# style = "margin-right:20px",
# `hx-confirm` = "Are you sure you want to go back?",
# `hx-get` = "/items",
# `hx-target` = "#page",
# `hx-swap` = "outerHTML",
# `hx-encoding` = "multipart/form-data"
# ),
# button(
# "Create",
# style = "margin-top:20px",
# `hx-post` = "/items",
# `hx-target` = "#page",
# `hx-swap` = "outerHTML",
# `hx-include` = "[name='name'], [name='content']",
# ),
# errors
# )))
# res$send(html)
# })
# #' Show an existing item
# app$get("/items/:id", \(req, res){
# if (!req$loggedin) {
# return(res$redirect("/login", status = 302L))
# }
# item_id <- req$params$id %||% ""
# item <- items$read_row(id = item_id)
# html <- render_tags(withTags(tagList(
# h2("Show item details"),
# items$render_row(item),
# a(
# "Go back",
# href = "/",
# style = "margin-right:20px",
# `hx-get` = "/items",
# `hx-target` = "#page",
# `hx-swap` = "outerHTML",
# ),
# a(
# "Delete",
# href = "/",
# style = "color: red; margin-right:20px",
# `hx-confirm` = "Are you sure you want to delete the item?",
# `hx-delete` = glue("/items/{item$id}"),
# `hx-target` = "#page",
# `hx-swap` = "outerHTML",
# `hx-encoding` = "multipart/form-data"
# ),
# button(
# "Edit",
# style = "margin-top:20px",
# `hx-get` = glue("/items/{item_id}/edit"),
# `hx-target` = "#main",
# `hx-swap` = "innerHTML"
# )
# )))
# res$send(html)
# })
# #' Edit item form
# app$get("/items/:id/edit", \(req, res){
# if (!req$loggedin) {
# return(res$redirect("/login", status = 302L))
# }
# item_id <- req$params$id %||% ""
# item <- items$read_row(id = item_id)
# html <- render_tags(withTags(tagList(
# h2("Edit item"),
# input(type = "hidden", name = "id", value = item$id),
# div(label("Name", p(input(name = "name", value = item$name)))),
# div(HTML(glue('<textarea rows=5 name="content">{item$content}</textarea>'))),
# a(
# "Go back",
# href = "/",
# style = "margin-right:20px",
# `hx-confirm` = "Are you sure you want to go back?",
# `hx-get` = "/items",
# `hx-target` = "#page",
# `hx-swap` = "outerHTML",
# `hx-encoding` = "multipart/form-data"
# ),
# button(
# "Update",
# style = "margin-top:20px",
# `hx-put` = glue("/items/{item$id}"),
# `hx-target` = "#page",
# `hx-swap` = "outerHTML",
# `hx-include` = "[name='name'], [name='content']",
# )
# )))
# res$send(html)
# })
# #' Create a new item
# app$post("/items", \(req, res){
# if (!req$loggedin) {
# return(res$redirect("/login", status = 302L))
# }
# params <- parse_multipart(req)
# if (is.null(params[["name"]])) {
# return(process_error_post(
# req,
# res,
# errors = "Name is required",
# error_url = "/items/new"
# ))
# }
# if (is.null(params[["content"]])) {
# params[["content"]] = ""
# }
# tryCatch({
# params |>
# as_tibble() |>
# items$add_row()
# },
# error = \(e) print(e)
# )
# res$send(items$render_index())
# })
# #' Update an existing item
# app$put("/items/:id", \(req, res){
# if (!req$loggedin) {
# return(res$redirect("/login", status = 302L))
# }
# item_id <- req$params$id %||% ""
# params <- parse_multipart(req) |>
# as_tibble() |>
# mutate(id = item_id)
# item <- items$read_row(id = item_id)
# tryCatch({
# item |>
# dplyr::rows_upsert(params, by = "id") |>
# items$update_row()
# },
# error = \(e) print(e)
# )
# res$send(items$render_index())
# })
# #' Delete an existing item
# app$delete("/items/:id", \(req, res){
# if (!req$loggedin) {
# return(res$redirect("/login", status = 302L))
# }
# item_id <- req$params$id %||% ""
# items$delete_row(id = item_id)
# res$send(items$render_index())
# })
# #' Start the app with all the previous defined routes
# app$start(open = FALSE)