diff --git a/.deploy/temporary_db.py b/.deploy/temporary_db.py new file mode 100644 index 0000000..4507e39 --- /dev/null +++ b/.deploy/temporary_db.py @@ -0,0 +1,6 @@ + + +# reflex-dev/templates:.deploy/temporary_db.py to create default reflex.db when deployed +import reflex as rx +rx.utils.prerequisites.check_db_initialized() or rx.Model.alembic_init() +rx.Model.migrate(autogenerate=True) diff --git a/.github/workflows/check_export.yml b/.github/workflows/check_export.yml index 6adeaba..614370f 100644 --- a/.github/workflows/check_export.yml +++ b/.github/workflows/check_export.yml @@ -13,24 +13,14 @@ on: description: 'Reflex dep (raw pip spec)' jobs: - list-examples: - runs-on: ubuntu-latest - outputs: - examples: ${{ steps.generate-matrix.outputs.examples }} - steps: - - uses: actions/checkout@v4 - - name: Generate Matrix - id: generate-matrix - run: | - EXAMPLES="$(find . -not -name '.*' -maxdepth 1 -type d | cut -f2 -d/ | sort | grep -vw chakra_apps | jq -R | jq -s -c)" - echo $EXAMPLES - echo "examples=$EXAMPLES" >> $GITHUB_OUTPUT - + list-templates: + uses: ./.github/workflows/list-templates.yml + check-export: - needs: [list-examples] + needs: [list-templates] strategy: matrix: - example: ${{ fromJSON(needs.list-examples.outputs.examples) }} + folder: ${{ fromJSON(needs.list-templates.outputs.templates) }} fail-fast: false runs-on: ubuntu-latest steps: @@ -42,7 +32,7 @@ jobs: python-version: 3.9 - id: export-check run: | - f=${{ matrix.example }} + f=${{ matrix.folder }} if [[ ! -d $f ]]; then echo "$f is not a directory!" exit 1 @@ -80,7 +70,7 @@ jobs: - name: Check for DeprecationWarning in logs run: | - cd ${{ matrix.example }} + cd ${{ matrix.folder }} dep_lines=$(grep -i "DeprecationWarning:" export_logs.txt || true) if [ -n "$dep_lines" ]; then echo "Found Deprecation warning:" diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..881beaf --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,63 @@ +name: deploy + +# only redeploy when we push a new release. +on: + release: + types: [published] + push: + branches: + - lendemor/deploy_pipeline + +jobs: + list-templates: + uses: ./.github/workflows/list-templates.yml + + deploy: + needs: list-templates + runs-on: ubuntu-latest + environment: Cloud Deploy + strategy: + matrix: + folder: ${{ fromJSON(needs.list-templates.outputs.templates) }} + exclude: + # No deploy due to missing service dependencies. + - folder: reflex-llamaindex-template + fail-fast: false + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Set environment variables + id: set-env + run: | + case ${{ matrix.folder }} in + ai_image_gen) + echo "EXTRA_ARGS=--env REPLICATE_API_TOKEN=${{ secrets.REPLICATE_API_TOKEN }}" >> $GITHUB_ENV + ;; + customer_data_app) + cat .deploy/temporary_db.py >> ${{ matrix.folder }}/customer_data/customer_data.py + ;; + sales) + echo "EXTRA_ARGS=--env OPENAI_API_KEY=${{ secrets.OPEN_AI_KEY }}" >> $GITHUB_ENV + cat .deploy/temporary_db.py >> ${{ matrix.folder }}/${{ matrix.folder }}/${{ matrix.folder }}.py + ;; + reflex-chat) + echo "EXTRA_ARGS=--env OPENAI_API_KEY=${{ secrets.OPEN_AI_KEY }}" >> $GITHUB_ENV + echo "OPENAI_API_KEY=${{ secrets.OPEN_AI_KEY }}" >> $GITHUB_ENV + ;; + nba) + echo "EXTRA_ARGS=--vmtype ${{ vars.NBA_VM_TYPE }}" >> $GITHUB_ENV + ;; + *) + echo "EXTRA_ARGS=" >> $GITHUB_ENV + ;; + esac + - name: Deploy to ReflexCloud + uses: reflex-dev/reflex-deploy-action@masenf/skip-checkout + with: + auth_token: ${{ secrets.REFLEX_AUTH_TOKEN }} + project_id: ${{ secrets.REFLEX_PROJECT_ID }} + app_directory: ${{ matrix.folder }} + extra_args: ${{ env.EXTRA_ARGS }} + dry_run: ${{ vars.DRY_RUN }} + skip_checkout: "true" \ No newline at end of file diff --git a/.github/workflows/list-templates.yml b/.github/workflows/list-templates.yml new file mode 100644 index 0000000..1ac1159 --- /dev/null +++ b/.github/workflows/list-templates.yml @@ -0,0 +1,22 @@ +on: + workflow_call: + outputs: + templates: + description: 'List of templates' + value: ${{ jobs.list-templates.outputs.templates }} +jobs: + list-templates: + runs-on: ubuntu-latest + outputs: + templates: ${{ steps.generate-matrix.outputs.templates }} + steps: + - uses: actions/checkout@v4 + - name: List all templates + id: generate-matrix + run: | + TEMPLATES="$(find . -not -name '.*' -maxdepth 1 -type d | cut -f2 -d/ | sort | grep -vw chakra_apps | jq -R | jq -s -c)" + TEMPLATES=$(echo "$TEMPLATES" | jq -c '.') # Ensure valid JSON format + echo "templates=$TEMPLATES" >> $GITHUB_OUTPUT + - name: Debug output + run: | + echo "Templates: ${{ steps.generate-matrix.outputs.templates }}" \ No newline at end of file diff --git a/ai_image_gen/ai_image_gen/backend/options.py b/ai_image_gen/ai_image_gen/backend/options.py index a8447ba..71d2574 100644 --- a/ai_image_gen/ai_image_gen/backend/options.py +++ b/ai_image_gen/ai_image_gen/backend/options.py @@ -78,13 +78,13 @@ def set_guidance_scale(self, value: list): def randomize_prompt(self): self.prompt = random.choice(prompt_list) - @rx.var + @rx.var(cache=False) def selected_style_prompt(self) -> str: if self.selected_style == "": return "" return self.styles_preset[self.selected_style]["prompt"] - @rx.var + @rx.var(cache=False) def dimensions_str(self) -> str: width, height = self.selected_dimensions return f"{width} × {height}" diff --git a/api_admin_panel/app/__init__.py b/api_admin_panel/api_admin_panel/__init__.py similarity index 100% rename from api_admin_panel/app/__init__.py rename to api_admin_panel/api_admin_panel/__init__.py diff --git a/api_admin_panel/app/app.py b/api_admin_panel/api_admin_panel/api_admin_panel.py similarity index 77% rename from api_admin_panel/app/app.py rename to api_admin_panel/api_admin_panel/api_admin_panel.py index ad33fc4..4803010 100644 --- a/api_admin_panel/app/app.py +++ b/api_admin_panel/api_admin_panel/api_admin_panel.py @@ -1,5 +1,5 @@ import reflex as rx -from app.pages import * +from api_admin_panel.pages import * class State(rx.State): diff --git a/api_admin_panel/app/components/__init__.py b/api_admin_panel/api_admin_panel/components/__init__.py similarity index 100% rename from api_admin_panel/app/components/__init__.py rename to api_admin_panel/api_admin_panel/components/__init__.py diff --git a/api_admin_panel/app/components/drawer.py b/api_admin_panel/api_admin_panel/components/drawer.py similarity index 97% rename from api_admin_panel/app/components/drawer.py rename to api_admin_panel/api_admin_panel/components/drawer.py index d63d5b0..eb7e37c 100644 --- a/api_admin_panel/app/components/drawer.py +++ b/api_admin_panel/api_admin_panel/components/drawer.py @@ -1,6 +1,6 @@ import reflex as rx -from app.states.queries import QueryAPI +from api_admin_panel.states.queries import QueryAPI def render_data(data: tuple[str, str]): diff --git a/api_admin_panel/app/components/navbar.py b/api_admin_panel/api_admin_panel/components/navbar.py similarity index 91% rename from api_admin_panel/app/components/navbar.py rename to api_admin_panel/api_admin_panel/components/navbar.py index d6a0081..562d647 100644 --- a/api_admin_panel/app/components/navbar.py +++ b/api_admin_panel/api_admin_panel/components/navbar.py @@ -1,7 +1,7 @@ import reflex as rx -from app.states.base import BaseState -from app.styles import text +from api_admin_panel.states.base import BaseState +from api_admin_panel.styles import text navbar: dict[str, str] = { "width": "100%", diff --git a/api_admin_panel/app/components/output.py b/api_admin_panel/api_admin_panel/components/output.py similarity index 95% rename from api_admin_panel/app/components/output.py rename to api_admin_panel/api_admin_panel/components/output.py index 7d622b8..4cb1dec 100644 --- a/api_admin_panel/app/components/output.py +++ b/api_admin_panel/api_admin_panel/components/output.py @@ -1,7 +1,7 @@ import reflex as rx -from app.states.queries import QueryAPI -from app.components.drawer import render_drawer +from api_admin_panel.states.queries import QueryAPI +from api_admin_panel.components.drawer import render_drawer import reflex_chakra as rc diff --git a/api_admin_panel/app/components/query.py b/api_admin_panel/api_admin_panel/components/query.py similarity index 97% rename from api_admin_panel/app/components/query.py rename to api_admin_panel/api_admin_panel/components/query.py index 9fbed15..e7b347a 100644 --- a/api_admin_panel/app/components/query.py +++ b/api_admin_panel/api_admin_panel/components/query.py @@ -1,8 +1,8 @@ import reflex as rx -from app.states.base import BaseState -from app.states.queries import QueryState, QueryAPI -from app.styles import text +from api_admin_panel.states.base import BaseState +from api_admin_panel.states.queries import QueryState, QueryAPI +from api_admin_panel.styles import text import reflex_chakra as rc diff --git a/api_admin_panel/app/pages/__init__.py b/api_admin_panel/api_admin_panel/pages/__init__.py similarity index 100% rename from api_admin_panel/app/pages/__init__.py rename to api_admin_panel/api_admin_panel/pages/__init__.py diff --git a/api_admin_panel/app/pages/dashboard.py b/api_admin_panel/api_admin_panel/pages/dashboard.py similarity index 68% rename from api_admin_panel/app/pages/dashboard.py rename to api_admin_panel/api_admin_panel/pages/dashboard.py index acb1c42..bf68234 100644 --- a/api_admin_panel/app/pages/dashboard.py +++ b/api_admin_panel/api_admin_panel/pages/dashboard.py @@ -2,10 +2,10 @@ import reflex as rx -from app.components.navbar import render_navbar -from app.components.query import render_query_component -from app.components.output import render_output -from app.states.queries import QueryAPI +from api_admin_panel.components.navbar import render_navbar +from api_admin_panel.components.query import render_query_component +from api_admin_panel.components.output import render_output +from api_admin_panel.states.queries import QueryAPI @rx.page("/", on_load=QueryAPI.run_get_request) diff --git a/api_admin_panel/app/states/__init__.py b/api_admin_panel/api_admin_panel/states/__init__.py similarity index 100% rename from api_admin_panel/app/states/__init__.py rename to api_admin_panel/api_admin_panel/states/__init__.py diff --git a/api_admin_panel/app/states/base.py b/api_admin_panel/api_admin_panel/states/base.py similarity index 100% rename from api_admin_panel/app/states/base.py rename to api_admin_panel/api_admin_panel/states/base.py diff --git a/api_admin_panel/app/states/queries.py b/api_admin_panel/api_admin_panel/states/queries.py similarity index 99% rename from api_admin_panel/app/states/queries.py rename to api_admin_panel/api_admin_panel/states/queries.py index b81f25b..b36dfdf 100644 --- a/api_admin_panel/app/states/queries.py +++ b/api_admin_panel/api_admin_panel/states/queries.py @@ -1,6 +1,6 @@ import uuid import httpx -from app.states.base import BaseState +from api_admin_panel.states.base import BaseState # test URL: str = https://jsonplaceholder.typicode.com/posts @@ -8,7 +8,6 @@ class QueryState(BaseState): - # vars for handling request calls ... req_methods: list[str] = ["GET", "POST"] req_url: str = "https://jsonplaceholder.typicode.com/posts" @@ -97,7 +96,6 @@ async def update_value(self, value: str, data: dict[str, str]): class QueryAPI(QueryState): - # vars to update row entries ... is_open: bool = False selected_entry: dict[str, str] diff --git a/api_admin_panel/app/styles.py b/api_admin_panel/api_admin_panel/styles.py similarity index 100% rename from api_admin_panel/app/styles.py rename to api_admin_panel/api_admin_panel/styles.py diff --git a/api_admin_panel/rxconfig.py b/api_admin_panel/rxconfig.py index 454ba35..5c65ca2 100644 --- a/api_admin_panel/rxconfig.py +++ b/api_admin_panel/rxconfig.py @@ -1,3 +1,3 @@ import reflex as rx -config = rx.Config(app_name="app", telemetry_enabled=False) +config = rx.Config(app_name="api_admin_panel", telemetry_enabled=False) diff --git a/customer_data_app/customer_data_app/__init__.py b/customer_data_app/customer_data/__init__.py similarity index 100% rename from customer_data_app/customer_data_app/__init__.py rename to customer_data_app/customer_data/__init__.py diff --git a/customer_data_app/customer_data_app/backend/__init__.py b/customer_data_app/customer_data/backend/__init__.py similarity index 100% rename from customer_data_app/customer_data_app/backend/__init__.py rename to customer_data_app/customer_data/backend/__init__.py diff --git a/customer_data_app/customer_data_app/backend/backend.py b/customer_data_app/customer_data/backend/backend.py similarity index 100% rename from customer_data_app/customer_data_app/backend/backend.py rename to customer_data_app/customer_data/backend/backend.py diff --git a/customer_data_app/customer_data_app/components/__init__.py b/customer_data_app/customer_data/components/__init__.py similarity index 100% rename from customer_data_app/customer_data_app/components/__init__.py rename to customer_data_app/customer_data/components/__init__.py diff --git a/customer_data_app/customer_data_app/components/form_field.py b/customer_data_app/customer_data/components/form_field.py similarity index 100% rename from customer_data_app/customer_data_app/components/form_field.py rename to customer_data_app/customer_data/components/form_field.py diff --git a/customer_data_app/customer_data_app/components/stats_cards.py b/customer_data_app/customer_data/components/stats_cards.py similarity index 100% rename from customer_data_app/customer_data_app/components/stats_cards.py rename to customer_data_app/customer_data/components/stats_cards.py diff --git a/customer_data_app/customer_data_app/components/status_badges.py b/customer_data_app/customer_data/components/status_badges.py similarity index 100% rename from customer_data_app/customer_data_app/components/status_badges.py rename to customer_data_app/customer_data/components/status_badges.py diff --git a/customer_data_app/customer_data_app/customer_data_app.py b/customer_data_app/customer_data/customer_data.py similarity index 100% rename from customer_data_app/customer_data_app/customer_data_app.py rename to customer_data_app/customer_data/customer_data.py diff --git a/customer_data_app/customer_data_app/views/__init__.py b/customer_data_app/customer_data/views/__init__.py similarity index 100% rename from customer_data_app/customer_data_app/views/__init__.py rename to customer_data_app/customer_data/views/__init__.py diff --git a/customer_data_app/customer_data_app/views/navbar.py b/customer_data_app/customer_data/views/navbar.py similarity index 100% rename from customer_data_app/customer_data_app/views/navbar.py rename to customer_data_app/customer_data/views/navbar.py diff --git a/customer_data_app/customer_data_app/views/table.py b/customer_data_app/customer_data/views/table.py similarity index 100% rename from customer_data_app/customer_data_app/views/table.py rename to customer_data_app/customer_data/views/table.py diff --git a/customer_data_app/rxconfig.py b/customer_data_app/rxconfig.py index b19da25..8fe1e07 100644 --- a/customer_data_app/rxconfig.py +++ b/customer_data_app/rxconfig.py @@ -4,6 +4,6 @@ database_url = os.getenv("DATABASE_URL", "sqlite:///reflex.db") config = rx.Config( - app_name="customer_data_app", + app_name="customer_data", db_url=database_url, - ) \ No newline at end of file +) diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..5500213 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# Exit immediately if a command exits with a non-zero status +set -e + +# Validate input +if [ -z "$1" ]; then + echo "Error: No subfolder specified." + echo "Usage: $0 " + exit 1 +fi + +SUBFOLDER=$1 +EXTRA_ENV=$2 + +# Ensure the subfolder exists +if [ ! -d "$SUBFOLDER" ]; then + echo "Error: Subfolder '$SUBFOLDER' does not exist." + exit 1 +fi + +# Navigate to the subfolder +cd "$SUBFOLDER" + +# Print the current working directory for debugging +echo "Deploying content from: $(pwd)" + +# Check if reflex CLI is installed +if ! command -v reflex &> /dev/null; then + echo "Error: Reflex CLI not found. Please ensure it is installed." + exit 1 +fi + +# Store the project ID in a variable +template_id=$(reflex apps project-list --token $REFLEX_AUTH_TOKEN | awk '/templates/ {print $1}') + +echo "Starting deployment..." +reflex deployv2 --token $REFLEX_AUTH_TOKEN --project $template_id --no-interactive $EXTRA_ENV +echo "Deployment for '$SUBFOLDER' completed successfully." diff --git a/reflex-chat b/reflex-chat index fa8f03d..4f97ea1 160000 --- a/reflex-chat +++ b/reflex-chat @@ -1 +1 @@ -Subproject commit fa8f03d7a0c04a8e6e891b7e8cbc7d5d064725cc +Subproject commit 4f97ea182e274753e790f8fc5e9712b43b49d3ae diff --git a/sales/README.md b/sales/README.md index 3553a65..1c62d6e 100644 --- a/sales/README.md +++ b/sales/README.md @@ -11,21 +11,21 @@ First, install all the necessary dependencies: pip install -r requirements.txt ``` ## 2. Set Your OpenAI API Key -To utilize OpenAI in this template, you need to set your OPEN_AI_KEY environment variable. Here’s how you can set it based on your operating system: +To utilize OpenAI in this template, you need to set your OPENAI_API_KEY environment variable. Here’s how you can set it based on your operating system: ### On Linux / macOS: ```shell -export OPEN_AI_KEY=your-openai-api-key +export OPENAI_API_KEY=your-openai-api-key ``` ### On Windows (Command Prompt): ```shell -set OPEN_AI_KEY=your-openai-api-key +set OPENAI_API_KEY=your-openai-api-key ``` ### On Windows (PowerShell): ```shell -$env:OPEN_AI_KEY="your-openai-api-key" +$env:OPENAI_API_KEY="your-openai-api-key" ``` ### 3. Run the App diff --git a/sales/alembic.ini b/sales/alembic.ini deleted file mode 100644 index c10d4ca..0000000 --- a/sales/alembic.ini +++ /dev/null @@ -1,116 +0,0 @@ -# A generic, single database configuration. - -[alembic] -# path to migration scripts -script_location = alembic - -# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s -# Uncomment the line below if you want the files to be prepended with date and time -# see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file -# for all available tokens -# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s - -# sys.path path, will be prepended to sys.path if present. -# defaults to the current working directory. -prepend_sys_path = . - -# timezone to use when rendering the date within the migration file -# as well as the filename. -# If specified, requires the python>=3.9 or backports.zoneinfo library. -# Any required deps can installed by adding `alembic[tz]` to the pip requirements -# string value is passed to ZoneInfo() -# leave blank for localtime -# timezone = - -# max length of characters to apply to the -# "slug" field -# truncate_slug_length = 40 - -# set to 'true' to run the environment during -# the 'revision' command, regardless of autogenerate -# revision_environment = false - -# set to 'true' to allow .pyc and .pyo files without -# a source .py file to be detected as revisions in the -# versions/ directory -# sourceless = false - -# version location specification; This defaults -# to alembic/versions. When using multiple version -# directories, initial revisions must be specified with --version-path. -# The path separator used here should be the separator specified by "version_path_separator" below. -# version_locations = %(here)s/bar:%(here)s/bat:alembic/versions - -# version path separator; As mentioned above, this is the character used to split -# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep. -# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas. -# Valid values for version_path_separator are: -# -# version_path_separator = : -# version_path_separator = ; -# version_path_separator = space -version_path_separator = os # Use os.pathsep. Default configuration used for new projects. - -# set to 'true' to search source files recursively -# in each "version_locations" directory -# new in Alembic version 1.10 -# recursive_version_locations = false - -# the output encoding used when revision files -# are written from script.py.mako -# output_encoding = utf-8 - -sqlalchemy.url = driver://user:pass@localhost/dbname - - -[post_write_hooks] -# post_write_hooks defines scripts or Python functions that are run -# on newly generated revision scripts. See the documentation for further -# detail and examples - -# format using "black" - use the console_scripts runner, against the "black" entrypoint -# hooks = black -# black.type = console_scripts -# black.entrypoint = black -# black.options = -l 79 REVISION_SCRIPT_FILENAME - -# lint with attempts to fix using "ruff" - use the exec runner, execute a binary -# hooks = ruff -# ruff.type = exec -# ruff.executable = %(here)s/.venv/bin/ruff -# ruff.options = --fix REVISION_SCRIPT_FILENAME - -# Logging configuration -[loggers] -keys = root,sqlalchemy,alembic - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = WARN -handlers = console -qualname = - -[logger_sqlalchemy] -level = WARN -handlers = -qualname = sqlalchemy.engine - -[logger_alembic] -level = INFO -handlers = -qualname = alembic - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(levelname)-5.5s [%(name)s] %(message)s -datefmt = %H:%M:%S diff --git a/sales/sales/backend/backend.py b/sales/sales/backend/backend.py index e519e4f..60b0adf 100644 --- a/sales/sales/backend/backend.py +++ b/sales/sales/backend/backend.py @@ -119,35 +119,34 @@ def get_user(self, user: Customer): self.current_user = user def add_customer_to_db(self, form_data: dict): - self.current_user = form_data + self.current_user = Customer(**form_data) with rx.session() as session: if session.exec( - select(Customer).where(Customer.email == self.current_user["email"]) + select(Customer).where(Customer.email == self.current_user.email) ).first(): return rx.window_alert("User with this email already exists") - session.add(Customer(**self.current_user)) + session.add(self.current_user) session.commit() + session.refresh(self.current_user) self.load_entries() return rx.toast.info( - f"User {self.current_user['customer_name']} has been added.", + f"User {self.current_user.customer_name} has been added.", position="bottom-right", ) def update_customer_to_db(self, form_data: dict): - self.current_user.update(form_data) with rx.session() as session: customer = session.exec( - select(Customer).where(Customer.id == self.current_user["id"]) + select(Customer).where(Customer.id == self.current_user.id) ).first() - for field in Customer.get_fields(): - if field != "id": - setattr(customer, field, self.current_user[field]) - session.add(customer) + customer.set(**form_data) session.commit() + session.refresh(customer) + self.current_user = customer self.load_entries() return rx.toast.info( - f"User {self.current_user['customer_name']} has been modified.", + f"User {self.current_user.customer_name} has been modified.", position="bottom-right", ) @@ -191,7 +190,7 @@ async def call_openai(self): self.gen_response = False def generate_email(self, user: Customer): - self.current_user = Customer(**user) + self.current_user = user self.gen_response = True self.email_content_data = "" return State.call_openai