Skip to content

Commit a7edf82

Browse files
committed
Add new login module
1 parent 9acf832 commit a7edf82

File tree

2 files changed

+179
-60
lines changed

2 files changed

+179
-60
lines changed

server.R

Lines changed: 32 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ plan(multisession)
3636

3737
# source function lib
3838
source("functions.R")
39-
39+
source("ui_login.R")
4040
## Some language package stuff
4141

4242
### CB: added these lines for treeToJSON
@@ -157,51 +157,16 @@ server <- function(input, output, session) {
157157

158158

159159
# -- MAKE POP UP MODAL FOR ENTERING USER CREDENTIALS AND DATA
160-
161160
# Return the UI for a modal dialog with data selection input. If 'failed'
162161
# is TRUE, then display a message that the previous value was invalid.
163-
dataModal <- function(failed = FALSE) {
164-
modalDialog(
165-
tags$script(HTML(js)),
166-
title = i18n$t("labels.clueyCredentials"), #"Cluey credentials",
167-
# the selectbox for a server will only show in apps for testing
168-
if (grepl("test", session$clientData$url_pathname)) {
169-
message(paste("Adding selectbox for server because we are running on", session$clientData$url_pathname))
170-
selectInput("server", label = "Server",
171-
choices = c("focus.sensingclues", "focus.test.sensingclues"),
172-
selected = "focus.sensingclues")
173-
},
174-
selectInput("lang", label = i18n$t("labels.chooseLanguage"),
175-
choices = language_table$lang_short, selected = session$userData$sel_lang), #lang_short),
176-
textInput("username", i18n$t("labels.Cluey-username")),
177-
passwordInput("password", i18n$t("labels.Cluey-password")),
178-
size = "s",
179-
if (failed)
180-
div(tags$b(i18n$t("labels.invalid-credential"), style = "color: red;")),
181-
footer = tagList(
182-
actionButton("ok", "OK")
183-
)
184-
)
185-
}
186-
187-
resetModal <- function() {
188-
modalDialog(
189-
title = i18n$t("commands.logout"),
190-
size = "s",
191-
footer = tagList(
192-
modalButton(i18n$t("commands.cancel")),
193-
actionButton("reset", "OK")
194-
)
195-
)
196-
}
197-
resetModal <- function() {
162+
dataModal <- function() {
198163
modalDialog(
199-
title = i18n$t("commands.logout"),
200-
size = "s",
201-
footer = tagList(
202-
modalButton(i18n$t("commands.cancel")),
203-
actionButton("reset", "OK")
204-
)
164+
mod_login_ui("login", browser_path = session$clientData$url_pathname),
165+
title = div(style = "text-align: center; width: 100%;", i18n$t("labels.clueyCredentials")),
166+
size = "s",
167+
footer = NULL,
168+
easyClose = FALSE,
169+
fade = TRUE
205170
)
206171
}
207172

@@ -211,15 +176,15 @@ server <- function(input, output, session) {
211176
showModal(dataModal())
212177
})
213178

214-
215179
# When OK button is pressed, attempt to authenticate. If successful,
216180
# remove the modal.
217181

218182
obs2 <- observe({
219183
req(input$ok)
220184
isolate({
221-
Username <- input$username
222-
Password <- input$password
185+
Username <- input$username
186+
Password <- input$password
187+
223188
session$userData$clueyUser <- Username
224189
})
225190

@@ -232,44 +197,51 @@ server <- function(input, output, session) {
232197
session$userData$url <- "https://focus.test.sensingclues.org/"
233198
}
234199
}
235-
message(paste("LOGGING INTO", session$userData$url))
200+
message(paste0("LOGGING INTO ", session$userData$url))
236201

237-
session$userData$cookie_mt <- sensingcluesr::login_cluey(username = Username, password = Password, url = session$userData$url)
202+
session$userData$cookie_mt <- sensingcluesr::login_cluey(username = Username,
203+
password = Password,
204+
url = session$userData$url)
238205
if (!is.null(session$userData$cookie_mt)) {
239206
session$userData$authenticated <- TRUE
240207
obs1$suspend()
241208
removeModal()
242209
# after successful login
243-
session$userData$hierarchy <- sensingcluesr::get_hierarchy(url = session$userData$url, lang = session$userData$lang_short)
210+
session$userData$hierarchy <- sensingcluesr::get_hierarchy(url = session$userData$url,
211+
lang = session$userData$lang_short)
244212
session$userData$concepts <- session$userData$hierarchy$concepts
245-
213+
# get groups needs to be done only once
214+
# debug
215+
# message(paste0("Get initial groups for ",session$userData$clueyUser,' from ',from,' to ',to))
216+
# session$userData$groups <- sensingcluesr::get_groups(from = from,
217+
# to = to,
218+
# cookie = session$userData$cookie_mt,
219+
# url = session$userData$url)
246220
# put start en end date in dateRangeInput
247221
updateDateRangeInput(session, "DateRange",
248222
start = isolate(session$userData$date_from),
249-
end = isolate(session$userData$date_to),
250-
max = Sys.Date())
223+
end = isolate(session$userData$date_to))
251224

252225
# which layers are available to the user
253-
layers <- sensingcluesr::get_layer_details(cookie = session$userData$cookie_mt, url = session$userData$url)
254-
# filter layers of the (Multi)Polygon type for the per area tab
255-
session$userData$layers <- layers %>% filter(geometryType %in% c("Polygon", "MultiPolygon"))
226+
session$userData$layers <- sensingcluesr::get_layer_details(cookie = session$userData$cookie_mt, url = session$userData$url)
256227
# message(paste0("LAYERS ", paste(session$userData$layers, sep = "|")))
228+
updateSelectInput(session, "MapLayers", choices = c(i18n$t("labels.noneSelected"), sort(unlist(session$userData$layers$layerName))))
229+
session$userData$selectedLayer <- i18n$t("labels.noneSelected")
257230

258231
# enable input fields/buttons
259232
enable("DateRange")
260233
enable("GroupListDiv")
261-
enable("GetData")
234+
enable("BuildMap")
235+
enable("MapLayers")
262236

263237
} else {
264238
session$userData$authenticated <- FALSE
265239
# inform user
266-
showModal(dataModal(failed = TRUE))
267-
}
240+
showNotification(i18n$t("labels.invalid-credential"), type = "error")
241+
}
268242
}
269243
)
270244

