How to create different dashboards for different users of a Shiny app? (on the same app code)

I need to create a Shiny App that will generate 6 different versions of the same dashboard layout, to 6 different users. Each user will see its own historical data during production, and it's all in the same database (I'm guessing I just need to filter the whole database for each specific user).

Specifically:

1 - How do I detect which user is which? I'm gonna use Authentication so I'm guessing I can probably retrieve the information from the user by how he logged. But how do I retrieve this information in code terms?

2 - Knowing which user is which, how do I create the 6 different versions on the same app code? They'll be the same layout, the only difference is the filtering of the dataset based on the user.

(optional) 3 - How does Shiny servers conciliate different users' displays? Thinking about a dashboard that has user interaction, different inputs don't interfere each others' displays? Do they have to replicate the code for each access so they're independent results?

I haven't made it yet, and even if I did I think it would be too complex to resolve here, so I'm posting the Hello World of Shiny. This way, imagine that the dataset used for plotting the Histogram has a column called 'user'. What would be the code used for discriminating the users?

library(shiny)

  output$distPlot <- renderPlot({

    dist <- dataset[1:obs,1] %>% filter(???)
    hist(dist)
  })

})

shinyUI(fluidPage(

  titlePanel("Hello Shiny!"),

  # Sidebar with a slider input for number of observations
  sidebarLayout(
    sidebarPanel(
      sliderInput("obs", 
                  "Number of observations:", 
                  min = 1, 
                  max = 1000, 
                  value = 500)
    ),  

    mainPanel(
      plotOutput("distPlot")
    )
  )
))

Thanks!

Upvotes: 6

Views: 1893

Answers (2)

Sada93
Sada93

Reputation: 2835

If you are using the authentication provided in shinyapps.io here is a simple solution to showing different UI elements to different users.

library(shiny)
library(dplyr)
ui <- fluidPage(
  titlePanel("Hello Shiny!"),

  # Sidebar with a slider input for number of observations
  sidebarLayout(
    sidebarPanel(
      uiOutput("slider")
    ),  

    mainPanel(
      plotOutput("distPlot")
    )
  )
)

server <- function(input, output, session) {

  # If using shinyapps.io the users email is stored in session$user

  #session$user = "testuser1"
  # session$user = "testuser2"
  session$user = "testuser3"


  slider_max_limit <- switch(session$user,
                       "testuser1" = 100,
                       "testuser2" = 200,
                       "testuser3" = 500)

  output$slider <- renderUI(sliderInput("hp", 
                                       "Filter Horsepower:", 
                                       min = min(mtcars$hp), 
                                       max = slider_max_limit, 
                                       value = 70))

  output$distPlot <- renderPlot({
    req(input$hp)

    mtcars %>%
      filter(hp < input$hp) %>%
      .$mpg %>%
      hist(.)

  })
}

shinyApp(ui, server)

By uncommenting the different users in the server function you can see how the slider changes.

Upvotes: 1

DSGym
DSGym

Reputation: 2867

login1 <- c("user1", "pw1")
login2 <- c("user2", "pw2")

library(shiny)

# Define UI for application that draws a histogram
ui <- fluidPage(

    # Application title
    uiOutput("ui")

    # Sidebar with a slider input for number of bins 
)

# Define server logic required to draw a histogram
server <- function(input, output) {

    logged <- reactiveValues(logged = FALSE, user = NULL)

    observeEvent(input$signin, {
        if(input$name == "user1" & input$pw == "pw1") {
            logged$logged <- TRUE
            logged$user <- "user1"
        } else if (input$name == "user2" & input$pw == "pw2") {
            logged$logged <- TRUE
            logged$user <- "user2"
        } else {}
    })


    output$ui <- renderUI({


        if(logged$logged == FALSE) {
            return(
                tagList(
                    textInput("name", "Name"),
                    passwordInput("pw", "Password"),
                    actionButton("signin", "Sign In")
                )
            )
        } else if(logged$logged == TRUE & logged$user == "user1") {
            return(
                tagList(
                    titlePanel("This is user 1 Panel"),
                    tags$h1("User 1 is only able to see text, but no plots")
                )
            )
        } else if(logged$logged == TRUE & logged$user == "user2") {
            return(
                tagList(
                    titlePanel("This is user 2 Panel for Executetives"),
                    sidebarLayout(
                        sidebarPanel(
                            sliderInput("bins",
                                        "Number of bins:",
                                        min = 1,
                                        max = 50,
                                        value = 30)
                        ),


                        # Show a plot of the generated distribution
                        mainPanel(
                            plotOutput("distPlot")
                        )
                    )
                )
            )
        } else {}
    })



    output$distPlot <- renderPlot({
        x    <- faithful[, 2]
        bins <- seq(min(x), max(x), length.out = input$bins + 1)
        hist(x, breaks = bins, col = 'darkgray', border = 'white')
    })
}

# Run the application 
shinyApp(ui = ui, server = server)

This is a SIMPLE way to make it work. You get reactiveValues passed as conditional inputs to the renderUI function.

However, this is a very dangerous solution, since passwords and users are not encrypted. For professional deployment with R Shiny, think about Shiny-Server or my personal favorite ShinyProxy (https://www.shinyproxy.io/)

Upvotes: 3

Related Questions