diff --git a/.gitignore b/.gitignore index 5b6a065..7b732e7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .Rhistory .RData .Ruserdata +.DS_Store diff --git a/app/logic/__init__.R b/app/logic/__init__.R deleted file mode 100644 index 51c4357..0000000 --- a/app/logic/__init__.R +++ /dev/null @@ -1,2 +0,0 @@ -# Logic: application code independent from Shiny. -# https://go.appsilon.com/rhino-project-structure diff --git a/app/main.R b/app/main.R index 8cd1b74..ba01871 100644 --- a/app/main.R +++ b/app/main.R @@ -25,6 +25,7 @@ box::use( app/view/mod_app_table, app/view/mod_job_list, app/view/mod_logs, + app/view/mod_header, app/logic/api_utils[get_app_list] ) @@ -33,17 +34,27 @@ ui <- function(id) { ns <- NS(id) fluidPage( class = "dashboard-body", + mod_header$ui("header"), div( - class = "app-table", - mod_app_table$ui(ns("app_table")) - ), - div( - class = "job-list", - uiOutput(ns("job_list_pane")) - ), - div( - class = "logs", - uiOutput(ns("logs_pane")) + class = "dashboard-container", + div( + class = "app-table", + mod_app_table$ui(ns("app_table")) + ), + div( + class = "vertical-line" + ), + div( + class = "job-list", + uiOutput(ns("job_list_pane")) + ), + div( + class = "vertical-line" + ), + div( + class = "logs", + uiOutput(ns("logs_pane")) + ) ) ) } @@ -54,6 +65,8 @@ server <- function(id) { ns <- session$ns + mod_header$server("header") + state <- reactiveValues() state$selected_app <- reactive({}) state$selected_job <- reactive({}) diff --git a/app/static/appsilon-logo.png b/app/static/appsilon-logo.png new file mode 100644 index 0000000..973de3d Binary files /dev/null and b/app/static/appsilon-logo.png differ diff --git a/app/static/css/app.min.css b/app/static/css/app.min.css index 4962e5a..0ed24aa 100644 --- a/app/static/css/app.min.css +++ b/app/static/css/app.min.css @@ -1 +1 @@ -.red-text{color:#a50e0e}.green-text{color:#3a5a40}.yellow-text{color:#a58e0e}.red-highlight{background-color:rgba(252,232,230,.3137254902)}.green-highlight{background-color:rgba(224,240,223,.3137254902)}.yellow-highlight{background-color:rgba(240,235,187,.3137254902)}.red-text{color:#a50e0e}.green-text{color:#3a5a40}.yellow-text{color:#a58e0e}.red-highlight{background-color:rgba(252,232,230,.3137254902)}.green-highlight{background-color:rgba(224,240,223,.3137254902)}.yellow-highlight{background-color:rgba(240,235,187,.3137254902)}.logs .rt-td-inner{padding:0 !important}.logs>div{text-align:center}.logs>div .empty-state-container{margin-top:10%}.logs>div .empty-state-container .empty-state-image{width:50%}.logs>div .empty-state-container .empty-state-text{color:gray;margin-bottom:40px}.logs-container{position:relative}.logs-container .log-entry{display:flex;align-items:center;gap:20px;padding:10px;margin:5px 10px}.logs-container .log-entry i{font-size:1.5em}.logs-container .log-entry .log-info-block{display:flex;flex-direction:column;gap:10px}.logs-container .log-entry .log-info-block .log-info{font-weight:600}.logs-container .log-entry .log-info-block .log-time{font-size:.75em}.logs-container .logs-download{position:absolute;z-index:2;right:0;margin:10px;background:0;border-radius:0;padding:5px 10px}.wrapper{background:none !important}.content-wrapper{background:#fff;color:#333;height:90vh;font-family:"Segoe UI VSS (Regular)","Segoe UI",sans-serif}.dashboard-body{display:flex;flex-direction:row;padding:0;height:92.5%}.dashboard-body .Reactable{background:rgba(0,0,0,0)}.dashboard-body .rt-search{width:80%;margin:10px;align-self:center;text-align:center;border-radius:0}.dashboard-body .rt-tr-header{display:none !important}.dashboard-body .rt-tr{align-items:center}.dashboard-body .rt-tr-selected{background:rgba(0,0,0,.062745098)}.dashboard-body .app-table{background:#eaeaea;border-right:#d8d8d8 solid 1px;width:20%;height:100%;overflow-y:auto}.dashboard-body .job-list{background:#f8f8f8;border-right:#eee solid 1px;width:15%;height:100%;overflow-y:auto}.dashboard-body .logs{background:#fff;width:65%;height:100%;overflow-y:auto}.app-entry{display:flex;flex-direction:column;width:100%}.app-entry .app-title{font-size:1.1em}.app-entry .app-link-icon{font-size:.5em;margin-left:10px;margin-bottom:10px}.app-entry .app-metadata{display:flex;flex-direction:column;gap:5px;color:gray;font-size:.75em}.red-text{color:#a50e0e}.green-text{color:#3a5a40}.yellow-text{color:#a58e0e}.red-highlight{background-color:rgba(252,232,230,.3137254902)}.green-highlight{background-color:rgba(224,240,223,.3137254902)}.yellow-highlight{background-color:rgba(240,235,187,.3137254902)}.job-entry .job-key,.job-entry .job-start-time,.job-entry .job-end-time{font-size:.75em;color:gray} +@import"https://fonts.googleapis.com/css2?family=Maven+Pro:wght@400;600&display=swap";.red-text{color:#a50e0e}.green-text{color:#3a5a40}.yellow-text{color:#a58e0e}.red-highlight{background-color:rgba(252,232,230,.3137254902)}.green-highlight{background-color:rgba(224,240,223,.3137254902)}.yellow-highlight{background-color:rgba(240,235,187,.3137254902)}.red-text{color:#a50e0e}.green-text{color:#3a5a40}.yellow-text{color:#a58e0e}.red-highlight{background-color:rgba(252,232,230,.3137254902)}.green-highlight{background-color:rgba(224,240,223,.3137254902)}.yellow-highlight{background-color:rgba(240,235,187,.3137254902)}.logs .rt-td-inner{padding:0 !important}.logs>div{text-align:center}.logs>div .empty-state-container{margin-top:150px}.logs>div .empty-state-container .empty-state-image{width:50%}.logs>div .empty-state-container .empty-state-text{color:gray;margin-bottom:40px}.logs-container{position:relative}.logs-container .log-entry{display:flex;align-items:center;gap:20px;padding:10px;margin:5px 10px}.logs-container .log-entry i{font-size:1.5em}.logs-container .log-entry .log-info-block{display:flex;flex-direction:column;gap:10px}.logs-container .log-entry .log-info-block .log-info{font-weight:600}.logs-container .log-entry .log-info-block .log-time{font-size:.75em}.logs-container .logs-download{position:absolute;z-index:2;right:0;margin:10px;background:0;border-radius:0;padding:5px 10px}.wrapper{background:none !important}.content-wrapper{background:#fff;color:#333;height:90vh}.dashboard-body{display:flex;flex-direction:column;padding:0}.dashboard-body .dashboard-container{display:flex;flex-direction:row;height:100vh}.dashboard-body .Reactable{background:rgba(0,0,0,0)}.dashboard-body .rt-search{width:80%;margin:10px 10px 20px 10px;align-self:center;text-align:center;border-radius:0}.dashboard-body .rt-tr-header{display:none !important}.dashboard-body .rt-tr{align-items:center}.dashboard-body .rt-tr-selected{background:rgba(0,0,0,.062745098)}.dashboard-body .app-table{width:30%;height:100%;overflow-y:auto}.dashboard-body .job-list{width:15%;height:100%;overflow-y:auto}.dashboard-body .logs{background:#fff;width:55%;height:100%;overflow-y:auto}.app-entry{display:flex;flex-direction:column;width:100%}.app-entry .app-title{font-size:1.1em}.app-entry .app-link-icon{font-size:.5em;margin-left:10px;margin-bottom:10px}.app-entry .app-metadata{display:flex;flex-direction:column;gap:5px;color:gray;font-size:.75em}.red-text{color:#a50e0e}.green-text{color:#3a5a40}.yellow-text{color:#a58e0e}.red-highlight{background-color:rgba(252,232,230,.3137254902)}.green-highlight{background-color:rgba(224,240,223,.3137254902)}.yellow-highlight{background-color:rgba(240,235,187,.3137254902)}.job-entry .job-key,.job-entry .job-start-time,.job-entry .job-end-time{font-size:.75em;color:gray}.header{display:flex;width:100%;align-items:center;justify-content:space-between;gap:10px;margin-bottom:20px}.header .header-section{display:flex;align-items:center;gap:10px}.header .left img{width:200px}.header .left h2{margin:0;margin-bottom:5px;margin-left:20px}.header .left .vertical-line{height:50px}.header .right .cta-button{background:#0099f9;color:#fff;padding:10px;border-radius:10px;margin:0 10px}*{font-family:Maven Pro,"sans-serif"}.vertical-line{border-left:1px #eee solid;height:80%;align-self:center} diff --git a/app/static/empty_state.svg b/app/static/empty_state.svg index ff8f2cf..f64d1ee 100644 --- a/app/static/empty_state.svg +++ b/app/static/empty_state.svg @@ -1 +1,32 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/static/rhino.png b/app/static/rhino.png new file mode 100644 index 0000000..b46cf47 Binary files /dev/null and b/app/static/rhino.png differ diff --git a/app/styles/_colors.scss b/app/styles/_colors.scss index 7b0e880..9c7f1cb 100644 --- a/app/styles/_colors.scss +++ b/app/styles/_colors.scss @@ -13,6 +13,7 @@ $white: white; $grey-text: grey; $black-text: #333; $selected-row: #00000010; +$appsilon-blue: #0099f9; .red-text { color: $red; diff --git a/app/styles/_dashboard.scss b/app/styles/_dashboard.scss index 79674e1..134570b 100644 --- a/app/styles/_dashboard.scss +++ b/app/styles/_dashboard.scss @@ -6,14 +6,18 @@ background: $white; color: $black-text; height: 90vh; - font-family: "Segoe UI VSS (Regular)", "Segoe UI", sans-serif; } .dashboard-body { display: flex; - flex-direction: row; + flex-direction: column; padding: 0; - height: 92.5%; + + .dashboard-container { + display: flex; + flex-direction: row; + height: 100vh; + } .Reactable { background: transparent; @@ -21,7 +25,7 @@ .rt-search { width: 80%; - margin: 10px; + margin: 10px 10px 20px 10px; align-self: center; text-align: center; border-radius: 0; @@ -40,16 +44,12 @@ } .app-table { - background: $grey1; - border-right: $grey1-border solid 1px; - width: 20%; + width: 30%; height: 100%; overflow-y: auto; } .job-list { - background: $grey2; - border-right: $grey2-border solid 1px; width: 15%; height: 100%; overflow-y: auto; @@ -57,7 +57,7 @@ .logs { background: $white; - width: 65%; + width: 55%; height: 100%; overflow-y: auto; } diff --git a/app/styles/_header.scss b/app/styles/_header.scss new file mode 100644 index 0000000..b959d4e --- /dev/null +++ b/app/styles/_header.scss @@ -0,0 +1,40 @@ +.header { + display: flex; + width: 100%; + align-items: center; + justify-content: space-between; + gap: 10px; + margin-bottom: 20px; + + .header-section { + display: flex; + align-items: center; + gap: 10px; + } + + .left { + img { + width: 200px; + } + + h2 { + margin: 0; + margin-bottom: 5px; + margin-left: 20px; + } + + .vertical-line { + height: 50px; + } + } + + .right { + .cta-button { + background: $appsilon-blue; + color: white; + padding: 10px; + border-radius: 10px; + margin: 0 10px; + } + } +} diff --git a/app/styles/_logs.scss b/app/styles/_logs.scss index a414864..5f4535e 100644 --- a/app/styles/_logs.scss +++ b/app/styles/_logs.scss @@ -9,7 +9,7 @@ text-align: center; .empty-state-container { - margin-top: 10%; + margin-top: 150px; .empty-state-image { width: 50%; diff --git a/app/styles/main.scss b/app/styles/main.scss index 847a889..f7e4c7e 100644 --- a/app/styles/main.scss +++ b/app/styles/main.scss @@ -1,5 +1,17 @@ +@import url('https://fonts.googleapis.com/css2?family=Maven+Pro:wght@400;600&display=swap'); @import "colors"; @import "logs"; @import "dashboard"; @import "app_table"; @import "job_list"; +@import "header"; + +* { + font-family: Maven Pro, 'sans-serif'; +} + +.vertical-line { + border-left: 1px $grey2-border solid; + height: 80%; + align-self: center; +} diff --git a/app/view/mod_header.R b/app/view/mod_header.R new file mode 100644 index 0000000..999f176 --- /dev/null +++ b/app/view/mod_header.R @@ -0,0 +1,50 @@ +box::use( + shiny[ + NS, + moduleServer, + div, + img, + h2, + icon, + actionButton, + actionLink + ] +) + +#' @export +ui <- function(id) { + ns <- NS(id) + div( + class = "header", + div( + class = "left header-section", + img( + src = "static/appsilon-logo.png", + alt = "Appsilon logo", + href = "https://demo.appsilon.com" + ), + div( + class = "vertical-line" + ), + h2( + "LogAnalyzer" + ) + ), + div( + class = "right header-section", + actionLink( + "lets-talk", + label = "Let's Talk", + class = "cta-button", + onclick = "window.open('https://appsilon.com/#contact', '_blank');" + ) + ) + ) +} + +#' @export +server <- function(id) { + moduleServer(id, function(input, output, session) { + + }) +} diff --git a/strings.yml b/strings.yml new file mode 100644 index 0000000..d4c9b7c --- /dev/null +++ b/strings.yml @@ -0,0 +1,23 @@ +about: + intro: "Shiny Drug Flow helping pharmaceutical manufacturers to track the quality and performance of their manufactured batches" + about_project: "The main goal for the App Sprint was to create a life sciences dedicated application for visualizing the whole manufacturing process for a pharmaceutical ingredient that allows the end-users to identify whether or not a given batch falls within the quality standards." + dataset_info: "The app uses data shared in an article linked below. Laboratory.csv file downloaded from the Dataset link is used by API created in Rust for fetching the data." + missing_note: "Incoming Raw Materials and Manufacturing app views are not implemented yet." +references: + link1: + name: "Article" + link: "https://www.nature.com/articles/s41597-022-01203-x" + link2: + name: "Dataset" + link: "https://doi.org/10.6084/m9.figshare.c.5645578.v3" +powered_by: + rhino: + name: "Rhino" + link: "https://appsilon.github.io/rhino/" + img_name: "rhino.png" + desc: "Rhino is an Open-Source Package developed by Appsilon to + help the R community make more professional Shiny Apps. Rhino allows you to + create Shiny apps The Appsilon Way - like a fullstack software engineer. + Apply best software engineering practices, modularize your code, + test it well, make UI beautiful, and think about user adoption + from the very beginning."