Skip to content

Commit 29ddd2c

Browse files
committed
update Dev log
1 parent ce730cc commit 29ddd2c

File tree

2 files changed

+193
-5
lines changed

2 files changed

+193
-5
lines changed

source/content/.obsidian/workspace.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@
156156
}
157157
],
158158
"direction": "horizontal",
159-
"width": 300
159+
"width": 300,
160+
"collapsed": true
160161
},
161162
"left-ribbon": {
162163
"hiddenItems": {

source/content/BSGOU-System/RNA-seq Tool Kits/DeVlog/20250729-fenA-processx_convert-theme.md

Lines changed: 191 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,86 @@ tags:
1717
# 1. Add code blocks for [loc](https://github.com/LabOnoM/ShinyAppsManager)
1818

1919
## Basic functions
20-
1. Handle crash
21-
2. Email notification
22-
3. Communications with [loc](https://github.com/LabOnoM/ShinyAppsManager) based on [jwt](https://en.wikipedia.org/wiki/JSON_Web_Token)
20+
1. Handle crash (inside **header** of navbarPage)
21+
2. Handle shiny theme selection
22+
3. Handle live console
23+
4. Email notification (inside **header** of navbarPage)
24+
5. Live Console (inside **footer** of navbarPage)
25+
6. Communications with [loc](https://github.com/LabOnoM/ShinyAppsManager) based on [jwt](https://en.wikipedia.org/wiki/JSON_Web_Token)(inside **header** of navbarPage)
2326

24-
Example codes:
27+
Helper functions (global.R)
2528
```R
29+
# Get Info ----
30+
print_to_console <- function(msg) {
31+
js_line <- gsub("\\\\", "\\\\\\\\", msg)
32+
js_line <- gsub("\"", "\\\\\"", js_line)
33+
shinyjs::runjs(sprintf(
34+
"if (document.getElementById('console')) {
35+
let el = document.getElementById('console');
36+
let lines = el.innerText.split('\\n');
37+
if (lines.length > 2000) {
38+
lines = lines.slice(lines.length - 1999); // keep last 1999 lines
39+
}
40+
lines.push(\"%s\");
41+
el.innerText = lines.join('\\n');
42+
el.scrollTop = el.scrollHeight;
43+
} else {
44+
console.warn('#console element not found!');
45+
}",
46+
js_line
47+
))
48+
return(js_line)
49+
}
50+
# 获取当前登录用户邮箱
51+
get_user_email <- function(token){
52+
headers <- add_headers(`Token` = token, `Content-Type` = "application/json")
53+
res <- try(GET('http://10.2.26.152:7156/sqx_fast/app/user/info', headers), silent = TRUE)
54+
if(!inherits(res, "try-error") && status_code(res) == 200){
55+
res_data <- fromJSON(content(res, "text", encoding = "UTF-8"))
56+
return(res_data$data$email)
57+
}
58+
return(NA)
59+
}
60+
if(!is.na(Sys.getenv("SHINY_SERVER_VERSION", unset = NA))){
61+
smtp_creds <- creds_envvar(
62+
user = Sys.getenv("EMAIL_USER"),
63+
pass_envvar = "EMAIL_PASS",
64+
host = "smtp.gmail.com",
65+
port = 587,
66+
use_ssl = TRUE
67+
)
68+
email <- "Email_Template.html" %>% file.path("..", "GlobalEnvironment", .) %>% readLines(., , warn = FALSE) %>%
69+
paste(., collapse = "\n") %>% HTML() %>% compose_email(body = .)
70+
email_fail <- "Email_Template_fail.html" %>% file.path("..", "GlobalEnvironment", .) %>% readLines(., , warn = FALSE) %>%
71+
paste(., collapse = "\n") %>% HTML() %>% compose_email(body = .)
72+
# get user home
73+
UsrHome <- file.path("/mnt","Public")
74+
}else{
75+
UsrHome <- path_home() %>% as.character()
76+
}
77+
options(shiny.fullstacktrace = TRUE)
78+
```
79+
80+
Example codes: Error Trigger (server.R):
81+
```R
82+
tryCatch(
83+
., error = function(e) {
84+
isolate(values$error_state <- paste0("Error:\n", e$message))
85+
showNotification(e$message, type = "error")
86+
return(NULL)
87+
})
88+
```
89+
90+
Example codes (server.R):
91+
```R
92+
# Initiation ----
93+
px <- reactiveVal(NULL)
94+
# Make reactive values ----
95+
values<-reactiveValues(
96+
is_on_shiny_server = !is.na(Sys.getenv("SHINY_SERVER_VERSION", unset = NA))
97+
)
98+
para<-reactiveValues()
99+
26100
# Fetch information if running on BSGOU loc (local allocation controller) system.
27101
observe({
28102
req(values$is_on_shiny_server)
@@ -96,7 +170,120 @@ Example codes:
96170
observeEvent(input$Crash_modal_ok, {
97171
shiny::removeModal()
98172
})
173+
# Handle shiny theme selection ----
174+
observe({
175+
req(is.null(para$UI_Init))
176+
updateSelectInput(
177+
session = session, inputId = "shinytheme-selector",
178+
selected = "yeti"
179+
)
180+
isolate(para$UI_Init <- "Done")
181+
})
182+
# Handle live console----
183+
# Clean console history
184+
observeEvent(input$clear_console, {
185+
runjs("
186+
var consoleEl = document.getElementById('console');
187+
if (consoleEl) {
188+
consoleEl.innerText = '';
189+
} else {
190+
console.warn('#console element not found!');
191+
}
192+
")
193+
isolate({values$console_log <- NULL})
194+
})
195+
# Download console monitor log
196+
output$download_console <- downloadHandler(
197+
filename = function() {
198+
paste0("console_log_", Sys.Date(), ".log")
199+
},
200+
content = function(file) {
201+
writeLines(values$console_log, file)
202+
}
203+
)
204+
205+
206+
# Session End Function ----
207+
# Shutdown everything if connection closed
208+
session$onSessionEnded(function() {
209+
if(!is.na(Sys.getenv("SHINY_SERVER_VERSION"))){
210+
headers <- add_headers(`Token`=session$userData$token, `Content-Type`="application/json")
211+
connect_req_end = list(`appName`=session$userData$appName, `action`="disconnect", `id`=session$userData$id)
212+
connect_end_data <- try(
213+
url_execute(
214+
2, 'http://10.2.26.152/sqx_fast/app/workstation/shiny-connect-action',
215+
toJSON(connect_req_end, pretty = FALSE, auto_unbox = TRUE), headers
216+
), silent = TRUE
217+
)
218+
}
219+
stopApp()
220+
})
99221
```
100222

223+
Example codes (ui.R):
224+
```R
225+
## For BSGOU ----
226+
header = tagList(
227+
### For lac system----
228+
uiOutput("conditional_head"), ## start-1嵌入代码开始,作用:异常跳转到预约系统首页
229+
## Costume CSS----
230+
tags$style(HTML(
231+
'.navbar-nav > li > a, .navbar-brand {
232+
padding-top: 3px !important;
233+
padding-bottom: 0px !important;
234+
margin-top: 2px;
235+
margin-bottom: 0px;
236+
height: 25px;
237+
}
238+
.navbar {
239+
min-height:26px !important;
240+
z-index:99999 !important;
241+
margin-top: 1px;
242+
margin-bottom: 1px;
243+
}'
244+
)),
245+
tags$head(
246+
## Google Analytics----
247+
# Embed Google Analytics
248+
tags$script(async = NA, src = "https://www.googletagmanager.com/gtag/js?id=G-RWF876HNKW"),
249+
tags$script(HTML("
250+
window.dataLayer = window.dataLayer || [];
251+
function gtag(){dataLayer.push(arguments);}
252+
gtag('js', new Date());
253+
gtag('config', 'G-RWF876HNKW');
254+
")),
255+
## Favicons----
256+
tags$link(rel = "icon", type = "image/png", sizes = "32x32", href = "GREP1_Logo_32x32.png"),
257+
tags$link(rel = "icon", type = "image/png", sizes = "16x16", href = "GREP1_Logo_32x32.png")
258+
),
259+
h5(HTML(
260+
"<strong>B</strong>ulk <strong>R</strong>NA-seq <strong>A</strong>uto-<strong>P</strong>ipeline"
261+
))
262+
),
263+
## Live Console----
264+
footer = absolutePanel(
265+
id = "ConsoleRealTime", class = "panel panel-default",
266+
bottom = 50, left = 25, width = "75%", fixed = FALSE,
267+
draggable = TRUE, height = "100px",
268+
style = "opacity: 0.95; z-index: 20;", ## z-index modification
269+
uiOutput("EmailNotif_ui"),
270+
# Horizontal bar
271+
tags$div(
272+
style = "display: flex; align-items: center; gap: 10px; padding-left: 5px;",
273+
HTML('<button data-toggle="collapse" data-target="#GlobalSettingMainPanel">Collapse</button>'),
274+
tags$a("Console Monitor"),
275+
downloadButton("download_console", "💾 Download Console Log"),
276+
actionButton("clear_console", "🧹 Clear Console", icon = icon("eraser"), class = "btn-danger")
277+
),
278+
tags$div(
279+
id = "GlobalSettingMainPanel",
280+
style = "max-height: 300px; overflow-y: auto; padding: 5px;",
281+
tags$div(
282+
id = "console",
283+
style = "white-space: pre-wrap; font-family: monospace; background-color: #111; color: #0f0; height: 280px; overflow-y: scroll; padding: 10px; border: 1px solid #333;"
284+
)
285+
)
286+
),
287+
```
101288
# 2. Convert Main loop with [processx](https://github.com/r-lib/processx)
102289

0 commit comments

Comments
 (0)