271-
# -- End modal stuff --
272-
273245
# Evt. taal wijzigen
274246

275247
obs3 <- observe({

ui_login.R

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# ui/mod_login_ui.R
2+
3+
mod_login_ui <- function(id, browser_path) {
4+
# ns <- NS(id)
5+
6+
# Main container with set width
7+
div(style = "margin-left: 10px; margin-right: 10px;",
8+
9+
# Server selector, only shows up for test version
10+
if (grepl("test", browser_path)) {
11+
shinyWidgets::pickerInput(
12+
inputId = "server",
13+
label = "Server",
14+
choices = c("focus.sensingclues", "focus.test.sensingclues"),
15+
selected = "focus.sensingclues",
16+
multiple = FALSE,
17+
width = "100%"
18+
)
19+
},
20+
21+
# LANGUAGE SELECTOR
22+
shinyWidgets::pickerInput(
23+
inputId = "lang",
24+
label = "Select your language",
25+
choices = c("Dutch" = "nl", "English"= "en", "French" = "fr"),
26+
# c("Dutch", "English", "French", "German", "Hindi", "Romanian", "Spanish", "Swahili", "Ukrainian"),
27+
selected = "en",
28+
multiple = FALSE,
29+
options = shinyWidgets::pickerOptions(
30+
# noneSelectedText = "Select your language...",
31+
liveSearch = TRUE,
32+
liveSearchPlaceholder = "Type to search..."
33+
),
34+
width = "100%"
35+
),
36+
br(),
37+
38+
# Username input (full width)
39+
textInput(
40+
inputId = "username",
41+
label = "Enter your Cluey username",
42+
placeholder = "Username",
43+
width = "100%"
44+
),
45+
46+
# Password input with toggle icon
47+
tags$div(style = "position: relative; margin-top: 10px;",
48+
# Label
49+
tags$label(`for` = "password", "Password"),
50+
# Eigen input ipv shiny::passwordInput om custom styling mogelijk te maken
51+
tags$input(
52+
id = "password",
53+
type = "password",
54+
class = "form-control",
55+
placeholder = "Password",
56+
style = "width: 100%; padding-right: 30px;"
57+
),
58+
# Oogje voor toggle
59+
tags$span(
60+
class = "toggle-password",
61+
tags$i(class = "fa fa-eye fa-lg"),
62+
style = "position: absolute; top: 34px; right: 10px; cursor: pointer;"
63+
)
64+
),
65+
66+
# Remember me checkbox onder de login knop
67+
tags$div(
68+
style = "margin-top: 15px; font-size: 0.9em;",
69+
checkboxInput(
70+
inputId = "remember_me",
71+
label = "Remember me",
72+
value = FALSE,
73+
width = NULL
74+
)
75+
),
76+
77+
# Login button (full width)
78+
actionButton(
79+
inputId = "ok",
80+
label = "Log in",
81+
class = "btn btn-primary",
82+
style = "width: 100%; color: white; background-color: #004d40;"
83+
),
84+
85+
# "Forgot password" link
86+
tags$a(
87+
href = "https://sensingclues.freshdesk.com/support/solutions/articles/48001167031-forgot-password",
88+
"Forgot password",
89+
target = "_blank",
90+
style = "display: block; text-align: right; margin-top: 8px;
91+
color: #004d40; text-decoration: none; font-weight: 300;"
92+
),
93+
94+
# "Create account" link
95+
tags$div(
96+
style = "margin-top: 20px; border-top: 1px solid #ccc; padding-top: 10px; text-align: center; font-size: 0.9em; color: #666;",
97+
"No account yet? ",
98+
tags$a(
99+
href = "https://sensingclues.freshdesk.com/support/solutions/articles/48000944302-create-an-account",
100+
"Create one.",
101+
target = "_blank",
102+
style = "color: #004d40; text-decoration: none; font-weight: 500;"
103+
)
104+
),
105+
106+
# Script to toggle password visibility
107+
tags$script(HTML(
108+
"$(document).on('click', '.toggle-password', function() {\n",
109+
" var input = $(this).siblings('input');\n",
110+
" var type = input.attr('type') === 'password' ? 'text' : 'password';\n",
111+
" input.attr('type', type);\n",
112+
" $(this).find('i').toggleClass('fa-eye fa-eye-slash');\n",
113+
"});"
114+
)),
115+
116+
# Script to close modal on clicking enter
117+
tags$script(HTML(
118+
' $(document).keyup(function(event) {
119+
if ($("#password").is(":focus") && (event.keyCode == 13)) {
120+
$("#ok").click();
121+
}
122+
});'
123+
)),
124+
125+
tags$script(HTML(glue::glue("
126+
$(document).ready(function() {{
127+
// Bij laden van de pagina: check localStorage
128+
if (localStorage.getItem('remember_me') === 'true') {{
129+
$('#{'remember_me'}').prop('checked', true);
130+
$('#{'username'}').val(localStorage.getItem('username'));
131+
}}
132+
133+
// Bij klikken op login: onthoud gegevens als aangevinkt
134+
$('#{'ok'}').on('click', function() {{
135+
if ($('#{'remember_me'}').is(':checked')) {{
136+
localStorage.setItem('remember_me', 'true');
137+
localStorage.setItem('username', $('#{'username'}').val());
138+
}} else {{
139+
localStorage.removeItem('remember_me');
140+
localStorage.removeItem('username');
141+
}}
142+
}});
143+
}});
144+
"))
145+
)
146+
)
147+
}

0 commit comments

Comments
 (0)