Skip to content

Commit 28ac1ba

Browse files
authored
Contextual help (#167)
* functions and wrapper for context help * adjust visibility of help icon * expand help on CSV import * update NEWS/version --------- Co-authored-by: hlageek <[email protected]>
1 parent cb539e1 commit 28ac1ba

File tree

5 files changed

+181
-30
lines changed

5 files changed

+181
-30
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: requal
22
Title: Shiny Application for Computer-Assisted Qualitative Data Analysis
3-
Version: 1.1.4.9001
3+
Version: 1.1.5.9001
44
Authors@R:
55
c(
66
person(given = "Radim",

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
- Codebook import
44
- code names, descriptions, and colors can be imported via a CSV file
5+
- Contextual help
6+
- functionality to display contextual help
57

68
# requal 1.1.3 Rieppeleon
79

R/app_server.R

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,26 @@ app_server <- function(input, output, session) {
1010

1111
# check_credentials returns a function to authenticate users
1212
auth <- shinymanager::secure_server(
13-
check_credentials = shinymanager::check_credentials(
14-
db = golem::get_golem_options(which = "credentials_path"),
15-
passphrase = golem::get_golem_options(which = "credentials_pass")),
16-
timeout = 60
17-
)
13+
check_credentials = shinymanager::check_credentials(
14+
db = golem::get_golem_options(which = "credentials_path"),
15+
passphrase = golem::get_golem_options(which = "credentials_pass")
16+
),
17+
timeout = 60
18+
)
1819

1920
observeEvent(auth, {
20-
glob$user$user_login <- auth$user
21-
glob$user$user_id <- as.integer(auth$user_id)
22-
glob$user$name <- auth$user_name
23-
glob$user$mail <- auth$user_mail
24-
glob$user$project_admin <- as.logical(auth$project_admin)
25-
glob$user$is_admin <- as.logical(auth$admin)
21+
glob$user$user_login <- auth$user
22+
glob$user$user_id <- as.integer(auth$user_id)
23+
glob$user$name <- auth$user_name
24+
glob$user$mail <- auth$user_mail
25+
glob$user$project_admin <- as.logical(auth$project_admin)
26+
glob$user$is_admin <- as.logical(auth$admin)
2627
})
27-
2828

2929
mod_launchpad_loader_server("launchpad_loader_ui_1", glob)
3030

3131
mod_launchpad_creator_server("launchpad_creator_ui_1", glob)
32-
32+
3333
observeEvent(glob$active_project, {
3434
updateControlbar("control_bar")
3535
shinyjs::show(id = "btn-memo")
@@ -40,7 +40,7 @@ app_server <- function(input, output, session) {
4040

4141
# Project ----
4242
mod_project_server("mod_project_ui_1", glob)
43-
# Manage users ----
43+
# Manage users ----
4444
mod_user_manager_server("user_manager_1", glob)
4545
# output: no output, permissions and membership written to DB
4646
# to prevent manipulation via UI
@@ -50,11 +50,9 @@ app_server <- function(input, output, session) {
5050
# Data ----
5151
mod_data_server("data_1", glob)
5252

53-
5453
# attributes ----
5554
mod_attributes_server("attributes_1", glob)
5655

57-
5856
# codebook ----
5957
# output: glob$codebook
6058
mod_codebook_server("codebook_ui_1", glob)
@@ -63,7 +61,7 @@ app_server <- function(input, output, session) {
6361
# workdesk ----
6462
# output: glob$segments_observer
6563
mod_document_code_server("document_code_ui_1", glob)
66-
64+
6765
# analysis ----
6866
mod_analysis_server("analysis_ui_1", glob)
6967
mod_download_html_server("download_html_ui_1", glob)
@@ -74,7 +72,6 @@ app_server <- function(input, output, session) {
7472
mod_browser_server("browser_ui_1", glob)
7573
mod_summary_server("summary_ui_1", glob)
7674

77-
7875
# user
7976
mod_user_server("user_ui_1", glob)
8077

@@ -83,21 +80,30 @@ app_server <- function(input, output, session) {
8380

8481
# show admin interface
8582
observeEvent(glob$user$is_admin, {
86-
if (req(glob$user$is_admin)){
87-
shinyjs::show(selector = ".mfb-component--bl")
88-
}
83+
if (req(glob$user$is_admin)) {
84+
shinyjs::show(selector = ".mfb-component--bl")
85+
}
8986
})
9087

9188
# observe screens
92-
observeEvent(input$analyze_link,{
93-
updateTabsetPanel(session, "tab_menu", input$analyze_link$tab_menu)
94-
glob$analyze_link <- list(
95-
doc_id = input$analyze_link$doc_id,
96-
segment_start = input$analyze_link$segment_start
97-
)
89+
observeEvent(input$analyze_link, {
90+
updateTabsetPanel(session, "tab_menu", input$analyze_link$tab_menu)
91+
glob$analyze_link <- list(
92+
doc_id = input$analyze_link$doc_id,
93+
segment_start = input$analyze_link$segment_start
94+
)
95+
})
96+
97+
# Observers for the help system
98+
observeEvent(input$show_help, {
99+
item <- input$show_help$item
100+
shinyjs::toggle(selector = paste0("#help-", item))
101+
})
102+
observeEvent(input$hide_help, {
103+
item <- input$hide_help$item
104+
shinyjs::toggle(selector = paste0("#help-", item))
98105
})
99106

100107
# shared
101108
mod_download_csv_server("download_csv_ui_1", glob)
102-
103109
}

R/contextual_help.R

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
with_help <- function(tag = NULL, help_item = NULL, visible = FALSE) {
2+
# Create help button
3+
help_button <- div(
4+
class = "help-icon",
5+
style = paste(
6+
"
7+
display: inline-block;
8+
width: 16px;
9+
height: 16px;
10+
border-radius: 50%;
11+
background-color: #007bff;
12+
color: white;
13+
text-align: center;
14+
line-height: 16px;
15+
font-size: 11px;
16+
font-weight: bold;
17+
margin-left: 5px;
18+
cursor: pointer;
19+
vertical-align: middle;
20+
visibility: ",
21+
if (visible) "visible;" else "hidden;"
22+
),
23+
onclick = paste0(
24+
"Shiny.setInputValue('show_help', {item: '",
25+
help_item,
26+
"'}, {priority: 'event'});"
27+
),
28+
"?"
29+
)
30+
31+
help_data <- help_items(help_item)
32+
33+
help_element <- div(
34+
id = paste0("help-", help_item),
35+
style = "
36+
position: fixed;
37+
top: 50%;
38+
left: 50%;
39+
transform: translate(-50%, -50%);
40+
background-color: white;
41+
border: 1px solid black;
42+
padding: 10px;
43+
z-index: 100000;
44+
min-width: 60vw;
45+
max-width: 80vw;
46+
font-size: initial;
47+
font-weight: initial;
48+
color: black;
49+
overflow-y: scroll;
50+
max-height: 80vh;
51+
border-radius: 5px;
52+
",
53+
div(
54+
# Div for closing of help content
55+
style = "text-align: right;",
56+
span(
57+
style = "
58+
cursor: pointer;
59+
font-weight: bold;
60+
color: gray;
61+
",
62+
onclick = paste0(
63+
"Shiny.setInputValue('hide_help', {item: '",
64+
help_item,
65+
"'}, {priority: 'event'});"
66+
),
67+
shiny::icon("x")
68+
)
69+
),
70+
strong(help_data$title),
71+
br(),
72+
br(),
73+
help_data$content
74+
)
75+
76+
# Return wrapped content
77+
div(
78+
style = "display: inline-block;",
79+
div(
80+
onmouseover = if (!visible) {
81+
"this.querySelector('.help-icon').style.visibility = 'visible';"
82+
} else {
83+
NULL
84+
},
85+
onmouseout = if (!visible) {
86+
"this.querySelector('.help-icon').style.visibility = 'hidden';"
87+
} else {
88+
NULL
89+
},
90+
tag,
91+
help_button
92+
),
93+
shinyjs::hidden(help_element)
94+
)
95+
}
96+
# Function to generate help content based on help item
97+
help_items <- function(help_item) {
98+
switch(
99+
help_item,
100+
"codebook_csv_import" = list(
101+
title = "Importing Codebooks from CSV",
102+
content = div(
103+
p(
104+
"To import codebooks from a CSV file, the file can include columns for the following content:",
105+
tags$ul(
106+
tags$li(
107+
tags$b("Code name"),
108+
"(required) This is the unique identifier for each code."
109+
),
110+
tags$li(
111+
tags$b("Code description"),
112+
"(optional) A brief explanation or details about the code."
113+
),
114+
tags$li(
115+
tags$b("Code color"),
116+
"(optional) The color associated with the code, which can be specified in RGB (e.g., 'rgb(255, 0, 0)') or HEX format (e.g., '#FF0000')."
117+
)
118+
)
119+
),
120+
p(
121+
"Note that the specific column names in the CSV file do not matter, as long as the CSV input is correctly formatted. You can map the column names to the corresponding codebook content in the import wizard.",
122+
),
123+
p(
124+
"When importing the CSV file, you can specify certain properties to ensure it is processed correctly:",
125+
tags$ul(
126+
tags$li(
127+
tags$b("Header"),
128+
"Select this option if the first row of the CSV contains column names. This helps in identifying the columns correctly. The default value assumes that the first row of the file contains column names."
129+
),
130+
tags$li(
131+
tags$b("Separator"),
132+
"Define the character used to separate values in the file, such as a comma (',') or semicolon (';'). The default value is a comma (',')."
133+
)
134+
)
135+
)
136+
)
137+
)
138+
)
139+
}

R/mod_codebook.R

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,11 @@ mod_codebook_server <- function(id, glob) {
143143
#---Import codebook UI --------------
144144
mod_rql_button_server(
145145
id = "code_import_ui",
146-
custom_title = "Import codebook",
146+
custom_title = with_help(
147+
"Import codebook",
148+
help_item = "codebook_csv_import",
149+
visible = TRUE
150+
),
147151
custom_tagList = mod_codebook_import_ui(ns("codebook_import_1")),
148152
glob,
149153
permission = "codebook_modify"

0 commit comments

Comments
 (0)