You are on page 1of 22
0130022, 11:10 PM. Creating @ Shiny App for Database Management Dashboard layout Authentication Losin ut Logout ut Losin redemats Dynamic UI reacting to user inputs Making sure the SQL. parts work in Shiny Web development in Shiny Creating a Shiny App for Database Management Yun Dai 02/2023, Proviously, we have created a business inteligence web app, PineApple Sales Dashboard (hitps/lyundai.shinyapps io!2020- business-ineligencel). The app connects a back-end SQLite database and a front-end dashboard using RSALite and Shiny. We summarized how we bul this business intoligence dashboar in this post (htpishanghai.hosting nyu eduldatalricaso-3.sql- shiny html) and in these sequenced video tutorials (pitps:istveam.nyu.edulchannel/SQLite%28Database'2Band%428Shiny'2BApp%2Bfor%:26Business%;2Bintelligencel 193288383) (open to NYU community) ‘As an extension to the PineApple Sales Dashboard, this Shiny app (hitps:/yundal.shinyapps.io/2020-database-management) (shown below) isa prototype of a database management platform. It allows users to view tables, create tables, update tables, insert entries, and, depending on the user rle, delete tables, While the business inteligence dashboard focuses on the frontend user interactions, this app addresses the needs in back-end database management. ‘Tho app below is embedded on this webpage and you may interact with it directly. hitpsshanghal hosting nyu. eduldataricase-4.database-managomont-shiy.himl 22 0130022, 11:10 PM Creating @ Shiny App for Database Management Please log in username Gracsword Please use the usernames and passwords provided below totest this database ‘management platform. We have crested two kinds of accounts: manager and admin The admin account allows one alter tales, columns, and records, and delete tables. The ‘manager account allows ane ta do everyting sbove except for deleting tables. ‘username passwerd permissions sel pass manager 89 6 aro Bongroi ON. In this post, we share the key features of tis app and what we feel most excited about building this app up. “Tho packages we have used to create the app include DBI, RSOLite, DT, shiny, shiny, shinythemes, shinyWidgets, shinydashboard, shinyauthr, and shinyFeedback Dashboard layout ‘The app uses the package shinydashboard (hpe:/studi. github la/shnydashboardindex hm! to lay outa dashboard structure. As shown below, it consists of @ header, a sidebar and a main body hitpsiishanghal hosting nyu edulGataricase-4-databaso-management-shiny.html 202 0130022, 11:10 PM Creating @ Shiny App for Database Management Figure 1. Structure of te dashboard layout: header, sidebar and body Code below generates the header, sidebar and main body right away. We don't need to know the technical detals of HTML, CSS of JavaScript to achieve this Lbrary(shiny) Library(shinydashooara) uf & cashboardPage( dashooardHeader(), dashooarasiaebar(), dashooaraboay() > server <- function(input, output) ( ) shinytop(ut, server) Sidebar menu items and tabs Inthe dashbosrdstde! 1) the menu items are defined by si bartenu(renurten()) Icons (htps:/ishiny.rstudlo.comeferencelshiny/0,14licon htm) are drawn from the Font Awesome (hps:fontawesome.convicons? {rom=io) and Glyphicons (htips:!getbootstrap.com/docs/5.Olcomponents/accordion)iraries. itpsiishanghal hosting nyu edulGataricase-4-database-management-shiny html 0130022, 11:10 PM. Creating @ Shiny App for Database Management a = ture ype tab content Figure 2. Sidebar menu items and tabitems. ashooarasidebar( collapsed = TRUE, iv(ntmloutput(“welcone”), style = “padding: 2px"), sidebartenu( Imerurten("View Tables", tabNawe = “view table", icon = icon("search")), Imenurten("Create Tables”, tabNane = "create table”, icon = icon("plus-square")), Imenurten("Update Tables”, tabNane = "update table”, icon = icon("exchange-alt")), mmeruten("Insert Entries", tabNane = “insert_value", icon = icon("edit")), rmenulten("Delete Tables”, tabNane = “del_table", icon = icon("trash-alt")), Imenulten("About™, tabNane = “about”, icon = icon(“info-cirele")) Inthe dashbosrdaody() the tab items are defined by tabrtens(tabtten()) . We give each ofthe tb items an output ID. Therefore, ‘when a user clicks a menu item, it becomes active and its content willbe visible inthe predefined tab inside the dashboard body. ashooardbody( ‘sabitens( ‘cablten(tablane = “view table", uidvtput(“tabiui")), tabrtem(tabWane = “del_table", uioutput("tab2uT")), ‘tabrtem(tabWane = “update table", uidutput("tab3ur")), ‘ablten(tablane = “create table", uidutput("tabeUr")), fanteertathone © "insertaatue™, vlosepet(-eaesur7)), abtten(tablane = "about", viovtput("tabeuI")) d d Collapsible sidebar layout ‘We can set the sidebar to be collapsed by default and to be expanded after user authorization, itpsiishanghal hosting nyu edulGataricase-4-database-management-shiny html 0130022, 11:10 PM. Creating @ Shiny App for Database Management observe({ if (credentials()Suser_auth) { shinyjs: :penoveclass (selector = "body", class = "sidebar-cotlapse") } else ( shinyjs::addClass(selector = "body", class = “sidevar-collapse”) > » Using box as container ‘The fundamental unit of containers in shinydashboard is box (https://rstudio.github.io/shinydashboard/structure htmistboxes). A box can be thought o asa block to define a content area on a webpage. For example, in afuid page layout, elements in the tab Update Tables are grouped into two Fluidtow s. The top Fluictow contains ‘a box to dsplay and hide a Note’. The bottom Flusdow contains tree box 8s for users to rename table, rename column and add ‘column respectively box Figure 3, Using box o create containing blocks in afuid page layout ‘The code to lay out the structure above is provided below. itps1ishanghal hosting nyu edulGataicase-4-databaso-management-shiny html 0130022, 11:10 PM. Creating @ Shiny App for Database Management ourputStabsur <- renderur(¢ ‘FlusPage( ‘FluidRow( box(width = 12, collapsible = TAUE, title = "Note: » ‘luidron( box(title = "Rename Table", width = 4, solidieader = TRUE, status = "primary", selectraput(), wellPanel( textinpat(), actionButton()) de box(title = "Rename Coluan”, width = 4, solicieader = TRUE, status = "primary", selectinput(), wellPanel() » box(title + "Add Column", width = 4, solidNeader = TRUE, status + "prinary", selectraput(), wweltPanel() ) » For another example, in a sidebar layout all elements inthe tab View Tables are contained in @ tox. Inside this box , the nextlayer Isa siaebartayout that consists ofa sidebareanel anda main?anel. Inthe sidebarvanel , we use another box that is collapsible to display and hide “Database Info" aan a mainPanel eee seas] el see tonya geen Fe box Figure 4. Using box to create containing blacks ina sidebar layout. hitpsi/shangha hosting nyu edulcataricase-4-database-management-sniny html 0130022, 11:10 PM. Creating @ Shiny App for Database Management outputStabiur <- rendert box(uigth = NULL, status = sidebarLayout( sidabarPanel( box(nidth » 12, collapsible aiv(style title = "oa PCD), selectinput(), textoutput(outputtd = tagsshead( tagssstyle( » ainvanel( ha(strong("Table Preview"), dataTableoutput(outputté = "se > > > » “height: 15px; background-color: whites pase Info! tab_intro"), tab_intro{font-size: 1Spx;font-style: italie:)")) table_view") Authentication “The app leverages the package shinyauthr (nipsiirdrofgithub/PaulC3 t/shinyauttr) to add a user authentication layer and to build dynamic user interfaces based on user information, “The app provides two types of access roles that need to be authenticated in the login stage: admin and manager. Both roles are able to viow tables, create tables, update tables, and insert entries. Beyond those, the admin role is able to dete tables, while the manager role is not Login UI Users may log in as one ofthe two roles. hitpsshanghal hosting nyu. oduldataricase-4.database-managomont-shiy.himl 22 0130022, 11:10 PM. Creating @ Shiny App for Database Management Please log in ser tame: Grasswort Please use the usernames and passwords provided below to test this database management platform. We have crested two kinds of accounts:manager and admin The ‘admin account allows net alter tables, columns, and records, and delet tables. The manager acount allows ‘one to do everything above except for deleting tables. username password permissions ert passt_ manager — wer passz admin Figure 5. Login. ‘The Login form and button is created with shinyauthr::Loginur() (hitps:rdrio/gthub/PaulC9 /shinyauthrimanviog NUL ht). LogioUT(id = “ogin’ title = "Please log in", user_sitle = "User Nane", pass title = "Password", Login title = “Log in ferron_message = “Tavalid username om password! addstional_si = NULL) Logout UI ‘Once users have logged in, they wil ee the logout button inthe header. Figure 6. Logout. ‘The Logout button is created with shinyauth::logoutUT() (htps:/tdrio/githubyPaulC91/shinyauthr/marvlogoutUL hin). LogoutUI(id = "logout", abel = "Log out", ean = NULL, class = *btn-danger*, style = “color: white; Login credentials hitpsiishanghal hosting nyu eduldataricase-4-database-management-shiny html 0130022, 11:10 PM. Creating @ Shiny App for Database Management In order to make lagging in and logging out function, we followed and adapted the example (putpsrdrioigthub/PaulC3/shinyauthlsrcfinsishiny-examples/shinyauthr_examplelapp R) provided by the author ofthe package shinyauthe, user data First of al, we created a data frame user_pase to store user data, ‘The line of code password_hash = sapply(e("pass2", “pass2"), sodiua::password store) (hlipslipaul.bind.o(shinyauthe) means that user passwords are encrypted with a hashing algorithm withthe sodium (https:igithub.comijeroenfsodium) package to protect stored passwords from brute-force attacks. Later, passwords will be decrypted when login is requested. user_base < data. frame( username = c("usert", “user2"), password = c("passi", “pass2"), password hash = sapply(c("passi", “pass2"), sodiun::password store), peraissions = c("manager", "ada logging in and out ‘We then put the login and logoul Ul as well as the user data table inthe ui function. Note that we must nitate the package shinyjs with shinyjs::usesniny3s() in aur Ul cade for things to work. Library (shiny) Library (shinydashooara) Library(shinyjs) Library (shinyauthe) ui <- aashboardPage( dashooarcHeader( title=", cagssi(), ‘tags$1i(shinyauthe: slogoutur("logout")) ds dashboareSidebar(), dashooardbody( shinyjs::useshinys(), ‘agsshead(tags$style(".table(nargin: @ auto;}"), ‘tags$script (src="https://cdnjs.cloudflare.con/ajax/1ibs/ifrane-resizer/3.5.16/ifraneResizer.conte tiindow.min.js*,types"text/Javascript”), Ancludescrspt(“returnclick.Js")), shinyauthr::loginUz(“login”), uioutput("usen table") ) ) ‘The script relumClickis (htps:i/gist. github .com/PauiC9 1fod5035875305diad50411a37942331 86Hfle-etumclickjs) ensures successful login when a user clicks the Enter key. reactive output Inthe server function, we created login and logout modules that would react to user action and user information, calls the «allModule(login) calls the login module (tipsrdrjolgithub/PauiC9"/shinyauthr/marilogin.himl), ca2 edule (logos logout module (htipsiirdr-jigithub/PaulC3 /shinyauttr/manflogout him). Here, callModute() Invokes a Shiny module; login() land logout() are Shiny madule server functions. hitpsshangha hosting nyu. oduldataricase-4.database-managomont-shry.html 9122 0130022, 11:10 PM. Creating @ Shiny App for Database Management server < function(input, output, session){ ogout_Anit <- caliMedule(shinyauthr: Logout, id = "logout", reactive(credentials()$user_auth)) credentials < caliNedule(shinyauthr::login, id = "login", data = user_base, user_col = usernane, pad_Eol = password hash, sodiun hashed = TAUE, Logout = reactive(ogout_init())) cutputfuser_table <- renderut(( if(credentials()$user_auth) return(WJLL) ‘luidRow(colum(4, p*Please use the usernames and passwords «..", class = “text-center", style = “font-size: 25px;"), bro, renderTable({user_base[, -3]}), offset = 4 » "When we call the login module, it will return a reactive list containing two elements: user_auth and info. user_avth is @ boolean Indicating whether there has been a successful login or not. info isthe user data provided to the function, fltered to the ow, to match the logged in usemame. The inital values of user_auth and info are FALSE and NULL respectively. When user_auth is FALSE, Snfo is NULL When the user gives the correct username and password, user_auth will become TRUE. info wil then become the row of data associated with that user. (Later, in the section below, we will see how user info controls the content displayed in te sidebar menu and the body of the dashboard, based on user permission and other variables.) From tha logout, reactive(credentials()Suser_auth) hides or shows the logout button. When user_auth is TRUE, the logout button willbe visible, Clicking the lagout button will reset user_auth back to FALSE, which will hide the button and show the login panel again From the login, reactiveClogout_init()) triggers @ user logout using the relurned reactive from logout The line of code s¢(credentials()$user_auth) return(NULL) In renderur means thatthe login information user base will only be rendered ina table before a user is logged in; it wll be invisible after a user fs logged in Dynamic UI reacting to user inputs Several Ul outputs ofthis app are reactive to user inputs, For instance, the welcome message in the sidebar wil ether say “Welcome ‘managet” or ‘Welcome admin!" based on the authenticates user role. X number of forms willbe rendered on the fly as a user sets a rhumber in the numeric input When a user selects a table to view from the drop-down menu, a short message describing that table vill be displayed, Values of several drop-down menus will be updated dynamically in response to user actions (e.g, choices of tables will be added to the lst of menu items when a user creates new tables), ‘There are several more cases like these inthis app, which we discuss below. To make these things work, we will be frequently using the function renderui() in server.& in conjunction withthe function usovepue() jn ui.R. rangerut() generates calls to Ul functions and makes the results appear in a predetermined place in the Ul. We will also be using the function paste() often to concatenate what is known and what is dynamically generated, hitpsshanghal hosting nyu. oduldataricase-4.database-managemont-shiy.himl 1022 0130022, 11:10 PM. Creating @ Shiny App for Database Management Embedding {user role! in the welcome message In the sidebar, ater user authentication, a welcome message wil be displayed. Based on the user role, it will either say "Welcome manager!” or ‘Welcome admin", as shown below, Tomo aaa eres eee ena een Figure 7. Dynamically displaying the user role inthe weleome message, How does itwork? As defined inthe server function, after user authentication req(credentials()suser_auth) , user role {user_info()$pernissions> will be embedded in the welcome message. user_info <- reactive((credentials()Sinfo}) curput$uelcone <- rendertext({ dentials()Suser_auth) paste(*Welcone ","", {user_info()$permissions}, "","I") » Displaying {text output] based on user selection In the tab View Tables, the sidebar panel below the drop-down menu, a short message describing the selected table willbe Alisplayed. The description is dynamic, responsive to which table a user selects from the database. Tablesin Database customer information, including customer id, name, email, gender, cit, state, and date of bith Tablesin Database order. items = Order items information, including order id, product, and vont. hitpsshanghal hosting nyu. eduldataricase-4.database-managomont-shiy html i122 0130022, 11:10 PM. Creating @ Shiny App for Database Management ‘ables in Database test table = This is table created by you or other users. Figure 8. Dynamically displaying table descriptions based on user selection. ‘To make it work, we frst create a table_intro list that stores the descriptions of two kinds of tables. These include the original tables, in the database, and tables that vill be created by any user, named other table_intro < List(custs = “Customer information, including custorer {4 ...", prods. n, Ancluding product 4¢ ...", stores = "Store information, including store id ...", orders = “Orders information, including order 3¢ ...", order _stens = "Order tens information ...", other = “This is a table created by you or other users. = "Product inform: We then use renderur() to render reactive HTML ina vextoutput() .In the extoutput (output ‘tab_ntro), fa selected table (input id "sel table_1")is one ofthe existing tables c(custs","order_ttens", “orders”, "prods_t*, "stores" , ts description willbe rendered accordingly. Otherwise, the description willbe “Ths s a table created by you or other users.” AStablur <- rendert req(credentials()Suser_auth) box(uidth = NULL, status sidebarLayout( ‘sidebarPanel( primary", box(), selectInput inputrd = “sel_tablea abel = "Tables in Database”, choices = dbListTables(db), selected = "custs! d textoutput(outputtd = “tab_intro"), ‘tagsshead(tags$style("#tab_intret font-size: 15px; font-style: italic; oo) » rnaineanel() > » {$se1_table_view <- renderbatarable() cutputStab_intro <- renderText( AF (inputssel_table_1 Xint c("custs","orden_itens", "orders", "prads_i", "stores")) {table sntro[[input$sel_table_s}}) else (Fable_introsother} ) Rendering {X} number of forms In the tab Croate Tables, users have the option to set how many columns that a new table will have in the numeric input Number of columns. Once a user fils in @ number X, X forms willbe rendered dynamically and immediately, In these forms, a user can further set the column name inthe text input Column name and set the column type in the select input Column type. hitpsshanghal hosting nyu. eduldataricase-4.database-managomont-shiy html 122 0130022, 11:10 PM. Creating a Shiny Ap for Database Management For instance, ifwe fil n 4" inthe numeric input Number of columns, 4 forms wil be rendered where we can define each column's nam and type. For the tile of each form, the index ofthe form will also be allached, which wil look ike “Column I. In this case, they are "Column Figure 9. Dynamically rendering forms. Now we will describe how to generate these dynamic forms, ‘There are two groups of Ul outputs here. The frst group of Ul outputs take care of user inputs. We have a text input Table name, a numeric input Number of columns for users to input the number af dynamic forms to be rendered below, and an action button Create {able to submit the form, We use box() {0 house these elements. outputStabaur <- renderur(( req(credentials()Suser_auth) ox(width = HLL, status = "primary" CextInput(inputTd = “table pane", label = "Table nase"), unericinput(ingutid = "ncols", label = "Nunser of columns", 1, min = 2), output (outputrd = “cols"), actionButton(inputTd = “create table", Label = “Create table”, class = btn-info", style = » Inthe second group of UI outputs, the dynamic forme will be rendered with utoutput() and renderUL() . usovtput() creates an HTML output element; renderut() renders reactve HTML. For each of these forms, we have a text input Column name and a select input Column type. outputscois <- renderT(( rreq(input$ncols >= 1) cols <- vector(*Iist", Input$ncols) for (4 tn seq len(nput$ncols)) { cols[ [iT] <= box( ‘title = paste("Colunn", §), width = 6, solideader = TRUE, status = “primary”, toxtInput(inputId = paste@("coINane", 1), 1abel = selectInput(inputld = paste@(*colType", i), label = ‘chokes = c(°MNERIC", cols » itpsiishanghal hosting nyu eduldataicase-4-database-management-shiny html 1322 0130022, 11:10 PM. Creating @ Shiny App for Database Management Inthe code chunk above, the numberof forms to be rendered is defined by the user inthe numeric input (id = then runs through each form cols[{s]] fram the fst to the last elament inthe user input cols 1cols") The program or (A. sn seq_len(nput$ncols)) { cols{[i]] © box() » Each form cols{[4]] is tendered dynamically. The title of each form is also dynamically generated: the index of each form is embedded in the ie with paste(*coluan", 4) ‘Additionally, the input ids associated with each output are dynamic. The input id of the column name is generated by pastea("colNane", 1) ;the input id ofthe column type is generated by pastea("colType", 1) For both inputs, the form index is built nto the ids so that each output is mapped to each input Updating {values} of select inputs “Tne choces ina drop-down menu, or values ofa select input, can be dynamicaly updated in response to user actions. Far instance, after we create a table and adit othe database, as shown n Figure 9 the choiees in several drop-down menus wl also need to be Updated, Therefore, users wil always have the up-to-date list of able names and column names fo choose from when they View tables, update tales and columns, insert entes, and delete tables. For example, in Viow Tables, the name of the newly created table needs to be added tothe drop-down menu Tablos in Database, where users select a table to view. a Figure 10. Dynamically updating values ofa select input to view tables. In Update Tables, the name ofthe new table and its elds need to be added to the drop-own menus in the forms Rename Table, Rename Column and Add Column go that the choices are up ta date, Figure 11. Dynamically updating values of select inputs to rename a table, rename a column and add a column. Likewise, in Insert Entries and Delete Tables, the new table is added tothe ist. hitpsshanghal hosting nyu. oduldataricase-4.database-managomont-shiny.himl 1422 0130022, 11:10 PM. Creating @ Shiny App for Database Management Figure 13, Dynamically updating values of a select input to delete a table, ‘To update the values ofthe select inputs as described above, we use the function updateselectInput(session, inputtd, choices) « For instance, after we create a new table in the database do , we have an updated list of able names dbLstrables(ab) , Inclueing the name of the new table. Therefore, al select inputs whose values are tables names will ned to be updated For instance, the code block below updates the values ofthe gelect input fr viewing tables (input id= “sel_table_1"). updateselectinput(session, “sel_table.i", choices = cblistTables(ab)) ‘There are several other select inputs whose values are tables names, These are selec inputs for deleting table, renaming column, adding column, renaming table, and inserting values. But in these select inputs, we only allow for newly ereated tables to be modifed. ‘Therefore, in the code block below, we use setaitf() to remove the names ofthe original tables in the database from the choices in those select inputs, for (sel_input in ("sel_table_2","sel_table_3","sel_table_3_1","sel_table_3_11","sel_table_5*)){ updateselectInput(session, sel_input, choices = sotdiff(dotistrables(db), ("cust “order stems", “orders, "prods_s*,"stores*))) "When we need to update select inputs of column names, the choices are colnares() instead of biistTables() . The example below updates column names in the resuling data extracted from the database, stored in 4 updateselectinput(session, |) choices = colnanes(d)) Rendering {input} types matched with predefined data types In Insert Entries, after we select a table, the column name predefined by user will appear inthe tile ofthe form together with its predefined column type. Both have been set by users in Create Tables. hitpsshanghal hosting nyu. oduldataricage-4.database-managomont-shiny.himl 1922 0130022, 1:10 PM. Creating @ Shiny App for Database Management Figure 14, Rendering input types matched with predefined data types. ‘There are four preset data types in Groate Tables: NUMERIC, VARCHAR(2S8), BOOLEAN and DATE. In Insort Entries, users may further insert records for each predefined column, as shown above, Ifa predefined column type is NUMERIC, users will ee a numeric input o insert numbers. If predefined column type is BOOLEAN, users will see radio buttons with values “True” or "False" la predefined column type is string, users wil see a text input to type characters. Finally, if a predefined column type is DATE, users will $60 a date input o pick a date. ‘Caxle chunk below generates the input type for users ta insert entries that is matched with the predefined datatype of a column, and ‘embeds the column type inthe tle ofthe for. cutputsvaiues <- renderur(( 4 UE outputs rendered in the place that has an uiOutput i¢ “values” req(isTruthy (Input$sel_table_s)) values <- List) 4 dosetquery( conn = db, statenent = paste@(*SELECT * fron *,Snput$sel_table5) > typ < docerquery( conn = db, staterent = pasteo( "PRAGMA table_info(’,input$sel_table_s,")') > for (col in colnames(d)) { typ = typstypel typ$nane valuest{col]] <- boxt title = partea(as.character(cel)," ytye4,'2"), width = 6, solidveader = TRUE, status = "primary", 1) if (typ "BOOLEAN") {radioButtons(inputTd = pastea("value*, col), label ‘eCTRUE®,“FALSE) )> else Sf (typ A <= "MUMEREC™ | typ_t == “FLOAT” | ‘typi == TINTEGER™ | typ_t == "NUM" ) {nusericInput (SnputId = pastea("vaiue", col) else SF (typ abel = "Value", value = @)) DATE") (dateTnput(InputTd = paste@("value", col), abel = “Value”, value = "2020-12-@2") } else (tagList(useshinyFeedback(), ‘textinput(inputld = pastea("value", col), Zabel = "Value"))} ) > values » hitpssishanghal hosting nyu eduldataicase-4-database-management-shiny html 16122 0130022, 11:10 PM. Creating @ Shiny App for Database Management PRAGMA table. info statement ‘As shown in the code above, rst we make sure there are user inputs in the select input Select Tab (id = “sel table_5") with req(isTrothy(ingut$sel_table_5)) . We then select data from our database and store the rotumed data in a result table Next, we query information about the table we selected, stored in typ , using SOLte statement PRAGHA [database. ]table_info( table naxe ); ‘The result from the PRAGMA table_in‘o (hitos:/hvuw.sqite.orgipragma.htmipragma_table_info) statement contains one row for each column in the table we are asking about. Columns in the returned data include the column name, datatype, whether or not tne column can be NULL, and the default value forthe column. The “pk” column is zero for columns that are not part ofthe primary key, and isthe index of the colurmn in the primary key for colurnns that are part of the primary key, cid name type notnull dft_value Pk ° ia NUMERIC ° NA ° name VARCHAR(255) ° NA ° 2 pass BOOLEAN ° NA ° 3 date DATE ° NA ° embedding column type in the form title For each column in the returned data 4, we retrieve its data type and addi othe form tive. for (col in colnanes(é)) { typi > typstypeltyptnane--col) values{[¢ol]} < box( title = pastea(as.character(col)," ('styP4,")')s rendering the correct input type Finaly the correct input type is rendered, which is matched withthe predefined datatype, where users may insert entries for the column, Making sure the SQL parts work in Shiny “There are numerous ways to break our app, especially when we are not careful enough with the SQL parts, HI, THIS 'S OH DEAR - DID HE | DID YOU REALLY WELL, WEVE LOST THIS YOUR SONS SCHOOL. | BREAK SOMETHING? | NANE YOUR SON YEAR'S STUDENT RECORDS. VERE HAVING SOME | ya ay Robert’); DROP HOPE YOURE HAPPY. COMPUTER TROUBLE: (TABLE Stuse { ay x x AND T HOPE s OH, YES UTE YOUVE LEARNED é Ti BOBBY TABLES, TOSMIMZE YOUR /\ WE CALL HIM. DATABASE INPUTS. Figure 15. Exploits of a Mom. Source: hips Diked.com/3271 (hipsdiked com/3277) Invalid table name hitpsshanghal hosting nyu. oduldataricase-4.database-managomont-shiy html se 0130022, 11:10 PM. Creating @ Shiny App for Database Management In our app, there are several scenarios where the app may fall to function properly. For instance, when creating a new table or rename an existing fable, have we go! the table name right? In aur app, a modal box with an ale message will pop up if) the table already exis in the database, 2) the table name is blank, or if) Its an invalid table name, Figure 16. Alert for invalid table name. AF (tolower(inputStable_nane) ink tolover(doListTables(de)) | istruthy(inputstable_nane) | grepl("*[a-zA-Z_][a-zA-20-9_]*$", inputStable_nane) == FALSE) { shoaedal (noda10ia108¢ title = "Invalié table name", You get this message possibly because 2) the table already exists; 2) the table nane is blanks for 3) this is an invalid table nare.", Footer = nodalButton("OK"), easyClose = TRUE ) ) retuen() > ‘Additionally, there might be no value in the input to indicate number of columns, or the input value of column number is smaller than ine. We have fo make sure none of these happens once a user clicks the action button (id =“create_table”) to create the table. 4 make sure there ds value in the input Af (LisTruthy(inpat$neols)) ( shonodal nodalDialog( title = "invalic table nane", "please type in the right colunn nuaber.", jodalsuttan("0K"), easyClose = TRUE ) ) ? 4 make sure the input value of column nunber is larger than one Af (Anputsncols < 1) { shontiodal (nodaiDiaiog( ‘title = "No coluens, reach table must have one or nore colunns.", Footer = modalButton("OK"), easyClose = TRUE » ? Invalid column name hitpsshanghal hosting nyu. oduldataricase-4.database-managemont-shiy.himl 18122 0130022, 11:10 PM. Creating @ Shiny App for Database Management When creating a new table, renaming a column, or adding a coulmn, an alert message will pop up ifthe column name is invalid. Itis lriggered when 1) one or mare fields are blank, 2) one oF mare fields contain invalid SQLite column name(s), 3) there are duplicate column names, or when 4) one or more felds conflict with @ SQLite keyword (tips /iwmv.sqite.orglang._ Keywords, htm) Figure 17. Alert for invalid column name, 4 gather al col_panes_list = 1ist() for (4 in seq_len(input$ncols)) { col_nanes list ¢- ¢(col_nanes_list, in ? {e{[pastea("coiNane”, 4)})) 4 make sure the coluen mane 4 valid 46 ( any(col_nanes_list ==") | sun(duplicated(col_nanes_List)) > 0 | any (grepl("*[a-2A-2_][a-2A-20-9_]*$",col_nanes_list) « any(tolower(col_panes_List) tink sqlite kw_t0) ) ( shoodal (noda0ia108( ‘title = "Invalic column ane”, You get this ressage possibly because 41) the colunn nare already exists; 2) the field fs blanks 3) this is an invalid SQLite coluen name; for 4) the Field nane conflicts with 2 SQLite keyword footer = modalbutton("OK"), easyclose = TRUE » return() > Compiling SQLite queries Finally, we have to make sure the SQLite statements are compiled correctly, hitpsshanghal hosting nyu. oduldataricase-4-database-managomont-shny.himl 1922 0130022, 11:10 PM. Creating @ Shiny App for Database Management observetvent(inpurgcreate_table, { ‘t make sure table nase is not the same as an existing table in the database, blank, or invalié 00 4 make sure there is value in the input Od 4 make sure the input value of coluen number is larger than one else 16.0 0 else { 4 gather all 4 make sure the coluon nane is valid Oo 1¢ column names into a list 4 compite query query < paste®("CREATE TABLE *,inputStable_nane,” (°) for (J in seq_ten(inputsncols)) { query < pasteB(query, input{[paste@("colNane", £)]]," ‘yinput([paste@(“coltype", 1))]."s') ? query < paste@(str_sub(query,2,-2),")") ace query( conn = db, staterent = query } HAF successful, update inputs updatenuneriernput(session, "neo! value = "2") updateTexcinput (session, "table_nane”, value = ° in c("sel_table_2","sel_table_3","sel_table 3 i", "sel nput(session, sel_input, cholces = sotdiFf(ebListrables(sb), able_3_1i","sel_tables°)) ( updateSelectInput(session, “sel_table shontiodal (noda10{a108( 1 choices = abListTables(db)) "the table has been successfully created.” footer = modalButton("0t"), easyClose = TRUE) ) » ‘Web development in Shiny This isa “Praise Shiny” list. As you may have heard many times, you don't ned fo know HTML, CSS and JavaScript to build a web app with Shiny. Indeed, the powerful Shiny functions and add-on packages have made creating a Shiny web app flexible and intuitive. Layout and style By default, Shiny uses Bootstrap, the most popular HTMLICSS framework for developing responsive, mobile fst projects on the web. layout features Shiny provides @ numberof layout features to arrange the components of an application, made available via Bootstrap, many of ‘hich we have seen earlier. These include functions such as fluidPage() , fluidRow(), sidebartayout() , sidebarPanel() nain?anel() , and well?anel() , and the package shinydashboard that we rely onto structure the Ul ofthis app. HTML tags We used the HTML tags in our Shiny Ul or custom HTML and CSS, With the help ofthe tags functions, we were able to write HTML using R functions. hitpsshanghal hosting nyu. oduldataricage-4-database-managomont-sniy.himl 20122 0130022, 11:10 PM. Creating @ Shiny App for Database Management ashooarebleader( Le = span("Database Managenent Platforn", style titlenidth = 369, ‘tagssii(class = “éropdown" tagsta("Pinetpple Database", style = “color: white")), ‘agsSii(class = “éropdown", ‘tagsSaCing(sre = "pineapple_logo.prg", height = 28), href = “hetps://yundal.shinyapps. 10/2028-business-intelligence/", title = "check out the Pineapple Sales Dashboard!*)), s$Li(class = “éropdown", style = "padéing: 8px;", ‘shinyauthe: logout (“Iogout")) font-size: 28x"), ‘We were also able to add custom CSS class with the tags functions ‘The code chunck below appeared where we discussed displaying dynamic text outputs based on user selection, extoutput(outputld = “tab_intro"), agsShead{tagsSstyle("#tab_introt font-size: 5px; font-style: italic; YD Shiny provides many HTML builder functions (hipsilishiny rstudio.convreference/shiny/1 5. Ofbuilder html). The tags environment contains convenience functions for al vad HTMLS tags. modal dialog ‘We used the modal functions to create modal dialogs. nodaloialog() createa a modal dialog UI. showoda1() shows a moda dialog shostiedal (nodalDiaiog( title » "Invalid colunn nane", ‘You get this nessage possibly because 2) the colunn nate already exists; 2) the Field is blank; 3) this 1s an invalid sqLite colunn nane; for 4) the field nane conflicts with a SgLite keyword.", footer = nodalsutton("0K"), easyClose = TRUE )) Font Awesome In Shiny, we can eroate icons withthe function icon() (httpsifshinyrstudlo.comreferencefshiny1.5.0Fcon.him)). loons are drawn {rom the Font Awesome Free and Glyphicans lars. UI Inputs We allowed user inputs with several UI input functions, including selec to create drop-down menus, tex inpuis, numeric inputs and date inputs respectively (), textangut() , nunerdeznput() and dateznpus() ‘The values ofthese inputs can be updated with functions updateselectinput() , vpdateTextinput() , upéateMunerscInput() , and updatepateraput() respectively We also used the function actionsutten() to create action buttons. Writing JavaScript In Shiny, we get to enjoy the beauty of JavaScript without nesding to lear its technical details hitpsshanghal hosting nyu. oduldataricase-4.database-managomont-shiry html 211e2 0130022, 1:10 PM Creating @ Shiny App for Database Management shinyjs ‘Wo used te package shiny (hpsiideanatal.comyshiyjs to help us perform common useful JavaSerpt operation in ur app. observe({ ir(credentials()Suser_avth) ( shinyjs::renoveClass(selector = "body", class = y else ( shinyys::addclass(selector > ‘sidebar-collapse") body", class -sidebar-collapse") » req(), istruthy() We have used the functions req() and istruthy() (hipsilishinyrstudio.comireference/shiny/t§.Olreq.htmi) to check for required values many times, {steuthy() evaluates whether a value is missing or available, the user inputs available, or whether the button has been clicked, req()_can be called like a statement betore attempting operations using the required values, or can be used to wrap an expression that must be wuthy. For instance, we used req(credentiais()Suser_auth) to set the code to only run after a successful login, In one example, we used req(credentiais()$user_auth) inside the function rencerTable() to ensure thatthe table showing the returned user information Is only rendered when user_auth is TRUE, We used req(inputsncels >= 1) to Sot the code to only run when the user input ofthe numberof columns is larger than or equal to We used req(isrruthy(inpur$sel_table_5)) to set the code to only run when there is user input in the select input Select Table in the tab Insert Values. hitpsshanghal hosting nyu. oduldataricase-4.database-managemont-shiy.himl 22102

You might also like