From 70a2fe2526d067080b268b0138d7a7430fff3b65 Mon Sep 17 00:00:00 2001 From: Christian Oswald Date: Thu, 19 Mar 2026 17:06:40 +0100 Subject: [PATCH] =?UTF-8?q?Filter=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- R/_funktionen/f_table.R | 14 +++++++++++-- R/buchungen_mod.R | 40 +++++++++++++++++++++++++++--------- R/postings/buchungen.R | 3 ++- db/data_transfer.R | 45 +++++++++++++++++++++++++++++++++++++++++ server.R | 13 ++++++++++-- ui.R | 33 +++++++++++++++++++++++++----- www/main.css | 11 ++++++++++ 7 files changed, 140 insertions(+), 19 deletions(-) create mode 100644 www/main.css diff --git a/R/_funktionen/f_table.R b/R/_funktionen/f_table.R index 805de9c..5b96ed0 100644 --- a/R/_funktionen/f_table.R +++ b/R/_funktionen/f_table.R @@ -1,4 +1,5 @@ -f_reactable <- function(daten, coldefs = NULL, selection = "single", defaultSelected = NULL, hoehe = NULL) { +f_reactable <- function(daten, coldefs = NULL, selection = "single", + defaultSelected = NULL, hoehe = NULL, highlight_valuta = NULL) { reactable( daten, selection = selection, @@ -18,7 +19,16 @@ f_reactable <- function(daten, coldefs = NULL, selection = "single", defaultSele # borderColor = "#dfe2e5", rowSelectedStyle = list(backgroundColor = "#98F5FF")# ), - rowStyle = list(cursor = "pointer"), + rowStyle = function(index) { + style <- list(cursor = "pointer") # immer aktiv + + if (!is.null(highlight_valuta) && + daten$valuta[index] == highlight_valuta) { + style$background <- "#fff3cd" + } + + style + }, onClick = "select", columns = coldefs ) diff --git a/R/buchungen_mod.R b/R/buchungen_mod.R index 6504a57..f3661fa 100644 --- a/R/buchungen_mod.R +++ b/R/buchungen_mod.R @@ -19,7 +19,7 @@ buchungenUI <- function(id) { ) } -buchungenServer <- function(id, conn) { +buchungenServer <- function(id, conn, aktiver_filter = reactive("alle")) { moduleServer(id, function(input, output, session) { ns <- session$ns @@ -30,18 +30,39 @@ buchungenServer <- function(id, conn) { current_main_idx <- reactiveVal(NULL) reset_trigger <- reactiveVal(0) # ← neu: erzwingt Re-render mit Filter-Reset modal_trigger <- reactiveVal(list(post_id = NULL, counter = 0)) + highlighted_valuta <- reactiveVal(NULL) + update_db_trigger <- postingModuleServer("posting_modal", conn, selected_trans_id, modal_trigger) + gefilterte_daten <- reactive({ + d <- postings_data() + switch(aktiver_filter(), + "giro" = d |> filter(grepl("0130", account_name)), + "monat" = d |> filter( + floor_date(as.Date(valuta), "month") == floor_date(Sys.Date(), "month") + + ), + d + ) + }) + + observeEvent(aktiver_filter(), { + current_main_idx(NULL) + selected_trans_id(NULL) + details_data(NULL) + }) + # * Haupttabelle rendern ---- output$buchungen_table <- renderReactable({ - reset_trigger() # Abhängigkeit – bei Increment wird neu gerendert + reset_trigger() f_reactable( - daten = postings_data(), - coldefs = coldef_entries_tabelle, - selection = "single", - hoehe = "60vh", - defaultSelected = current_main_idx() + daten = gefilterte_daten(), # ← geändert + coldefs = coldef_entries_tabelle, + selection = "single", + hoehe = "60vh", + defaultSelected = current_main_idx(), + highlight_valuta = highlighted_valuta() ) }) @@ -49,8 +70,9 @@ buchungenServer <- function(id, conn) { sel_details <- reactive(getReactableState("buchungen_table", "selected")) observeEvent(sel_details(), ignoreInit = TRUE, { req(sel_details()) + highlighted_valuta(gefilterte_daten()[sel_details(), "valuta"]) current_main_idx(sel_details()) - t_id <- postings_data()[sel_details(), "entry_id"] |> pull() + t_id <- gefilterte_daten()[sel_details(), "entry_id"] |> pull() # ← geändert selected_trans_id(t_id) details_data(read_buch_tabelle(conn, trans_id = t_id)) }) @@ -91,7 +113,7 @@ buchungenServer <- function(id, conn) { observeEvent(input$add_trans, { new_t_id <- max_id(conn, "entries") + 1 dbxInsert(conn, "entries", data.frame(id = new_t_id)) - p_id1 <- max_id(conn, "postings") + 1 + p_id1 <- max_id(conn, "postings") + 1 p_id2 <- p_id1 + 1 dbxInsert(conn, "postings", data.frame( id = c(p_id1, p_id2), diff --git a/R/postings/buchungen.R b/R/postings/buchungen.R index 580529c..78115e6 100644 --- a/R/postings/buchungen.R +++ b/R/postings/buchungen.R @@ -16,7 +16,8 @@ read_buch_tabelle <- function(conn, trans_id = NULL){ left_join(projects, by = c("project_id" = "id")) |> select(id, valuta, account_name, projektname, display_name, amount, entry_id) |> collect() %>% - mutate(saldo = 0) + mutate(saldo = 0) %>% + arrange(valuta, entry_id) } read_posting <- function(conn, id){ diff --git a/db/data_transfer.R b/db/data_transfer.R index 97bc4eb..c834855 100644 --- a/db/data_transfer.R +++ b/db/data_transfer.R @@ -218,6 +218,22 @@ if (ok) { creditorid TEXT );") + # Attachments ---- + exec_sql("CREATE TABLE attachments ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + entry_id INTEGER, + quittung_id INTEGER, + adress_id INTEGER, + wiso_id INTEGER, + btisch_id TEXT, + original_name TEXT, + kategorie TEXT, + path TEXT NOT NULL, + note TEXT, + created_at TEXT DEFAULT (datetime('now')), + updated_at TEXT DEFAULT (datetime('now')) +);") + error_f <- fehler_add("Schema created", TRUE, error_f) } @@ -412,6 +428,35 @@ if (ok) { dbWriteTable(con_s, "hibiscus_transactions", hib, append = TRUE) } + + + +# Transfer Attachments +## * Daten aus Attachments Tabelle übertragen ---- +if(ok){ + att <- dbxSelect(con_f, "SELECT id, trans_id, quittung_id, wiso_id, btisch_id, + adress_id, ft_dateiname, beschreibung, created_at, updated_at, ft_extension FROM Attachments") %>% + mutate( + id = as.integer(id), + trans_id = as.integer(trans_id), + quittung_id = as.integer(quittung_id), + wiso_id = as.integer(wiso_id), + btisch_id = as.integer(btisch_id), + adress_id = as.integer(adress_id), + created_at = as.character(created_at), + updated_at = as.character(updated_at), + path = paste0(id,".", ft_extension) + ) %>% + rename( + entry_id = trans_id, + note = beschreibung, + original_name = ft_dateiname + ) %>% + select(-ft_extension) + dbWriteTable(con_s, "Attachments", att, append = T) +} ## ------------------------------------------------------- 2026-03-19 16:38 + + # Close ---- dbDisconnect(con_s) diff --git a/server.R b/server.R index f5a7f29..c777fa0 100644 --- a/server.R +++ b/server.R @@ -1,5 +1,14 @@ server <- function(input, output) { - - buchungenServer("buchungen_tab", conn) + aktiver_filter <- reactive({ + if (input$filter_giro > 0 && + input$filter_giro == max(input$filter_giro, input$filter_monat, input$filter_alle)) + "giro" + else if (input$filter_monat > 0 && + input$filter_monat == max(input$filter_giro, input$filter_monat, input$filter_alle)) + "monat" + else + "alle" + }) + buchungenServer("buchungen_tab", conn, aktiver_filter = aktiver_filter) } diff --git a/ui.R b/ui.R index fb83fc7..33d90a1 100644 --- a/ui.R +++ b/ui.R @@ -1,11 +1,34 @@ ## ui.R ## dashboardPage( - dashboardHeader(), + dashboardHeader( ), ## Sidebar content dashboardSidebar( - sidebarMenu( - menuItem("buchungen", tabName = "buchungen", icon = icon("dashboard")), - menuItem("konten", tabName = "Konten", icon = icon("th")) + sidebarMenu(id = "tabs", + menuItem("buchungen", tabName = "buchungen", icon = icon("list")), + menuItem("konten", tabName = "konten", icon = icon("building-columns")) + ), + conditionalPanel( + condition = "input.tabs == 'buchungen'", + tags$ul( + class = "sidebar-menu", + tags$li( + class = "treeview", + tags$a(href = "#", + tags$i(class = "fa fa-filter"), + tags$span("Filter"), + tags$span(class = "pull-right-container", + tags$i(class = "fa fa-angle-left pull-right") + ) + ), + tags$ul( + class = "treeview-menu", + style = "padding: 5px 0;", + tags$li(actionBttn("filter_alle", "Alle", size = "xs", style = "minimal")), + tags$li(actionBttn("filter_giro", "Girokonto", size = "xs", style = "minimal")), + tags$li(actionBttn("filter_monat", "Dieser Monat", size = "xs", style = "minimal")) + ) + ) + ) ) ), dashboardBody( @@ -14,7 +37,6 @@ dashboardPage( tabItem(tabName = "buchungen", buchungenUI("buchungen_tab") ), - # Second tab content tabItem(tabName = "widgets", h2("Widgets tab content") @@ -22,3 +44,4 @@ dashboardPage( ) ) ) + diff --git a/www/main.css b/www/main.css new file mode 100644 index 0000000..3d83975 --- /dev/null +++ b/www/main.css @@ -0,0 +1,11 @@ + + /* Verringert den Abstand in der Filter-Zelle */ + .rt-filter-group { + padding: 2px 4px !important; + } + + /* Macht die Eingabefelder selbst flacher */ + .rt-filter-input { + height: 28px !important; + font-size: 14px !important; + }