Buchungen-popup funktioniert
This commit is contained in:
+4
-48
@@ -1,50 +1,6 @@
|
|||||||
# These are some examples of commonly ignored file patterns.
|
|
||||||
# You should customize this list as applicable to your project.
|
|
||||||
# Learn more about .gitignore:
|
|
||||||
# https://www.atlassian.com/git/tutorials/saving-changes/gitignore
|
|
||||||
|
|
||||||
# Node artifact files
|
.Rproj.user
|
||||||
node_modules/
|
.Rhistory
|
||||||
dist/
|
.RData
|
||||||
|
.Ruserdata
|
||||||
# Compiled Java class files
|
|
||||||
*.class
|
|
||||||
|
|
||||||
# Compiled Python bytecode
|
|
||||||
*.py[cod]
|
|
||||||
|
|
||||||
# Log files
|
|
||||||
*.log
|
|
||||||
|
|
||||||
# Package files
|
|
||||||
*.jar
|
|
||||||
|
|
||||||
# Maven
|
|
||||||
target/
|
|
||||||
dist/
|
|
||||||
|
|
||||||
# JetBrains IDE
|
|
||||||
.idea/
|
|
||||||
|
|
||||||
# Unit test reports
|
|
||||||
TEST*.xml
|
|
||||||
|
|
||||||
# Generated by MacOS
|
|
||||||
.DS_Store
|
|
||||||
|
|
||||||
# Generated by Windows
|
|
||||||
Thumbs.db
|
|
||||||
|
|
||||||
# Applications
|
|
||||||
*.app
|
|
||||||
*.exe
|
|
||||||
*.war
|
|
||||||
|
|
||||||
# Large media files
|
|
||||||
*.mp4
|
|
||||||
*.tiff
|
|
||||||
*.avi
|
|
||||||
*.flv
|
|
||||||
*.mov
|
|
||||||
*.wmv
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
read_accounts <- function(conn){
|
||||||
|
tbl(conn, "accounts")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
get_account_choices <- function(conn) {
|
||||||
|
tbl(conn, "accounts") |>
|
||||||
|
select(id, konto) |>
|
||||||
|
collect() |>
|
||||||
|
arrange(konto) |>
|
||||||
|
(\(df) setNames(df$id, df$konto))()
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
read_buch_tabelle <- function(conn){
|
||||||
|
postings <- tbl(conn, "postings")
|
||||||
|
entries <- tbl(conn, "entries")
|
||||||
|
accounts <- tbl(conn, "accounts")
|
||||||
|
projects <- tbl(conn, "projects")
|
||||||
|
contacts <- tbl(conn, "contacts")
|
||||||
|
result <- postings |>
|
||||||
|
left_join(entries, by = c("entry_id" = "id")) |>
|
||||||
|
left_join(contacts, by = c("contact_id" = "id")) |> # contact_id jetzt verfügbar
|
||||||
|
left_join(accounts, by = c("account_id" = "id")) |>
|
||||||
|
left_join(projects, by = c("project_id" = "id")) |>
|
||||||
|
select(id, valuta, konto, projektname, display_name, amount, entry_id) |>
|
||||||
|
collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
read_posting <- function(conn, id){
|
||||||
|
dbxSelect(conn, paste0("SELECT * FROM postings WHERE id =", id))
|
||||||
|
}
|
||||||
|
read_postings_by_entry <- function(conn, id){
|
||||||
|
dbxSelect(conn, paste0("SELECT * FROM postings WHERE entry_id =", id))
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
buchungenUI <- function(id) {
|
||||||
|
ns <- NS(id)
|
||||||
|
tagList(
|
||||||
|
reactableOutput(ns("buchungen_table"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
buchungenServer <- function(id) {
|
||||||
|
moduleServer( id, function(input, output, session) {
|
||||||
|
ns <- session$ns
|
||||||
|
|
||||||
|
postings <- reactiveVal(read_buch_tabelle(conn))
|
||||||
|
|
||||||
|
|
||||||
|
output$buchungen_table <- renderReactable({
|
||||||
|
reactable(
|
||||||
|
postings(),
|
||||||
|
onClick = "expand",
|
||||||
|
selection = "single",
|
||||||
|
details = function(index) {
|
||||||
|
entry_id <- postings()$entry_id[index]
|
||||||
|
detail_rows <- postings()[postings()$entry_id == entry_id, ]
|
||||||
|
|
||||||
|
div(
|
||||||
|
style = "padding: 10px; background: #f4f4f4; border-left: 4px solid #3c8dbc; max-width: 800px; margin-left: auto",
|
||||||
|
|
||||||
|
reactable(
|
||||||
|
dplyr::select(detail_rows, konto, projektname, amount),
|
||||||
|
fullWidth = TRUE,
|
||||||
|
columns = list(
|
||||||
|
konto = colDef(name = "Konto", minWidth = 150),
|
||||||
|
projektname = colDef(name = "Projekt", minWidth = 150),
|
||||||
|
amount = colDef(name = "Betrag", minWidth = 80)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
columns = list(
|
||||||
|
id = colDef(name = "ID", minWidth = 80),
|
||||||
|
valuta = colDef(name = "Wertstellung", minWidth = 80),
|
||||||
|
konto = colDef(name = "Kontoname", minWidth = 200),
|
||||||
|
entry_id = colDef(show = FALSE)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
# Modal zum editieren
|
||||||
|
selected <- reactive(getReactableState("buchungen_table", "selected"))
|
||||||
|
observeEvent(selected(),{
|
||||||
|
idwert <- postings()[selected(), "id"]
|
||||||
|
selected_row <- read_posting(conn, idwert) %>%
|
||||||
|
mutate(verzicht = ifelse(is.na(verzicht), F, verzicht))
|
||||||
|
showModal(modalDialog(
|
||||||
|
title = "Buchung bearbeiten",
|
||||||
|
size = "l",
|
||||||
|
tags$style(HTML(".modal-dialog { max-width: 90% !important; width: 90% !important; }")),
|
||||||
|
|
||||||
|
entryEditUI(ns("entry_edit")),
|
||||||
|
footer = tagList(
|
||||||
|
modalButton("Abbrechen"),
|
||||||
|
actionButton(ns("speichern"), "Speichern")
|
||||||
|
)
|
||||||
|
))
|
||||||
|
|
||||||
|
entryEditServer("entry_edit", entry_id = selected_row$entry_id, conn = conn)
|
||||||
|
|
||||||
|
}, ignoreInit = TRUE)
|
||||||
|
|
||||||
|
observeEvent(input$speichern, {
|
||||||
|
browser()
|
||||||
|
dbExecute(conn, "UPDATE postings SET
|
||||||
|
account_id = ?, project_id = ?, amount = ?, valuta = ?,
|
||||||
|
notiz = ?, rechnungsnummer = ?, betrag_muenzen = ?, verzicht = ?
|
||||||
|
WHERE id = ?",
|
||||||
|
params = list(
|
||||||
|
input$account_id, input$project_id, input$amount, input$valuta,
|
||||||
|
input$notiz, input$rechnungsnummer, input$betrag_muenzen, input$verzicht,
|
||||||
|
selected_row$id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
removeModal()
|
||||||
|
buchungen(read_buch_tabelle(conn)) # Tabelle neu laden
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
get_contact_choices <- function(conn) {
|
||||||
|
tbl(conn, "contacts") |>
|
||||||
|
select(id, display_name) |>
|
||||||
|
collect() |>
|
||||||
|
arrange(display_name) |>
|
||||||
|
(\(df) setNames(df$id, df$display_name))()
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
read_entry <- function(conn, idwert) {
|
||||||
|
dbxSelect(conn, paste0("SELECT * FROM entries WHERE id=", idwert))
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
# entry_edit_mod.R
|
||||||
|
entryEditUI <- function(id) {
|
||||||
|
ns <- NS(id)
|
||||||
|
tagList(
|
||||||
|
|
||||||
|
uiOutput(ns("entry_ui")),
|
||||||
|
uiOutput(ns("postings_ui"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
entryEditServer <- function(id, entry_id, conn) {
|
||||||
|
moduleServer(id, function(input, output, session) {
|
||||||
|
ns <- session$ns
|
||||||
|
|
||||||
|
entry_postings <- reactiveVal(read_postings_by_entry(conn, entry_id))
|
||||||
|
entry_data <- reactiveVal(read_entry(conn, entry_id))
|
||||||
|
|
||||||
|
output$entry_ui <- renderUI({
|
||||||
|
e <- entry_data()
|
||||||
|
tagList(
|
||||||
|
fluidRow(
|
||||||
|
column(6, selectizeInput(ns("contact_id"), "Kontakt",
|
||||||
|
choices = get_contact_choices(conn),
|
||||||
|
selected = e$contact_id)),
|
||||||
|
column(6, textInput(ns("purpose"), "Verwendungszweck", value = e$purpose))
|
||||||
|
),
|
||||||
|
hr()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
# Choices für contact nach dem Flush setzen
|
||||||
|
|
||||||
|
|
||||||
|
output$postings_ui <- renderUI({
|
||||||
|
alle <- entry_postings()
|
||||||
|
lapply(seq_len(nrow(alle)), function(i) {
|
||||||
|
print(paste("project selected:", alle$project_id[i]))
|
||||||
|
print(head(get_project_choices(conn)))
|
||||||
|
print(class(get_project_choices(conn)))
|
||||||
|
div(
|
||||||
|
style = "border-left: 3px solid #3c8dbc; padding: 5px; margin-bottom: 5px",
|
||||||
|
fluidRow(
|
||||||
|
column(3,
|
||||||
|
selectInput(ns(paste0("account_id_", i)), "Konto",
|
||||||
|
choices = get_account_choices(conn),
|
||||||
|
selected = as.character(alle$account_id[i]))
|
||||||
|
),
|
||||||
|
column(3, selectizeInput(ns(paste0("project_id_", i)), "Projekt",
|
||||||
|
choices = get_project_choices(conn),
|
||||||
|
selected = ifelse(is.na(alle$project_id[i]), "", as.character(alle$project_id[i])))
|
||||||
|
),
|
||||||
|
column(2, numericInput(ns(paste0("amount_", i)), "Betrag", value = alle$amount[i])),
|
||||||
|
column(3, textInput(ns(paste0("notiz_", i)), "Notiz", value = alle$notiz[i])),
|
||||||
|
column(1, actionButton(ns(paste0("delete_", i)), "", icon = icon("trash"), class = "btn-danger btn-sm"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
# Choices befüllen nachdem renderUI fertig ist
|
||||||
|
observe({
|
||||||
|
alle <- entry_postings()
|
||||||
|
e <- entry_data()
|
||||||
|
req(nrow(alle) > 0, nrow(e) > 0)
|
||||||
|
|
||||||
|
session$onFlushed(function() {
|
||||||
|
# Contact
|
||||||
|
updateSelectizeInput(session, "contact_id",
|
||||||
|
choices = get_contact_choices(conn),
|
||||||
|
selected = e$contact_id)
|
||||||
|
|
||||||
|
# Postings
|
||||||
|
lapply(seq_len(nrow(alle)), function(i) {
|
||||||
|
updateSelectizeInput(session, paste0("account_id_", i),
|
||||||
|
choices = get_account_choices(conn),
|
||||||
|
selected = alle$account_id[i])
|
||||||
|
updateSelectizeInput(session, paste0("project_id_", i),
|
||||||
|
choices = get_project_choices(conn),
|
||||||
|
selected = alle$project_id[i])
|
||||||
|
})
|
||||||
|
}, once = TRUE)
|
||||||
|
})
|
||||||
|
|
||||||
|
# Speichern-Logik
|
||||||
|
observeEvent(input$speichern, {
|
||||||
|
alle <- entry_postings()
|
||||||
|
lapply(seq_len(nrow(alle)), function(i) {
|
||||||
|
# update posting i in DB
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
get_project_choices <- function(conn) {
|
||||||
|
projekte <- tbl(conn, "projects") |>
|
||||||
|
select(id, projektname) |>
|
||||||
|
collect() |>
|
||||||
|
arrange(projektname)
|
||||||
|
|
||||||
|
choices <- setNames(as.character(projekte$id), projekte$projektname)
|
||||||
|
c("-" = "", choices)
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -0,0 +1,13 @@
|
|||||||
|
Version: 1.0
|
||||||
|
|
||||||
|
RestoreWorkspace: Default
|
||||||
|
SaveWorkspace: Default
|
||||||
|
AlwaysSaveHistory: Default
|
||||||
|
|
||||||
|
EnableCodeIndexing: Yes
|
||||||
|
UseSpacesForTab: Yes
|
||||||
|
NumSpacesForTab: 2
|
||||||
|
Encoding: UTF-8
|
||||||
|
|
||||||
|
RnwWeave: Sweave
|
||||||
|
LaTeX: pdfLaTeX
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
library("dbplyr")
|
||||||
|
library("tidyverse")
|
||||||
|
library("shiny")
|
||||||
|
library("DBI")
|
||||||
|
library("RSQLite")
|
||||||
|
library("dbx")
|
||||||
|
library("shinydashboard")
|
||||||
|
library("reactable")
|
||||||
|
library("conflicted")
|
||||||
|
library("R.utils")
|
||||||
|
|
||||||
|
conflicts_prefer(dplyr::select)
|
||||||
|
conflicts_prefer(dplyr::filter)
|
||||||
|
|
||||||
|
options(shiny.reactlog = TRUE)
|
||||||
|
options(shiny.error = browser)
|
||||||
|
|
||||||
|
conn <- dbConnect(RSQLite::SQLite(), "db/development.sqlite3")
|
||||||
|
sourceDirectory("R/")
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
server <- function(input, output) {
|
||||||
|
|
||||||
|
buchungenServer("buchungen_tab")
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
## ui.R ##
|
||||||
|
dashboardPage(
|
||||||
|
dashboardHeader(),
|
||||||
|
## Sidebar content
|
||||||
|
dashboardSidebar(
|
||||||
|
sidebarMenu(
|
||||||
|
menuItem("buchungen", tabName = "buchungen", icon = icon("dashboard")),
|
||||||
|
menuItem("konten", tabName = "Konten", icon = icon("th"))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
dashboardBody(
|
||||||
|
tabItems(
|
||||||
|
# First tab content
|
||||||
|
tabItem(tabName = "buchungen",
|
||||||
|
buchungenUI("buchungen_tab")
|
||||||
|
),
|
||||||
|
|
||||||
|
# Second tab content
|
||||||
|
tabItem(tabName = "widgets",
|
||||||
|
h2("Widgets tab content")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user