[英]Starting Shiny app after password input (with Shinydashboard)
In this topic is well explained how to start the shinyapp after some password input.在本主题中很好地解释了如何在输入一些密码后启动 Shinyapp。 I am trying to do the same, but instead of "navbarPage", I would like to have a "dashboardPage".
我正在尝试做同样的事情,但我想要一个“dashboardPage”而不是“navbarPage”。
I tried to change the argument in do.call function form 'navbarPage' to 'dashboardPage', but the app crashes.我试图将 do.call 函数表单“navbarPage”中的参数更改为“dashboardPage”,但应用程序崩溃了。
rm(list = ls())
library(shiny)
Logged = FALSE;
my_username <- "test"
my_password <- "test"
ui1 <- function(){
tagList(
div(id = "login",
wellPanel(textInput("userName", "Username"),
passwordInput("passwd", "Password"),
br(),actionButton("Login", "Log in"))),
tags$style(type="text/css", "#login {font-size:10px; text-align: left;position:absolute;top: 40%;left: 50%;margin-top: -100px;margin-left: -150px;}")
)}
ui2 <- function(){tagList(tabPanel("Test"))}
ui = (htmlOutput("page"))
server = (function(input, output,session) {
USER <- reactiveValues(Logged = Logged)
observe({
if (USER$Logged == FALSE) {
if (!is.null(input$Login)) {
if (input$Login > 0) {
Username <- isolate(input$userName)
Password <- isolate(input$passwd)
Id.username <- which(my_username == Username)
Id.password <- which(my_password == Password)
if (length(Id.username) > 0 & length(Id.password) > 0) {
if (Id.username == Id.password) {
USER$Logged <- TRUE
}
}
}
}
}
})
observe({
if (USER$Logged == FALSE) {
output$page <- renderUI({
div(class="outer",do.call(bootstrapPage,c("",ui1())))
})
}
if (USER$Logged == TRUE)
{
output$page <- renderUI({
div(class="outer",do.call(dashboardPage,c(inverse=TRUE,title = "Contratulations you got in!",ui2())))
})
print(ui)
}
})
})
runApp(list(ui = ui, server = server))
I woder if my code is enough to get you started on the "right" path.我想知道我的代码是否足以让您开始“正确”的道路。 Please let me know if it is not the case.
如果不是这样,请告诉我。
The code below, if the login and password are correct, will display a shinydashboard.下面的代码,如果登录名和密码正确,将显示一个闪亮的仪表板。
but the following issues will need addressing:但需要解决以下问题:
observe
will keep on "winning" on the renderUI (with or without a second observe
, strictly speaking unnecessary hence eliminated) and the message relative to the wrong login is never executed.observe
将继续在renderUI 上“获胜”(有或没有第二个observe
,严格来说是不必要的,因此被消除)并且永远不会执行与错误登录相关的消息。 There are number of things you could try to fix the above.您可以尝试解决许多问题。
But please let me know if it is clear enough.但请让我知道它是否足够清楚。
This is the code:这是代码:
rm(list = ls())
library(shiny)
library(shinydashboard)
Logged = FALSE
my_username <- "test"
my_password <- "test"
ui1 <- function() {
tagList(
div(
id = "login",
wellPanel(
textInput("userName", "Username"),
passwordInput("passwd", "Password"),
br(),
actionButton("Login", "Log in")
)
),
tags$style(
type = "text/css",
"#login {font-size:10px; text-align: left;position:absolute;top: 40%;left: 50%;margin-top: -100px;margin-left: -150px;}"
)
)
}
ui2 <- function() {
tagList(dashboardHeader(),
dashboardSidebar(),
dashboardBody("Test"))
}
ui = (htmlOutput("page"))
server = function(input, output, session) {
USER <- reactiveValues(Logged = Logged)
observe({
if (USER$Logged == FALSE) {
if (!is.null(input$Login)) {
if (length(input$Login) > 0) {
Username <- isolate(input$userName)
Password <- isolate(input$passwd)
Id.username <- which(my_username == Username)
Id.password <- which(my_password == Password)
if (length(Id.username) > 0 &
length(Id.password) > 0) {
if (Id.username == Id.password) {
USER$Logged <- TRUE
}
}
}
}
}
})
output$page <- renderUI({
if (USER$Logged == FALSE) {
do.call(bootstrapPage, c("", ui1()))
} else {
do.call(dashboardPage, #c(inverse=TRUE,title = "Contratulations you got in!",
ui2())
}
})
}
shinyApp(ui, server)
October 30, 2017 Update 2017 年 10 月 30 日更新
It seems that the above code doesn't work anymore (thanks to @5249203 for pointing this out).上面的代码似乎不再起作用(感谢@5249203 指出这一点)。
I've tried to fix it, but I haven't managed to make the do.call
function work with dashboardBody
(if somebody knows of a way, please let me know!).我试图修复它,但我还没有设法使
do.call
函数与dashboardBody
工作(如果有人知道某种方法,请告诉我!)。
Therefore I approached the problem in another way, thanks to recent shiny
functions.因此,由于最近的
shiny
功能,我以另一种方式解决了这个问题。
See what you think (of course as usual the solution is just a template needing extensions).看看你的想法(当然,像往常一样,解决方案只是一个需要扩展的模板)。
library(shiny)
library(shinydashboard)
Logged = FALSE
my_username <- "test"
my_password <- "test"
ui <- dashboardPage(skin='blue',
dashboardHeader( title = "Dashboard"),
dashboardSidebar(),
dashboardBody("Test",
# actionButton("show", "Login"),
verbatimTextOutput("dataInfo")
)
)
server = function(input, output,session) {
values <- reactiveValues(authenticated = FALSE)
# Return the UI for a modal dialog with data selection input. If 'failed'
# is TRUE, then display a message that the previous value was invalid.
dataModal <- function(failed = FALSE) {
modalDialog(
textInput("username", "Username:"),
passwordInput("password", "Password:"),
footer = tagList(
# modalButton("Cancel"),
actionButton("ok", "OK")
)
)
}
# Show modal when button is clicked.
# This `observe` is suspended only whith right user credential
obs1 <- observe({
showModal(dataModal())
})
# When OK button is pressed, attempt to authenticate. If successful,
# remove the modal.
obs2 <- observe({
req(input$ok)
isolate({
Username <- input$username
Password <- input$password
})
Id.username <- which(my_username == Username)
Id.password <- which(my_password == Password)
if (length(Id.username) > 0 & length(Id.password) > 0) {
if (Id.username == Id.password) {
Logged <<- TRUE
values$authenticated <- TRUE
obs1$suspend()
removeModal()
} else {
values$authenticated <- FALSE
}
}
})
output$dataInfo <- renderPrint({
if (values$authenticated) "OK!!!!!"
else "You are NOT authenticated"
})
}
shinyApp(ui,server)
Here is another solution that takes a slightly different approach than @Enzo's.这是另一种与@Enzo 的方法略有不同的解决方案。 It creates a second UI so users cannot see what the app is displaying on the first menu tab.
它创建了第二个 UI,因此用户无法看到应用程序在第一个菜单选项卡上显示的内容。 The only downside is everything is basically brought to the Server side which may cause some issues for your code depending on how it is written.
唯一的缺点是一切基本上都被带到了服务器端,这可能会导致您的代码出现一些问题,具体取决于它的编写方式。
library(shiny)
library(shinydashboard)
my_username <- "test"
my_password <- "abc"
###########################/ui.R/##################################
header <- dashboardHeader(title = "my heading")
sidebar <- dashboardSidebar(uiOutput("sidebarpanel"))
body <- dashboardBody(uiOutput("body") )
ui <- dashboardPage(header, sidebar, body)
###########################/server.R/##################################
server <- function(input, output, session) {
Logged <- FALSE
USER <<- reactiveValues(Logged = Logged)
observe({
if (USER$Logged == FALSE) {
if (!is.null(input$Login)) {
if (input$Login > 0) {
Username <- isolate(input$userName)
Password <- isolate(input$passwd)
Id.username <- which(my_username == Username)
Id.password <- which(my_password == Password)
if (length(Id.username) > 0 & length(Id.password) > 0) {
if (Id.username == Id.password) {
USER$Logged <<- TRUE
}
}
}
}
}
})
output$sidebarpanel <- renderUI({
if (USER$Logged == TRUE) {
dashboardSidebar(
sidebarUserPanel("myuser", subtitle = a(icon("user"), "Logout", href="")),
selectInput("in_var", "myvar", multiple = FALSE,
choices = c("option 1","option 2")),
sidebarMenu(
menuItem("Item 1", tabName = "t_item1", icon = icon("line-chart")),
menuItem("Item 2", tabName = "t_item2", icon = icon("dollar")),
menuItem("Item 3", tabName = "t_item3", icon = icon("credit-card")),
menuItem("Item 4", tabName = "t_item4", icon = icon("share-alt"))
))}
})
output$body <- renderUI({
if (USER$Logged == TRUE) {
B <- c(2,3,4,3,7,5,4)
box(
title = p("Histogram", actionLink("Expand", "", icon = icon("expand"))), status = "primary", solidHeader = TRUE, width = 4,
hist(B)
)
}
if (USER$Logged == FALSE) {
box(title = "Login",textInput("userName", "Username"),
passwordInput("passwd", "Password"),
br(),
actionButton("Login", "Log in"))
}
})
}
shinyApp(ui, server)
September 2018 Update 2018 年 9 月更新
I was able to figure out @Enzo's original code to make the do.call
function work with shinydashboard
.我能够找出
shinydashboard
的原始代码,使do.call
函数与shinydashboard
工作。 Please see below.请参阅下文。 Credit to @Enzo for this, I just slightly changed some lines.
归功于@Enzo,我只是稍微更改了一些行。 I think this solution is better than my first code above since it allows the correct output codes to stay in the UI side.
我认为这个解决方案比我上面的第一个代码更好,因为它允许正确的输出代码留在 UI 端。 I've also added a message pop-up if the username and password is incorrect.
如果用户名和密码不正确,我还添加了一个消息弹出窗口。
rm(list = ls())
library(shiny)
library(shinydashboard)
my_username <- "test"
my_password <- "abc"
###########################/ui.R/##################################
ui1 <- function(){
tagList(
div(id = "login",
wellPanel(textInput("userName", "Username"),
passwordInput("passwd", "Password"),
br(),
actionButton("Login", "Log in"),
verbatimTextOutput("dataInfo")
)
),
tags$style(type="text/css", "#login {font-size:10px; text-align: left;position:absolute;top: 40%;left: 50%;margin-top: -100px;margin-left: -150px;}")
)}
ui2 <- function(){tagList(
"You did it!"
)}
header <- dashboardHeader(title = "Test Login")
sidebar <- dashboardSidebar()
body <- dashboardBody(
tags$head(tags$style("#dataInfo{color: red")),
htmlOutput("page")
)
ui <- dashboardPage(header, sidebar, body)
###########################/server.R/##################################
server = (function(input, output,session) {
Logged <- FALSE
Security <- TRUE
USER <- reactiveValues(Logged = Logged)
SEC <- reactiveValues(Security = Security)
observe({
if (USER$Logged == FALSE) {
if (!is.null(input$Login)) {
if (input$Login > 0) {
Username <- isolate(input$userName)
Password <- isolate(input$passwd)
if(my_username == Username & my_password == Password) {
USER$Logged <- TRUE
} else {SEC$Security <- FALSE}
}
}
}
})
observe({
if (USER$Logged == FALSE) {output$page <- renderUI({ui1()})}
if (USER$Logged == TRUE) {output$page <- renderUI({ui2()})}
})
observe({
output$dataInfo <- renderText({
if (SEC$Security) {""}
else {"Your username or password is not correct"}
})
})
})
runApp(list(ui = ui, server = server))
Your example uses a single user.您的示例使用单个用户。 I made some modifications for multiple user/password situations.
我对多个用户/密码情况做了一些修改。 This seems to work for me.
这似乎对我有用。 Hopefully, others may find it helpful:
希望其他人可能会发现它有帮助:
library(shiny)
library(shinydashboard)
library(tidyverse)
user_base <- tibble(
user = c("Test1", "Test2", "Test3"),
password = c("abc", "bcd", "cde"),
name = c("User1", "User2", "User3")
)
###########################/ui.R/##################################
header <- dashboardHeader(title = "my heading")
sidebar <- dashboardSidebar(uiOutput("sidebarpanel"))
body <- dashboardBody(uiOutput("body") )
ui <- dashboardPage(header, sidebar, body)
###########################/server.R/##################################
server <- function(input, output, session) {
Logged <- FALSE
USER <<- reactiveValues(Logged = Logged)
observe({
if (USER$Logged == FALSE) {
if (!is.null(input$Login)) {
if (input$Login > 0) {
Username <- isolate(input$userName)
Password <- isolate(input$passwd)
Id.username <- which(user_base$user == Username)
Id.password <- which(user_base$password == Password)
if (length(Id.username) > 0 & length(Id.password) > 0) {
if (Id.username == Id.password) {
USER$Logged <<- TRUE
}
}
}
}
}
})
output$sidebarpanel <- renderUI({
if (USER$Logged == TRUE) {
dashboardSidebar(
sidebarUserPanel("myuser", subtitle = a(icon("user"), "Logout", href="")),
selectInput("in_var", "myvar", multiple = FALSE,
choices = c("option 1","option 2")),
sidebarMenu(
menuItem("Item 1", tabName = "t_item1", icon = icon("line-chart")),
menuItem("Item 2", tabName = "t_item2", icon = icon("dollar")),
menuItem("Item 3", tabName = "t_item3", icon = icon("credit-card")),
menuItem("Item 4", tabName = "t_item4", icon = icon("share-alt"))
))}
})
output$body <- renderUI({
if (USER$Logged == TRUE) {
B <- c(2,3,4,3,7,5,4)
box(
title = p("Histogram", actionLink("Expand", "", icon = icon("expand"))),
status = "primary", solidHeader = TRUE, width = 4,
hist(B)
)
}
if (USER$Logged == FALSE) {
box(title = "Login",textInput("userName", "Username"),
passwordInput("passwd", "Password"),
br(),
actionButton("Login", "Log in"))
}
})
}
shinyApp(ui, server)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.