gws_core

Introduction
Getting Started
Developer guide
Release
Architecture
CLI
Technical documentations
Version

Reflex

App task


 To see how to develop an app in a task within your brick check: Develop a task app in your brick.  


State


The main base state must be initialized by calling method on_load on page to check user authentication and load inputs and config.


# Declare the page and init the main state
@rx.page(on_load=ReflexMainState.on_load)
def index():
    # Render the main container with the app content.
    # The content will be displayed once the state is initialized.
    # If the state is not initialized, a loading spinner will be shown.
    return render_main_container(
        rx.heading("Reflex app"),
    )

Access input and param in normal app


Here is an example of how to access input and params in a normal reflex app from the state.  It uses the ReflexMainState state base class to have access to method to get input resources and config.  


from gws_reflex_main import ReflexMainState

class State(ReflexMainState):

    @rx.var
    async def get_resource_name(self) -> str:
        """Return the name of the first resource."""

        # Secure the method to ensure it checks authentication
        # before accessing resources.
        if not self.check_authentication():
            return 'Unauthorized'
        resources = self.get_resources()
        return resources[0].name if resources else 'No resource'

    @rx.var
    def get_param_name(self) -> Optional[str]:
        """
        Get a parameter from the app configuration.
        This route is not secured, so it can be accessed without authentication.
        """
        return self.get_param('param_name', 'default_value')

Access input files and param in virtual env app


Here is an example of how to access input and params in a virtual environment reflex app from the state. It uses the ReflexMainStateEnv state base class to have access to method to get input files and config.


from gws_reflex_base import ReflexMainStateEnv

class State(ReflexMainStateEnv):
    value = 0

    @rx.var
    async def get_resource_file_path(self) -> str:
        """Return the first resource file pth"""

        # Secure the method to ensure it checks authentication
        # before accessing resources.
        if not self.check_authentication():
            return 'Unauthorized'
        file_paths = self.get_source_paths()
        return file_paths[0] if file_paths else 'No file'

    @rx.var
    def get_param_name(self) -> Optional[str]:
        """
        Get a parameter from the app configuration.
        This route is not secured, so it can be accessed without authentication.
        """
        return self.get_param('param_name', 'default_value')


Example of a reflex app task


Here is an example of a reflex app using a folder and multiple files. Code from gws_core brick.


First we create the structure for our ReflexApp and our task using the CLI.


Text editor image

Here is the detail of the files


  • generate_reflex_showcase_app: This file includes the task that generate the reflex application
    • _reflex_showcase_app: This folder contains the reflex application. It starts with an underscore ('_') to ensure it is skipped during the lab startup process.
      • rxconfig.py: This folder is part of the application. It contains all the pages and states of the app. It houses the core functionality and layout components required for the application to operate effectively.
        • reflex_showcase: fodler of the app. it will contains the pages and states of the app!;
          • reflex_showcase.py: This is the main file for the reflex application. It is loaded by the rxconfig.py file. 

        generate_reflex_showcase_app.py


        
        import os
        
        from gws_core import (AppConfig, app_decorator, AppType,  ReflexResource, ConfigParams, 
                              ConfigSpecs, StrParam, InputSpec, OutputSpec,  InputSpecs, OutputSpecs,
                              Resource, Task,  task_decorator, TaskInputs, TaskOutputs)
        
        
        @app_decorator("ReflexShowcaseApp", app_type=AppType.REFLEX,
                       human_name="Generate reflex showcase app")
        class ReflexShowcaseApp(AppConfig):
        
            # retrieve the path of the app folder, relative to this file
            # the dashboard code folder starts with a underscore to avoid being loaded when the brick is loaded
            def get_app_folder_path(self):
                return self.get_app_folder_from_relative_path(
                    __file__,
                    "_reflex_showcase_app"
                )
        
        
        @task_decorator("GenerateReflexShowcaseApp", human_name="Generate reflex showcase app",
                        short_description="App that showcases Constellab components for reflex",
                        style=ReflexResource.copy_style())
        class GenerateReflexShowcaseApp(Task):
            """
            Task that generates the reflex showcase app.
        
            This app showcases the reflex component developped by Gencovery to simplify
            the creation of reflex apps.
        
            Some components are generic reflex components (like containers), other wrap Constellab UI components.
            """
        
            input_specs = InputSpecs({
                'resource': InputSpec(Resource)
            })
        
            output_specs = OutputSpecs({
                'reflex_app': OutputSpec(ReflexResource)
            })
        
            config_specs = ConfigSpecs({
                'my_param': InputSpec(StrParam,)
            })
        
            def run(self, params: ConfigParams, inputs: TaskInputs) -> TaskOutputs:
                """ Run the task """
        
                reflex_app = ReflexResource()
        
                # pass the task input resource to the reflex app
                task_input = inputs.get('resource')
                reflex_app.add_resource(task_input, create_new_resource=False)
        
                task_param = params.get('my_param')
                reflex_app.set_param('my_param', task_param)
        
                reflex_app.set_app_config(ReflexShowcaseApp())
                reflex_app.set_requires_authentication(False)
                reflex_app.set_name("Reflex Showcase App")
        
                return {"reflex_app": reflex_app}
        

        reflex_showcase.py


        from typing import Optional
        
        import reflex as rx
        from gws_reflex_base import (add_unauthorized_page, get_theme,
                                     render_main_container)
        from gws_reflex_main import ReflexMainState
        
        # define the custom app state and extends ReflexMainState 
        # to have access to inputs and params
        class State(ReflexMainState):
            value = 0
        
            @rx.var
            async def get_resource_name(self) -> str:
                """Return the name of the resource."""
        
                # Secure the method to ensure it checks authentication
                # before accessing resources.
                if not self.check_authentication():
                    return 'Unauthorized'
                resources = self.get_resources()
                return resources[0].name if resources else 'No resource'
        
            @rx.var
            def get_param_name(self) -> Optional[str]:
                """
                Get a parameter from the app configuration.
                This route is not secured, so it can be accessed without authentication.
                """
                return self.get_param('param_name', 'default_value')
        
            @rx.event
            def increment(self):
                """Increment the value."""
                self.value += 1
        
        # define the app with the default them
        app = rx.App(
            theme=get_theme()
        )
        
        
        # Declare the page and init the main state
        @rx.page(on_load=ReflexMainState.on_load)
        def index():
            # Render the main container with the app content.
            # The content will be displayed once the state is initialized.
            # If the state is not initialized, a loading spinner will be shown.
            return render_main_container(rx.box(
                rx.heading("Reflex app", font_size="2em"),
                rx.text("Input resource name: " + State.get_resource_name),
                rx.text("Param name: " + State.get_param_name),
                rx.text("Value: " + State.value.to_string()),
                rx.button(
                    "Click me",
                    on_click=State.increment,
                    style={"margin-top": "20px"}
                )
            ))
        
        
        # Add the unauthorized page to the app.
        # This page will be displayed if the user is not authenticated
        add_unauthorized_page(app)
        

        • The State extends ReflexMainState to have access to methods to get inputs and params
          • The ReflexMainState.on_load method must be called in index @rx.page(on_load=ReflexMainState.on_load) initialize the app, check user authorization.
            • the render_main_container component is useful to show a loader during the app initialization and load the content once the app is loaded. In the content of this you know the user is authenticated and you can access input and configs.
              • the add_unauthorized_page(app) is useful to declare a default page displayed when the user is not authenticated.