App to launch apps

Hi there,

I was not very satisfied with the way the apps menu was displayed using Thymeleaf (as it seemed really complicated to me) and I coded a little shiny app (run from shinyproxy of course) which does the job by parsing the application.yml file. I thought it might be of interest for some of you.

In our case, depending from the environement, the docker images used are different (prod, test, user1, user2). According to the group it belongs to, the user cannot have access to all apps.

In the www folder, there must be two subdirs :

  • yml (which contains the application.yml file)
  • img (which contains the “icons”)

Hope it can be of some help,

Sylvain

ui.R

library(shiny)

shinyUI(
  fluidPage(
    tags$head(tags$style(HTML('#bordercol { padding:20px;}'))),  
	HTML("<h2 align = 'center'>My main title</H2>"),
	uiOutput("myAppDisplayer")
  
  
  )
  

)

server.R

shinyServer(function(input, output,session) {




	output$myAppDisplayer <- renderUI({
		applications <- read_yaml("www/yml/application.yml")$proxy$specs
		SHINYPROXY_USERGROUPS <- Sys.getenv('SHINYPROXY_USERGROUPS')
		groups <- toupper(strsplit(SHINYPROXY_USERGROUPS, ",")[[1]])
		base.url <- "http://baseurl:8080/app"
		if (group == "") {
		  HTML("Not launched from a shiny proxy server or no defined user groups");
		} else {

			applications.list <- list()
			for (i in 1:length( applications)) {
				application.id  <- applications[[i]]$id
				application.family  <- unlist(strsplit( applications[[i]]$`container-image`,":"))[[1]][1]
				if (application.family == 'app_displayer') next;
				application.type  <- unlist(strsplit( applications[[i]]$`container-image`,":"))[[2]][1]
				application.groups <- applications[[i]]$`access-groups`
				if (length(intersect(groups, application.groups)) > 0) {
					applications.list[[length(applications.list)+1]] <- list("id" = application.id, "family" =  application.family, "env" = application.type)
				}
			}

			applications.dt <- rbindlist(applications.list)
			applications.dt$env <- factor(applications.dt$env, levels=c("prod", "test", "user1", "user2"))
                        applications.dt$link <- applications.dt$id
			applications.dt <- applications.dt[order(family, env)]

			
			
			applications.families <- unique(applications.dt$family)
			print(applications.dt)
			apps.per.line <- 3
			
			apps.nb <- length( unique(applications.dt$family))
			line.nb <- ceiling(apps.nb/apps.per.line)
			colwidth <- ceiling(12/apps.nb)
			print(colwidth)
			brol <- letters

			column(11,
				lapply(1:line.nb, 
					function(i) {
						fluidRow(
							lapply(1:min(apps.per.line, length(applications.families)-(i-1)*apps.per.line), 
								function(colnb, linenb = i) {
									list(
										column(colwidth, id = 'bordercol',
											fluidRow(HTML(paste0("<h3>",applications.families[((linenb-1)*apps.per.line)+colnb],"</h3>"))),
											fluidRow(HTML("<BR>")),
											fluidRow(
												tags$a(href = file.path(base.url, applications.dt[family == applications.families[((linenb-1)*apps.per.line)+colnb]]$link[1]), 
													tags$img(height = '150px', width = '300px',src=paste0('img/',applications.families[((linenb-1)*apps.per.line)+colnb],'.png'))
												)
											),
											fluidRow(
												lapply(1:nrow(applications.dt[family == applications.families[((linenb-1)*apps.per.line)+colnb]]), 
													function(famnb){
														column(12/nrow(applications.dt[family == applications.families[((linenb-1)*apps.per.line)+colnb]]),
														tags$a(href = file.path(base.url, applications.dt[family == applications.families[((linenb-1)*apps.per.line)+colnb]]$link[famnb]), 
															tags$b(applications.dt[family == applications.families[((linenb-1)*apps.per.line)+colnb]]$env[famnb]))
														)
													}
												)
											)
										),
										column(1,""))
								}
							)
						)
					}
				)
			)

		}


		 
	})
   
})
1 Like

Interesting approach!
I edited the navbar.html so it displayed the spec names and linked to app/{spec_id}
To make it fully functional I added a new entry to application.yml so include nav-groups which would be the header text, say, “stats about spiders” and then for each spec that belonged to that group I’d add a nav-group options and write the full name as it appears in nav-groups

Of course, there is some custom parsing to do to get this all joined up!

I hope this inspires someone. I’d love to share the code to the GitHub but I don’t have the time to ready the code for more general use (aka make it robust!)