From 6aeb4d5a63d02ffb8fbfbdf57af43e23695766f2 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Thu, 24 Jul 2025 15:26:17 +0530 Subject: [PATCH 1/2] Add login/logout app example with dynamic UI Introduced a new Shiny app demonstrating login and logout functionality using dynamic UI rendering based on authentication state. Updated index.qmd to document and showcase the new example, including preview and code links. --- .../outputs/ui/app-variation-login-core.py | 75 +++++++++++++++++++ components/outputs/ui/index.qmd | 11 +++ 2 files changed, 86 insertions(+) create mode 100644 components/outputs/ui/app-variation-login-core.py diff --git a/components/outputs/ui/app-variation-login-core.py b/components/outputs/ui/app-variation-login-core.py new file mode 100644 index 00000000..4bdd937b --- /dev/null +++ b/components/outputs/ui/app-variation-login-core.py @@ -0,0 +1,75 @@ +from shiny import App, ui, render, reactive + +USERS = {"admin": "password123", "user": "mypass"} + + +def login_ui(): + return ui.page_fluid( + ui.h2("Login"), + ui.input_text("username", "Username", placeholder="Enter username"), + ui.input_password("password", "Password", placeholder="Enter password"), + ui.input_action_button("login_btn", "Login"), + ui.output_text("login_status"), + ui.br(), + ui.card( + ui.h2("Demo credentials:"), + ui.div("admin / password123"), + ui.div("user / mypass"), + ), + ) + + +def dashboard_ui(): + return ui.page_fluid( + ui.h1("Dashboard"), + ui.output_text("current_user_display"), + ui.input_action_button("logout_btn", "Logout"), + ) + + +def server(input, output, session): + authenticated = reactive.Value(False) + current_user = reactive.Value("") + + @reactive.Effect + @reactive.event(input.login_btn) + def handle_login(): + username = input.username() + password = input.password() + + if USERS.get(username) == password: + authenticated.set(True) + current_user.set(username) + else: + authenticated.set(False) + current_user.set("") + + @reactive.Effect + @reactive.event(input.logout_btn) + def handle_logout(): + authenticated.set(False) + current_user.set("") + + @render.ui + def dynamic_ui(): + if authenticated(): + return dashboard_ui() + else: + return login_ui() + + @render.text + def login_status(): + if not authenticated() and input.login_btn() > 0: + return "Invalid credentials. Please try again." + return "" + + @render.text + def current_user_display(): + if user := current_user(): + return f"You are logged in as: {user}" + return "" + + +app_ui = ui.page_fluid(ui.output_ui("dynamic_ui")) + +app = App(app_ui, server) diff --git a/components/outputs/ui/index.qmd b/components/outputs/ui/index.qmd index 63ddbe17..3d3fb221 100644 --- a/components/outputs/ui/index.qmd +++ b/components/outputs/ui/index.qmd @@ -57,6 +57,17 @@ listing: - title: Core file: app-variation-update-an-input-core.py shinylive: https://shinylive.io/py/editor/#code=NobwRAdghgtgpmAXAAjFADugdOgnmAGlQGMB7CAFzkqVQDMAnUmZAZwAsBLCXZTmdKQYVkAQUxEG1ACZwGRAK6cAOhFUZ0AfSXIAvMiU4oAczia6AGyXSAFKuQODnLBai5SCiprJWYEVnYQjsFOWNzonpoMUNKcpJoARp4U5AH2IRnKYDCksllEWQAinKzorrw5eYTIwFkAKlAJFnD5yFkAChakFFkAukSscM3EVNK69Y3NWekZAJQEMyGGHhQRXkp22blmZJRMFqxZ84uzqqdqF7J0bHIAbnI24Z5EK2sDcKyscRCziIsAAlIILIGFglIsrshKjtyBR9gFfotgpxrk8KFhoTZZnp9BMmi0kEiMsgmAB3Vh6PgQNZYMkIvjXLJ0rJUqlrZBDQbIACMAAYiRkfBT9GisEKsQy2mAhSzuGzPByDnBkAAWAUhKQUBQMIKGBrGAAyJQogWJZtCaM0rAsnBBm2Z1SyACVSOS-tVblArHBdHSiDBuLpuf6oAAPIO845Bc0ZQyW622h5ZGWOsAAYVIvn87qInu9uiF-sDwahYYjUZjDnOZs5cD+0Zj7DgnGM7BEIupniwTZbbYlKKlPdbPTArLRiq5AFZefyG+bSbaKOxKaKF9Il-3GWA10vZUFx7XkNPZ5WSXAtTrQvqjawTeqzXHO14E3askO260sgAJZvDnPIPMFB9d8KCLCAI15ENwz5GcK1PRxHzWK0bVfbdF3YT8wAAdXQ-9AJ9Hd2DAiCoIgyMFjnM1zlUdRMEpcR0BsDRtE4d4GHuBhzmqMAKFwdAEBQHi4FDCgwAAX16IA + - title: Login/logout application + description: 'Dynamic UI can be used to create completely different interfaces based on application state. This login example demonstrates switching between a login form and a dashboard interface using `@render.ui`. + + The app maintains authentication state using reactive values and renders different UIs based on whether the user is logged in or not.' + apps: + - title: Preview + file: app-variation-login-core.py + height: 350 + - title: Core + file: app-variation-login-core.py + shinylive: https://shinylive.io/py/editor/#code=NobwRAdghgtgpmAXAAjFADugdOgnmAGlQGMB7CAFzkqVQDMAnUmZAZwAsBLCXZTmdKQYVkAQUxEG1ACZwGRAK6cAOhCMZ0AfSXIAvMi04oAczia6AGyXSAFKuQODnLBai5SCimLJmyhBfLs+jqGRiEhYZJkJMJuMmBOjsyuJnZKbGoAFFCGTgAqcJqsRQBOcOycEgSarNZOCeFh5jZw9vYKMQnIcqHIDZws7cEAhgxgWZKycJrIanAAltKlcNy8bqUKVHTt0hl9KjpZBWZaKQBGCmFwSfV19VDIchxaO57e7T1GepFKh8eiTEgaGjWYIZAAUW2QcFhyWu3zudxibQgZV4cBOHkI5wYcjQ7GBlyIAHd2MggSNLnJHvY1K9lONwlA8BRaNlPo80u1pnJGm0Oop2GZqYZyZ5uCJNIgzDhVNiEANJIQWa4lUQAGy6xlM9JKEoVeTcPZzJRERxEaGqZJqFKcLQKA5mWgvRFwZAARiIEeVwMAIpILJaaAoWjL1kkAG5QfzlRUKJCxN2zJKsLxSEzlWZgY2aOYUSJMKAjKQNJ3lZI2R1yE5FqAVlWaKoSdRkpR0eRO4rOQhOLxBQZV5TdNrxlU8KCm7YNP1+4JBNwRb1RlBZcozJRAA --- :::{#example} From 9934ece95e2d69599486e07e6347ed92356978c5 Mon Sep 17 00:00:00 2001 From: Karan Gathani Date: Thu, 24 Jul 2025 15:37:27 +0530 Subject: [PATCH 2/2] Update shinylive link for Core example Replaced the shinylive URL for the Core example in the listing to use the new format with updated parameters. --- components/outputs/ui/index.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/outputs/ui/index.qmd b/components/outputs/ui/index.qmd index 3d3fb221..20152a9b 100644 --- a/components/outputs/ui/index.qmd +++ b/components/outputs/ui/index.qmd @@ -67,7 +67,7 @@ listing: height: 350 - title: Core file: app-variation-login-core.py - shinylive: https://shinylive.io/py/editor/#code=NobwRAdghgtgpmAXAAjFADugdOgnmAGlQGMB7CAFzkqVQDMAnUmZAZwAsBLCXZTmdKQYVkAQUxEG1ACZwGRAK6cAOhCMZ0AfSXIAvMi04oAczia6AGyXSAFKuQODnLBai5SCimLJmyhBfLs+jqGRiEhYZJkJMJuMmBOjsyuJnZKbGoAFFCGTgAqcJqsRQBOcOycEgSarNZOCeFh5jZw9vYKMQnIcqHIDZws7cEAhgxgWZKycJrIanAAltKlcNy8bqUKVHTt0hl9KjpZBWZaKQBGCmFwSfV19VDIchxaO57e7T1GepFKh8eiTEgaGjWYIZAAUW2QcFhyWu3zudxibQgZV4cBOHkI5wYcjQ7GBlyIAHd2MggSNLnJHvY1K9lONwlA8BRaNlPo80u1pnJGm0Oop2GZqYZyZ5uCJNIgzDhVNiEANJIQWa4lUQAGy6xlM9JKEoVeTcPZzJRERxEaGqZJqFKcLQKA5mWgvRFwZAARiIEeVwMAIpILJaaAoWjL1kkAG5QfzlRUKJCxN2zJKsLxSEzlWZgY2aOYUSJMKAjKQNJ3lZI2R1yE5FqAVlWaKoSdRkpR0eRO4rOQhOLxBQZV5TdNrxlU8KCm7YNP1+4JBNwRb1RlBZcozJRAA + shinylive: https://shinylive.io/py/editor/#h=0&code=NobwRAdghgtgpmAXGKAHVA6VBPMAaMAYwHsIAXOcpMAMwCdiYACAZwAsBLCbJjmVYnTJMAgujxMArhwl1KAEzh1ZcKITIcAbnAA6EPQFUAygFEASkaYBeJiB0p5MLvcRN7qKCxYB3QfICMAEwAzPYS9pIsSi5uYDDYHl72AL56aRCKNEwANsQA5lwA+tIAFACUiHpM1UxyZJJ0EFIcWFB5cIU02dLyJVU1A9IYbIF9YAAy+c5gZXj9A9VDXKiSZIUUAB5kY5FK0PBhsQZRjbC6+Eyo2WpwbMTZinRW9ibkSlIn++ez8wtLECs1okfH4xsDfHR5Id7AAFTwgyGHK43O4PJTPMCvCh0S7wiFQmZzJoLRYtZarQpqDSkQoAI1WZFIY1yBQgdLI+gu9kmrPsP2JJKGxFWgPWcC2zKmbJYZCg9RYfKJJNJGFpdHKSuVQ0IUEhfQFypVIzGABE4DBiExCHJFOQOFBsixKoTfoahvItGMoI4uEwAPS4rz4oKhF0Gt0tD2aHYnf1MeLAxWumr8gZldJ6TJMeSeNi04i6+TFDjlSoGuoNJpDDztTrdDi9ZNG-ym3P5wtJ8M1IUiimbbb2QgNOTkYonQoeljI7CdiMYclrKkcGn0siMiCSvLCta0jnQib5bezlMZjJwLInbTqhcSbeAiRRLzLiAVX5QVZsSgaHUUeTWWqqOoWhwBgABqDqSHAJQAGIOlE6YGkOdAjmsuw4jYchLtoYEQVB9h8ukAwAAKYUB2EmDQNBwOovwkYBGjYXA2jkCUC4YCyRS7i+vxZmwUAZNkHQcRur5dosnxnP+bFoV85RNoGCJ-jYbHgqCCHyRwWTGOYRgYO02wyWcZTWDYqmQmWhoDO+ZCfnaP5wPIGBRNsAAqdCQQhlk1EhKFjkoTlwAZEnwJ5ypwI6cAWV5TDWbZ35yg5AXbLBEWhV5Plfn5dBJWMBH6AadFYSBFFUTRBWkQxIFMV+rEAqs7GHhSXFpdm55MHxAlCY12yiYasVfhw9mOc5MFwXALUDBlo5oTl+EzIRNR0We2XSDxbXyNg+yDcWpYaVk-V2QlvS9dFFaNNmbYFpCO0TTU4VRFFXlnU0wk3Qt1RLY8GD9mtWSvTKcqRLtYm8FkEDEMIB3xb+5QxRkvB1WQDWsuyIlMAAfEwAAMj2Wc9sQAJIQJoDoNlaNoDXBGBMDCgmeHATBkHQPBtFAXAYPhIP43N71MJ9-k-QaWZTah46TtOwOGppHzvIgNgi1lkunYFlZMDQ9gAJrCjFcg5Pk7R-r6niuCAaGpGA8ncxbFv5XoaCoMW-7Vm0HRdD0JQ9mQoqlPYG1bYQxZ8up0DoP+YioCU9vFg+ShXghYDJAAukAA --- :::{#example}